bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, float display_aspect, bool deinterlace, bool hdmi_clock_sync, void* boblight_instance, int boblight_sizedown, int boblight_margin, int boblight_timeout) { OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; //copy boblight parameter m_boblight_sizedown = boblight_sizedown; m_boblight_margin = boblight_margin; COMXVideo::m_boblight = boblight_instance; COMXVideo::m_boblight_timeout = boblight_timeout; if(!m_decoded_width || !m_decoded_height) return false; m_converter = new CBitstreamConverter(); m_video_convert = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, false); if(m_video_convert) { if(m_converter->GetExtraData() != NULL && m_converter->GetExtraSize() > 0) { m_extrasize = m_converter->GetExtraSize(); m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, m_converter->GetExtraData(), m_converter->GetExtraSize()); } } else { if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: printf("Vcodec id unknown: %x\n", hints.codec); return false; break; } if(deinterlace) { printf("enable deinterlace\n"); m_deinterlace = true; } else { m_deinterlace = false; } std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) return false; if(COMXVideo::m_boblight){ componentName = "OMX.broadcom.video_splitter"; if(!m_omx_split.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.resize"; if(!m_omx_resize.Initialize(componentName, OMX_IndexParamImageInit)) return false; } if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize(componentName, OMX_IndexParamImageInit)) return false; } componentName = "OMX.broadcom.text_scheduler"; if(!m_omx_text.Initialize(componentName, OMX_IndexParamOtherInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } if(COMXVideo::m_boblight){ m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_split, m_omx_split.GetInputPort()); m_omx_tunnel_split.Initialize(&m_omx_split, m_omx_split.GetOutputPort()+1, &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_resize.Initialize(&m_omx_split, m_omx_split.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort()); } else { m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); } m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); m_omx_tunnel_text.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 2, &m_omx_text, m_omx_text.GetInputPort() + 2); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = VIDEO_BUFFERS; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigLatencyTarget error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetInputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nBufferCountActual = 100; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers\n"); return false; } OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetOutputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.eDir = OMX_DirOutput; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.nBufferCountActual = 1; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocOutputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOutputBuffers\n"); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_decoder.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_image_fx.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_image_fx.Establish\n"); return false; } omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_image_fx.SetStateForComponent\n"); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_sched.Establish\n"); return false; } /** omx_err = m_omx_tunnel_write.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_write.Establish\n"); return false; } **/ omx_err = m_omx_text.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_text.SetStateForComponent\n"); return false; } omx_err = m_omx_tunnel_text.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_text.Establish\n"); return false; } OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_text.GetOutputBuffer(); if(!omx_buffer) return false; omx_err = m_omx_text.FillThisBuffer(omx_buffer); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open FillThisBuffer\n"); return false; } omx_buffer = NULL; omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_sched.SetStateForComponent\n"); return false; } if(COMXVideo::m_boblight){ omx_err = m_omx_split.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_split.SetStateForComponent\n"); return false; } //set up the resizer //make sure output of the splitter and input of the resize match OMX_PARAM_PORTDEFINITIONTYPE port_def; OMX_INIT_STRUCTURE(port_def); port_def.nPortIndex = m_omx_split.GetOutputPort(); m_omx_split.GetParameter(OMX_IndexParamPortDefinition, &port_def); port_def.nPortIndex = m_omx_resize.GetInputPort(); m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); omx_err = m_omx_tunnel_resize.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_resize.Establish\n", CLASSNAME, __func__); return false; } omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x\n", CLASSNAME, __func__, omx_err); return false; } port_def.nPortIndex = m_omx_resize.GetOutputPort(); m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def); port_def.nPortIndex = m_omx_resize.GetOutputPort(); port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; port_def.format.image.eColorFormat = OMX_COLOR_Format32bitARGB8888; //calculate the size of the sized-down image if(m_boblight_sizedown%2==1)m_boblight_sizedown--; //make sure we have even dimensions, since resize component requires it float factor; if(m_decoded_width>m_decoded_height){ factor = (float)m_boblight_sizedown / m_decoded_width; }else{ factor = (float)m_boblight_sizedown / m_decoded_height; } port_def.format.image.nFrameWidth = round(factor * m_decoded_width); port_def.format.image.nFrameHeight = round(factor * m_decoded_height); 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; } COMXVideo::m_boblight_width = (int)round(factor * m_decoded_width); COMXVideo::m_boblight_height = (int)round(factor * m_decoded_height); //calculate margins of processed pixels on the outer border of the image COMXVideo::m_boblight_margin_t = (int)round(m_boblight_margin*m_boblight_height/100); COMXVideo::m_boblight_margin_b = m_boblight_height - m_boblight_margin_t; COMXVideo::m_boblight_margin_l = (int)round(m_boblight_margin*m_boblight_width/100); COMXVideo::m_boblight_margin_r = m_boblight_width - m_boblight_margin_l; CLog::Log(LOGDEBUG, "Setting boblight scanrange to %ix%i, scan margin is %i percent\n", COMXVideo::m_boblight_width, COMXVideo::m_boblight_height, m_boblight_margin); boblight_setscanrange(COMXVideo::m_boblight, COMXVideo::m_boblight_width, COMXVideo::m_boblight_height); OMX_PARAM_PORTDEFINITIONTYPE m_decoded_format; OMX_INIT_STRUCTURE(m_decoded_format); 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; } assert(m_decoded_format.nBufferCountActual == 1); 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; } omx_err = m_omx_tunnel_split.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_split.Establish\n"); return false; } omx_err = m_omx_tunnel_resize.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_resize.Establish\n"); return false; } //setting the custom callback to broadcast a signal COMXVideo::Thread is waiting for m_omx_resize.SetCustomDecoderFillBufferDoneHandler(&COMXVideo::BufferDoneHandler); //prepare boblight client thread and start it pthread_cond_init(&COMXVideo::m_boblight_bufferdone_cond, NULL); pthread_mutex_init(&COMXVideo::m_boblight_bufferdone_mutex, NULL); COMXCoreComponent* args[2]; args[0] = &m_omx_split; args[1] = &m_omx_resize; pthread_create(&COMXVideo::m_boblight_clientthread, NULL, &COMXVideo::BoblightClientThread, (void*)&args); } omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_render.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; m_setStartTime = true; m_setStartTimeText = true; // only set aspect when we have a aspect and display doesn't match the aspect if(display_aspect != 0.0f && (hints.aspect != display_aspect)) { OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); AVRational aspect; float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; aspect = av_d2q(fAspect, 100); printf("Aspect : num %d den %d aspect %f display aspect %f\n", aspect.num, aspect.den, hints.aspect, display_aspect); configDisplay.set = OMX_DISPLAY_SET_PIXEL; configDisplay.pixel_x = aspect.num; configDisplay.pixel_y = aspect.den; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; } /* configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 2; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_DEST_RECT; configDisplay.dest_rect.x_offset = 100; configDisplay.dest_rect.y_offset = 100; configDisplay.dest_rect.width = 640; configDisplay.dest_rect.height = 480; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; configDisplay.transform = OMX_DISPLAY_ROT180; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_FULLSCREEN; configDisplay.fullscreen = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_MODE; configDisplay.mode = OMX_DISPLAY_MODE_FILL; //OMX_DISPLAY_MODE_LETTERBOX; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 1; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_ALPHA; configDisplay.alpha = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; */ CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_first_frame = true; m_first_text = true; return true; }
bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, const CRect &DestRect, float display_aspect, int deinterlace, bool hdmi_clock_sync, float fifo_size) { OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_settings_changed = false; m_src_rect.SetRect(0, 0, 0, 0); m_dst_rect = DestRect; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_deinterlace_request = deinterlace; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) return false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP6: case CODEC_ID_VP6F: case CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case CODEC_ID_MJPEG: case CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: printf("Vcodec id unknown: %x\n", hints.codec); return false; break; } std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.text_scheduler"; if(!m_omx_text.Initialize(componentName, OMX_IndexParamOtherInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = fifo_size ? fifo_size * 1024 * 1024 / portParam.nBufferSize : 80; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } // request portsettingschanged on aspect ratio change OMX_CONFIG_REQUESTCALLBACKTYPE notifications; OMX_INIT_STRUCTURE(notifications); notifications.nPortIndex = m_omx_decoder.GetOutputPort(); notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio; notifications.bEnable = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if (m_deinterlace_request != -1) { // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2). OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 3; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. if(hints.ptsinvalid) { OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); return false; } } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_omx_tunnel_text.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 2, &m_omx_text, m_omx_text.GetInputPort() + 2); OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetInputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nBufferCountActual = 100; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers\n"); return false; } OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetOutputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.eDir = OMX_DirOutput; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.nBufferCountActual = 1; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocOutputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOutputBuffers\n"); return false; } omx_err = m_omx_text.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_text.SetStateForComponent\n"); return false; } omx_err = m_omx_tunnel_text.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_text.Establish\n"); return false; } OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_text.GetOutputBuffer(); if(!omx_buffer) return false; omx_err = m_omx_text.FillThisBuffer(omx_buffer); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open FillThisBuffer\n"); return false; } omx_buffer = NULL; m_is_open = true; m_drop_state = false; m_setStartTime = true; m_setStartTimeText = true; CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), deinterlace, m_hdmi_clock_sync); m_first_text = true; // start from assuming all recent frames had valid pts m_history_valid_pts = ~0; float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; m_pixel_aspect = hints.aspect ? fAspect/display_aspect : 0.0f; return true; }
bool OMXEGLImage::Open(COMXStreamInfo &hints, OMXClock *clock) { OMX_ERRORTYPE error = OMX_ErrorNone; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; if(!m_decoded_width || !m_decoded_height) return false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } ProcessCodec(hints); std::string componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.egl_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } if(clock == NULL) { return false; } m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); m_omx_tunnel_sched.Initialize( &m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize( m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); error = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_StateIdle FAIL"; return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } error = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder SET OMX_IndexParamVideoPortFormat PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder GET OMX_IndexParamVideoPortFormat FAIL error: 0x%08x\n", error); return false; } OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); error = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder GET OMX_IndexParamPortDefinition PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder GET OMX_IndexParamPortDefinition FAIL error: 0x%08x\n", error); return false; } ofLogVerbose(__func__) << "portParam.nBufferCountActual GET VAR --------------------------:" << portParam.nBufferCountActual; ofLogVerbose(__func__) << "portParam.format.video.nFrameWidth GET VAR --------------------------:" << portParam.format.video.nFrameWidth; int numVideoBuffers = 80; //20 is minimum - can get up to 80 portParam.nBufferCountActual = numVideoBuffers; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; error = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder SET OMX_IndexParamPortDefinition PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder SET OMX_IndexParamPortDefinition FAIL error: 0x%08x\n", error); return false; } error = m_omx_tunnel_clock.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_clock.Establish FAIL"; return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; error = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment FAIL error: 0x%08x\n", error); return false; } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatOneNaluPerBuffer; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (error == OMX_ErrorNone) { ofLogVerbose() << "Open OMX_IndexParamNalStreamFormatSelect PASS"; }else { ofLog(OF_LOG_ERROR, "Open OMX_IndexParamNalStreamFormatSelect FAIL (0%08x)\n", error); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. if(hints.ptsinvalid) { OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (error == OMX_ErrorNone) { ofLogVerbose() << "Open OMX_IndexParamBrcmVideoTimestampFifo PASS"; }else { ofLog(OF_LOG_ERROR, "Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", error); return false; } } // Alloc buffers for the omx intput port. error = m_omx_decoder.AllocInputBuffers(); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder AllocInputBuffers PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder AllocInputBuffers FAIL error: 0x%08x\n", error); return false; } error = m_omx_tunnel_decoder.Establish(false); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_tunnel_decoder Establish PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_tunnel_decoder Establish FAIL error: 0x%08x\n", error); return false; } error = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder OMX_StateExecuting FAIL error: 0x%08x", error); return false; } error = m_omx_tunnel_sched.Establish(false); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_tunnel_sched Establish PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_tunnel_sched Establish FAIL error: 0x%08x", error); return false; } error = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_sched OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_sched OMX_StateExecuting FAIL error: 0x%08x", error); return false; } error = m_omx_render.SetStateForComponent(OMX_StateIdle); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render OMX_StateIdle PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render OMX_StateIdle FAIL error: 0x%08x", error); return false; } ofLogVerbose() << "m_omx_render.GetOutputPort(): " << m_omx_render.GetOutputPort(); m_omx_render.EnablePort(m_omx_render.GetOutputPort(), false); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render Enable OUTPUT Port PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render Enable OUTPUT Port FAIL error: 0x%08x", error); return false; } error = m_omx_render.UseEGLImage(&eglBuffer, m_omx_render.GetOutputPort(), NULL, GlobalEGLContainer::getInstance().eglImage); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render UseEGLImage PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render UseEGLImage FAIL error: 0x%08x", error); return false; } if(SendDecoderConfig()) { ofLogVerbose() << "SendDecoderConfig PASS"; }else { ofLog(OF_LOG_ERROR, "SendDecoderConfig FAIL"); return false; } m_omx_render.SetCustomDecoderFillBufferDoneHandler(onFillBufferDone); error = m_omx_render.SetStateForComponent(OMX_StateExecuting); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render OMX_StateExecuting FAIL error: 0x%08x", error); return false; } error = m_omx_render.FillThisBuffer(eglBuffer); if(error == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render FillThisBuffer PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render FillThisBuffer FAIL error: 0x%08x", error); if (error == OMX_ErrorIncorrectStateOperation) { ofLogError(__func__) << "NEED EGL HACK"; } return false; } m_is_open = true; m_drop_state = false; m_setStartTime = true; ofLog(OF_LOG_VERBOSE, "%s::%s - decoder_component: 0x%p, input_port: 0x%x, output_port: 0x%x \n", "OMXEGLImage", __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort()); m_first_frame = true; // start from assuming all recent frames had valid pts m_history_valid_pts = ~0; return true; }
bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, bool deinterlace, bool hdmi_clock_sync) { if(m_is_open) Close(); OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) return false; m_converter = new CBitstreamConverter(); m_video_convert = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, false); if(m_video_convert) { if(m_converter->GetExtraData() != NULL && m_converter->GetExtraSize() > 0) { m_extrasize = m_converter->GetExtraSize(); m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, m_converter->GetExtraData(), m_converter->GetExtraSize()); } } else { if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: return false; break; } m_deinterlace = deinterlace; if(m_deinterlace) CLog::Log(LOGDEBUG, "COMXVideo::Open : enable deinterlace\n"); std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; /* OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); OMX_U32 nIndex = 1; bool bFound = false; omx_err = OMX_ErrorNone; do { formatType.nIndex = nIndex; omx_err = m_omx_decoder.GetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(formatType.eCompressionFormat == m_codingType) { bFound = true; break; } nIndex++; } while(omx_err == OMX_ErrorNone); if(!bFound) { CLog::Log(LOGINFO, "COMXVideo::Open coding : %s not supported\n", m_video_codec_name.c_str()); return false; } */ if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = VIDEO_BUFFERS; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); if(g_advancedSettings.m_omxDecodeStartWithValidFrame) concanParam.bStartWithValidFrame = OMX_TRUE; else concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigLatencyTarget error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_decoder.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_image_fx.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_image_fx.Establish\n"); return false; } omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_image_fx.SetStateForComponent\n"); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_sched.Establish\n"); return false; } omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_sched.SetStateForComponent\n"); return false; } omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_render.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; switch(hints.orientation) { case 90: configDisplay.transform = OMX_DISPLAY_ROT90; break; case 180: configDisplay.transform = OMX_DISPLAY_ROT180; break; case 270: configDisplay.transform = OMX_DISPLAY_ROT270; break; default: configDisplay.transform = OMX_DISPLAY_ROT0; break; } omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGWARNING, "COMXVideo::Open could not set orientation : %d\n", hints.orientation); } /* configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 2; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_DEST_RECT; configDisplay.dest_rect.x_offset = 100; configDisplay.dest_rect.y_offset = 100; configDisplay.dest_rect.width = 640; configDisplay.dest_rect.height = 480; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; configDisplay.transform = OMX_DISPLAY_ROT180; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_FULLSCREEN; configDisplay.fullscreen = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_MODE; configDisplay.mode = OMX_DISPLAY_MODE_FILL; //OMX_DISPLAY_MODE_LETTERBOX; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 1; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_ALPHA; configDisplay.alpha = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; */ CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_av_clock->OMXStateExecute(false); m_first_frame = true; return true; }
bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, float display_aspect, bool deinterlace, bool hdmi_clock_sync) { OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) return false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP6: case CODEC_ID_VP6F: case CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case CODEC_ID_MJPEG: case CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: ofLog(OF_LOG_VERBOSE, "Vcodec id unknown: %x\n", hints.codec); return false; break; } if(deinterlace) { ofLog(OF_LOG_VERBOSE, "enable deinterlace\n"); m_deinterlace = true; } else { m_deinterlace = false; } std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) return false; if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize(componentName, OMX_IndexParamImageInit)) return false; } if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); int videoBuffers = 60; portParam.nBufferCountActual = videoBuffers; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if (m_deinterlace) { // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2). OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 3; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. if(hints.ptsinvalid) { OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); return false; } } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err); return false; } } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open OMX_IndexConfigLatencyTarget error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx inpput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open m_omx_tunnel_decoder.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_image_fx.Establish(false); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open m_omx_tunnel_image_fx.Establish\n"); return false; } omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error m_omx_image_fx.SetStateForComponent\n"); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open m_omx_tunnel_sched.Establish\n"); return false; } omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error m_omx_sched.SetStateForComponent\n"); return false; } omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "COMXVideo::Open error m_omx_render.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; m_setStartTime = true; float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; float par = hints.aspect ? fAspect/display_aspect : 0.0f; // only set aspect when we have a aspect and display doesn't match the aspect if(par != 0.0f && fabs(par - 1.0f) > 0.01f) { OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); AVRational aspect; aspect = av_d2q(par, 100); configDisplay.set = OMX_DISPLAY_SET_PIXEL; configDisplay.pixel_x = aspect.num; configDisplay.pixel_y = aspect.den; ofLog(OF_LOG_VERBOSE, "Aspect : num %d den %d aspect %f pixel aspect %f\n", aspect.num, aspect.den, hints.aspect, par); omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; } ofLog(OF_LOG_VERBOSE, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_first_frame = true; return true; }
bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, bool deinterlace, bool hdmi_clock_sync) { bool vflip = false; Close(); OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_res_ctx = NULL; m_res_callback = NULL; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) return false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } /* check interlaced */ if(m_extrasize > 9 && m_extradata[0] == 1) { CBitstreamConverter converter; converter.Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); int32_t max_ref_frames = 0; uint8_t *spc = m_extradata + 6; uint32_t sps_size = BS_RB16(spc); bool interlaced = true; if (sps_size) converter.parseh264_sps(spc+3, sps_size-1, &interlaced, &max_ref_frames); if(!interlaced && deinterlace) deinterlace = false; converter.Close(); } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP6: // this form is encoded upside down vflip = true; // fall through case CODEC_ID_VP6F: case CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case CODEC_ID_MJPEG: case CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: return false; break; } /* enable deintelace on SD and 1080i */ if(m_decoded_width <= 720 && m_decoded_height <=576 && deinterlace) m_deinterlace = deinterlace; else if(m_decoded_width >= 1920 && m_decoded_height >= 540 && deinterlace) m_deinterlace = deinterlace; if(m_deinterlace) CLog::Log(LOGDEBUG, "COMXVideo::Open : enable deinterlace\n"); std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize((const std::string)componentName, OMX_IndexParamVideoInit)) return false; if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize((const std::string)componentName, OMX_IndexParamImageInit)) return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; /* OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); OMX_U32 nIndex = 1; bool bFound = false; omx_err = OMX_ErrorNone; do { formatType.nIndex = nIndex; omx_err = m_omx_decoder.GetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(formatType.eCompressionFormat == m_codingType) { bFound = true; break; } nIndex++; } while(omx_err == OMX_ErrorNone); if(!bFound) { CLog::Log(LOGINFO, "COMXVideo::Open coding : %s not supported\n", m_video_codec_name.c_str()); return false; } */ if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = VIDEO_BUFFERS; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); if(g_advancedSettings.m_omxDecodeStartWithValidFrame) concanParam.bStartWithValidFrame = OMX_TRUE; else concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if (m_deinterlace) { // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2). OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 3; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. if(hints.ptsinvalid) { OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); return false; } } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err); return false; } } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigLatencyTarget error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_decoder.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_image_fx.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_image_fx.Establish\n"); return false; } omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_image_fx.SetStateForComponent\n"); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_sched.Establish\n"); return false; } omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_sched.SetStateForComponent\n"); return false; } omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_render.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; switch(hints.orientation) { case 90: configDisplay.transform = OMX_DISPLAY_ROT90; break; case 180: configDisplay.transform = OMX_DISPLAY_ROT180; break; case 270: configDisplay.transform = OMX_DISPLAY_ROT270; break; default: configDisplay.transform = OMX_DISPLAY_ROT0; break; } if (vflip) configDisplay.transform = OMX_DISPLAY_MIRROR_ROT180; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGWARNING, "COMXVideo::Open could not set orientation : %d\n", hints.orientation); } /* configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 2; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_DEST_RECT; configDisplay.dest_rect.x_offset = 100; configDisplay.dest_rect.y_offset = 100; configDisplay.dest_rect.width = 640; configDisplay.dest_rect.height = 480; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; configDisplay.transform = OMX_DISPLAY_ROT180; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_FULLSCREEN; configDisplay.fullscreen = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_MODE; configDisplay.mode = OMX_DISPLAY_MODE_FILL; //OMX_DISPLAY_MODE_LETTERBOX; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 1; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_ALPHA; configDisplay.alpha = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; */ if(m_omx_decoder.BadState()) return false; CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); // start from assuming all recent frames had valid pts m_history_valid_pts = ~0; return true; }
bool COMXVideo::Open(COMXStreamInfo& hints, OMXClock *clock, float display_aspect, bool deinterlace, bool hdmi_clock_sync) { OMX_ERRORTYPE error = OMX_ErrorNone; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) { return false; } if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } ProcessCodec(hints); if(deinterlace) { ofLog(OF_LOG_VERBOSE, "enable deinterlace\n"); m_deinterlace = true; } else { m_deinterlace = false; } std::string componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize(componentName, OMX_IndexParamImageInit)) { return false; } } if(clock == NULL) { return false; } m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); error = m_omx_tunnel_clock.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_clock Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_StateIdle FAIL: " << COMXCore::getOMXError(error); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } error = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(error != OMX_ErrorNone) { return false; } OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); error = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder Get OMX_IndexParamPortDefinition FAIL: " << COMXCore::getOMXError(error); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); int videoBuffers = 60; portParam.nBufferCountActual = videoBuffers; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; error = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder Set OMX_IndexParamPortDefinition FAIL: " << COMXCore::getOMXError(error); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; error = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment FAIL: " << COMXCore::getOMXError(error); return false; } if (m_deinterlace) { // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2). OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 3; error = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmExtraBuffers FAIL: " << COMXCore::getOMXError(error); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. // recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmVideoTimestampFifo FAIL: " << COMXCore::getOMXError(error); return false; } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamNalStreamFormatSelect FAIL: " << COMXCore::getOMXError(error); return false; } } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; error = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_render OMX_IndexConfigLatencyTarget FAIL: " << COMXCore::getOMXError(error); return false; } } // Alloc buffers for the omx input port. error = m_omx_decoder.AllocInputBuffers(); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder AllocInputBuffers FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_tunnel_decoder.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_decoder Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; error = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx SetConfig FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_tunnel_image_fx.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } error = m_omx_tunnel_sched.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_sched Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_sched OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_render OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } ofAddListener(ofEvents().update, this, &COMXVideo::onUpdate); if(!SendDecoderConfig()) { return false; } m_is_open = true; m_drop_state = false; m_setStartTime = true; OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); //we provided a rectangle but returned early as we were not ready if (displayRect.getWidth()>0) { configureDisplay(); }else { float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; float par = hints.aspect ? fAspect/display_aspect : 0.0f; // only set aspect when we have a aspect and display doesn't match the aspect bool doDisplayChange = true; if(doDisplayChange) { if(par != 0.0f && fabs(par - 1.0f) > 0.01f) { AVRational aspect; aspect = av_d2q(par, 100); configDisplay.set = OMX_DISPLAY_SET_PIXEL; configDisplay.pixel_x = aspect.num; configDisplay.pixel_y = aspect.den; ofLog(OF_LOG_VERBOSE, "Aspect : num %d den %d aspect %f pixel aspect %f\n", aspect.num, aspect.den, hints.aspect, par); error = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(error != OMX_ErrorNone) { return false; } } } } ofLog(OF_LOG_VERBOSE, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", "OMXVideo", __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_first_frame = true; // start from assuming all recent frames had valid pts m_history_valid_pts = ~0; return true; }
bool COMXVideo::Open(OMXClock *clock, const OMXVideoConfig &config) { CSingleLock lock (m_critSection); bool vflip = false; Close(); OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_settings_changed = false; m_setStartTime = true; m_config = config; m_src_rect.SetRect(0, 0, 0, 0); m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_submitted_eos = false; m_failed_eos = false; if(!m_config.hints.width || !m_config.hints.height) return false; switch (m_config.hints.codec) { case AV_CODEC_ID_H264: { switch(m_config.hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } if (m_config.allow_mvc && m_codingType == OMX_VIDEO_CodingAVC) { m_codingType = OMX_VIDEO_CodingMVC; m_video_codec_name = "omx-mvc"; } break; case AV_CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case AV_CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case AV_CODEC_ID_VP6: // this form is encoded upside down vflip = true; // fall through case AV_CODEC_ID_VP6F: case AV_CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case AV_CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case AV_CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: printf("Vcodec id unknown: %x\n", m_config.hints.codec); return false; break; } if(!m_omx_decoder.Initialize(decoder_name, OMX_IndexParamVideoInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (m_config.hints.fpsscale > 0 && m_config.hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*m_config.hints.fpsrate / m_config.hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = m_config.fifo_size ? m_config.fifo_size * 1024 * 1024 / portParam.nBufferSize : 80; portParam.format.video.nFrameWidth = m_config.hints.width; portParam.format.video.nFrameHeight = m_config.hints.height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } // request portsettingschanged on aspect ratio change OMX_CONFIG_REQUESTCALLBACKTYPE notifications; OMX_INIT_STRUCTURE(notifications); notifications.nPortIndex = m_omx_decoder.GetOutputPort(); notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio; notifications.bEnable = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); if(1) concanParam.bStartWithValidFrame = OMX_TRUE; else concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if(NaluFormatStartCodes(m_config.hints.codec, (uint8_t *)m_config.hints.extradata, m_config.hints.extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } SendDecoderConfig(); m_is_open = true; m_drop_state = false; m_setStartTime = true; switch(m_config.hints.orientation) { case 90: m_transform = OMX_DISPLAY_ROT90; break; case 180: m_transform = OMX_DISPLAY_ROT180; break; case 270: m_transform = OMX_DISPLAY_ROT270; break; case 1: m_transform = OMX_DISPLAY_MIRROR_ROT0; break; case 91: m_transform = OMX_DISPLAY_MIRROR_ROT90; break; case 181: m_transform = OMX_DISPLAY_MIRROR_ROT180; break; case 271: m_transform = OMX_DISPLAY_MIRROR_ROT270; break; default: m_transform = OMX_DISPLAY_ROT0; break; } if (vflip) m_transform = OMX_DISPLAY_MIRROR_ROT180; if(m_omx_decoder.BadState()) return false; CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_config.deinterlace, m_config.hdmi_clock_sync); float fAspect = m_config.hints.aspect ? (float)m_config.hints.aspect / (float)m_config.hints.width * (float)m_config.hints.height : 1.0f; m_pixel_aspect = fAspect / m_config.display_aspect; return true; }
bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE deinterlace, bool hdmi_clock_sync) { CSingleLock lock (m_critSection); bool vflip = false; Close(); OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_settings_changed = false; m_setStartTime = true; m_res_ctx = NULL; m_res_callback = NULL; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; m_submitted_eos = false; m_failed_eos = false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } switch (hints.codec) { case AV_CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case AV_CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case AV_CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case AV_CODEC_ID_VP6: // this form is encoded upside down vflip = true; // fall through case AV_CODEC_ID_VP6F: case AV_CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case AV_CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case AV_CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: CLog::Log(LOGERROR, "COMXVideo::Open : Video codec unknown: %x", hints.codec); return false; break; } m_deinterlace_request = deinterlace; if(!m_omx_decoder.Initialize(decoder_name, OMX_IndexParamVideoInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); bool small_mem = g_RBP.GetArmMem() < 256; portParam.nBufferCountActual = small_mem ? VIDEO_BUFFERS:2*VIDEO_BUFFERS; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } // request portsettingschanged on aspect ratio change OMX_CONFIG_REQUESTCALLBACKTYPE notifications; OMX_INIT_STRUCTURE(notifications); notifications.nPortIndex = m_omx_decoder.GetOutputPort(); notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio; notifications.bEnable = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err); return false; } // request portsettingschanged on refresh rate change if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_ALWAYS) { notifications.nIndex = OMX_IndexParamPortDefinition; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err); //return false; } } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); if(g_advancedSettings.m_omxDecodeStartWithValidFrame) concanParam.bStartWithValidFrame = OMX_TRUE; else concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. // recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable { OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); return false; } } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; switch(hints.orientation) { case 90: m_transform = OMX_DISPLAY_ROT90; break; case 180: m_transform = OMX_DISPLAY_ROT180; break; case 270: m_transform = OMX_DISPLAY_ROT270; break; default: m_transform = OMX_DISPLAY_ROT0; break; } if (vflip) m_transform = OMX_DISPLAY_MIRROR_ROT180; if(m_omx_decoder.BadState()) return false; CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace_request, m_hdmi_clock_sync); return true; }
bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, float display_aspect, bool deinterlace, bool hdmi_clock_sync) { OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) return false; m_converter = new CBitstreamConverter(); m_video_convert = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, false); if(m_video_convert) { if(m_converter->GetExtraData() != NULL && m_converter->GetExtraSize() > 0) { m_extrasize = m_converter->GetExtraSize(); m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, m_converter->GetExtraData(), m_converter->GetExtraSize()); } } else { if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: printf("Vcodec id unknown: %x\n", hints.codec); return false; break; } if(m_decoded_width <= 720 && m_decoded_height <=576 && deinterlace) { printf("enable deinterlace\n"); m_deinterlace = true; } else { m_deinterlace = false; } std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) return false; if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize(componentName, OMX_IndexParamImageInit)) return false; } componentName = "OMX.broadcom.text_scheduler"; if(!m_omx_text.Initialize(componentName, OMX_IndexParamOtherInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); m_omx_tunnel_text.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 2, &m_omx_text, m_omx_text.GetInputPort() + 2); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); portParam.nBufferCountActual = VIDEO_BUFFERS; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err); return false; } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigLatencyTarget error (0%08x)\n", omx_err); return false; } } // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err); return false; } OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetInputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.nBufferCountActual = 100; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocInputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers\n"); return false; } OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_text.GetOutputPort(); omx_err = m_omx_text.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } portParam.eDir = OMX_DirOutput; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.format.other.eFormat = OMX_OTHER_FormatText; portParam.nBufferCountActual = 1; portParam.nBufferSize = MAX_TEXT_LENGTH; omx_err = m_omx_text.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_text.AllocOutputBuffers(); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open AllocOutputBuffers\n"); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_decoder.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n"); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_image_fx.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_image_fx.Establish\n"); return false; } omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_image_fx.SetStateForComponent\n"); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_sched.Establish\n"); return false; } omx_err = m_omx_text.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_text.SetStateForComponent\n"); return false; } omx_err = m_omx_tunnel_text.Establish(false); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open m_omx_tunnel_text.Establish\n"); return false; } OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_text.GetOutputBuffer(10); if(!omx_buffer) return false; omx_err = m_omx_text.FillThisBuffer(omx_buffer); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open FillThisBuffer\n"); return false; } omx_buffer = NULL; omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_sched.SetStateForComponent\n"); return false; } omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_render.SetStateForComponent\n"); return false; } if(!SendDecoderConfig()) return false; m_is_open = true; m_drop_state = false; m_setStartTime = true; m_setStartTimeText = true; // only set aspect when we have a aspect and display doesn't match the aspect if(display_aspect != 0.0f && (hints.aspect != display_aspect)) { OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); AVRational aspect; float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; aspect = av_d2q(fAspect, 100); printf("Aspect : num %d den %d aspect %f display aspect %f\n", aspect.num, aspect.den, hints.aspect, display_aspect); configDisplay.set = OMX_DISPLAY_SET_PIXEL; configDisplay.pixel_x = aspect.num; configDisplay.pixel_y = aspect.den; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; } /* configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 2; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_DEST_RECT; configDisplay.dest_rect.x_offset = 100; configDisplay.dest_rect.y_offset = 100; configDisplay.dest_rect.width = 640; configDisplay.dest_rect.height = 480; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; configDisplay.transform = OMX_DISPLAY_ROT180; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_FULLSCREEN; configDisplay.fullscreen = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_MODE; configDisplay.mode = OMX_DISPLAY_MODE_FILL; //OMX_DISPLAY_MODE_LETTERBOX; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_LAYER; configDisplay.layer = 1; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; configDisplay.set = OMX_DISPLAY_SET_ALPHA; configDisplay.alpha = OMX_FALSE; omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(omx_err != OMX_ErrorNone) return false; */ CLog::Log(LOGDEBUG, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_first_frame = true; m_first_text = true; return true; }
bool OMXEGLImage::Open(COMXStreamInfo &hints, OMXClock *clock, EGLImageKHR eglImage_) { eglImage = eglImage_; OMX_ERRORTYPE omx_err = OMX_ErrorNone; std::string decoder_name; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; if(!m_decoded_width || !m_decoded_height) return false; if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } switch (hints.codec) { case CODEC_ID_H264: { switch(hints.profile) { case FF_PROFILE_H264_BASELINE: // (role name) video_decoder.avc // H.264 Baseline profile decoder_name = OMX_H264BASE_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_MAIN: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264MAIN_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_H264_HIGH: // (role name) video_decoder.avc // H.264 Main profile decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; case FF_PROFILE_UNKNOWN: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; default: decoder_name = OMX_H264HIGH_DECODER; m_codingType = OMX_VIDEO_CodingAVC; m_video_codec_name = "omx-h264"; break; } } break; case CODEC_ID_MPEG4: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-mpeg4"; break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: // (role name) video_decoder.mpeg2 // MPEG-2 decoder_name = OMX_MPEG2V_DECODER; m_codingType = OMX_VIDEO_CodingMPEG2; m_video_codec_name = "omx-mpeg2"; break; case CODEC_ID_H263: // (role name) video_decoder.mpeg4 // MPEG-4, DivX 4/5 and Xvid compatible decoder_name = OMX_MPEG4_DECODER; m_codingType = OMX_VIDEO_CodingMPEG4; m_video_codec_name = "omx-h263"; break; case CODEC_ID_VP6: case CODEC_ID_VP6F: case CODEC_ID_VP6A: // (role name) video_decoder.vp6 // VP6 decoder_name = OMX_VP6_DECODER; m_codingType = OMX_VIDEO_CodingVP6; m_video_codec_name = "omx-vp6"; break; case CODEC_ID_VP8: // (role name) video_decoder.vp8 // VP8 decoder_name = OMX_VP8_DECODER; m_codingType = OMX_VIDEO_CodingVP8; m_video_codec_name = "omx-vp8"; break; case CODEC_ID_THEORA: // (role name) video_decoder.theora // theora decoder_name = OMX_THEORA_DECODER; m_codingType = OMX_VIDEO_CodingTheora; m_video_codec_name = "omx-theora"; break; case CODEC_ID_MJPEG: case CODEC_ID_MJPEGB: // (role name) video_decoder.mjpg // mjpg decoder_name = OMX_MJPEG_DECODER; m_codingType = OMX_VIDEO_CodingMJPEG; m_video_codec_name = "omx-mjpeg"; break; case CODEC_ID_VC1: case CODEC_ID_WMV3: // (role name) video_decoder.vc1 // VC-1, WMV9 decoder_name = OMX_VC1_DECODER; m_codingType = OMX_VIDEO_CodingWMV; m_video_codec_name = "omx-vc1"; break; default: ofLog(OF_LOG_VERBOSE, "Video codec id unknown: %x\n", hints.codec); return false; break; } std::string componentName = ""; componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.egl_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) return false; componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) return false; if(clock == NULL) return false; m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); omx_err = m_omx_tunnel_clock.Establish(false); if(omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "\nOMXEGLImage::Open m_omx_tunnel_clock.Establish\n"); return false; } omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (omx_err != OMX_ErrorNone) { ofLog(OF_LOG_VERBOSE, "\nOMXEGLImage::Open m_omx_decoder.SetStateForComponent\n"); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder SET OMX_IndexParamVideoPortFormat PASS"; }else { ofLogError() << "m_omx_decoder SET OMX_IndexParamVideoPortFormat FAIL"; return false; } OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder GET OMX_IndexParamPortDefinition PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder GET OMX_IndexParamPortDefinition FAIL omx_err(0x%08x)\n", omx_err); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); // JVC: I think numVideoBuffers can be probed for an optimal amount // omxplayer uses 60 but maybe that takes away GPU memory for other operations? int numVideoBuffers = 60; portParam.nBufferCountActual = numVideoBuffers; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder SET OMX_IndexParamPortDefinition PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder SET OMX_IndexParamPortDefinition FAIL omx_err(0x%08x)\n", omx_err); return false; } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images /*OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment FAIL omx_err(0x%08x)\n", omx_err); return false; } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatOneNaluPerBuffer; omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (omx_err == OMX_ErrorNone) { ofLogVerbose() << "Open OMX_IndexParamNalStreamFormatSelect PASS"; }else { ofLog(OF_LOG_ERROR, "Open OMX_IndexParamNalStreamFormatSelect FAIL (0%08x)\n", omx_err); return false; } }*/ // Alloc buffers for the omx intput port. omx_err = m_omx_decoder.AllocInputBuffers(); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder AllocInputBuffers PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder AllocInputBuffers FAIL omx_err(0x%08x)\n", omx_err); return false; } omx_err = m_omx_tunnel_decoder.Establish(false); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_tunnel_decoder Establish PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_tunnel_decoder Establish FAIL omx_err(0x%08x)\n", omx_err); return false; } m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL); m_av_clock->OMXStateExecute(); m_av_clock->OMXStart(); omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_decoder OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_decoder OMX_StateExecuting FAIL omx_err(0x%08x)", omx_err); return false; } omx_err = m_omx_tunnel_sched.Establish(false); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_tunnel_sched Establish PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_tunnel_sched Establish FAIL omx_err(0x%08x)", omx_err); return false; } omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_sched OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_sched OMX_StateExecuting FAIL omx_err(0x%08x)", omx_err); return false; } omx_err = m_omx_render.SetStateForComponent(OMX_StateIdle); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render OMX_StateIdle PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render OMX_StateIdle FAIL omx_err(0x%08x)", omx_err); return false; } ofLogVerbose() << "m_omx_render.GetOutputPort(): " << m_omx_render.GetOutputPort(); m_omx_render.EnablePort(m_omx_render.GetOutputPort(), true); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render Enable OUTPUT Port PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render Enable OUTPUT Port FAIL omx_err(0x%08x)", omx_err); return false; } omx_err = m_omx_render.UseEGLImage(&eglBuffer, m_omx_render.GetOutputPort(), NULL, eglImage); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render UseEGLImage PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render UseEGLImage FAIL omx_err(0x%08x)", omx_err); return false; } if(SendDecoderConfig()) { ofLogVerbose() << "SendDecoderConfig PASS"; }else { ofLog(OF_LOG_ERROR, "SendDecoderConfig FAIL"); return false; } m_omx_render.SetCustomDecoderFillBufferDoneHandler(onFillBufferDone); omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render OMX_StateExecuting PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render OMX_StateExecuting FAIL omx_err(0x%08x)", omx_err); return false; } omx_err = m_omx_render.FillThisBuffer(eglBuffer); if(omx_err == OMX_ErrorNone) { ofLogVerbose() << "m_omx_render FillThisBuffer PASS"; }else { ofLog(OF_LOG_ERROR, "m_omx_render FillThisBuffer FAIL omx_err(0x%08x)", omx_err); return false; } m_is_open = true; m_drop_state = false; m_setStartTime = true; m_setStartTimeText = true; ofLog(OF_LOG_VERBOSE, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x)\n", CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort()); m_first_frame = true; return true; }