bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEVDA) && !hints.software) { CCocoaAutoPool pool; // int width = hints.width; int height = hints.height; int level = hints.level; int profile = hints.profile; switch(profile) { case FF_PROFILE_H264_HIGH_10: case FF_PROFILE_H264_HIGH_10_INTRA: case FF_PROFILE_H264_HIGH_422: case FF_PROFILE_H264_HIGH_422_INTRA: case FF_PROFILE_H264_HIGH_444_PREDICTIVE: case FF_PROFILE_H264_HIGH_444_INTRA: case FF_PROFILE_H264_CAVLC_444: CLog::Log(LOGNOTICE, "%s - unsupported h264 profile(%d)", __FUNCTION__, hints.profile); return false; break; } if (width <= 0 || height <= 0) { CLog::Log(LOGNOTICE, "%s - bailing with bogus hints, width(%d), height(%d)", __FUNCTION__, width, height); return false; } if (Cocoa_GPUForDisplayIsNvidiaPureVideo3() && !CDVDCodecUtils::IsVP3CompatibleWidth(width)) { CLog::Log(LOGNOTICE, "%s - Nvidia 9400 GPU hardware limitation, cannot decode a width of %d", __FUNCTION__, width); return false; } CFDataRef avcCData; switch (hints.codec) { case AV_CODEC_ID_H264: m_bitstream = new CBitstreamConverter; if (!m_bitstream->Open(hints.codec, (uint8_t*)hints.extradata, hints.extrasize, false)) return false; avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)m_bitstream->GetExtraData(), m_bitstream->GetExtraSize()); m_format = 'avc1'; m_pFormatName = "vda-h264"; break; default: return false; break; } // check the avcC atom's sps for number of reference frames and // bail if interlaced, VDA does not handle interlaced h264. uint32_t avcc_len = CFDataGetLength(avcCData); if (avcc_len < 8) { // avcc atoms with length less than 8 are borked. CFRelease(avcCData); delete m_bitstream, m_bitstream = NULL; return false; } else { bool interlaced = true; uint8_t *spc = (uint8_t*)CFDataGetBytePtr(avcCData) + 6; uint32_t sps_size = BS_RB16(spc); if (sps_size) m_bitstream->parseh264_sps(spc+3, sps_size-1, &interlaced, &m_max_ref_frames); if (interlaced) { CLog::Log(LOGNOTICE, "%s - possible interlaced content.", __FUNCTION__); CFRelease(avcCData); return false; } } if (profile == FF_PROFILE_H264_MAIN && level == 32 && m_max_ref_frames > 4) { // [email protected], VDA cannot handle greater than 4 reference frames CLog::Log(LOGNOTICE, "%s - [email protected] detected, VDA cannot decode.", __FUNCTION__); CFRelease(avcCData); return false; } std::string rendervendor = g_Windowing.GetRenderVendor(); StringUtils::ToLower(rendervendor); if (rendervendor.find("nvidia") != std::string::npos) { // Nvidia gpu's are all powerful and work the way god intended m_decode_async = true; // The gods are liars, ignore the sirens for now. m_use_cvBufferRef = false; } else if (rendervendor.find("intel") != std::string::npos) { // Intel gpu are borked when using cvBufferRef m_decode_async = true; m_use_cvBufferRef = false; } else { // ATI gpu's are borked when using async decode m_decode_async = false; // They lie here too. m_use_cvBufferRef = false; } if (!m_use_cvBufferRef) { // allocate a YV12 DVDVideoPicture buffer. // first make sure all properties are reset. memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); unsigned int iPixels = width * height; unsigned int iChromaPixels = iPixels/4; m_videobuffer.dts = DVD_NOPTS_VALUE; m_videobuffer.pts = DVD_NOPTS_VALUE; m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; m_videobuffer.format = RENDER_FMT_YUV420P; m_videobuffer.color_range = 0; m_videobuffer.color_matrix = 4; m_videobuffer.iWidth = width; m_videobuffer.iHeight = height; m_videobuffer.iDisplayWidth = width; m_videobuffer.iDisplayHeight = height; m_videobuffer.iLineSize[0] = width; //Y m_videobuffer.iLineSize[1] = width/2; //U m_videobuffer.iLineSize[2] = width/2; //V m_videobuffer.iLineSize[3] = 0; m_videobuffer.data[0] = (uint8_t*)malloc(16 + iPixels); m_videobuffer.data[1] = (uint8_t*)malloc(16 + iChromaPixels); m_videobuffer.data[2] = (uint8_t*)malloc(16 + iChromaPixels); m_videobuffer.data[3] = NULL; // set all data to 0 for less artifacts.. hmm.. what is black in YUV?? memset(m_videobuffer.data[0], 0, iPixels); memset(m_videobuffer.data[1], 0, iChromaPixels); memset(m_videobuffer.data[2], 0, iChromaPixels); } // setup the decoder configuration dict CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable( kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFNumberRef avcWidth = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width); CFNumberRef avcHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height); CFNumberRef avcFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &m_format); CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_Height, avcHeight); CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_Width, avcWidth); CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_SourceFormat, avcFormat); CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_avcCData, avcCData); // release the retained object refs, decoderConfiguration owns them now CFRelease(avcWidth); CFRelease(avcHeight); CFRelease(avcFormat); CFRelease(avcCData); // setup the destination image buffer dict, vda will output this pict format CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable( kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8; CFNumberRef pixelFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType); // an IOSurface properties dictionary CFDictionaryRef iosurfaceDictionary = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat); CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferIOSurfacePropertiesKey, iosurfaceDictionary); // release the retained object refs, destinationImageBufferAttributes owns them now CFRelease(pixelFormat); CFRelease(iosurfaceDictionary); // create the VDADecoder object OSStatus status; try { status = VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes, (VDADecoderOutputCallback*)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder); } catch (...) { CLog::Log(LOGERROR, "%s - exception",__FUNCTION__); status = kVDADecoderDecoderFailedErr; } CFRelease(decoderConfiguration); CFRelease(destinationImageBufferAttributes); if (CDarwinUtils::DeviceHasLeakyVDA()) CFRelease(pixelFormat); if (status != kVDADecoderNoErr) { if (status == kVDADecoderDecoderFailedErr) CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process", __FUNCTION__); else CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)", __FUNCTION__, (int)status, profile, level); return false; } m_DropPictures = false; m_max_ref_frames = std::max(m_max_ref_frames + 1, 5); m_sort_time = 0; return true; } return false; }
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; }