tizen/hello_video test non-tunneled EmptyBufferDone call-back sandbox/hackseung/userland_20171030git
authorHackseung Lee <lhs@dignsys.com>
Thu, 9 Nov 2017 03:52:35 +0000 (12:52 +0900)
committerHackseung Lee <lhs@dignsys.com>
Thu, 9 Nov 2017 03:52:57 +0000 (12:52 +0900)
Change-Id: I11a2a5e87bf0e7679df8f739fe9db552fbc40bc3
Signed-off-by: Hackseung Lee <lhs@dignsys.com>
14 files changed:
host_applications/linux/CMakeLists.txt
host_applications/linux/apps/hello_pi/CMakeLists.txt
host_applications/linux/apps/hello_pi/hello_video/CMakeLists.txt
host_applications/linux/apps/hello_pi/hello_video/Makefile
host_applications/linux/apps/hello_pi/hello_video/omx_comp_debug_levels.h [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/queue.c [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/queue.h [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/tags [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/tsemaphore.c [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/tsemaphore.h [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/user_debug_levels.h [new file with mode: 0644]
host_applications/linux/apps/hello_pi/hello_video/video.c
host_applications/linux/apps/hello_pi/hello_video/video.h [new file with mode: 0644]
packaging/raspberrypi-userland.spec

index e8615cc463d81c26db72efe40c52d22834358e90..80a1908d435549f17c0d20718f511f6f5da84825 100644 (file)
@@ -2,6 +2,7 @@
 
 if(NOT ARM64)
    add_subdirectory(libs/bcm_host)
+   add_subdirectory(apps/hello_pi)
 endif()
 add_subdirectory(apps/gencmd)
 add_subdirectory(apps/tvservice)
@@ -22,4 +23,3 @@ if(ALL_APPS)
  add_subdirectory(apps/edid_parser)
  add_subdirectory(apps/hello_pi)
 endif()
-
index f2c6aefffbdd1779ebf7056f258af2c2cce54917..21b29f320c4c1e7bd392bf91f500e5c79df61136 100644 (file)
@@ -13,14 +13,14 @@ set(HELLO_PI_LIBS ilclient openmaxil bcm_host vcos vchiq_arm)
 add_subdirectory(hello_world)
 add_subdirectory(hello_video)
 add_subdirectory(hello_audio)
-add_subdirectory(hello_triangle)
-add_subdirectory(hello_triangle2)
-add_subdirectory(hello_dispmanx)
-add_subdirectory(hello_tiger)
-add_subdirectory(hello_encode)
-add_subdirectory(hello_jpeg)
-add_subdirectory(hello_videocube)
-add_subdirectory(hello_teapot)
+#add_subdirectory(hello_triangle)
+#add_subdirectory(hello_triangle2)
+#add_subdirectory(hello_dispmanx)
+#add_subdirectory(hello_tiger)
+#add_subdirectory(hello_encode)
+#add_subdirectory(hello_jpeg)
+#add_subdirectory(hello_videocube)
+#add_subdirectory(hello_teapot)
 
 if(BUILD_FONT)
 set(VGFONT_SRCS libs/vgfont/font.c libs/vgfont/vgft.c libs/vgfont/graphics.c)
index 42187aff0db071a73f66f552430477236b98e337..fdc1182124849c53eae4eccd8e9fecfaa3494285 100644 (file)
@@ -1,8 +1,10 @@
 set(EXEC hello_video.bin)
-set(SRCS video.c)
+set(SRCS tsemaphore.c queue.c video.c)
+#SET(pc_dependents "libtbm")
 
 add_executable(${EXEC} ${SRCS})
-target_link_libraries(${EXEC} ${HELLO_PI_LIBS})
+#add_dependencies(${EXEC} ${pc_dependents})
+target_link_libraries(${EXEC} ${HELLO_PI_LIBS} -ltbm)
 
 install(TARGETS ${EXEC}
         RUNTIME DESTINATION bin)
index be21fd5fd00dcfa34088e7d77bdf5fc27c080fc6..c86256aaa04a2492a5409c60dd620b9953d51d8c 100755 (executable)
@@ -1,4 +1,4 @@
-OBJS=video.o
+OBJS=tsemaphore.o queue.o video.o
 BIN=hello_video.bin
 LDFLAGS+=-lilclient
 
diff --git a/host_applications/linux/apps/hello_pi/hello_video/omx_comp_debug_levels.h b/host_applications/linux/apps/hello_pi/hello_video/omx_comp_debug_levels.h
new file mode 100644 (file)
index 0000000..3ba1d1a
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+  @file src/omx_comp_debug_levels.h
+
+  Define the level of debug prints on standard err. The different levels can 
+  be composed with binary OR.
+  The debug levels defined here belong to OpenMAX components and IL core
+
+  Copyright (C) 2007-2008 STMicroelectronics
+  Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+  This library is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation; either version 2.1 of the License, or (at your option)
+  any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+  details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this library; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St, Fifth Floor, Boston, MA
+  02110-1301  USA
+
+  $Date: 2008-07-16 09:39:31 +0200 (Wed, 16 Jul 2008) $
+  Revision $Rev: 577 $
+  Author $Author: gsent $
+
+*/
+
+#ifndef __OMX_COMP_DEBUG_LEVELS_H__
+#define __OMX_COMP_DEBUG_LEVELS_H__
+
+#include <stdio.h>
+
+/** Remove all debug output lines
+ */
+#define DEB_LEV_NO_OUTPUT  0
+
+/** Messages explaing the reason of critical errors 
+ */
+#define DEB_LEV_ERR        1
+/** Messages showing values related to the test and the component/s used
+ */
+#define DEB_LEV_PARAMS     2
+
+/** Messages representing steps in the execution. These are the simple messages, because 
+ * they avoid iterations 
+ */
+#define DEB_LEV_SIMPLE_SEQ 4
+
+/** Messages representing steps in the execution. All the steps are described, 
+ * also with iterations. With this level of output the performances are 
+ * seriously compromised
+ */
+#define DEB_LEV_FULL_SEQ   8
+
+/** Messages that indicates the beginning and the end of a function.
+ * It can be used to trace the execution
+ */
+#define DEB_LEV_FUNCTION_NAME 16
+
+/** All the messages - max value
+ */
+#define DEB_ALL_MESS   255
+
+/** \def DEBUG_LEVEL is the current level do debug output on standard err */
+#define DEBUG_LEVEL (DEB_LEV_ERR)
+#if DEBUG_LEVEL > 0
+#define DEBUG(n, fmt, args...) do { if (DEBUG_LEVEL & (n)){fprintf(stderr, "OMX-" fmt, ##args);} } while (0)
+#else
+#define DEBUG(n, fmt, args...) 
+#endif
+
+#endif
diff --git a/host_applications/linux/apps/hello_pi/hello_video/queue.c b/host_applications/linux/apps/hello_pi/hello_video/queue.c
new file mode 100644 (file)
index 0000000..e6ee4b7
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+  @file src/queue.c
+
+  Implements a simple LIFO structure used for queueing OMX buffers.
+
+  Copyright (C) 2007-2008 STMicroelectronics
+  Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+  This library is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation; either version 2.1 of the License, or (at your option)
+  any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+  details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this library; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St, Fifth Floor, Boston, MA
+  02110-1301  USA
+
+  $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $
+  Revision $Rev: 554 $
+  Author $Author: pankaj_sen $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "queue.h"
+#include "omx_comp_debug_levels.h"
+
+/** Initialize a queue descriptor
+ * 
+ * @param queue The queue descriptor to initialize. 
+ * The user needs to allocate the queue
+ */
+void queue_init(queue_t* queue) {
+  int i;
+  qelem_t* newelem;
+  qelem_t* current;
+  queue->first = malloc(sizeof(qelem_t));
+  memset(queue->first, 0, sizeof(qelem_t));
+  current = queue->last = queue->first;
+  queue->nelem = 0;
+  for (i = 0; i<MAX_QUEUE_ELEMENTS - 2; i++) {
+    newelem = malloc(sizeof(qelem_t));
+    memset(newelem, 0, sizeof(qelem_t));
+    current->q_forw = newelem;
+    current = newelem;
+  }
+  current->q_forw = queue->first;
+  
+  pthread_mutex_init(&queue->mutex, NULL);
+}
+
+/** Deinitialize a queue descriptor
+ * flushing all of its internal data
+ * 
+ * @param queue the queue descriptor to dump
+ */
+void queue_deinit(queue_t* queue) {
+  int i;
+  qelem_t* current;
+  current = queue->first;
+  for (i = 0; i<MAX_QUEUE_ELEMENTS - 2; i++) {
+    if (current != NULL) {
+      current = current->q_forw;
+      free(queue->first);
+      queue->first = current;
+    }
+  }
+  if(queue->first) {
+    free(queue->first);
+    queue->first = NULL;
+  }
+  pthread_mutex_destroy(&queue->mutex);
+}
+
+/** Enqueue an element to the given queue descriptor
+ * 
+ * @param queue the queue descritpor where to queue data
+ * 
+ * @param data the data to be enqueued
+ */
+void queue(queue_t* queue, void* data) {
+  if (queue->last->data != NULL) {
+    return;
+  }
+  pthread_mutex_lock(&queue->mutex);
+  queue->last->data = data;
+  queue->last = queue->last->q_forw;
+  queue->nelem++;
+  pthread_mutex_unlock(&queue->mutex);
+}
+
+/** Dequeue an element from the given queue descriptor
+ * 
+ * @param queue the queue descriptor from which to dequeue the element
+ * 
+ * @return the element that has bee dequeued. If the queue is empty
+ *  a NULL value is returned
+ */
+void* dequeue(queue_t* queue) {
+  void* data;
+  if (queue->first->data == NULL) {
+    return NULL;
+  }
+  pthread_mutex_lock(&queue->mutex);
+  data = queue->first->data;
+  queue->first->data = NULL;
+  queue->first = queue->first->q_forw;
+  queue->nelem--;
+  pthread_mutex_unlock(&queue->mutex);
+
+  return data;
+}
+
+/** Returns the number of elements hold in the queue
+ * 
+ * @param queue the requested queue
+ * 
+ * @return the number of elements in the queue
+ */
+int getquenelem(queue_t* queue) {
+  int qelem;
+  pthread_mutex_lock(&queue->mutex);
+  qelem = queue->nelem;
+  pthread_mutex_unlock(&queue->mutex);
+  return qelem;
+}
diff --git a/host_applications/linux/apps/hello_pi/hello_video/queue.h b/host_applications/linux/apps/hello_pi/hello_video/queue.h
new file mode 100644 (file)
index 0000000..745ca70
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+  @file src/queue.h
+
+  Implements a simple LIFO structure used for queueing OMX buffers.
+
+  Copyright (C) 2007-2008 STMicroelectronics
+  Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+  This library is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation; either version 2.1 of the License, or (at your option)
+  any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+  details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this library; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St, Fifth Floor, Boston, MA
+  02110-1301  USA
+
+  $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $
+  Revision $Rev: 554 $
+  Author $Author: pankaj_sen $
+*/
+
+#ifndef __TQUEUE_H__
+#define __TQUEUE_H__
+
+#include <pthread.h>
+/** Maximum number of elements in a queue 
+ */
+#define MAX_QUEUE_ELEMENTS 10
+/** Output port queue element. Contains an OMX buffer header type
+ */
+typedef struct qelem_t qelem_t;
+struct qelem_t{
+  qelem_t* q_forw;
+  void* data;
+};
+
+/** This structure contains the queue
+ */
+typedef struct queue_t{
+  qelem_t* first; /**< Output buffer queue head */
+  qelem_t* last; /**< Output buffer queue tail */
+  int nelem; /**< Number of elements in the queue */
+  pthread_mutex_t mutex;
+} queue_t;
+
+/** Initialize a queue descriptor
+ * 
+ * @param queue The queue descriptor to initialize. 
+ * The user needs to allocate the queue
+ */
+void queue_init(queue_t* queue);
+
+/** Deinitialize a queue descriptor
+ * flushing all of its internal data
+ * 
+ * @param queue the queue descriptor to dump
+ */
+void queue_deinit(queue_t* queue);
+
+/** Enqueue an element to the given queue descriptor
+ * 
+ * @param queue the queue descritpor where to queue data
+ * 
+ * @param data the data to be enqueued
+ */
+void queue(queue_t* queue, void* data);
+
+/** Dequeue an element from the given queue descriptor
+ * 
+ * @param queue the queue descriptor from which to dequeue the element
+ * 
+ * @return the element that has bee dequeued. If the queue is empty
+ *  a NULL value is returned
+ */
+void* dequeue(queue_t* queue);
+
+/** Returns the number of elements hold in the queue
+ * 
+ * @param queue the requested queue
+ * 
+ * @return the number of elements in the queue
+ */
+int getquenelem(queue_t* queue);
+
+#endif
diff --git a/host_applications/linux/apps/hello_pi/hello_video/tags b/host_applications/linux/apps/hello_pi/hello_video/tags
new file mode 100644 (file)
index 0000000..eb7bd70
--- /dev/null
@@ -0,0 +1,10 @@
+!_TAG_FILE_FORMAT      2       /extended format; --format=1 will not append ;" to lines/
+!_TAG_FILE_SORTED      1       /0=unsorted, 1=sorted, 2=foldcase/
+!_TAG_PROGRAM_AUTHOR   Darren Hiebert  /dhiebert@users.sourceforge.net/
+!_TAG_PROGRAM_NAME     Exuberant Ctags //
+!_TAG_PROGRAM_URL      http://ctags.sourceforge.net    /official site/
+!_TAG_PROGRAM_VERSION  5.9~svn20110310 //
+BIN    Makefile        /^BIN=hello_video.bin$/;"       m
+OBJS   Makefile        /^OBJS=video.o$/;"      m
+main   video.c /^int main (int argc, char **argv)$/;"  f       signature:(int argc, char **argv)
+video_decode_test      video.c /^static int video_decode_test(char *filename)$/;"      f       file:   signature:(char *filename)
diff --git a/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.c b/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.c
new file mode 100644 (file)
index 0000000..6f2b6ad
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+  @file src/tsemaphore.c
+
+  Implements a simple inter-thread semaphore so not to have to deal with IPC
+  creation and the like.
+
+  Copyright (C) 2007-2008 STMicroelectronics
+  Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+  This library is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation; either version 2.1 of the License, or (at your option)
+  any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+  details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this library; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St, Fifth Floor, Boston, MA
+  02110-1301  USA
+
+  $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $
+  Revision $Rev: 554 $
+  Author $Author: pankaj_sen $
+*/
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <errno.h>
+#include "tsemaphore.h"
+#include "omx_comp_debug_levels.h"
+
+/** Initializes the semaphore at a given value
+ * 
+ * @param tsem the semaphore to initialize
+ * @param val the initial value of the semaphore
+ * 
+ */
+void tsem_init(tsem_t* tsem, unsigned int val) {
+  pthread_cond_init(&tsem->condition, NULL);
+  pthread_mutex_init(&tsem->mutex, NULL);
+  tsem->semval = val;
+}
+
+/** Destroy the semaphore
+ *  
+ * @param tsem the semaphore to destroy
+ */
+void tsem_deinit(tsem_t* tsem) {
+  pthread_cond_destroy(&tsem->condition);
+  pthread_mutex_destroy(&tsem->mutex);
+}
+
+/** Decreases the value of the semaphore. Blocks if the semaphore
+ * value is zero.
+ * 
+ * @param tsem the semaphore to decrease
+ */
+void tsem_down(tsem_t* tsem) {
+  pthread_mutex_lock(&tsem->mutex);
+  while (tsem->semval == 0) {
+    pthread_cond_wait(&tsem->condition, &tsem->mutex);
+  }
+  tsem->semval--;
+  pthread_mutex_unlock(&tsem->mutex);
+}
+
+/** Increases the value of the semaphore
+ * 
+ * @param tsem the semaphore to increase
+ */
+void tsem_up(tsem_t* tsem) {
+  pthread_mutex_lock(&tsem->mutex);
+  tsem->semval++;
+  pthread_cond_signal(&tsem->condition);
+  pthread_mutex_unlock(&tsem->mutex);
+}
+
+/** Reset the value of the semaphore
+ * 
+ * @param tsem the semaphore to reset
+ */
+void tsem_reset(tsem_t* tsem) {
+  pthread_mutex_lock(&tsem->mutex);
+  tsem->semval=0;
+  pthread_mutex_unlock(&tsem->mutex);
+}
+
+/** Wait on the condition.
+ * 
+ * @param tsem the semaphore to wait
+ */
+void tsem_wait(tsem_t* tsem) {
+  pthread_mutex_lock(&tsem->mutex);
+  pthread_cond_wait(&tsem->condition, &tsem->mutex);
+  pthread_mutex_unlock(&tsem->mutex);
+}
+
+/** Signal the condition,if waiting
+ * 
+ * @param tsem the semaphore to signal
+ */
+void tsem_signal(tsem_t* tsem) {
+  pthread_mutex_lock(&tsem->mutex);
+  pthread_cond_signal(&tsem->condition);
+  pthread_mutex_unlock(&tsem->mutex);
+}
+
diff --git a/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.h b/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.h
new file mode 100644 (file)
index 0000000..4bc1ab2
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+  @file src/tsemaphore.h
+
+  Implements a simple inter-thread semaphore so not to have to deal with IPC
+  creation and the like.
+
+  Copyright (C) 2007-2008 STMicroelectronics
+  Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+  This library is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation; either version 2.1 of the License, or (at your option)
+  any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+  details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this library; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St, Fifth Floor, Boston, MA
+  02110-1301  USA
+
+  $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $
+  Revision $Rev: 554 $
+  Author $Author: pankaj_sen $
+
+*/
+
+#ifndef __TSEMAPHORE_H__
+#define __TSEMAPHORE_H__
+
+/** The structure contains the semaphore value, mutex and green light flag
+ */ 
+typedef struct tsem_t{
+  pthread_cond_t condition;
+  pthread_mutex_t mutex;
+  unsigned int semval;
+}tsem_t;
+
+/** Initializes the semaphore at a given value
+ * 
+ * @param tsem the semaphore to initialize
+ * 
+ * @param val the initial value of the semaphore
+ */
+void tsem_init(tsem_t* tsem, unsigned int val);
+
+/** Destroy the semaphore
+ *  
+ * @param tsem the semaphore to destroy
+ */
+void tsem_deinit(tsem_t* tsem);
+
+/** Decreases the value of the semaphore. Blocks if the semaphore
+ * value is zero.
+ * 
+ * @param tsem the semaphore to decrease
+ */
+void tsem_down(tsem_t* tsem);
+
+/** Increases the value of the semaphore
+ * 
+ * @param tsem the semaphore to increase
+ */
+void tsem_up(tsem_t* tsem);
+
+/** Reset the value of the semaphore
+ * 
+ * @param tsem the semaphore to reset
+ */
+void tsem_reset(tsem_t* tsem);
+
+/** Wait on the condition.
+ * 
+ * @param tsem the semaphore to wait
+ */
+void tsem_wait(tsem_t* tsem);
+
+/** Signal the condition,if waiting
+ * 
+ * @param tsem the semaphore to signal
+ */
+void tsem_signal(tsem_t* tsem);
+
+#endif
diff --git a/host_applications/linux/apps/hello_pi/hello_video/user_debug_levels.h b/host_applications/linux/apps/hello_pi/hello_video/user_debug_levels.h
new file mode 100644 (file)
index 0000000..b28b07f
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+       @file test/components/common/user_debug_levels.h
+       
+       Define the level of debug prints on standard err. The different levels can 
+       be composed with binary OR.
+       The debug levels defined here belong to the test applications
+       
+       Copyright (C) 2007-2008 STMicroelectronics
+       Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+
+       This library is free software; you can redistribute it and/or modify it under
+       the terms of the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at your option)
+       any later version.
+
+       This library is distributed in the hope that it will be useful, but WITHOUT
+       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+       FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+       details.
+
+       You should have received a copy of the GNU Lesser General Public License
+       along with this library; if not, write to the Free Software Foundation, Inc.,
+       51 Franklin St, Fifth Floor, Boston, MA
+       02110-1301  USA
+       
+       $Date: 2008-07-16 09:39:31 +0200 (Wed, 16 Jul 2008) $
+       Revision $Rev: 577 $
+       Author $Author: gsent $
+
+*/
+
+
+/** Remove all debug output lines
+ */
+#define DEB_LEV_NO_OUTPUT  0
+/** Messages explaing the reason of critical errors 
+ */
+#define DEB_LEV_ERR        1 
+/** Messages showing values related to the test and the component/s used
+ */
+#define DEB_LEV_PARAMS     2
+/** Messages representing steps in the execution. These are the simple messages, because 
+ * they avoid iterations 
+ */
+#define DEB_LEV_SIMPLE_SEQ 4
+/** Messages representing steps in the execution. All the steps are described, 
+ * also with iterations. With this level of output the performance is 
+ * seriously compromised
+ */
+#define DEB_LEV_FULL_SEQ   8
+/** Messages that indicate the beginning and the end of a function.
+ * It can be used to trace the execution
+ */
+#define DEB_LEV_FUNCTION_NAME 16
+
+/** Messages that are the default test application output. These message should be 
+       * shown every time
+       */
+#define DEFAULT_MESSAGES 32
+
+/** All the messages - max value
+ */
+#define DEB_ALL_MESS   255
+
+
+/** \def DEBUG_LEVEL is the current level do debug output on standard err */
+#define DEBUG_LEVEL (DEB_LEV_ERR | DEFAULT_MESSAGES)
+#if DEBUG_LEVEL > 0
+#define DEBUG(n, args...) do { if (DEBUG_LEVEL & (n)){fprintf(stderr, args);} } while (0)
+#else
+#define DEBUG(n, args...)
+#endif
+
index 2edf44cf6d8c9e3e64110bb2eabb9ff598073865..3275d572f8438a86aef793d1adc6277415527f8f 100755 (executable)
@@ -27,36 +27,476 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Video deocode demo using OpenMAX IL though the ilcient helper library
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "video.h"
+/*
+#define VERSIONMAJOR    1
+#define VERSIONMINOR    1
+#define VERSIONREVISION 0
+#define VERSIONSTEP     0
+
+#define OMX_VERSION ((VERSIONSTEP<<24) | (VERSIONREVISION<<16) | (VERSIONMINOR<<8) | VERSIONMAJOR)
+
+#define OMX_INIT_STRUCTURE(a) \
+memset(&(a), 0, sizeof(a)); \
+(a).nSize = sizeof(a); \
+(a).nVersion.nVersion = OMX_VERSION; \
+(a).nVersion.s.nVersionMajor = VERSIONMAJOR; \
+(a).nVersion.s.nVersionMinor = VERSIONMINOR; \
+(a).nVersion.s.nRevision = VERSIONREVISION; \
+(a).nVersion.s.nStep = VERSIONSTEP
+
+static void setHeader(OMX_PTR header, OMX_U32 size) {
+  OMX_VERSIONTYPE* ver = (OMX_VERSIONTYPE*)(header + sizeof(OMX_U32));
+  *((OMX_U32*)header) = size;
+
+  ver->s.nVersionMajor = VERSIONMAJOR;
+  ver->s.nVersionMinor = VERSIONMINOR;
+  ver->s.nRevision = VERSIONREVISION;
+  ver->s.nStep = VERSIONSTEP;
+}
+*/
+
+/*
+void allocateBuffer(int index, int actualBuffer, int width, int height)
+{
+  int i, err;
+  tbm_bo_handle handle_bo;
+  int y_size, uv_size;
+
+  y_size = ALIGN(width, 16) * ALIGN(height, 16);
+  uv_size = y_size /2;
+
+  for (i = 0; i < actualBuffer; i++) {
+
+    unsigned char *tmp;
+
+    //tmp = (MMVideoBuffer*) malloc(sizeof(MMVideoBuffer));
+    //tmp->handle.bo[0] = tbm_bo_alloc(hBufmgr, y_size, TBM_BO_WC);
+    handle_bo = tbm_bo_get_handle(tmp->handle.bo[0], TBM_DEVICE_CPU);
+    tmp = handle_bo.ptr;
+       //handle_bo = tbm_bo_get_handle(tmp->handle.bo[0], TBM_DEVICE_MM);
+       //tmp->handle.dmabuf_fd[0] = handle_bo.u32;
+       //tmp->size[0] = y_size;
+
+
+       if (index == 1) {
+         tmp->handle.bo[1] = tbm_bo_alloc(hBufmgr, uv_size, TBM_BO_WC);
+         handle_bo = tbm_bo_get_handle(tmp->handle.bo[1], TBM_DEVICE_CPU);
+         tmp->data[1] = handle_bo.ptr;
+         handle_bo = tbm_bo_get_handle(tmp->handle.bo[1], TBM_DEVICE_MM);
+         tmp->handle.dmabuf_fd[1] = handle_bo.u32;
+         tmp->size[1] = uv_size;
+       }
+
+       if (index == 0) {
+      err = OMX_UseBuffer(appPriv->videodechandle, &pInBuffer[i], 0, NULL, y_size, tmp);
+      printf( "index : %d -> OMX_UseBuffer :%x\n", index, err);
+      queue(pInBufQueue, pInBuffer[i]);
+      //queue(pInBufQueue, tmp);
+       } else if (index == 1) {
+      err = OMX_UseBuffer(appPriv->videodechandle, &pOutBuffer[i], 1, NULL, y_size + uv_size, tmp);
+      printf( "index : %d -> OMX_UseBuffer :%i\n", index, err);
+      queue(pOutBufQueue, pOutBuffer[i]);
+       }
+
+  }
+
+}
+*/
+
+#define COMPONENT_NAME_BASE "OMX.broadcom.video_decode"
+#define BASE_ROLE "video_decoder.avc"
+
+OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
+COMPONENT_T *video_decode = NULL;
+COMPONENT_T *list[5];
+TUNNEL_T tunnel[4];
+ILCLIENT_T *client;
+FILE *in;
+int status = 0;
+unsigned int data_len = 0;
+int err;
+int actualInBufferCount;
+int actualOutBufferCount;
+int nInBufferSize, nOutBufferSize;
+int nInBufferAlignment, nOutBufferAlignment;
+OMX_BUFFERHEADERTYPE *pInBuffer[20], *pOutBuffer[16];
+OMX_STRING full_component_name;
+appPrivateType* appPriv;
+tbm_bufmgr hBufmgr;
+int drm_fd;
+queue_t* pInBufQueue;
+queue_t* pOutBufQueue;
+
+OMX_CALLBACKTYPE videodeccallbacks = {
+    .EventHandler = videodecEventHandler,
+    .EmptyBufferDone = videodecEmptyBufferDone,
+    .FillBufferDone = videodecFillBufferDone
+  };
+/*
+static void setHeader(OMX_PTR header, OMX_U32 size) {
+  OMX_VERSIONTYPE* ver = (OMX_VERSIONTYPE*)(header + sizeof(OMX_U32));
+  *((OMX_U32*)header) = size;
+
+  ver->s.nVersionMajor = VERSIONMAJOR;
+  ver->s.nVersionMinor = VERSIONMINOR;
+  ver->s.nRevision = VERSIONREVISION;
+  ver->s.nStep = VERSIONSTEP;
+}
+*/
+OMX_ERRORTYPE test_OMX_ComponentNameEnum() {
+  char * name;
+  int index;
+
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  printf("GENERAL TEST %s\n", __func__);
+
+  name = malloc(OMX_MAX_STRINGNAME_SIZE);
+  index = 0;
+  while(1) {
+    err = OMX_ComponentNameEnum (name, OMX_MAX_STRINGNAME_SIZE, index);
+    if ((name != NULL) && (err == OMX_ErrorNone)) {
+      printf("component %i is %s\n", index, name);
+    } else break;
+    if (err != OMX_ErrorNone) break;
+    index++;
+  }
+  free(name);
+  name = NULL;
+  printf("GENERAL TEST %s result %i\n", __func__, err);
+  return err;
+}
+
+OMX_ERRORTYPE test_OMX_RoleEnum(OMX_STRING component_name) {
+  OMX_U32 no_of_roles;
+  OMX_U8 **string_of_roles;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  int index;
+
+  printf("GENERAL TEST %s\n", __func__);
+  printf("Getting roles of %s. Passing Null first...\n", component_name);
+  err = OMX_GetRolesOfComponent(component_name, &no_of_roles, NULL);
+  if (err != OMX_ErrorNone) {
+    printf("Not able to retrieve the number of roles of the given component\n");
+    printf("GENERAL TEST %s result %i\n", __func__, err);
+    return err;
+  }
+  printf("The number of roles for the component %s is: %i\n", component_name, (int)no_of_roles);
+
+  if(no_of_roles == 0) {
+    printf("The Number or roles is 0.\nThe component selected is not correct for the purpose of this test.\nExiting...\n");
+    err = OMX_ErrorInvalidComponentName;
+  } else {
+    string_of_roles = malloc(no_of_roles * sizeof(OMX_STRING));
+    for (index = 0; index < no_of_roles; index++) {
+      *(string_of_roles + index) = malloc(no_of_roles * OMX_MAX_STRINGNAME_SIZE);
+    }
+    printf("...then buffers\n");
+
+    err = OMX_GetRolesOfComponent(component_name, &no_of_roles, string_of_roles);
+    if (err != OMX_ErrorNone) {
+      printf("Not able to retrieve the roles of the given component\n");
+    } else if(string_of_roles != NULL) {
+      for (index = 0; index < no_of_roles; index++) {
+        printf("The role %i for the component:  %s \n", (index + 1), *(string_of_roles+index));
+      }
+    } else {
+      printf("role string is NULL!!! Exiting...\n");
+      err = OMX_ErrorInvalidComponentName;
+    }
+  }
+  printf("GENERAL TEST %s result %i\n", __func__, err);
+  return err;
+}
+
+OMX_ERRORTYPE test_OMX_ComponentEnumByRole(OMX_STRING role_name) {
+  OMX_U32 no_of_comp_per_role;
+  OMX_U8 **string_of_comp_per_role;
+  OMX_ERRORTYPE err;
+  int index;
+
+  printf("GENERAL TEST %s\n", __func__);
+  string_of_comp_per_role = malloc (10 * sizeof(OMX_STRING));
+  for (index = 0; index < 10; index++) {
+    string_of_comp_per_role[index] = malloc(OMX_MAX_STRINGNAME_SIZE);
+  }
+
+  printf("Getting number of components per role for %s\n", role_name);
+
+  err = OMX_GetComponentsOfRole(role_name, &no_of_comp_per_role, NULL);
+  if (err != OMX_ErrorNone) {
+    printf("Not able to retrieve the number of components of a given role\n");
+    printf( "GENERAL TEST %s result %i\n", __func__, err);
+    return err;
+  }
+  printf("Number of components per role for %s is %i\n", role_name, (int)no_of_comp_per_role);
+
+  err = OMX_GetComponentsOfRole(role_name, &no_of_comp_per_role, string_of_comp_per_role);
+  if (err != OMX_ErrorNone) {
+    printf("Not able to retrieve the components of a given role\n");
+    printf( "GENERAL TEST %s result %i\n",__func__, err);
+    return err;
+  }
+
+  printf(" The components are:\n");
+  for (index = 0; index < no_of_comp_per_role; index++) {
+    printf("%s\n", string_of_comp_per_role[index]);
+  }
+  for (index = 0; index<10; index++) {
+    if(string_of_comp_per_role[index]) {
+      free(string_of_comp_per_role[index]);
+      string_of_comp_per_role[index] = NULL;
+    }
+  }
+
+  if(string_of_comp_per_role)  {
+    free(string_of_comp_per_role);
+    string_of_comp_per_role = NULL;
+  }
+  printf("GENERAL TEST %s result OMX_ErrorNone\n", __func__);
+  return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE test_OpenClose(OMX_STRING component_name) {
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  printf("GENERAL TEST %s\n",__func__);
+  err = OMX_GetHandle(&appPriv->videodechandle, component_name, NULL /*appPriv */, &videodeccallbacks);
+  if(err != OMX_ErrorNone) {
+    printf("No component found\n");
+  } else {
+    err = OMX_FreeHandle(appPriv->videodechandle);
+  }
+  printf("GENERAL TEST %s result %i\n", __func__, err);
+  return err;
+}
+
+void allocateBuffer(int index, int actualBuffer, int width, int height, int aligned_size)
+{
+  int i, err;
+  tbm_bo_handle handle_bo;
+  int y_size, uv_size;
+  int size;
+
+  y_size = ALIGN(width + 128, 16) * ALIGN(height + 128, 16);
+  uv_size = y_size /2;
+  size = y_size + uv_size;
+
+  for (i = 0; i < actualBuffer; i++) {
+
+    void *tmp;
+       unsigned char *buf;
+
+
+
+       if (index == 130) {
+               buf = (unsigned char*) malloc (sizeof(unsigned char) * aligned_size);
+        err = OMX_UseBuffer(appPriv->videodechandle, &pInBuffer[i], 130, NULL, ALIGN(aligned_size, 16), buf);
+           printf("index : %d -> OMX_UseBuffer : %p, %x\n", index, pInBuffer[i], err);
+               //queue(pInBufQueue, pInBuffer[i]);
+       } else if (index == 131) {
+        tmp = tbm_bo_alloc(hBufmgr, ALIGN(aligned_size, 16), TBM_BO_WC);
+        handle_bo = tbm_bo_get_handle(tmp, TBM_DEVICE_CPU);
+           buf = handle_bo.ptr;
+
+        err = OMX_UseBuffer(appPriv->videodechandle, &pOutBuffer[i], 131, NULL, ALIGN(aligned_size, 16), buf);
+           printf("index : %d -> OMX_UseBuffer : %p, %x\n", index, pOutBuffer[i], err);
+               //queue(pOutBufQueue, pOutBuffer[i]);
+       } else
+               printf("invalid port\n");
+/*
+
+       if (index == 1) {
+         tmp->handle.bo[1] = tbm_bo_alloc(hBufmgr, uv_size, TBM_BO_WC);
+         handle_bo = tbm_bo_get_handle(tmp->handle.bo[1], TBM_DEVICE_CPU);
+         tmp->data[1] = handle_bo.ptr;
+         handle_bo = tbm_bo_get_handle(tmp->handle.bo[1], TBM_DEVICE_MM);
+         tmp->handle.dmabuf_fd[1] = handle_bo.u32;
+         tmp->size[1] = uv_size;
+       }
+
+       if (index == 0) {
+      err = OMX_UseBuffer(appPriv->videodechandle, &pInBuffer[i], 0, NULL, y_size, tmp);
+      DEBUG(DEFAULT_MESSAGES, "index : %d -> OMX_UseBuffer :%x\n", index, err);
+      queue(pInBufQueue, pInBuffer[i]);
+      //queue(pInBufQueue, tmp);
+       } else if (index == 1) {
+      err = OMX_UseBuffer(appPriv->videodechandle, &pOutBuffer[i], 1, NULL, y_size + uv_size, tmp);
+      DEBUG(DEFAULT_MESSAGES, "index : %d -> OMX_UseBuffer :%i\n", index, err);
+      queue(pOutBufQueue, pOutBuffer[i]);
+       }
+*/
+  }
+
+}
+/*
+void deallocateBuffer(int index, int actualBuffer)
+{
+  int i, err;
+  MMVideoBuffer *pTmp;
+
+  for (i = 0; i < actualBuffer; i++) {
+    if (index == 0) {
+               //pTmp = (MMVideoBuffer*)dequeue(pInBufQueue);
+               pTmp = pInBuffer[i];
+       } else if (index == 1) {
+               //pTmp = (MMVideoBuffer*)dequeue(pOutBufQueue);
+               pTmp = pOutBuffer[i];
+       }
+
+       tbm_bo_unref(pTmp->handle.bo[0]);
+       if (index == 1)
+               tbm_bo_unref(pTmp->handle.bo[1]);
+
+       err = OMX_FreeBuffer (appPriv->videodechandle, index, pTmp);
+    DEBUG(DEFAULT_MESSAGES, "%d port %d buffer free : %d\n", index, i, err);
+  }
+}
+*/
+const char * omx_state_to_string(OMX_STATETYPE state)
+{
+       switch (state)
+       {
+               case OMX_StateInvalid: return "Invalid"; break;
+               case OMX_StateLoaded: return "Loaded"; break;
+               case OMX_StateIdle: return "Idle"; break;
+               case OMX_StateExecuting: return "Executing"; break;
+               case OMX_StatePause: return "Pause"; break;
+               case OMX_StateWaitForResources:  return "Wait for resources"; break;
+               default: return "Bad state"; break;
+       }
+}
+
+void wait_for(appPrivateType *app, OMX_STATETYPE state)
+{
+       while (app->state != state)
+       {
+               printf("wait for %s \n", omx_state_to_string(state));
+               tsem_down(app->stateSem);
+               if (app->state != state) {
+                       printf("we got an event, but still waiting for %s \n", omx_state_to_string(state));
+               }
+
+       }
+}
+
+unsigned int FromByteStream2NalUnit(FILE *ByteStream, unsigned char *Nal)
+{
+       unsigned int NalLeng=0;
+
+       unsigned char Val, ZeroCount, i;
+       ZeroCount = 0;
+       if(feof(ByteStream))
+               return 0;
+       Val = fgetc(ByteStream);
+       while(!Val)
+       {
+               if(ZeroCount == 3)
+                       break;
+               ZeroCount++;
+               Val = fgetc(ByteStream);
+       }
+
+       if( (ZeroCount != 3) || (Val != 1) )
+       {
+               for(i=0;i<ZeroCount;i++)
+                       Nal[NalLeng++] = 0;
+               Nal[NalLeng++] = Val;
+       }
+
+       ZeroCount = 0;
+       while(1) {
+               Val = fgetc(ByteStream);
+               if(feof(ByteStream))
+                       break;
+               if(!Val)
+                       ZeroCount++;
+               else {
+                       if( (ZeroCount == 3) && (Val == 1) )
+                               break;
+                       else {
+                               for(i=0;i<ZeroCount;i++)
+                                       Nal[NalLeng++] = 0;
+                               Nal[NalLeng++] = Val;
+                               ZeroCount = 0;
+                       }
+               }
+       }
+
+       return NalLeng;
+}
 
-#include "bcm_host.h"
-#include "ilclient.h"
+void hex_dump(char *desc, void *addr, int len)
+{
+       int i;
+       unsigned char buff[17];
+       unsigned char *pc = (unsigned char *)addr;
+
+       if (desc != NULL)
+               printf("%s:\n", desc);
+
+       for (i = 0; i < len; i++) {
+
+               if ((i % 16) == 0) {
+                       if (i != 0)
+                               printf("  %s\n", buff);
+
+                       printf("  %04x ", i);
+               }
+
+               printf(" %02x", pc[i]);
+
+               if ((pc[i] < 0x20) || (pc[i] > 0x7e))
+                       buff[i % 16] = '.';
+               else
+                       buff[i % 16] = pc[i];
+               buff[(i % 16) + 1] = '\0';
+       }
+
+       while ((i % 16) != 0) {
+               printf("   ");
+               i++;
+       }
+       printf("  %s\n", buff);
+}
 
 static int video_decode_test(char *filename)
 {
-   OMX_VIDEO_PARAM_PORTFORMATTYPE format;
-   OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
-   COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL;
-   COMPONENT_T *list[5];
-   TUNNEL_T tunnel[4];
-   ILCLIENT_T *client;
-   FILE *in;
-   int status = 0;
-   unsigned int data_len = 0;
+   int i;
+   int offset;
+   int data_read;
+   int fd;
 
    memset(list, 0, sizeof(list));
-   memset(tunnel, 0, sizeof(tunnel));
 
    if((in = fopen(filename, "rb")) == NULL)
       return -2;
-
+   if ((fd = open(filename, O_RDONLY)) == -1)
+          return -2;
+/*
    if((client = ilclient_init()) == NULL)
    {
       fclose(in);
       return -3;
    }
+*/
+   /* Initialize application private data */
+   appPriv = malloc(sizeof(appPrivateType));
+   appPriv->decoderEventSem = malloc(sizeof(tsem_t));
+   appPriv->stateSem =  malloc(sizeof(tsem_t));
+   appPriv->state = OMX_StateInvalid;
+
+   appPriv->eofSem = malloc(sizeof(tsem_t));
+   tsem_init(appPriv->decoderEventSem, 0);
+   tsem_init(appPriv->stateSem, 0);
+   tsem_init(appPriv->eofSem, 0);
+
+   printf("Init the OMX Core\n");
 
    if(OMX_Init() != OMX_ErrorNone)
    {
@@ -64,47 +504,75 @@ static int video_decode_test(char *filename)
       fclose(in);
       return -4;
    }
+   printf("Omx core is initialized \n");
 
+/*
    // create video_decode
-   if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0)
+   if (ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0)
       status = -14;
    list[0] = video_decode;
+*/
 
-   // create video_render
-   if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0)
-      status = -14;
-   list[1] = video_render;
+   printf("------------------------------------\n");
+   test_OMX_ComponentNameEnum();
+   printf("------------------------------------\n");
+   test_OMX_RoleEnum(COMPONENT_NAME_BASE);
+   printf("------------------------------------\n");
+   test_OMX_ComponentEnumByRole(BASE_ROLE);
+   printf("------------------------------------\n");
+   test_OpenClose(COMPONENT_NAME_BASE);
+   printf("------------------------------------\n");
 
-   // create clock
-   if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0)
-      status = -14;
-   list[2] = clock;
-
-   memset(&cstate, 0, sizeof(cstate));
-   cstate.nSize = sizeof(cstate);
-   cstate.nVersion.nVersion = OMX_VERSION;
-   cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
-   cstate.nWaitMask = 1;
-   if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
-      status = -13;
-
-   // create video_scheduler
-   if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0)
-      status = -14;
-   list[3] = video_scheduler;
+   full_component_name = malloc(sizeof(char*) * OMX_MAX_STRINGNAME_SIZE);
+   strcpy(full_component_name, COMPONENT_NAME_BASE);
+   printf("The component selected for decoding is %s\n", full_component_name);
+
+   err = OMX_GetHandle(&appPriv->videodechandle, full_component_name, NULL, &videodeccallbacks);
+   if(err != OMX_ErrorNone){
+    printf("No video decoder component found. Exiting...\n");
+    exit(1);
+  } else {
+    printf("Found The component for decoding is %s\n", full_component_name);
+  }
+
+   /** sending command to video decoder component to go to idle state */
+   //pInBuffer1 = pInBuffer2 = NULL;
+   err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+
+   //wait_for(appPriv, OMX_StateIdle);
+   printf("state changed to Idle :%i\n", err);
+
+   hBufmgr = tbm_bufmgr_init(drm_fd);
+   if(hBufmgr == NULL){
+        printf("TBM initialization failed\n");
+   }
 
-   set_tunnel(tunnel, video_decode, 131, video_scheduler, 10);
-   set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90);
-   set_tunnel(tunnel+2, clock, 80, video_scheduler, 12);
 
-   // setup clock tunnel first
-   if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0)
-      status = -15;
-   else
-      ilclient_change_component_state(clock, OMX_StateExecuting);
+   OMX_PARAM_PORTDEFINITIONTYPE port_def;
+   memset(&port_def, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+   port_def.nVersion.nVersion = OMX_VERSION;
+   port_def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+   port_def.nPortIndex = 130;
 
-   if(status == 0)
-      ilclient_change_component_state(video_decode, OMX_StateIdle);
+   err = OMX_GetParameter (appPriv->videodechandle, OMX_IndexParamPortDefinition, &port_def);
+   printf( "OMX_GetParameter :%x, input buffer count : %d, nBufferSize : %d, nBufferAlignment : %d\n", err, port_def.nBufferCountActual, port_def.nBufferSize, port_def.nBufferAlignment);
+   actualInBufferCount = port_def.nBufferCountActual;
+   nInBufferSize = port_def.nBufferSize;
+   nInBufferAlignment = port_def.nBufferAlignment;
+
+   port_def.nPortIndex = 131;
+   err = OMX_GetParameter (appPriv->videodechandle, OMX_IndexParamPortDefinition, &port_def);
+   printf( "OMX_GetParameter :%x, output buffer count : %d, nBufferSize : %d, nBufferAlignment : %d\n", err, port_def.nBufferCountActual,  port_def.nBufferSize, port_def.nBufferAlignment);
+   actualOutBufferCount = port_def.nBufferCountActual;
+   nOutBufferSize = port_def.nBufferSize;
+   nOutBufferAlignment = port_def.nBufferAlignment;
+
+
+   err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandPortDisable, 130, NULL);
+   printf( "Input port OMX_CommandPortDisable : %x\n", err);
+
+   err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandPortDisable, 131, NULL);
+   printf( "Output port OMX_CommandPortDisable : %x\n", err);
 
    memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
    format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
@@ -112,16 +580,150 @@ static int video_decode_test(char *filename)
    format.nPortIndex = 130;
    format.eCompressionFormat = OMX_VIDEO_CodingAVC;
 
+   err = OMX_SetParameter(appPriv->videodechandle, OMX_IndexParamVideoPortFormat, &format);
+   printf("Input OMX_IndexParamVideoPortFormat: %x\n", err);
+
+   memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
+   format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
+   format.nVersion.nVersion = OMX_VERSION;
+   format.nPortIndex = 131;
+   err = OMX_SetParameter(appPriv->videodechandle, OMX_IndexParamVideoPortFormat, &format);
+   printf("Output OMX_IndexParamVideoPortFormat: %x\n", err);
+
+
+   pInBufQueue = calloc(1,sizeof(queue_t));
+   pOutBufQueue = calloc(1,sizeof(queue_t));
+
+   queue_init(pInBufQueue);
+   queue_init(pOutBufQueue);
+
+   //err = ilclient_change_component_state(video_decode, OMX_StateExecuting);
+   //printf("ilclient_change_component_state -> OMX_StateExecuting : err : %d\n", err);
+
+   err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandPortEnable, 130, NULL);
+   printf( "Input port OMX_CommandPortEnable : %x\n", err);
+   err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandPortEnable, 131, NULL);
+   printf( "Output port OMX_CommandPortEnable : %x\n", err);
+
+   allocateBuffer(130, actualInBufferCount, 1280, 720, nInBufferSize);
+   allocateBuffer(131, actualOutBufferCount, 1280, 720, nOutBufferSize);
+
+  wait_for(appPriv, OMX_StateIdle);
+
+  /** sending command to video decoder component to go to executing state */
+  err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandStateSet, OMX_StateExecuting, NULL);
+  printf("send Excuting :%d\n", err);
+
+  wait_for(appPriv, OMX_StateExecuting);
+  printf("Excuting state\n");
+
+  for (i = 0; i < actualOutBufferCount; i++) {
+    err = OMX_FillThisBuffer(appPriv->videodechandle, pOutBuffer[i]);
+    printf( "FillThisBuffer : %p, %x\n",pOutBuffer[i], err);
+  }
+
+  for (i = 0; i < actualInBufferCount; i++) {
+    //pthread_mutex_lock(&mutex);
+       unsigned char *pTmp;
+       offset = 0;
+
+       pTmp = pInBuffer[i]->pBuffer;
+       pTmp[offset++] = 0;
+       pTmp[offset++] = 0;
+       pTmp[offset++] = 0;
+       pTmp[offset++] = 1;
+
+       data_read = FromByteStream2NalUnit(in, pTmp + offset);
+
+    pInBuffer[i]->nFilledLen = data_read + offset;
+    pInBuffer[i]->nOffset = 0;
+    hex_dump("src0", pInBuffer[i]->pBuffer, 16);
+
+       //pthread_mutex_unlock(&mutex);
+
+    err = OMX_EmptyThisBuffer(appPriv->videodechandle, pInBuffer[i]);
+    printf("EmptyThisBuffer %x, %d\n", pInBuffer[i]->pBuffer, data_read + offset);
+       usleep(100000);
+  }
+
+  tsem_down(appPriv->decoderEventSem);
+  printf("port setting changed\n");
+
+  err = OMX_SendCommand(appPriv->videodechandle, OMX_CommandPortDisable, 131, NULL);
+  printf("Sending Port Disable Command : %d\n", err);
+#if 0
    if(status == 0 &&
       OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone &&
-      ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0)
+      ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0 &&
+         ilclient_enable_port_buffers(video_decode, 131, NULL, NULL, NULL) == 0)
    {
-      OMX_BUFFERHEADERTYPE *buf;
+      OMX_BUFFERHEADERTYPE *buf, *outbuf;
       int port_settings_changed = 0;
       int first_packet = 1;
 
-      ilclient_change_component_state(video_decode, OMX_StateExecuting);
+
+     while ((outbuf = ilclient_get_output_buffer(video_decode, 131, 1)) != NULL)
+        {
+                unsigned char *tmp = outbuf->pBuffer;
+
+               err = OMX_FillThisBuffer(ILC_GET_HANDLE(video_decode), outbuf);
+               if (err != OMX_ErrorNone)
+               {
+                   printf("Failed to call OMX_FillThisBuffer\n");
+                       status = -6;
+                       break;
+               }
+               printf("call OMX_FillThisBuffer : %d\n", err);
+        }
 
+      while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL)
+      {
+         // feed data and wait until we get port settings changed
+         unsigned char *dest = buf->pBuffer;
+
+         data_len += fread(dest, 1, buf->nAllocLen-data_len, in);
+         printf( "data_len :%i\n", data_len);
+
+         if(port_settings_changed == 0 &&
+            ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) ||
+             (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1,
+                                                       ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0)))
+         {
+            port_settings_changed = 1;
+
+            //err = ilclient_change_component_state(video_decode, OMX_StateExecuting);
+                       //printf("ilclient_change_component_state -> OMX_StateExecuting : err : %d\n", err);
+                       printf("port setting changed \n");
+            port_def.nPortIndex = 131;
+            err = OMX_GetParameter (ILC_GET_HANDLE(video_decode), OMX_IndexParamPortDefinition, &port_def);
+            printf( "OMX_GetParameter :%i\n", err);
+            actualOutBufferCount = port_def.nBufferCountActual;
+            printf("outbuf count :%d\n", actualOutBufferCount);
+                }
+
+                       if(!data_len)
+                               break;
+
+                       buf->nFilledLen = data_len;
+                       data_len = 0;
+
+                       buf->nOffset = 0;
+                       if(first_packet)
+                       {
+                               buf->nFlags = OMX_BUFFERFLAG_STARTTIME;
+                               first_packet = 0;
+                       }
+                       else
+                               buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
+
+                       if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
+                       {
+                           printf("Failed to call OMX_EmptyThisBuffer\n");
+                               status = -6;
+                               break;
+                       }
+         }
+/*
       while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL)
       {
          // feed data and wait until we get port settings changed
@@ -187,25 +789,25 @@ static int video_decode_test(char *filename)
 
       // need to flush the renderer to allow video_decode to disable its input port
       ilclient_flush_tunnels(tunnel, 0);
-
+*/
    }
-
+#endif
    fclose(in);
 
-   ilclient_disable_tunnel(tunnel);
-   ilclient_disable_tunnel(tunnel+1);
-   ilclient_disable_tunnel(tunnel+2);
-   ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL);
-   ilclient_teardown_tunnels(tunnel);
+   //ilclient_disable_tunnel(tunnel);
+   //ilclient_disable_tunnel(tunnel+1);
+   //ilclient_disable_tunnel(tunnel+2);
+   //ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL);
+   //ilclient_teardown_tunnels(tunnel);
 
-   ilclient_state_transition(list, OMX_StateIdle);
-   ilclient_state_transition(list, OMX_StateLoaded);
+   //ilclient_state_transition(list, OMX_StateIdle);
+   //ilclient_state_transition(list, OMX_StateLoaded);
 
-   ilclient_cleanup_components(list);
+   //ilclient_cleanup_components(list);
 
    OMX_Deinit();
 
-   ilclient_destroy(client);
+   //ilclient_destroy(client);
    return status;
 }
 
@@ -220,3 +822,234 @@ int main (int argc, char **argv)
 }
 
 
+OMX_ERRORTYPE videodecEventHandler(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_EVENTTYPE eEvent,
+  OMX_OUT OMX_U32 Data1,
+  OMX_OUT OMX_U32 Data2,
+  OMX_OUT OMX_PTR pEventData) {
+
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  printf("Hi there, I am in the %s callback\n", __func__);
+  if(eEvent == OMX_EventCmdComplete) {
+    if (Data1 == OMX_CommandStateSet) {
+      appPriv->state = (int)Data2;
+      printf( "State changed in ");
+      switch ((int)Data2) {
+        case OMX_StateInvalid:
+          printf( "OMX_StateInvalid\n");
+          break;
+        case OMX_StateLoaded:
+          printf( "OMX_StateLoaded\n");
+          break;
+        case OMX_StateIdle:
+          printf( "OMX_StateIdle\n");
+          break;
+        case OMX_StateExecuting:
+          printf( "OMX_StateExecuting\n");
+          break;
+        case OMX_StatePause:
+          printf( "OMX_StatePause\n");
+          break;
+        case OMX_StateWaitForResources:
+          printf( "OMX_StateWaitForResources\n");
+          break;
+               default:
+          printf( "default\n");
+                 break;
+
+      }
+      //tsem_up(appPriv->decoderEventSem);
+         tsem_up(appPriv->stateSem);
+      printf( "tsem up decoderEventSem\n");
+    } else if (OMX_CommandPortEnable || OMX_CommandPortDisable) {
+      printf( "In %s Received Port Enable/Disable Event\n",__func__);
+      tsem_up(appPriv->decoderEventSem);
+      printf( "tsem up decoderEventSem\n");
+    }
+  } else if(eEvent == OMX_EventPortSettingsChanged) {
+    printf( "\n port settings change event handler in %s %i\n", __func__, Data2);
+    if(Data2 == 0) {
+
+/*
+      if(!flagSetupTunnel) {
+        err = setPortParameters();
+        printf("set port param %i\n",err);
+        printf("tsem_up\n");
+        tsem_up(appPriv->decoderEventSem);
+        if(flagIsColorConvRequested == 1) {
+          pOutBufferColorConv1 = pOutBufferColorConv2 = NULL;
+          err = OMX_SendCommand(appPriv->colorconv_handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+#if 1
+          err = OMX_UseBuffer(appPriv->colorconv_handle, &pInBufferColorConv1, 0, NULL, buffer_out_size, pOutBuffer1->pBuffer);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to use the video dec comp allocate buffer\n");
+            exit(1);
+          }
+          err = OMX_UseBuffer(appPriv->colorconv_handle, &pInBufferColorConv2, 0, NULL, buffer_out_size, pOutBuffer2->pBuffer);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to use the video dec comp allocate buffer\n");
+            exit(1);
+          }
+#else
+          err = OMX_UseBuffer(appPriv->colorconv_handle, &pInBufferColorConv1, 0, NULL, buffer_out_size, pOutBuffer1->data[0]);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to use the video dec comp allocate buffer\n");
+            exit(1);
+          }
+          err = OMX_UseBuffer(appPriv->colorconv_handle, &pInBufferColorConv2, 0, NULL, buffer_out_size, pOutBuffer2->data[0]);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to use the video dec comp allocate buffer\n");
+            exit(1);
+          }
+#endif
+          omx_colorconvPortDefinition.nPortIndex = 1;
+          setHeader(&omx_colorconvPortDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+          err = OMX_GetParameter(appPriv->colorconv_handle, OMX_IndexParamPortDefinition, &omx_colorconvPortDefinition);
+          outbuf_colorconv_size = omx_colorconvPortDefinition.nBufferSize;
+          printf( " outbuf_colorconv_size : %d \n", (int)outbuf_colorconv_size);
+
+          err = OMX_AllocateBuffer(appPriv->colorconv_handle, &pOutBufferColorConv1, 1, NULL, outbuf_colorconv_size);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to allocate buffer in color conv\n");
+            exit(1);
+          }
+          err = OMX_AllocateBuffer(appPriv->colorconv_handle, &pOutBufferColorConv2, 1, NULL, outbuf_colorconv_size);
+          if(err != OMX_ErrorNone) {
+            printf(DEB_LEV_ERR, "Unable to allocate buffer in colro conv\n");
+            exit(1);
+          }
+
+          printf( "Before locking on idle wait semaphore\n");
+          tsem_down(appPriv->colorconvEventSem);
+          printf( "color conv Sem free\n");
+
+        }
+      }
+         */
+    }
+  } else if(eEvent == OMX_EventBufferFlag) {
+    printf( "In %s OMX_BUFFERFLAG_EOS\n", __func__);
+    if((int)Data2 == OMX_BUFFERFLAG_EOS) {
+      tsem_up(appPriv->eofSem);
+    }
+  } else {
+    printf( "Param1 is %x\n", (int)Data1);
+    printf( "Param2 is %x\n", (int)Data2);
+  }
+
+  return err;
+}
+
+OMX_ERRORTYPE videodecEmptyBufferDone(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) {
+
+  OMX_ERRORTYPE err;
+/*
+  int data_read;
+  static int iBufferDropped=0;
+  unsigned char *pTmp;
+  int offset = 0;
+
+  printf( "Hi there, I am in the %s callback.\n", __func__);
+
+  pthread_mutex_lock(&mutex);
+
+  pTmp = pBuffer->pBuffer;
+  pTmp[offset++] = 0;
+  pTmp[offset++] = 0;
+  pTmp[offset++] = 0;
+  pTmp[offset++] = 1;
+
+  data_read = FromByteStream2NalUnit(fd, pTmp+offset);
+  usleep(3000);
+  pBuffer->nFilledLen = data_read+offset;
+  pBuffer->nOffset = 0;
+  pthread_mutex_unlock(&mutex);
+
+  if (data_read <= 0) {
+         printf( "In the %s no more input data available\n", __func__);
+         iBufferDropped++;
+         if(iBufferDropped>=2) {
+                 bEOS=OMX_TRUE;
+                 return OMX_ErrorNone;
+         }
+         pBuffer->nFilledLen=0;
+         pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
+         memset(pBuffer->pBuffer, 0x0, 640*480);
+         err = OMX_EmptyThisBuffer(hComponent, pBuffer);
+         printf( "EmptyThisBuffer for EOS %d\n", err);
+         hex_dump("src2", pBuffer->pBuffer, 16);
+         return OMX_ErrorNone;
+  }
+
+  if(!bEOS) {
+    printf( "EmptyThisBuffer %x, %d\n", (int)pBuffer, offset);
+    err = OMX_EmptyThisBuffer(hComponent, pBuffer);
+    hex_dump("src1", pBuffer->pBuffer, 16);
+  } else {
+    printf( "In %s Dropping Empty This buffer to Audio Dec\n", __func__);
+  }
+*/
+  return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE videodecFillBufferDone(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) {
+
+  OMX_ERRORTYPE err;
+/*
+  OMX_STATETYPE eState;
+
+  printf( "Hi there, I am in the %s callback.\n", __func__);
+  if(pBuffer != NULL) {
+    if(!bEOS) {
+      if(flagIsColorConvRequested && (!flagSetupTunnel)) {
+        OMX_GetState(appPriv->colorconv_handle,&eState);
+        if(eState == OMX_StateExecuting || eState == OMX_StatePause) {
+          if(pInBufferColorConv1->pBuffer == pBuffer->pBuffer) {
+            pInBufferColorConv1->nFilledLen = pBuffer->nFilledLen;
+            err = OMX_EmptyThisBuffer(appPriv->colorconv_handle, pInBufferColorConv1);
+          } else {
+            pInBufferColorConv2->nFilledLen = pBuffer->nFilledLen;
+            err = OMX_EmptyThisBuffer(appPriv->colorconv_handle, pInBufferColorConv2);
+          }
+          if(err != OMX_ErrorNone) {
+            printf( "In %s Error %08x Calling FillThisBuffer\n", __func__,err);
+          }
+        } else {
+          err = OMX_FillThisBuffer(hComponent, pBuffer);
+        }
+      } else if((pBuffer->nFilledLen > 0) && (!flagSetupTunnel)) {
+          printf( "nFilledLen :%d \n", pBuffer->nFilledLen);
+          //fwrite(pBuffer->pBuffer, 1,  pBuffer->nFilledLen, outfile);
+                 decoder_output_dump(pBuffer->pBuffer);
+          pBuffer->nFilledLen = 0;
+      } else {
+          printf( "In %s Empty buffer in Else\n", __func__);
+          printf( "nFilledLen :%d \n", pBuffer->nFilledLen);
+      }
+      if(pBuffer->nFlags == OMX_BUFFERFLAG_EOS) {
+        printf( "In %s: eos=%x Calling Empty This Buffer\n", __func__, (int)pBuffer->nFlags);
+        bEOS = OMX_TRUE;
+      }
+      if(!bEOS && !flagIsColorConvRequested && (!flagSetupTunnel)) {
+        err = OMX_FillThisBuffer(hComponent, pBuffer);
+        printf( "FillThisBuffer :%d \n", err);
+      }
+    } else {
+      printf( "In %s: eos=%x Dropping Empty This Buffer\n", __func__,(int)pBuffer->nFlags);
+    }
+  } else {
+    printf( "Ouch! In %s: had NULL buffer to output...\n", __func__);
+  }
+*/
+  return OMX_ErrorNone;
+}
diff --git a/host_applications/linux/apps/hello_pi/hello_video/video.h b/host_applications/linux/apps/hello_pi/hello_video/video.h
new file mode 100644 (file)
index 0000000..056db03
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "queue.h"
+#include "bcm_host.h"
+#include "ilclient.h"
+#include <tbm_type.h>
+#include <tbm_surface.h>
+#include <tbm_bufmgr.h>
+#include "tsemaphore.h"
+
+#define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
+
+typedef struct appPrivateType{
+  tsem_t* stateSem;
+  tsem_t* decoderEventSem;
+  tsem_t* eofSem;
+  OMX_HANDLETYPE videodechandle;
+  OMX_STATETYPE state;
+} appPrivateType;
+
+/* Callback prototypes for video decoder */
+OMX_ERRORTYPE videodecEventHandler(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_EVENTTYPE eEvent,
+  OMX_OUT OMX_U32 Data1,
+  OMX_OUT OMX_U32 Data2,
+  OMX_OUT OMX_PTR pEventData);
+
+OMX_ERRORTYPE videodecEmptyBufferDone(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+
+OMX_ERRORTYPE videodecFillBufferDone(
+  OMX_OUT OMX_HANDLETYPE hComponent,
+  OMX_OUT OMX_PTR pAppData,
+  OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
index 0761fc681fc7c03c9037191a5584a24201e859ad..0c9669bb2f39266d612e4be4fd5fdb215875ccea 100644 (file)
@@ -10,6 +10,7 @@ License:       BSD
 BuildRequires: glibc-devel
 BuildRequires: cmake
 BuildRequires: gcc-c++
+BuildRequires: pkgconfig(libtbm)
 Requires:      lib%{name} = %{?epoch:%epoch:}%{version}-%{release}
 
 %description
@@ -111,6 +112,7 @@ popd
 %license LICENCE COPYING
 /opt/vc/lib/lib*.so
 /opt/vc/lib/plugins/*.so
+/opt/vc/bin/*
 
 %files -n libraspberrypi-devel
 #%defattr(-,root,root)