summaryrefslogtreecommitdiffstats
path: root/src/jogl/native/openmax/omx_tool.c
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2009-06-15 22:57:38 +0000
committerKenneth Russel <[email protected]>2009-06-15 22:57:38 +0000
commita959c53b7ac91e489bf0959391e892790b9ff248 (patch)
tree4664742a4f9f6daa694364292e376ad2e6ee97d1 /src/jogl/native/openmax/omx_tool.c
parent506b634b780dcd23aa61015c2ceba3e687196abf (diff)
Copied JOGL_2_SANDBOX r1957 on to trunk; JOGL_2_SANDBOX branch is now closed
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1959 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/jogl/native/openmax/omx_tool.c')
-rw-r--r--src/jogl/native/openmax/omx_tool.c1713
1 files changed, 1713 insertions, 0 deletions
diff --git a/src/jogl/native/openmax/omx_tool.c b/src/jogl/native/openmax/omx_tool.c
new file mode 100644
index 000000000..e9633af1b
--- /dev/null
+++ b/src/jogl/native/openmax/omx_tool.c
@@ -0,0 +1,1713 @@
+
+#include "omx_tool.h"
+
+#define VERBOSE_ON 1
+#define VERBOSE2_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+#if defined(VERBOSE_ON) && defined(VERBOSE2_ON)
+ #define DBG_PRINT2(...) fprintf(stdout, __VA_ARGS__)
+#else
+ #define DBG_PRINT2(...)
+#endif
+
+#ifdef VERBOSE_ON
+ #ifdef _WIN32_WCE
+ #define STDOUT_FILE "\\Storage Card\\stdout.txt"
+ #define STDERR_FILE "\\Storage Card\\stderr.txt"
+ #endif
+#endif
+
+#include <NVOMX_IndexExtensions.h>
+
+#define NOTSET_U8 ((OMX_U8)0xDE)
+#define NOTSET_U16 ((OMX_U16)0xDEDE)
+#define NOTSET_U32 ((OMX_U32)0xDEDEDEDE)
+#define INIT_PARAM(_X_) (memset(&(_X_), NOTSET_U8, sizeof(_X_)), ((_X_).nSize = sizeof (_X_)), (_X_).nVersion = vOMX)
+
+void OMXInstance_SaveJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback);
+void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pOMXAV, KDboolean issueJavaCallback);
+
+#if !defined(SELF_TEST)
+void java_throwNewRuntimeException(intptr_t jni_env, const char* format, ...);
+#else
+#include <stdarg.h>
+void java_throwNewRuntimeException(intptr_t jni_env, const char* format, ...) {
+ va_list ap;
+ char buffer[255];
+ va_start(ap, format);
+ #ifdef _WIN32
+ _vsnprintf(buffer, sizeof(buffer)-1, format, ap);
+ #else
+ vsnprintf(buffer, sizeof(buffer)-1, format, ap);
+ #endif
+ va_end(ap);
+ buffer[sizeof(buffer)-1]=0;
+ DBG_PRINT( "RuntimeException: %s\n", buffer);
+ exit(1);
+}
+#endif
+static void DestroyInstanceUnlock(OMXToolBasicAV_t * pOMXAV);
+
+#define OMXSAFEVOID(x) \
+do { \
+ OMX_ERRORTYPE err = (x); \
+ if (err != OMX_ErrorNone) { \
+ java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ if(NULL!=pOMXAV) { \
+ DestroyInstanceUnlock(pOMXAV); \
+ } \
+ return; \
+ } \
+} while (0);
+
+#define OMXSAFE(x) \
+do { \
+ OMX_ERRORTYPE err = (x); \
+ if (err != OMX_ErrorNone) { \
+ java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ if(NULL!=pOMXAV) { \
+ DestroyInstanceUnlock(pOMXAV); \
+ } \
+ return -1; \
+ } \
+} while (0);
+
+#define OMXSAFEERR(x) \
+do { \
+ OMX_ERRORTYPE err = (x); \
+ if (err != OMX_ErrorNone) { \
+ java_throwNewRuntimeException((NULL!=pOMXAV)?pOMXAV->jni_env:0, "FAILED at %s:%d, Error: 0x%x\n", __FILE__, __LINE__, err); \
+ if(NULL!=pOMXAV) { \
+ DestroyInstanceUnlock(pOMXAV); \
+ } \
+ return err; \
+ } \
+} while (0);
+
+static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
+static PFNEGLCREATEFENCESYNCKHRPROC eglCreateFenceSyncKHR;
+static PFNEGLFENCEKHRPROC eglFenceKHR;
+static PFNEGLGETSYNCATTRIBKHRPROC eglGetSyncAttribKHR;
+static PFNEGLSIGNALSYNCKHRPROC eglSignalSyncKHR;
+static int _hasEGLSync = 0;
+
+#define GETEXTENSION(type, ext) \
+do \
+{ \
+ ext = (type) eglGetProcAddress(#ext); \
+ if (!ext) \
+ { \
+ fprintf(stderr, "ERROR getting proc addr of " #ext "\n"); \
+ } \
+} while (0);
+
+int USE_OPENGL = 1;
+int USE_HWAUDIOOUT = 1;
+int USE_AUDIOBUFFERING = 0;
+const int PORT_VRENDERER = 6;
+
+static OMX_VERSIONTYPE vOMX;
+
+static int _initialized = 0;
+static void InitStatic()
+{
+ if(_initialized) return;
+
+#ifdef VERBOSE_ON
+ #ifdef _WIN32_WCE
+ _wfreopen(TEXT(STDOUT_FILE),L"w",stdout);
+ _wfreopen(TEXT(STDERR_FILE),L"w",stderr);
+ #endif
+#endif
+
+ _initialized = 1;
+
+ vOMX.s.nVersionMajor = 1;
+ vOMX.s.nVersionMinor = 1;
+ vOMX.s.nRevision = 0;
+ vOMX.s.nStep = 0;
+
+ GETEXTENSION(PFNEGLCREATEIMAGEKHRPROC, eglCreateImageKHR);
+ GETEXTENSION(PFNEGLCREATEFENCESYNCKHRPROC, eglCreateFenceSyncKHR);
+ GETEXTENSION(PFNEGLFENCEKHRPROC, eglFenceKHR);
+ GETEXTENSION(PFNEGLGETSYNCATTRIBKHRPROC, eglGetSyncAttribKHR);
+ GETEXTENSION(PFNEGLSIGNALSYNCKHRPROC, eglSignalSyncKHR);
+ if(NULL==eglFenceKHR||NULL==eglGetSyncAttribKHR||NULL==eglSignalSyncKHR) {
+ _hasEGLSync = 0;
+ } else {
+ _hasEGLSync = 1;
+ }
+
+ OMX_Init();
+}
+
+static void Invalidate(OMXToolBasicAV_t * pOMXAV)
+{
+ DBG_PRINT("INVALIDATE\n");
+ pOMXAV->status=OMXAV_INVALID;
+}
+
+static void GetComponentName(OMX_HANDLETYPE hComponent, KDchar *pName, int nameMaxLen)
+{
+ OMX_VERSIONTYPE v1, v2;
+ OMX_UUIDTYPE uuid;
+
+ OMX_GetComponentVersion(hComponent, pName, &v1, &v2, &uuid);
+}
+
+static OMX_ERRORTYPE UpdateStreamInfo(OMXToolBasicAV_t * pOMXAV, KDboolean issueCallback);
+
+static OMX_ERRORTYPE EventHandler(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ OMXToolBasicAV_t * pOMXAV = (OMXToolBasicAV_t *) pAppData;
+ KDchar name[128];
+
+ GetComponentName(hComponent, name, 128);
+
+ switch (eEvent)
+ {
+ case OMX_EventCmdComplete:
+ {
+ DBG_PRINT("event complete: cmd 0x%X, s:0x%X, component: %p - %s\n", (unsigned)nData1, (unsigned)nData2, hComponent, name);
+ if (nData1 == OMX_CommandStateSet && pOMXAV->status == OMXAV_INVALID)
+ {
+ if (nData2 > OMX_StateLoaded) {
+ DBG_PRINT("\t state -> StateLoaded\n");
+ // Transition the component down to StateLoaded
+ OMX_SendCommand(hComponent, OMX_CommandStateSet, OMX_StateLoaded, 0);
+ }
+ }
+ else if (nData1 == OMX_CommandFlush && nData2 == OMX_ALL)
+ {
+ DBG_PRINT("\t flush\n");
+ kdThreadSemPost(pOMXAV->flushSem);
+ }
+ break;
+ }
+ case OMX_EventBufferFlag:
+ if (nData2 & OMX_BUFFERFLAG_EOS)
+ {
+ DBG_PRINT("event buffer EOS: component: %p - %s\n", hComponent, name);
+ if (pOMXAV->endComponent == hComponent)
+ {
+ DBG_PRINT("\t end component - FIN\n");
+ pOMXAV->status = OMXAV_FIN;
+ }
+ }
+ break;
+ case OMX_EventError:
+ {
+ if (nData1 == OMX_ErrorIncorrectStateTransition)
+ {
+ DBG_PRINT("event error: 0x%X IncorrectTransition, component: %p - %s\n", (unsigned int) nData1, hComponent, name);
+ // We are shutting down, just continue with that process
+ OMX_SendCommand(hComponent, OMX_CommandStateSet, OMX_StateIdle, 0);
+ }
+ else if(nData1 == OMX_ErrorSameState)
+ {
+ DBG_PRINT("event error: Same State 0x%X, component: %p - %s\n", (unsigned int) nData2, hComponent, name);
+ }
+ else
+ {
+ DBG_PRINT("event error: 0x%X, component: %p - %s\n", (unsigned int) nData1, hComponent, name);
+ Invalidate(pOMXAV);
+ }
+ }
+ break;
+ case OMX_EventPortSettingsChanged:
+ {
+ (void) UpdateStreamInfo(pOMXAV, (pOMXAV->status>OMXAV_INIT)?KD_TRUE:KD_FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return OMX_ErrorNone;
+}
+
+
+static OMX_ERRORTYPE EmptyBufferDone(
+ OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE FillBufferDone(
+ OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ OMXToolBasicAV_t *pOMXAV = (OMXToolBasicAV_t *) pAppData;
+
+ if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ pOMXAV->status = OMXAV_FIN;
+ }
+ pOMXAV->available++;
+ DBG_PRINT("FillBufferDone avail %d\n", pOMXAV->available);
+
+ return OMX_ErrorNone;
+}
+
+#define STATE_SLEEP 10 // ms
+#define STATE_TIMEOUT 1000 // ms
+#define STATE_TIMEOUT_LOOP (STATE_TIMEOUT/STATE_SLEEP)
+
+static OMX_ERRORTYPE WaitForState(OMX_HANDLETYPE hComponent,
+ OMX_STATETYPE eTestState,
+ OMX_STATETYPE eTestState2,
+ OMX_STATETYPE *currentState)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_STATETYPE eState;
+ int loop=STATE_TIMEOUT_LOOP;
+
+ DBG_PRINT( "WaitForState p1 c:%p s1:0x%X s2:0x%X\n", hComponent, eTestState, eTestState2);
+ eError = OMX_GetState(hComponent, &eState);
+ DBG_PRINT( "WaitForState p2 s:0x%X e:0x%X\n", eState, eError);
+
+ while (loop>0 &&
+ OMX_ErrorNone == eError &&
+ eState != eTestState &&
+ eState != eTestState2)
+ {
+ usleep(STATE_SLEEP*1000);
+ loop--;
+
+ eError = OMX_GetState(hComponent, &eState);
+ DBG_PRINT( "WaitForState p3 s:0x%X e:0x%X\n", eState, eError);
+ }
+
+ if(NULL!=currentState) *currentState=eState;
+
+ return eError;
+}
+
+static KDint SyncOnState(OMX_HANDLETYPE hComponent, OMX_STATETYPE state)
+{
+ OMX_STATETYPE currentState;
+ OMX_ERRORTYPE eError = WaitForState(hComponent, state, OMX_StateInvalid, &currentState);
+ return ( OMX_ErrorNone != eError ) ? -1 : ( currentState!=state ) ? -2 : 0 ;
+}
+
+static KDint CheckState(OMX_HANDLETYPE hComponent, OMX_STATETYPE state)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_STATETYPE eState;
+
+ eError = OMX_GetState(hComponent, &eState);
+
+ return ( OMX_ErrorNone != eError ) ? -1 : ( eState!=state ) ? -2 : 0 ;
+}
+
+KDint OMXToolBasicAV_IsFileValid(const KDchar * file)
+{
+ #ifdef _WIN32
+ KDchar cvtdPath[_MAX_PATH];
+
+ if(NULL==file) return -1;
+
+ kdStrcpy_s(cvtdPath, _MAX_PATH, file);
+ while(kdStrchr(cvtdPath,'/'))
+ *kdStrchr(cvtdPath,'/')='\\';
+
+ {
+ #ifdef UNICODE
+ wchar_t properfilename[_MAX_PATH];
+ mbstowcs( properfilename, cvtdPath, _MAX_PATH );
+ #else
+ char *properfilename = cvtdPath;
+ #endif
+
+ if (INVALID_FILE_ATTRIBUTES==GetFileAttributes(properfilename))
+ {
+ fprintf(stderr, "!>Input file (%s) does not exist! EXITING.", file);
+ return -2;
+ }
+ }
+ #else
+ if(NULL==file) return -1;
+ #endif
+
+ return 0;
+}
+
+KDint OMXToolBasicAV_CheckState(OMXToolBasicAV_t * pOMXAV, OMX_STATETYPE state)
+{
+ KDint i, res;
+ if(NULL==pOMXAV) return -1;
+
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ if(0!=pOMXAV->comp[i]) {
+ if( 0!=(res=CheckState(pOMXAV->comp[i], state)) ) {
+ return res-(i*10);
+ }
+ }
+ }
+ return 0;
+}
+
+KDint OMXToolBasicAV_WaitForState(OMXToolBasicAV_t * pOMXAV, OMX_STATETYPE state)
+{
+ KDint res, i;
+ DBG_PRINT( "OMXToolBasicAV_WaitForState %p s:%d\n", pOMXAV, state);
+ if(NULL==pOMXAV) {
+ DBG_PRINT( "OMXToolBasicAV_WaitForState p1\n");
+ return -1;
+ }
+
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ if(0!=pOMXAV->comp[i]) {
+ DBG_PRINT( "OMXToolBasicAV_WaitForState p4 %d c:%p\n", i, pOMXAV->comp[i]);
+ if( 0!=(res=SyncOnState(pOMXAV->comp[i], state)) ) {
+ KDchar name[128];
+ GetComponentName(pOMXAV->comp[i], name, 128);
+ DBG_PRINT( "OMXToolBasicAV_WaitForState Failed (Wait) %d c:%p - %s, s:0x%X\n",
+ i, pOMXAV->comp[i], name, state);
+ return res-(i*10);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static OMX_ERRORTYPE RequestState(OMX_HANDLETYPE hComponent, OMX_STATETYPE state, KDboolean wait)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_STATETYPE eState;
+ eError = OMX_GetState(hComponent, &eState);
+ DBG_PRINT( "RequestState p2 c:%p, e:0x%X, s:0x%X\n",
+ hComponent, eError, eState);
+ // Skip StateSet in case the state is already reached ..
+ if(OMX_ErrorNone != eError || eState!=state) {
+ eError = OMX_SendCommand(hComponent, OMX_CommandStateSet, state, 0);
+ DBG_PRINT( "RequestState p3 c:%p e:0x%X s: 0x%X -> 0x%X\n",
+ hComponent, eError, eState, state);
+ if(wait) {
+ OMX_STATETYPE currentState;
+ eError = WaitForState(hComponent, state, OMX_StateInvalid, &currentState);
+ if ( OMX_ErrorNone==eError && currentState!=state ) eError=OMX_StateInvalid;
+ }
+ }
+ return eError;
+}
+
+KDint OMXToolBasicAV_RequestState(OMXToolBasicAV_t * pOMXAV, OMX_STATETYPE state, KDboolean wait)
+{
+ KDint i;
+ DBG_PRINT( "OMXToolBasicAV_RequestState %p s:%d, w:%d\n", pOMXAV, state, wait);
+ if(NULL==pOMXAV) {
+ DBG_PRINT( "OMXToolBasicAV_RequestState p1\n");
+ return -1;
+ }
+
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ if(0!=pOMXAV->comp[i]) {
+ OMXSAFE(RequestState(pOMXAV->comp[i], state, KD_FALSE));
+ }
+ }
+
+ if (wait)
+ {
+ return OMXToolBasicAV_WaitForState(pOMXAV, state);
+ }
+
+ return 0;
+}
+
+static KDint SendCommand(OMXToolBasicAV_t * pOMXAV, OMX_COMMANDTYPE cmd, OMX_U32 nParam1, OMX_PTR pCmdData)
+{
+ KDint i;
+ if(NULL==pOMXAV) return -1;
+
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ if(0!=pOMXAV->comp[i]) {
+ if(OMX_ErrorNone!=OMX_SendCommand(pOMXAV->comp[i], cmd, nParam1, pCmdData)) {
+ return -1;
+ }
+ if(OMX_CommandFlush==cmd) {
+ kdThreadSemWait(pOMXAV->flushSem);
+ }
+ }
+ }
+ return 0;
+}
+
+static KDint PlayStop(OMXToolBasicAV_t * pOMXAV);
+static int DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV);
+
+static void DestroyInstanceUnlock(OMXToolBasicAV_t * pOMXAV)
+{
+ // 0: Stop
+ // 1: X -> idle
+ // 2: Disable all ports
+ // 3: DetachVideoRenderer
+ // 3: X -> loaded
+ // 4: Free Handle
+ // 5: Free mutex/semaphores/struct
+ int i, res1=0, res2=0;
+ if(NULL==pOMXAV) return;
+
+ DBG_PRINT( "Destroy p1\n");
+ PlayStop(pOMXAV);
+
+ DBG_PRINT( "Destroy p2\n");
+ if(0!=(res1=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE)))
+ {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Destroy - Wait for Idle Failed (%d)", res1);
+ }
+
+ DBG_PRINT( "Destroy p3\n");
+ SendCommand(pOMXAV, OMX_CommandPortDisable, OMX_ALL, 0); // Ignore error ..
+
+ DBG_PRINT( "Destroy p3\n");
+ DetachVideoRenderer(pOMXAV);
+
+ DBG_PRINT( "Destroy p4\n");
+ if(0!=(res2=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateLoaded, KD_TRUE)))
+ {
+ if(!res1) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Destroy - Wait for Loaded Failed (%d)", res2);
+ }
+ }
+
+ DBG_PRINT( "Destroy p5\n");
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ if(0!=pOMXAV->comp[i]) {
+ OMX_FreeHandle(pOMXAV->comp[i]);
+ pOMXAV->comp[i]=0;
+ }
+ }
+
+ if(0!=pOMXAV->flushSem) {
+ DBG_PRINT( "Destroy p6\n");
+ kdThreadSemFree(pOMXAV->flushSem);
+ pOMXAV->flushSem=0;
+ }
+ if(0!=pOMXAV->mutex) {
+ DBG_PRINT( "Destroy p7\n");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ DBG_PRINT( "Destroy p8\n");
+ kdThreadMutexFree(pOMXAV->mutex);
+ pOMXAV->mutex=0;
+ }
+
+ DBG_PRINT( "Destroy DONE\n");
+
+ free(pOMXAV);
+}
+
+static OMX_ERRORTYPE AddFile(OMXToolBasicAV_t * pOMXAV, const KDchar* filename)
+{
+ // FIXME: Non NV case ..
+ OMX_ERRORTYPE eError;
+ NVX_PARAM_FILENAME oFilenameParam;
+ OMX_INDEXTYPE eIndexParamFilename;
+
+ eError = OMX_GetExtensionIndex(pOMXAV->comp[OMXAV_H_READER], NVX_INDEX_PARAM_FILENAME,
+ &eIndexParamFilename);
+ if (eError != OMX_ErrorNone)
+ return eError;
+
+ INIT_PARAM(oFilenameParam);
+ oFilenameParam.pFilename = (char*) filename;
+
+ eError = OMX_SetParameter(pOMXAV->comp[OMXAV_H_READER], eIndexParamFilename, &oFilenameParam);
+ if (eError != OMX_ErrorNone)
+ return eError;
+
+ return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE ProbePort(OMXToolBasicAV_t * pOMXAV, int port, KDchar *codec, KDchar* component)
+{
+ // FIXME: Non NV case ..
+ OMX_U32 roles = 1;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ OMX_INDEXTYPE eParam;
+ NVX_PARAM_STREAMTYPE oStreamType;
+ OMX_PARAM_PORTDEFINITIONTYPE oPortDef;
+
+ INIT_PARAM(oStreamType);
+ INIT_PARAM(oPortDef);
+ OMXSAFEERR(OMX_GetExtensionIndex(pOMXAV->comp[OMXAV_H_READER], NVX_INDEX_PARAM_STREAMTYPE, &eParam));
+
+ oPortDef.nPortIndex = port;
+ OMXSAFEERR(OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], OMX_IndexParamPortDefinition, &oPortDef));
+
+ oStreamType.nPort = port;
+ OMXSAFEERR(OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], eParam, &oStreamType));
+
+ if (oPortDef.eDomain != OMX_PortDomainVideo &&
+ oPortDef.eDomain != OMX_PortDomainAudio) {
+ return OMX_ErrorNotImplemented;
+ }
+
+ switch (oStreamType.eStreamType)
+ {
+#define CODEC(a, b) case a: kdStrncat_s(codec, 128, b, kdStrlen(b)); break
+ CODEC(NvxStreamType_MPEG4, "mpeg4");
+ CODEC(NvxStreamType_H264, "avc");
+ CODEC(NvxStreamType_H263, "mpeg4");
+ CODEC(NvxStreamType_WMV, "vc1");
+ CODEC(NvxStreamType_MP3, "mp3");
+ CODEC(NvxStreamType_AAC, "aac");
+ CODEC(NvxStreamType_AACSBR, "eaacplus");
+ CODEC(NvxStreamType_BSAC, "bsac");
+ CODEC(NvxStreamType_WMA, "wma");
+ CODEC(NvxStreamType_WMAPro, "wmapro");
+ CODEC(NvxStreamType_WMALossless, "wmalossless");
+ CODEC(NvxStreamType_AMRWB, "amrwb");
+ CODEC(NvxStreamType_AMRNB, "amrnb");
+ CODEC(NvxStreamType_VORBIS, "vorbis");
+#undef CODEC
+ default:
+ return OMX_ErrorNotImplemented;
+ }
+
+ {
+ KDchar ocodec[256];
+ OMX_U8 *tmp = (OMX_U8*) kdMalloc(OMX_MAX_STRINGNAME_SIZE + 1);
+ kdMemset(tmp, 0, sizeof(OMX_U8) * (OMX_MAX_STRINGNAME_SIZE + 1));
+
+ if (oPortDef.eDomain == OMX_PortDomainVideo)
+ kdStrcpy_s(ocodec, 128, "video_decoder.");
+ else if (oPortDef.eDomain == OMX_PortDomainAudio)
+ kdStrcpy_s(ocodec, 128, "audio_decoder.");
+ kdStrncat_s(ocodec, 128, codec, kdStrlen(codec));
+
+ err = OMX_GetComponentsOfRole(codec, &roles, &tmp);
+ kdStrcpy_s(component, 256, (KDchar*) tmp);
+ kdFree(tmp);
+ printf("%s(%s) -> %s\n", ocodec, codec, component);
+ }
+
+ return err != OMX_ErrorNone ? err : roles ? OMX_ErrorNone : OMX_ErrorComponentNotFound;
+}
+
+static int StartClock(OMXToolBasicAV_t * pOMXAV, KDboolean start, KDfloat32 time) {
+ OMX_TIME_CONFIG_CLOCKSTATETYPE oClockState;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ int loop=STATE_TIMEOUT_LOOP;
+ INIT_PARAM(oClockState);
+ oClockState.nOffset = 0;
+ oClockState.nStartTime = (KD_TRUE==start)? (OMX_TICKS) (time * 1000.0 * 1000.0) : 0;
+ oClockState.nWaitMask = 0;
+ oClockState.eState = (KD_TRUE==start)?OMX_TIME_ClockStateRunning:OMX_TIME_ClockStateStopped;
+
+ eError = OMX_SetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeClockState, &oClockState);
+ while (loop>0 && OMX_ErrorNotReady == eError)
+ {
+ DBG_PRINT( "Play 3.2\n");
+ usleep(STATE_SLEEP*1000);
+ loop--;
+ eError = OMX_SetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeClockState,
+ &oClockState);
+ }
+ return (OMX_ErrorNotReady == eError)?-1:0;
+}
+
+static KDfloat32 GetClockPosition(OMXToolBasicAV_t * pOMXAV)
+{
+ OMX_TIME_CONFIG_TIMESTAMPTYPE stamp;
+ INIT_PARAM(stamp);
+ stamp.nPortIndex = 0;
+
+ OMX_GetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeCurrentMediaTime, &stamp);
+ return (KDfloat32) (stamp.nTimestamp * (1.0f/(1000.0f*1000.0f)));
+}
+
+static KDfloat32 GetClockScale(OMXToolBasicAV_t * pOMXAV)
+{
+ OMX_TIME_CONFIG_SCALETYPE pScale;
+ INIT_PARAM(pScale);
+
+ OMX_GetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeScale, &pScale);
+ return (pScale.xScale / 65536.0f);
+}
+
+static KDint SetClockScale(OMXToolBasicAV_t * pOMXAV, KDfloat32 scale)
+{
+ OMX_TIME_CONFIG_SCALETYPE pScale;
+ INIT_PARAM(pScale);
+ pScale.xScale = (int) (scale * (1<<16));
+
+ OMX_SetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeScale, &pScale);
+ return 0;
+}
+
+static int SetMediaPosition(OMXToolBasicAV_t * pOMXAV, KDfloat32 time) {
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TIME_CONFIG_TIMESTAMPTYPE timestamp;
+ int loop=STATE_TIMEOUT_LOOP;
+ INIT_PARAM(timestamp);
+ timestamp.nPortIndex = 0;
+ timestamp.nTimestamp = (OMX_TICKS) (time * 1000.0 * 1000.0);
+
+ eError = OMX_SetConfig(pOMXAV->comp[OMXAV_H_READER], OMX_IndexConfigTimePosition, &timestamp);
+ while (loop>0 && OMX_ErrorNotReady == eError)
+ {
+ usleep(STATE_SLEEP*1000);
+ loop--;
+ eError = OMX_SetConfig(pOMXAV->comp[OMXAV_H_READER], OMX_IndexConfigTimePosition, &timestamp);
+ }
+ return (OMX_ErrorNotReady == eError)?-1:0;
+}
+
+static KDfloat32 GetMediaLength(OMXToolBasicAV_t * pOMXAV)
+{
+ NVX_PARAM_DURATION oDuration;
+ OMX_INDEXTYPE eParam;
+
+ if (OMX_ErrorNone != OMX_GetExtensionIndex(pOMXAV->comp[OMXAV_H_READER], NVX_INDEX_PARAM_DURATION, &eParam))
+ return -1.0f;
+
+ if (OMX_ErrorNone != OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], eParam, &oDuration))
+ return -1.0f;
+
+ return (KDfloat32) (oDuration.nDuration * (1.0f/(1000.0f*1000.0f)));
+}
+
+static OMX_ERRORTYPE UpdateStreamInfo(OMXToolBasicAV_t * pOMXAV, KDboolean issueCallback)
+{
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ OMX_PARAM_PORTDEFINITIONTYPE oPortDef;
+
+ DBG_PRINT( "Update StreamInfo p0\n" );
+
+ kdMemset(&oPortDef, 0, sizeof(oPortDef));
+ oPortDef.nSize = sizeof(oPortDef);
+ oPortDef.nVersion.s.nVersionMajor = 1;
+ oPortDef.nVersion.s.nVersionMinor = 1;
+ oPortDef.nPortIndex = 0;
+ err = OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], OMX_IndexParamPortDefinition, &oPortDef);
+ if(OMX_ErrorNone!=err) {
+ fprintf(stderr, "UpdateStreamInfo failed - p1 0x%X", err);
+ return err;
+ }
+
+ if (oPortDef.eDomain != OMX_PortDomainVideo)
+ {
+ kdMemset(&oPortDef, 0, sizeof(oPortDef));
+ oPortDef.nSize = sizeof(oPortDef);
+ oPortDef.nVersion.s.nVersionMajor = 1;
+ oPortDef.nVersion.s.nVersionMinor = 1;
+ oPortDef.nPortIndex = 1;
+ err = OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], OMX_IndexParamPortDefinition, &oPortDef);
+ if(OMX_ErrorNone!=err) {
+ fprintf(stderr, "UpdateStreamInfo failed - p2 0x%X", err);
+ return err;
+ }
+ }
+
+ DBG_PRINT( "Update StreamInfo p1\n" );
+ OMXInstance_SaveJavaAttributes(pOMXAV, issueCallback);
+
+ pOMXAV->width = oPortDef.format.video.nFrameWidth;
+ pOMXAV->height = oPortDef.format.video.nFrameHeight;
+ /* pOMXAV->stride = oPortDef.format.video.nStride;
+ pOMXAV->sliceHeight = oPortDef.format.video.nSliceHeight; */
+ pOMXAV->framerate = oPortDef.format.video.xFramerate;
+ pOMXAV->bitrate = oPortDef.format.video.nBitrate;
+ DBG_PRINT( "Update StreamInfo p2 %dx%d, fps %d, bps %d\n", pOMXAV->width, pOMXAV->height, pOMXAV->framerate, pOMXAV->bitrate );
+ pOMXAV->length = GetMediaLength(pOMXAV);
+ pOMXAV->speed = GetClockScale(pOMXAV);
+
+ OMXInstance_UpdateJavaAttributes(pOMXAV, issueCallback);
+
+ return err;
+}
+
+static int AttachAudioRenderer(OMXToolBasicAV_t * pOMXAV)
+{
+ int res=0;
+ // Configure audio port
+
+ if (USE_AUDIOBUFFERING)
+ {
+ // FIXME: proper audio buffering ..
+ OMXSAFE(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_ABUFFERING], "OMX.Nvidia.audio.visualization", pOMXAV, &pOMXAV->callbacks));
+ if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_ABUFFERING], OMX_StateLoaded))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Loading AudioBuffering Failed (%d)", res);
+ return res;
+ }
+ /**
+ if (m_settings.m_avsync)
+ {
+ // Tweak the avsync parameter
+ NVX_CONFIG_VISU conf;
+ INIT_PARAM(conf);
+ conf.nAVSyncOffset = m_settings.m_avsync;
+
+ OMX_INDEXTYPE idx;
+ OMX_GetExtensionIndex(pOMXAV->comp[OMXAV_H_ABUFFERING], NVX_INDEX_PARAM_VISUDATA, &idx);
+ OMX_SetConfig(pOMXAV->comp[OMXAV_H_ABUFFERING], idx, &conf);
+ }*/
+ }
+
+ OMXSAFE(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_ARENDERER], "OMX.Nvidia.audio.render",pOMXAV, &pOMXAV->callbacks));
+ pOMXAV->endComponent = pOMXAV->comp[OMXAV_H_ARENDERER];
+
+ // mandatory before SetupTunnel
+ if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_ARENDERER], OMX_StateLoaded))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Loading AudioRenderer Failed (%d)", res);
+ return res;
+ }
+
+ {
+ OMX_INDEXTYPE eIndexConfigOutputType;
+ NVX_CONFIG_AUDIOOUTPUT ao;
+ OMX_ERRORTYPE eError;
+
+ INIT_PARAM(ao);
+
+ eError = OMX_GetExtensionIndex(pOMXAV->comp[OMXAV_H_ARENDERER], NVX_INDEX_CONFIG_AUDIO_OUTPUT,
+ &eIndexConfigOutputType);
+ if (eError != OMX_ErrorNoMore)
+ {
+ /** FIXME: HDMI configuration ..
+ // for now, only put audio out hdmi if the settings say to, regardless of the hdmi-video flag.
+ // if (// m_settings.m_hdmiVideo || // m_settings.m_hdmiAudio)
+ // ao.eOutputType = NVX_AUDIO_OutputHdmi;
+ else */
+ ao.eOutputType = NVX_AUDIO_OutputI2S;
+
+ OMX_SetConfig(pOMXAV->comp[OMXAV_H_ARENDERER], eIndexConfigOutputType, &ao);
+ }
+ }
+
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_CLOCK], OMX_CommandPortEnable, pOMXAV->audioPort, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_ARENDERER], OMX_CommandPortEnable, 1, 0));
+
+ if (USE_AUDIOBUFFERING)
+ {
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_ADECODER], 1, pOMXAV->comp[OMXAV_H_ABUFFERING], 0));
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_ABUFFERING], 1, pOMXAV->comp[OMXAV_H_ARENDERER], 0));
+ }
+ else
+ {
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_ADECODER], 1, pOMXAV->comp[OMXAV_H_ARENDERER], 0));
+ }
+
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_CLOCK], pOMXAV->audioPort, pOMXAV->comp[OMXAV_H_ARENDERER], 1));
+
+ return OMX_ErrorNone;
+}
+
+static int AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
+{
+ int i, res=0;
+ if(KD_NULL!=pOMXAV->comp[OMXAV_H_VSCHEDULER]) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Detach Video first");
+ return -1;
+ }
+ OMXSAFE(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_VSCHEDULER], "OMX.Nvidia.video.scheduler", pOMXAV, &pOMXAV->callbacks));
+ pOMXAV->endComponent = pOMXAV->comp[OMXAV_H_VSCHEDULER];
+
+ // mandatory before SetupTunnel
+ if(0!=(res=SyncOnState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateLoaded))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Loading VideoScheduler Failed (%d)", res);
+ return res;
+ }
+ // mandatory before EGLUseImage
+ OMXSAFE(RequestState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateIdle, KD_FALSE));
+
+ DBG_PRINT( "Attach VR %p c:%p\n", pOMXAV, pOMXAV->comp[OMXAV_H_VSCHEDULER]);
+ OMXSAFE(UpdateStreamInfo(pOMXAV, KD_FALSE));
+
+ DBG_PRINT( "UseEGLImg port enable/tunneling %p\n", pOMXAV);
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_CLOCK], OMX_CommandPortEnable, PORT_VRENDERER, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VDECODER], OMX_CommandPortEnable, 1, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_CommandPortEnable, 0, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_CommandPortEnable, 2, 0));
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_VDECODER], 1, pOMXAV->comp[OMXAV_H_VSCHEDULER], 0));
+ OMXSAFE(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_CLOCK], PORT_VRENDERER, pOMXAV->comp[OMXAV_H_VSCHEDULER], 2));
+
+ for (i = 0; i < pOMXAV->vBufferNum; i++) {
+ OMXToolImageBuffer_t *pBuf = &pOMXAV->buffers[i];
+ // The Texture, EGLImage and EGLSync was created by the Java client,
+ // and registered using the OMXToolBasicAV_SetStreamEGLImageTexture2D command.
+
+ DBG_PRINT( "UseEGLImg %p #%d t:%d i:%p s:%p p1\n", pOMXAV, i, pBuf->tex, pBuf->image, pBuf->sync);
+
+ if(NULL==pBuf->image) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "AttachVideoRenderer: User didn't set buffer %d/%d\n", i, pOMXAV->vBufferNum);
+ return -1;
+ } else {
+ // tell decoder output port that it will be using EGLImage
+ OMXSAFE(OMX_UseEGLImage(
+ pOMXAV->comp[OMXAV_H_VSCHEDULER],
+ &pBuf->omxBufferHeader,
+ 1, // The port to use the EGLImage for
+ pOMXAV, // app private data
+ pBuf->image));
+ }
+ DBG_PRINT( "UseEGLImg %p #%d t:%d i:%p s:%p b:%p - p2\n",
+ pOMXAV, i, pBuf->tex, pBuf->image, pBuf->sync, pBuf->omxBufferHeader);
+ }
+
+ DBG_PRINT( "UseEGLImg %p #%d DONE\n", pOMXAV, i);
+ return 0;
+}
+
+static int DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV)
+{
+ int i;
+ if(NULL==pOMXAV) return -1;
+
+ if(KD_NULL==pOMXAV->comp[OMXAV_H_VSCHEDULER]) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Attach Video first");
+ return -1;
+ }
+ DBG_PRINT( "DetachVideoRenderer p0\n");
+ if(0==CheckState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateLoaded)) {
+ DBG_PRINT( "DetachVideoRenderer DONE (already state loaded)\n");
+ return 0;
+ }
+ OMXSAFE(RequestState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateIdle, KD_TRUE));
+
+ DBG_PRINT( "DetachVideoRenderer p1\n");
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_CLOCK], OMX_CommandPortDisable, PORT_VRENDERER, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VDECODER], OMX_CommandPortDisable, 1, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_CommandPortDisable, 0, 0));
+ OMXSAFE(OMX_SendCommand(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_CommandPortDisable, 2, 0));
+ DBG_PRINT( "DetachVideoRenderer p2\n");
+
+ for (i = 0; i < pOMXAV->vBufferNum; i++) {
+ OMXToolImageBuffer_t *pBuf = &pOMXAV->buffers[i];
+
+ // tell decoder output port to stop using EGLImage
+ if (NULL!=pBuf->omxBufferHeader) {
+ OMX_FreeBuffer(
+ pOMXAV->comp[OMXAV_H_VSCHEDULER],
+ 1,
+ pBuf->omxBufferHeader);
+ pBuf->omxBufferHeader=NULL;
+ }
+ }
+
+ OMXSAFE(RequestState(pOMXAV->comp[OMXAV_H_VSCHEDULER], OMX_StateLoaded, KD_TRUE));
+ DBG_PRINT( "DetachVideoRenderer p3\n");
+
+ OMX_FreeHandle(pOMXAV->comp[OMXAV_H_VSCHEDULER]);
+ pOMXAV->comp[OMXAV_H_VSCHEDULER]=NULL;
+ DBG_PRINT( "DetachVideoRenderer DONE\n");
+ return 0;
+}
+
+OMXToolBasicAV_t * OMXToolBasicAV_CreateInstance()
+{
+ int i;
+ OMXToolBasicAV_t * pOMXAV = NULL;
+ InitStatic();
+
+ pOMXAV = malloc(sizeof(OMXToolBasicAV_t));
+ if(NULL==pOMXAV) {
+ DBG_PRINT( "Init struct failed!\n");
+ return NULL;
+ }
+ memset(pOMXAV, 0, sizeof(OMXToolBasicAV_t));
+
+ pOMXAV->audioPort=-1;
+ pOMXAV->videoPort=-1;
+
+ for(i=0; i<OMXAV_H_NUMBER; i++) {
+ pOMXAV->comp[i] = KD_NULL;
+ }
+
+ pOMXAV->callbacks.EventHandler = EventHandler;
+ pOMXAV->callbacks.EmptyBufferDone = EmptyBufferDone;
+ pOMXAV->callbacks.FillBufferDone = FillBufferDone;
+
+ pOMXAV->mutex = kdThreadMutexCreate(KD_NULL);
+ pOMXAV->flushSem = kdThreadSemCreate(0);
+
+ pOMXAV->play_speed = 1.0f;
+ pOMXAV->status=OMXAV_INIT;
+
+ return pOMXAV;
+}
+
+void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const KDchar * stream)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ DBG_PRINT( "SetStream 1 %s ..\n", stream);
+
+ // FIXME: verify player state .. ie stop !
+ if(pOMXAV->status!=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Player instance in use\n");
+ return;
+ }
+ if(vBufferNum>EGLIMAGE_MAX_BUFFERS) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "buffer number %d > MAX(%d)\n", vBufferNum, EGLIMAGE_MAX_BUFFERS);
+ return;
+ }
+
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ DBG_PRINT( "SetStream 3\n");
+
+ pOMXAV->vBufferNum = vBufferNum;
+
+ // Use the "super parser" :) FIXME: Non NV case ..
+ eError = OMX_GetHandle(&pOMXAV->comp[OMXAV_H_READER], "OMX.Nvidia.reader", pOMXAV, &pOMXAV->callbacks);
+
+ eError = AddFile(pOMXAV, stream);
+ if(eError!=OMX_ErrorNone) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Couldn't open or handle stream: %s\n", stream);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ DBG_PRINT( "SetStream 4\n");
+
+ // Auto detect codecs
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE oPortDef;
+ INIT_PARAM(oPortDef);
+ oPortDef.nPortIndex = 0;
+ pOMXAV->videoPort = -1;
+ pOMXAV->audioPort = -1;
+ OMXSAFEVOID(OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], OMX_IndexParamPortDefinition, &oPortDef));
+
+ if (oPortDef.eDomain == OMX_PortDomainAudio)
+ pOMXAV->audioPort = oPortDef.nPortIndex;
+ else if (oPortDef.eDomain == OMX_PortDomainVideo)
+ pOMXAV->videoPort = oPortDef.nPortIndex;
+ else
+ OMXSAFEVOID(OMX_ErrorNotImplemented);
+
+ INIT_PARAM(oPortDef);
+ oPortDef.nPortIndex = 1;
+ if (OMX_GetParameter(pOMXAV->comp[OMXAV_H_READER], OMX_IndexParamPortDefinition, &oPortDef) == OMX_ErrorNone)
+ {
+ if (oPortDef.eDomain == OMX_PortDomainAudio)
+ pOMXAV->audioPort = oPortDef.nPortIndex;
+ else if (oPortDef.eDomain == OMX_PortDomainVideo)
+ pOMXAV->videoPort = oPortDef.nPortIndex;
+ else
+ OMXSAFEVOID(OMX_ErrorNotImplemented);
+ }
+ if (pOMXAV->audioPort != -1)
+ {
+ if (ProbePort(pOMXAV, pOMXAV->audioPort, pOMXAV->audioCodec, pOMXAV->audioCodecComponent) != OMX_ErrorNone)
+ {
+ printf("disabling audio port\n");
+ OMXSAFEVOID(OMX_SendCommand(pOMXAV->comp[OMXAV_H_READER], OMX_CommandPortDisable, pOMXAV->audioPort, 0));
+ pOMXAV->audioPort = -1;
+ }
+ }
+ if (pOMXAV->videoPort != -1)
+ if (ProbePort(pOMXAV, pOMXAV->videoPort, pOMXAV->videoCodec, pOMXAV->videoCodecComponent) != OMX_ErrorNone)
+ {
+ printf("disabling video port\n");
+ OMXSAFEVOID(OMX_SendCommand(pOMXAV->comp[OMXAV_H_READER], OMX_CommandPortDisable, pOMXAV->videoPort, 0));
+ pOMXAV->videoPort = -1;
+ }
+
+ if (pOMXAV->audioPort == -1 && pOMXAV->videoPort == -1)
+ {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Neither audioport or videoport could be played back!\n");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ }
+ DBG_PRINT( "SetStream 5 ; audioPort %d, videoPort %d\n", pOMXAV->audioPort, pOMXAV->videoPort);
+
+ OMXSAFEVOID(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_CLOCK], "OMX.Nvidia.clock.component", pOMXAV, &pOMXAV->callbacks));
+
+ DBG_PRINT( "Configuring comp[OMXAV_H_CLOCK]\n");
+ {
+
+ OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE oActiveClockType;
+ INIT_PARAM(oActiveClockType);
+ oActiveClockType.eClock = (pOMXAV->audioPort != -1) ?
+ OMX_TIME_RefClockAudio : OMX_TIME_RefClockVideo;
+ OMXSAFEVOID(OMX_SetConfig(pOMXAV->comp[OMXAV_H_CLOCK], OMX_IndexConfigTimeActiveRefClock,
+ &oActiveClockType));
+ }
+ OMXSAFEVOID(OMX_SendCommand(pOMXAV->comp[OMXAV_H_CLOCK], OMX_CommandPortDisable, (OMX_U32) -1, 0));
+
+ OMXSAFEVOID(UpdateStreamInfo(pOMXAV, KD_FALSE));
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+
+ DBG_PRINT( "SetStream X\n");
+}
+
+void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint i, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
+{
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ DBG_PRINT( "SetStreamEGLImg %p #%d/%d t:%d i:%p s:%p..\n", pOMXAV, i, pOMXAV->vBufferNum, tex, image, sync);
+ if(i<0||i>=pOMXAV->vBufferNum) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Buffer index out of range: %d\n", i);
+ return;
+ }
+
+ kdThreadMutexLock(pOMXAV->mutex);
+ {
+ OMXToolImageBuffer_t *pBuf = &pOMXAV->buffers[i];
+ pBuf->tex=tex;
+ pBuf->image=image;
+ pBuf->sync=sync;
+
+ }
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV) {
+ int res;
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ DBG_PRINT( "ActivateStream 1\n");
+
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ if (pOMXAV->audioPort != -1)
+ {
+ OMXSAFEVOID(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_ADECODER], pOMXAV->audioCodecComponent, pOMXAV, &pOMXAV->callbacks));
+ }
+
+ if (pOMXAV->videoPort != -1)
+ {
+ OMXSAFEVOID(OMX_GetHandle(&pOMXAV->comp[OMXAV_H_VDECODER], pOMXAV->videoCodecComponent, pOMXAV, &pOMXAV->callbacks));
+ }
+
+ //
+ // mandatory: before SetupTunnel (->Activate), wait until all devices are ready ..
+ // arender/vrender must wait as well ..
+ if(0!=(res=OMXToolBasicAV_WaitForState(pOMXAV, OMX_StateLoaded))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Loaded Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ if (pOMXAV->audioPort != -1)
+ {
+ if(0!=(res=AttachAudioRenderer(pOMXAV))) {
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return; // exception thrown
+ }
+ }
+
+ if (pOMXAV->videoPort != -1)
+ {
+ if(0!=(res=AttachVideoRenderer(pOMXAV))) {
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return; // exception thrown
+ }
+ }
+
+ DBG_PRINT( "Setup tunneling\n");
+ {
+ // do tunneling
+ if (pOMXAV->audioPort != -1)
+ {
+ DBG_PRINT( "Setup tunneling audio\n");
+ OMXSAFEVOID(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_READER], pOMXAV->audioPort, pOMXAV->comp[OMXAV_H_ADECODER], 0));
+ // The rest of the audio port is configured in AttachAudioRenderer
+ }
+
+ if (pOMXAV->videoPort != -1)
+ {
+ DBG_PRINT( "Setup tunneling video\n");
+ OMXSAFEVOID(OMX_SetupTunnel(pOMXAV->comp[OMXAV_H_READER], pOMXAV->videoPort, pOMXAV->comp[OMXAV_H_VDECODER], 0));
+ // The rest of the video port is configured in AttachVideoRenderer
+ }
+ }
+ DBG_PRINT( "ActivateStream .. %p\n", pOMXAV);
+
+ //
+ // mandatory: wait until all devices are idle
+ // failure means not all necessary ports/buffer are set.
+ //
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE)))
+ {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Wait for Idle Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ pOMXAV->status=OMXAV_STOPPED;
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ DBG_PRINT( "ActivateStream done %p\n", pOMXAV);
+}
+
+void OMXToolBasicAV_DetachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ (void) DetachVideoRenderer(pOMXAV);
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+void OMXToolBasicAV_AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV) {
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ (void) AttachVideoRenderer(pOMXAV);
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+void OMXToolBasicAV_SetPlaySpeed(OMXToolBasicAV_t * pOMXAV, KDfloat32 scale)
+{
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ if(!SetClockScale(pOMXAV, scale)) {
+ pOMXAV->play_speed=scale;
+ }
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+
+void OMXToolBasicAV_PlayStart(OMXToolBasicAV_t * pOMXAV)
+{
+ int res;
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ if(pOMXAV->status==OMXAV_PLAYING) {
+ return;
+ }
+
+ kdThreadMutexLock(pOMXAV->mutex);
+ DBG_PRINT( "Play 2\n");
+
+ SetClockScale(pOMXAV, pOMXAV->play_speed);
+
+ DBG_PRINT( "Play 3.1\n");
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateExecuting, KD_TRUE))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Play Execute Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ if(pOMXAV->status==OMXAV_STOPPED || pOMXAV->status==OMXAV_FIN) {
+ DBG_PRINT( "Play 3.2\n");
+ if(StartClock(pOMXAV, KD_TRUE, 0.0)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Play StartClock Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ }
+ DBG_PRINT( "Play 4.0\n");
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ pOMXAV->status=OMXAV_PLAYING;
+ DBG_PRINT( "Play DONE\n");
+}
+
+static int PlayStop(OMXToolBasicAV_t * pOMXAV)
+{
+ int res;
+ if(NULL==pOMXAV || pOMXAV->status<=OMXAV_INIT) {
+ return -1;
+ }
+ if( pOMXAV->status!=OMXAV_PLAYING && pOMXAV->status!=OMXAV_PAUSED ) {
+ return -1;
+ }
+
+ if(OMXToolBasicAV_CheckState(pOMXAV, OMX_StateLoaded)) {
+ if(StartClock(pOMXAV, KD_FALSE, 0.0)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Stop StopClock Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return -1;
+ }
+ if(OMXToolBasicAV_CheckState(pOMXAV, OMX_StateIdle)) {
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateIdle, KD_TRUE))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Stop Idle Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return res;
+ }
+ }
+ }
+ pOMXAV->status=OMXAV_STOPPED;
+ return 0;
+}
+
+void OMXToolBasicAV_PlayStop(OMXToolBasicAV_t * pOMXAV)
+{
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ (void) PlayStop(pOMXAV);
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+void OMXToolBasicAV_PlayPause(OMXToolBasicAV_t * pOMXAV)
+{
+ int res;
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ if(pOMXAV->status==OMXAV_PAUSED || pOMXAV->status!=OMXAV_PLAYING) {
+ return;
+ }
+
+ kdThreadMutexLock(pOMXAV->mutex);
+ SetClockScale(pOMXAV, 0);
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StatePause, KD_TRUE))) {
+ fprintf(stderr, "Err: Pause Pause Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ pOMXAV->status=OMXAV_PAUSED;
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+void OMXToolBasicAV_PlaySeek(OMXToolBasicAV_t * pOMXAV, KDfloat32 time)
+{
+ int res;
+
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ pOMXAV->length = GetMediaLength(pOMXAV);
+ if(pOMXAV->length<=time) {
+ (void) PlayStop(pOMXAV);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ // 1. Pause the component through the use of OMX_SendCommand requesting a
+ // state transition to OMX_StatePause.
+ if(pOMXAV->status!=OMXAV_PAUSED) {
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StatePause, KD_TRUE))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Pause Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ }
+
+ // 2. Stop the comp[OMXAV_H_CLOCK] component’s media comp[OMXAV_H_CLOCK] through the use of OMX_SetConfig
+ // on OMX_TIME_CONFIG_CLOCKSTATETYPE requesting a transition to
+ // OMX_TIME_ClockStateStopped.
+ if(StartClock(pOMXAV, KD_FALSE, 0.0)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek StopClock Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ // 3. Seek to the desired location through the use of OMX_SetConfig on
+ // OMX_IndexConfigTimePosition requesting the desired timestamp.
+ if(SetMediaPosition(pOMXAV, time)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek position Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ // 4. Flush all components.
+ if(SendCommand(pOMXAV, OMX_CommandFlush, OMX_ALL, 0)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Flush Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ // 5. Start the comp[OMXAV_H_CLOCK] component’s media comp[OMXAV_H_CLOCK] through the use of OMX_SetConfig
+ // on OMX_TIME_CONFIG_CLOCKSTATETYPE requesting a transition to either
+ // OMX_TIME_ClockStateRunning or
+ // OMX_TIME_ClockStateWaitingForStartTime.
+ if(StartClock(pOMXAV, KD_TRUE, time)) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek StartClock Failed");
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+
+ // 6. Un-pause the component through the use of OMX_SendCommand requesting a
+ // state transition to OMX_StateExecuting.
+ if(pOMXAV->status==OMXAV_PLAYING) {
+ if(0!=(res=OMXToolBasicAV_RequestState(pOMXAV, OMX_StateExecuting, KD_TRUE))) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "Seek Execute Failed (%d)", res);
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return;
+ }
+ }
+ kdThreadMutexUnlock(pOMXAV->mutex);
+}
+
+GLuint OMXToolBasicAV_GetNextTextureID(OMXToolBasicAV_t * pOMXAV) {
+ GLuint texID = 0;
+ int ret = pOMXAV->glPos;
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ if(pOMXAV->status==OMXAV_PLAYING) {
+ int next = (pOMXAV->omxPos + 1) % pOMXAV->vBufferNum;
+
+ DBG_PRINT2("GetNextTexture A avail %d, filled %d, pos o:%d g:%d\n",
+ pOMXAV->available, pOMXAV->filled, pOMXAV->omxPos, pOMXAV->glPos);
+
+ while (pOMXAV->filled < pOMXAV->vBufferNum)
+ {
+ int attr;
+ if ( !_hasEGLSync || (
+ eglGetSyncAttribKHR(pOMXAV->buffers[pOMXAV->omxPos].sync, EGL_SYNC_STATUS_KHR, &attr) &&
+ attr == EGL_SIGNALED_KHR )
+ )
+ {
+ DBG_PRINT2( "GetNextTexture p2.1 attr 0x%X\n", attr);
+ // OpenGL has finished rendering with this texture, so we are free
+ // to make OpenMAX IL fill it with new data.
+ OMX_FillThisBuffer(pOMXAV->comp[OMXAV_H_VSCHEDULER], pOMXAV->buffers[pOMXAV->omxPos].omxBufferHeader);
+ DBG_PRINT2( "GetNextTexture p2.2\n");
+ pOMXAV->omxPos = next;
+ next = (pOMXAV->omxPos + 1) % pOMXAV->vBufferNum;
+ pOMXAV->filled++;
+ }
+ else
+ {
+ DBG_PRINT2( "GetNextTexture p2.3\n");
+ break;
+ }
+ }
+ }
+ if (pOMXAV->available > 1)
+ {
+ DBG_PRINT2("GetNextTexture p3.1\n");
+ // We want to make sure that the previous eglImage
+ // has finished, so insert a fence command into the
+ // command stream to make sure that any rendering using
+ // the previous eglImage has finished.
+ //
+ // Only move on to rendering the next image if the insertion
+ // was successfull.
+ if (!_hasEGLSync || eglFenceKHR(pOMXAV->buffers[pOMXAV->glPos].sync))
+ {
+ DBG_PRINT2( "GetNextTexture p3.2\n");
+ pOMXAV->available--;
+ pOMXAV->filled--;
+ pOMXAV->glPos = (pOMXAV->glPos + 1) % pOMXAV->vBufferNum;
+ ret = pOMXAV->glPos;
+ }
+ }
+
+ texID = pOMXAV->available ? pOMXAV->buffers[ret].tex : 0;
+ DBG_PRINT2( "GetNextTexture B avail %d, filled %d, pos o:%d g:%d t:%d\n",
+ pOMXAV->available, pOMXAV->filled, pOMXAV->omxPos, pOMXAV->glPos, texID);
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+ return texID;
+}
+
+KDfloat32 OMXToolBasicAV_GetCurrentPosition(OMXToolBasicAV_t * pOMXAV) {
+ KDfloat32 res = -1.0f;
+ if(NULL==pOMXAV) {
+ java_throwNewRuntimeException(0, "OMX instance null\n");
+ return res;
+ }
+ if(pOMXAV->status<=OMXAV_INIT) {
+ java_throwNewRuntimeException(pOMXAV->jni_env, "OMX invalid status: %d <= INIT\n", pOMXAV->status);
+ return res;
+ }
+ kdThreadMutexLock(pOMXAV->mutex);
+
+ res = GetClockPosition(pOMXAV);
+
+ kdThreadMutexUnlock(pOMXAV->mutex);
+
+ return res;
+}
+
+void OMXToolBasicAV_DestroyInstance(OMXToolBasicAV_t * pOMXAV)
+{
+ if(NULL==pOMXAV) return;
+
+ kdThreadMutexLock(pOMXAV->mutex);
+ DestroyInstanceUnlock(pOMXAV);
+}
+
+#if defined(SELF_TEST)
+
+#include <KD/NV_extwindowprops.h>
+
+static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+
+int ModuleTest()
+{
+ int i;
+ OMXToolBasicAV_t * pOMXAV = NULL;
+ GLuint tex; EGLImageKHR image; EGLSyncKHR sync;
+ KDchar file[512];
+ EGLint attrib = EGL_NONE;
+
+#if 0
+ const EGLint s_configAttribs[] = {
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, 1,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+#else
+ const EGLint s_configAttribs[] = {
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, 16,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+#endif
+
+ const EGLint contextAttrs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ EGLint numConfigs;
+ EGLint majorVersion;
+ EGLint minorVersion;
+
+ EGLint sWidth, sHeight;
+
+ EGLDisplay eglDisplay;
+ EGLConfig eglConfig;
+ EGLContext eglContext;
+ EGLSurface eglWindowSurface;
+ KDWindow *kdWindow;
+ NativeWindowType ntWindow;
+
+// KDint wSize[2];
+
+ /*
+ * EGL initialisation.
+ */
+
+ eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(eglDisplay, &majorVersion, &minorVersion);
+ eglChooseConfig(eglDisplay, s_configAttribs, &eglConfig, 1, &numConfigs);
+ kdWindow = kdCreateWindow(eglDisplay, eglConfig, KD_NULL);
+
+ {
+ /* Set fullscreen mode */
+ KDboolean fullscreen = KD_TRUE;
+ kdSetWindowPropertybv(kdWindow,
+ KD_WINDOWPROPERTY_FULLSCREEN_NV, &fullscreen);
+ }
+
+ kdRealizeWindow(kdWindow, &ntWindow);
+
+ eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttrs);
+
+ eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglConfig, ntWindow, KD_NULL);
+ eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
+
+ printf("EGL Extensions : %s\n",eglQueryString(eglDisplay, EGL_EXTENSIONS));
+ printf("EGL CLIENT APIs: %s\n",eglQueryString(eglDisplay, EGL_CLIENT_APIS));
+
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH , &sWidth);
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT , &sHeight);
+
+ /* Set up the viewport and perspective. */
+ printf("screen dim %dx%d\n", sWidth, sHeight);
+ glViewport(0, 0, sWidth, sHeight);
+
+ /*
+ if (argc == 2)
+ kdStrcpy_s(file, 512, argv[1]);
+ else */
+ kdStrcpy_s(file, 512, "/Storage Card/resources/videoplayer/Luna_800x480_1_5M_H264.mp4");
+
+ if( OMXToolBasicAV_IsFileValid(file) ) {
+ fprintf(stderr, "File is invalid");
+ return -1;
+ }
+
+ GETEXTENSION(PFNEGLDESTROYIMAGEKHRPROC, eglDestroyImageKHR);
+
+ pOMXAV = OMXToolBasicAV_CreateInstance(3);
+ if(OMXToolBasicAV_SetStream(pOMXAV, file)) {
+ return -1;
+ }
+ printf("movie dim %dx%d\n", pOMXAV->width, pOMXAV->height);
+
+ glActiveTexture(GL_TEXTURE0);
+ printf("i1: 0x%X\n", glGetError());
+ glEnable(GL_TEXTURE_2D);
+ printf("i2: 0x%X\n", glGetError());
+
+ for (i = 0; i < 3; i++)
+ {
+ printf("0: 0x%X\n", glGetError());
+ glGenTextures(1, &tex);
+ printf("1: tex: %d, e 0x%X\n", tex, glGetError());
+ glBindTexture(GL_TEXTURE_2D, tex);
+ printf("2: 0x%X\n", glGetError());
+
+ // create space for buffer with a texture
+ glTexImage2D(
+ GL_TEXTURE_2D, // target
+ 0, // level
+ GL_RGBA, // internal format
+ pOMXAV->width, // width
+ pOMXAV->height, // height
+ 0, // border
+ GL_RGBA, // format
+ GL_UNSIGNED_BYTE, // type
+ NULL); // pixels -- will be provided later
+ printf("3: 0x%X\n", glGetError());
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ printf("4: 0x%X\n", glGetError());
+
+ // create EGLImage from texture
+ image = eglCreateImageKHR(
+ eglDisplay,
+ eglContext,
+ EGL_GL_TEXTURE_2D_KHR,
+ (EGLClientBuffer)(tex),
+ &attrib);
+ if (!image)
+ {
+ printf("eglGetError: 0x%x\n", eglGetError());
+ printf("ERROR creating EglImage\n");
+ return -1;
+ }
+ printf("5 eglGetError: 0x%x\n", eglGetError());
+
+ sync = eglCreateFenceSyncKHR(
+ eglDisplay, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR, &attrib);
+
+ printf("6 eglGetError: 0x%x\n", eglGetError());
+
+ if(OMXToolBasicAV_SetStreamEGLImageTexture2D(pOMXAV, i, tex, image, sync)) {
+ return -1;
+ }
+ }
+
+ printf("7\n");
+ if( OMXToolBasicAV_ActivateStream(pOMXAV) ) {
+ return -1;
+ }
+
+ printf("8\n");
+ if( OMXToolBasicAV_PlayStart(pOMXAV) ) {
+ return -1;
+ }
+
+ printf("8.2\n");
+
+ i = 0;
+ while (i++ < 10) {
+ glClear(GL_COLOR_BUFFER_BIT);
+ // set uniforms
+ // set attributes
+ // draw arrays ..
+ eglSwapBuffers(eglDisplay, eglWindowSurface);
+ printf("Sleep %d\n", i);
+ usleep(1000);
+ }
+
+ printf("9\n");
+ if( OMXToolBasicAV_PlayStop(pOMXAV) ) {
+ fprintf(stderr, "Err: Stop");
+ return -1;
+ }
+ printf("A1\n");
+ OMXToolBasicAV_DetachVideoRenderer(pOMXAV); // Stop before ..
+
+ printf("A2\n");
+ OMXToolBasicAV_AttachVideoRenderer(pOMXAV); // DetachVideoRenderer before ..
+
+ printf("B\n");
+ OMXToolBasicAV_DestroyInstance(pOMXAV);
+
+ printf("C\n");
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglWindowSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+
+ printf("D\n");
+ kdDestroyWindow(kdWindow);
+
+ printf("E\n");
+ eglTerminate(eglDisplay);
+ printf("F\n");
+ eglReleaseThread();
+
+ return 0;
+}
+
+KDint kdMain(KDint argc, const KDchar *const *argv)
+// int main(int argc, const char *const *argv)
+{
+ return ModuleTest();
+}
+#endif
+