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 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 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(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(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 VideoDecoderDirect::open(StreamInfo& streamInfo, OMXClock *clock, ofxOMXPlayerSettings& settings_) { OMX_ERRORTYPE error = OMX_ErrorNone; videoWidth = streamInfo.width; videoHeight = streamInfo.height; settings = settings_; omxClock = clock; clockComponent = omxClock->getComponent(); doHDMISync = settings.directDisplayOptions.doHDMISync; if(!videoWidth || !videoHeight) { return false; } if(streamInfo.extrasize > 0 && streamInfo.extradata != NULL) { extraSize = streamInfo.extrasize; extraData = (uint8_t *)malloc(extraSize); memcpy(extraData, streamInfo.extradata, streamInfo.extrasize); } processCodec(streamInfo); if(settings.enableFilters) { doFilters = true; } else { doFilters = false; } std::string componentName = "OMX.broadcom.video_decode"; if(!decoderComponent.init(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_render"; if(!renderComponent.init(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_scheduler"; if(!schedulerComponent.init(componentName, OMX_IndexParamVideoInit)) { return false; } if(doFilters) { decoderComponent.doFreeHandle = false; componentName = "OMX.broadcom.image_fx"; if(!imageFXComponent.init(componentName, OMX_IndexParamImageInit)) { return false; } decoderTunnel.init(&decoderComponent, decoderComponent.getOutputPort(), &imageFXComponent, imageFXComponent.getInputPort()); imageFXTunnel.init(&imageFXComponent, imageFXComponent.getOutputPort(), &schedulerComponent, schedulerComponent.getInputPort()); } else { decoderTunnel.init(&decoderComponent, decoderComponent.getOutputPort(), &schedulerComponent, schedulerComponent.getInputPort()); } schedulerTunnel.init(&schedulerComponent, schedulerComponent.getOutputPort(), &renderComponent, renderComponent.getInputPort()); clockTunnel.init(clockComponent, clockComponent->getInputPort() + 1, &schedulerComponent, schedulerComponent.getOutputPort() + 1); error = clockTunnel.Establish(false); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = decoderComponent.setState(OMX_StateIdle); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = decoderComponent.getInputPort(); formatType.eCompressionFormat = omxCodingType; if (streamInfo.fpsscale > 0 && streamInfo.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*streamInfo.fpsrate / streamInfo.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } error = decoderComponent.setParameter(OMX_IndexParamVideoPortFormat, &formatType); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = decoderComponent.getInputPort(); error = decoderComponent.getParameter(OMX_IndexParamPortDefinition, &portParam); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; portParam.nPortIndex = decoderComponent.getInputPort(); portParam.format.video.nFrameWidth = videoWidth; portParam.format.video.nFrameHeight = videoHeight; error = decoderComponent.setParameter(OMX_IndexParamPortDefinition, &portParam); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; error = decoderComponent.setParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; if (doFilters) { OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 5; error = decoderComponent.setParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); OMX_TRACE(error); if(error != OMX_ErrorNone) 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 = decoderComponent.setParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; if(NaluFormatStartCodes(streamInfo.codec, extraData, extraSize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = decoderComponent.getInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; error = decoderComponent.setParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; } if(doHDMISync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = renderComponent.getInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; error = renderComponent.setConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; } // Alloc buffers for the omx input port. error = decoderComponent.allocInputBuffers(); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = decoderTunnel.Establish(false); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = decoderComponent.setState(OMX_StateExecuting); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; if(doFilters) { error = imageFXTunnel.Establish(false); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = imageFXComponent.setState(OMX_StateExecuting); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; filterManager.setup(&imageFXComponent); filterManager.setFilter(settings.filter); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; } error = schedulerTunnel.Establish(false); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = schedulerComponent.setState(OMX_StateExecuting); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; error = renderComponent.setState(OMX_StateExecuting); OMX_TRACE(error); if(error != OMX_ErrorNone) return false; if(!sendDecoderConfig()) { return false; } isOpen = true; doSetStartTime = true; display.setup(&renderComponent, streamInfo, settings); isFirstFrame = true; doUpdate = true; ofAddListener(ofEvents().update, this, &VideoDecoderDirect::onUpdate); // start from assuming all recent frames had valid pts validHistoryPTS = ~0; return true; }