/*------------------------------------------------------------------------------ | OpenMAXILTextureLoader::instantiateTexture +-----------------------------------------------------------------------------*/ OMX_TextureData* OMX_TextureProviderQQuickItem::instantiateTexture(QSize size) { EGLDisplay eglDisplay = get_egl_display(); EGLContext eglContext = get_egl_context(); EGLint attr[] = {EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE}; GLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // It seems that only 4byte pixels is supported here. GLubyte* pixel = new GLubyte[size.width()*size.height()*4]; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel); EGLImageKHR eglImage = eglCreateImageKHR( eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)textureId, attr ); EGLint eglErr = eglGetError(); if (eglErr != EGL_SUCCESS) { LOG_ERROR(LOG_TAG, "Failed to create KHR image: %d.", eglErr); return 0; } OMX_TextureData* textureData = new OMX_TextureData; textureData->m_textureId = textureId; textureData->m_textureData = pixel; textureData->m_eglImage = eglImage; textureData->m_textureSize = size; return textureData; }
OMX_VideoGraph::OMX_VideoGraph( OMX_TextureProvider* provider, QObject* parent ) : m_eglDisplay(get_egl_display()), m_eglContext(get_egl_context()), m_provider(provider), m_eglBuffer(NULL), m_texture(m_eglDisplay), port_settings_changed(0), first_packet(1), fillCalled(false) { // Get core. // TODO: Init of core must be changed. m_core = OMX_Core::instance(); if (!m_core) throw OMX_Exception("Failed to init core."); // Create the components. LOG_VERBOSE(LOG_TAG, "Instantiating components..."); compEGLRender = OMXComponentFactory<MyEGLRenderer>::getInstance( "OMX.broadcom.egl_render" ); compDecoder = OMXComponentFactory<OMXComponent>::getInstance( "OMX.broadcom.video_decode" ); compClock = OMXComponentFactory<OMXComponent>::getInstance( "OMX.broadcom.clock" ); compScheduler = OMXComponentFactory<OMXComponent>::getInstance( "OMX.broadcom.video_scheduler" ); if (!(compEGLRender && compDecoder && compClock && compScheduler)) throw OMX_Exception("Failed to create component."); // Disable all ports. It is necessary to do it here because otherwise // I'll not be able to make the components switch to IDLE state. LOG_VERBOSE(LOG_TAG, "Disabling all the ports..."); compEGLRender->sendCommand(OMX_CommandPortDisable, 220, NULL); compEGLRender->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, 220, TIMEOUT_MS); compEGLRender->sendCommand(OMX_CommandPortDisable, 221, NULL); compEGLRender->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, 221, TIMEOUT_MS); compDecoder->sendCommand(OMX_CommandPortDisable, 130, NULL); compDecoder->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, 130, TIMEOUT_MS); compDecoder->sendCommand(OMX_CommandPortDisable, 131, NULL); compDecoder->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, 131, TIMEOUT_MS); for (int i = 80; i <= 85; i++) { compClock->sendCommand(OMX_CommandPortDisable, i, NULL); compClock->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, i, TIMEOUT_MS); } for (int i = 10; i <= 12; i++) { compScheduler->sendCommand(OMX_CommandPortDisable, i, NULL); compScheduler->waitForEvent(OMX_EventCmdComplete, OMX_CommandPortDisable, i, TIMEOUT_MS); } LOG_VERBOSE(LOG_TAG, "All the ports were disabled."); // Setup clock. LOG_VERBOSE(LOG_TAG, "Setting params."); OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; compClock->SetParameter(OMX_IndexConfigTimeClockState, &cstate); // Setup the tunnels. tunnelDecSched = new OMXTunnel( compDecoder.get(), OMXCompVideoDecoder::outputPort, compScheduler.get(), OMXCompVideoScheduler::inputVideoPort ); tunnelSchedRender = new OMXTunnel( compScheduler.get(), OMXCompVideoScheduler::outputPort, compEGLRender.get(), 220 ); tunnelClockSched = new OMXTunnel( compClock.get(), 80, compScheduler.get(), OMXCompVideoScheduler::inputClockPort ); LOG_VERBOSE(LOG_TAG, "Setting up tunnel clock/scheduler."); tunnelClockSched->setupTunnel(0, 0); compClock->sendCommand(OMX_CommandStateSet, OMX_StateExecuting, NULL); compDecoder->sendCommand(OMX_CommandStateSet, OMX_StateIdle, NULL); LOG_VERBOSE(LOG_TAG, "Setting input parameters."); OMX_VIDEO_PARAM_PORTFORMATTYPE format; memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); format.nVersion.nVersion = OMX_VERSION; format.nPortIndex = 130; format.eCompressionFormat = OMX_VIDEO_CodingAVC; compDecoder->SetParameter(OMX_IndexParamVideoPortFormat, &format); OMX_NALSTREAMFORMATTYPE nalFormat; OMX_INIT_STRUCTURE(nalFormat); nalFormat.nPortIndex = 130; //assert(OMX_GetParameter(compDecoder->GetHandle(), , &nalFormat) == OMX_ErrorNone); //compDecoder->GetParameter(OMX_IndexParamNalStreamFormatSupported, &nalFormat); nalFormat.eNaluFormat = OMX_NaluFormatOneNaluPerBuffer; compDecoder->SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalFormat); //assert(false); // Provide buffers and enabled the port. compDecoder->enablePortBuffers(130); LOG_VERBOSE(LOG_TAG, "Changing decoder state to executing."); compDecoder->sendCommand(OMX_CommandStateSet, OMX_StateExecuting, NULL); }