bool COMXImage::Decode(unsigned width, unsigned height) { std::string componentName = ""; bool m_firstFrame = true; unsigned int demuxer_bytes = 0; const uint8_t *demuxer_content = NULL; OMX_ERRORTYPE omx_err = OMX_ErrorNone; OMX_BUFFERHEADERTYPE *omx_buffer = NULL; OMX_INIT_STRUCTURE(m_decoded_format); CSingleLock lock(g_OMXSection); if(!m_image_buffer) { CLog::Log(LOGERROR, "%s::%s no input buffer\n", CLASSNAME, __func__); return false; } if(GetCompressionFormat() == OMX_IMAGE_CodingMax) { CLog::Log(LOGERROR, "%s::%s error unsupported image format\n", CLASSNAME, __func__); return false; } if(IsProgressive()) { CLog::Log(LOGWARNING, "%s::%s progressive images not supported by decoder\n", CLASSNAME, __func__); return false; } if(!m_is_open) { CLog::Log(LOGERROR, "%s::%s error not opened\n", CLASSNAME, __func__); return false; } componentName = "OMX.broadcom.image_decode"; if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) { CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize\n", CLASSNAME, __func__); return false; } componentName = "OMX.broadcom.resize"; if(!m_omx_resize.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) { CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__); return false; } m_decoder_open = true; m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort()); omx_err = m_omx_tunnel_decode.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish\n", CLASSNAME, __func__); return false; } if(width == 0 || height == 0) { #ifndef STANDALONE height = g_advancedSettings.m_imageRes; if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes) { // a separate fanart resolution is specified - check if the image is exactly equal to this res if (m_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 && m_height == (unsigned int)g_advancedSettings.m_fanartRes) { // special case for fanart res height = g_advancedSettings.m_fanartRes; } } width = height * 16/9; if(!width || !height) { //width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iScreenWidth; //height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iScreenHeight; width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iWidth; height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iHeight; } #else width = 2048; height = 2048; #endif } OMX_PARAM_PORTDEFINITIONTYPE port_def; OMX_INIT_STRUCTURE(port_def); port_def.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } port_def.format.image.eCompressionFormat = GetCompressionFormat(); port_def.format.image.eColorFormat = OMX_COLOR_FormatUnused; port_def.format.image.nFrameWidth = 0; port_def.format.image.nFrameHeight = 0; port_def.format.image.nStride = 0; port_def.format.image.nSliceHeight = 0; port_def.format.image.bFlagErrorConcealment = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_decoder.AllocInputBuffers(); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } OMX_INIT_STRUCTURE(port_def); port_def.nPortIndex = m_omx_resize.GetOutputPort(); omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; port_def.format.image.eColorFormat = OMX_COLOR_Format32bitARGB8888; port_def.format.image.nFrameWidth = (width + 15)&~15; port_def.format.image.nFrameHeight = (height + 15)&~15; port_def.format.image.nStride = 0; port_def.format.image.nSliceHeight = 0; port_def.format.image.bFlagErrorConcealment = OMX_FALSE; omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_resize.AllocOutputBuffers(); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.AllocOutputBuffers result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } demuxer_bytes = GetImageSize(); demuxer_content = GetImageBuffer(); if(!demuxer_bytes || !demuxer_content) return false; m_firstFrame = true; while(demuxer_bytes > 0) { omx_buffer = m_omx_decoder.GetInputBuffer(1000); if(omx_buffer == NULL) return false; omx_buffer->nOffset = omx_buffer->nFlags = 0; omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); demuxer_content += omx_buffer->nFilledLen; demuxer_bytes -= omx_buffer->nFilledLen; if(demuxer_bytes == 0) omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); break; } if(m_firstFrame) { m_firstFrame = false; m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), false); m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), false); OMX_PARAM_PORTDEFINITIONTYPE port_image; OMX_INIT_STRUCTURE(port_image); port_image.nPortIndex = m_omx_decoder.GetOutputPort(); m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_image); port_image.nPortIndex = m_omx_resize.GetInputPort(); m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_image); m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), false); omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged); if(omx_err == OMX_ErrorStreamCorrupt) { CLog::Log(LOGERROR, "%s::%s image not unsupported\n", CLASSNAME, __func__); return false; } m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), false); omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged); if(omx_err == OMX_ErrorStreamCorrupt) { CLog::Log(LOGERROR, "%s::%s image not unsupported\n", CLASSNAME, __func__); return false; } } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventBufferFlag, 1000); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } m_decoded_buffer = m_omx_resize.GetOutputBuffer(); if(!m_decoded_buffer) { CLog::Log(LOGERROR, "%s::%s no output buffer\n", CLASSNAME, __func__); return false; } omx_err = m_omx_resize.FillThisBuffer(m_decoded_buffer); omx_err = m_omx_resize.WaitForEvent(OMX_EventBufferFlag, 1000); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } m_decoded_format.nPortIndex = m_omx_resize.GetOutputPort(); omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &m_decoded_format); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } m_omx_tunnel_decode.Deestablish(); return true; }
bool COMXImage::Decode(unsigned width, unsigned height) { CSingleLock lock(g_OMXSection); std::string componentName = ""; unsigned int demuxer_bytes = 0; const uint8_t *demuxer_content = NULL; OMX_ERRORTYPE omx_err = OMX_ErrorNone; OMX_BUFFERHEADERTYPE *omx_buffer = NULL; if(!m_image_buffer) { CLog::Log(LOGERROR, "%s::%s no input buffer\n", CLASSNAME, __func__); return false; } if(GetCompressionFormat() == OMX_IMAGE_CodingMax) { CLog::Log(LOGERROR, "%s::%s error unsupported image format\n", CLASSNAME, __func__); return false; } if(IsProgressive()) { CLog::Log(LOGWARNING, "%s::%s progressive images not supported by decoder\n", CLASSNAME, __func__); return false; } if(!m_is_open) { CLog::Log(LOGERROR, "%s::%s error not opened\n", CLASSNAME, __func__); return false; } componentName = "OMX.broadcom.image_decode"; if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) { CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize\n", CLASSNAME, __func__); return false; } componentName = "OMX.broadcom.resize"; if(!m_omx_resize.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) { CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__); return false; } m_decoder_open = true; if(width == 0 || height == 0) { height = g_advancedSettings.m_imageRes; if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes) { // a separate fanart resolution is specified - check if the image is exactly equal to this res if (m_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 && m_height == (unsigned int)g_advancedSettings.m_fanartRes) { // special case for fanart res height = g_advancedSettings.m_fanartRes; } } width = height * 16/9; if(!width || !height) { width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iWidth; height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iHeight; } } ClampLimits(width, height); // set input format OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat; OMX_INIT_STRUCTURE(imagePortFormat); imagePortFormat.nPortIndex = m_omx_decoder.GetInputPort(); imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamImagePortFormat, &imagePortFormat); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter OMX_IndexParamImagePortFormat result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_decoder.AllocInputBuffers(); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } demuxer_bytes = GetImageSize(); demuxer_content = GetImageBuffer(); if(!demuxer_bytes || !demuxer_content) return false; while(demuxer_bytes > 0 || !m_decoded_buffer) { long timeout = 0; if (demuxer_bytes) { omx_buffer = m_omx_decoder.GetInputBuffer(1000); if(omx_buffer == NULL) return false; omx_buffer->nOffset = omx_buffer->nFlags = 0; omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); demuxer_content += omx_buffer->nFilledLen; demuxer_bytes -= omx_buffer->nFilledLen; if(demuxer_bytes == 0) omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } } else { // we've submitted all buffers so can wait now timeout = 1000; } omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, timeout); if(omx_err == OMX_ErrorNone) { if (!HandlePortSettingChange(width, height)) { CLog::Log(LOGERROR, "%s::%s HandlePortSettingChange() failed\n", CLASSNAME, __func__); return false; } } // we treat it as an error if a real timeout occurred else if (timeout) { CLog::Log(LOGERROR, "%s::%s HandlePortSettingChange() failed\n", CLASSNAME, __func__); return false; } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventBufferFlag, 1000); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_decoder.WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err); return false; } m_omx_tunnel_decode.Deestablish(); if(m_omx_decoder.BadState()) return false; return true; }