From: Hackseung Lee Date: Thu, 9 Nov 2017 03:52:35 +0000 (+0900) Subject: tizen/hello_video test non-tunneled EmptyBufferDone call-back X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fsandbox%2Fhackseung%2Fuserland_20171030git;p=platform%2Fadaptation%2Fbroadcom%2Flibomxil-vc4.git tizen/hello_video test non-tunneled EmptyBufferDone call-back Change-Id: I11a2a5e87bf0e7679df8f739fe9db552fbc40bc3 Signed-off-by: Hackseung Lee --- diff --git a/host_applications/linux/CMakeLists.txt b/host_applications/linux/CMakeLists.txt index e8615cc..80a1908 100644 --- a/host_applications/linux/CMakeLists.txt +++ b/host_applications/linux/CMakeLists.txt @@ -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() - diff --git a/host_applications/linux/apps/hello_pi/CMakeLists.txt b/host_applications/linux/apps/hello_pi/CMakeLists.txt index f2c6aef..21b29f3 100644 --- a/host_applications/linux/apps/hello_pi/CMakeLists.txt +++ b/host_applications/linux/apps/hello_pi/CMakeLists.txt @@ -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) diff --git a/host_applications/linux/apps/hello_pi/hello_video/CMakeLists.txt b/host_applications/linux/apps/hello_pi/hello_video/CMakeLists.txt index 42187af..fdc1182 100644 --- a/host_applications/linux/apps/hello_pi/hello_video/CMakeLists.txt +++ b/host_applications/linux/apps/hello_pi/hello_video/CMakeLists.txt @@ -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) diff --git a/host_applications/linux/apps/hello_pi/hello_video/Makefile b/host_applications/linux/apps/hello_pi/hello_video/Makefile index be21fd5..c86256a 100755 --- a/host_applications/linux/apps/hello_pi/hello_video/Makefile +++ b/host_applications/linux/apps/hello_pi/hello_video/Makefile @@ -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 index 0000000..3ba1d1a --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/omx_comp_debug_levels.h @@ -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 + +/** 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 index 0000000..e6ee4b7 --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/queue.c @@ -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 +#include +#include + +#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; iq_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; iq_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 index 0000000..745ca70 --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/queue.h @@ -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 +/** 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 index 0000000..eb7bd70 --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/tags @@ -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 index 0000000..6f2b6ad --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.c @@ -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 +#include +#include +#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 index 0000000..4bc1ab2 --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/tsemaphore.h @@ -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 index 0000000..b28b07f --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/user_debug_levels.h @@ -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 + diff --git a/host_applications/linux/apps/hello_pi/hello_video/video.c b/host_applications/linux/apps/hello_pi/hello_video/video.c index 2edf44c..3275d57 100755 --- a/host_applications/linux/apps/hello_pi/hello_video/video.c +++ b/host_applications/linux/apps/hello_pi/hello_video/video.c @@ -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 -#include -#include +#include +#include +#include +#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 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 index 0000000..056db03 --- /dev/null +++ b/host_applications/linux/apps/hello_pi/hello_video/video.h @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "queue.h" +#include "bcm_host.h" +#include "ilclient.h" +#include +#include +#include +#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); diff --git a/packaging/raspberrypi-userland.spec b/packaging/raspberrypi-userland.spec index 0761fc6..0c9669b 100644 --- a/packaging/raspberrypi-userland.spec +++ b/packaging/raspberrypi-userland.spec @@ -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)