2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
23 #elif defined(TARGET_WINDOWS)
29 #include "utils/log.h"
30 #include "linux/XMemUtils.h"
31 #include "DVDDemuxers/DVDDemuxUtils.h"
32 #include "settings/AdvancedSettings.h"
33 #include "xbmc/guilib/GraphicContext.h"
34 #include "settings/Settings.h"
35 #include "utils/BitstreamConverter.h"
37 #include "linux/RBP.h"
45 #define CLASSNAME "COMXVideo"
47 #define OMX_VIDEO_DECODER "OMX.broadcom.video_decode"
48 #define OMX_H264BASE_DECODER OMX_VIDEO_DECODER
49 #define OMX_H264MAIN_DECODER OMX_VIDEO_DECODER
50 #define OMX_H264HIGH_DECODER OMX_VIDEO_DECODER
51 #define OMX_MPEG4_DECODER OMX_VIDEO_DECODER
52 #define OMX_MSMPEG4V1_DECODER OMX_VIDEO_DECODER
53 #define OMX_MSMPEG4V2_DECODER OMX_VIDEO_DECODER
54 #define OMX_MSMPEG4V3_DECODER OMX_VIDEO_DECODER
55 #define OMX_MPEG4EXT_DECODER OMX_VIDEO_DECODER
56 #define OMX_MPEG2V_DECODER OMX_VIDEO_DECODER
57 #define OMX_VC1_DECODER OMX_VIDEO_DECODER
58 #define OMX_WMV3_DECODER OMX_VIDEO_DECODER
59 #define OMX_VP6_DECODER OMX_VIDEO_DECODER
60 #define OMX_VP8_DECODER OMX_VIDEO_DECODER
61 #define OMX_THEORA_DECODER OMX_VIDEO_DECODER
62 #define OMX_MJPEG_DECODER OMX_VIDEO_DECODER
64 #define MAX_TEXT_LENGTH 1024
66 COMXVideo::COMXVideo() : m_video_codec_name("")
71 m_deinterlace = false;
72 m_deinterlace_request = VS_DEINTERLACEMODE_OFF;
73 m_hdmi_clock_sync = false;
79 m_res_callback = NULL;
81 m_submitted_eos = false;
83 m_settings_changed = false;
84 m_setStartTime = false;
85 m_transform = OMX_DISPLAY_ROT0;
88 COMXVideo::~COMXVideo()
93 bool COMXVideo::SendDecoderConfig()
95 CSingleLock lock (m_critSection);
96 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
98 /* send decoder config */
99 if(m_extrasize > 0 && m_extradata != NULL)
101 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
103 if(omx_buffer == NULL)
105 CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
109 omx_buffer->nOffset = 0;
110 omx_buffer->nFilledLen = m_extrasize;
111 if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
113 CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__);
117 memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
118 memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen);
119 omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
121 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
122 if (omx_err != OMX_ErrorNone)
124 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
131 bool COMXVideo::NaluFormatStartCodes(enum AVCodecID codec, uint8_t *in_extradata, int in_extrasize)
135 case AV_CODEC_ID_H264:
136 if (in_extrasize < 7 || in_extradata == NULL)
138 // valid avcC atom data always starts with the value 1 (version), otherwise annexb
139 else if ( *in_extradata != 1 )
146 bool COMXVideo::PortSettingsChanged()
148 CSingleLock lock (m_critSection);
149 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
151 if (m_settings_changed)
153 m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
156 OMX_PARAM_PORTDEFINITIONTYPE port_image;
157 OMX_INIT_STRUCTURE(port_image);
158 port_image.nPortIndex = m_omx_decoder.GetOutputPort();
159 omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_image);
160 if(omx_err != OMX_ErrorNone)
162 CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
165 OMX_CONFIG_POINTTYPE pixel_aspect;
166 OMX_INIT_STRUCTURE(pixel_aspect);
167 pixel_aspect.nPortIndex = m_omx_decoder.GetOutputPort();
168 omx_err = m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio, &pixel_aspect);
169 if(omx_err != OMX_ErrorNone)
171 CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
174 // let OMXPlayerVideo know about resolution so it can inform RenderManager
177 float display_aspect = 0.0f;
178 if (pixel_aspect.nX && pixel_aspect.nY)
179 display_aspect = (float)pixel_aspect.nX * port_image.format.video.nFrameWidth /
180 ((float)pixel_aspect.nY * port_image.format.video.nFrameHeight);
181 m_res_callback(m_res_ctx, port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight, display_aspect);
184 if (m_settings_changed)
186 m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
190 OMX_CONFIG_INTERLACETYPE interlace;
191 OMX_INIT_STRUCTURE(interlace);
192 interlace.nPortIndex = m_omx_decoder.GetOutputPort();
193 omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
195 if(m_deinterlace_request == VS_DEINTERLACEMODE_FORCE)
196 m_deinterlace = true;
197 else if(m_deinterlace_request == VS_DEINTERLACEMODE_OFF)
198 m_deinterlace = false;
200 m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
202 if(!m_omx_render.Initialize("OMX.broadcom.video_render", OMX_IndexParamVideoInit))
205 m_omx_render.ResetEos();
207 CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
208 port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
209 port_image.format.video.xFramerate / (float)(1<<16), interlace.eMode, m_deinterlace);
211 if(!m_omx_sched.Initialize("OMX.broadcom.video_scheduler", OMX_IndexParamVideoInit))
216 if(!m_omx_image_fx.Initialize("OMX.broadcom.image_fx", OMX_IndexParamImageInit))
220 OMX_CONFIG_DISPLAYREGIONTYPE configDisplay;
221 OMX_INIT_STRUCTURE(configDisplay);
222 configDisplay.nPortIndex = m_omx_render.GetInputPort();
224 configDisplay.set = OMX_DISPLAY_SET_TRANSFORM;
225 configDisplay.transform = m_transform;
226 omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay);
227 if(omx_err != OMX_ErrorNone)
229 CLog::Log(LOGWARNING, "%s::%s - could not set transform : %d", CLASSNAME, __func__, m_transform);
233 if(m_hdmi_clock_sync)
235 OMX_CONFIG_LATENCYTARGETTYPE latencyTarget;
236 OMX_INIT_STRUCTURE(latencyTarget);
237 latencyTarget.nPortIndex = m_omx_render.GetInputPort();
238 latencyTarget.bEnabled = OMX_TRUE;
239 latencyTarget.nFilter = 2;
240 latencyTarget.nTarget = 4000;
241 latencyTarget.nShift = 3;
242 latencyTarget.nSpeedFactor = -135;
243 latencyTarget.nInterFactor = 500;
244 latencyTarget.nAdjCap = 20;
246 omx_err = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget);
247 if (omx_err != OMX_ErrorNone)
249 CLog::Log(LOGERROR, "%s::%s - OMX_IndexConfigLatencyTarget omx_err(0%08x)", CLASSNAME, __func__, omx_err);
256 OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter;
257 OMX_INIT_STRUCTURE(image_filter);
259 image_filter.nPortIndex = m_omx_image_fx.GetOutputPort();
260 image_filter.nNumParams = 1;
261 image_filter.nParams[0] = 3;
262 image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced;
264 omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter);
265 if(omx_err != OMX_ErrorNone)
267 CLog::Log(LOGERROR, "%s::%s - OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
274 m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort());
275 m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort());
279 m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort());
281 m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort());
283 m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1);
285 omx_err = m_omx_tunnel_clock.Establish();
286 if(omx_err != OMX_ErrorNone)
288 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
292 omx_err = m_omx_tunnel_decoder.Establish();
293 if(omx_err != OMX_ErrorNone)
295 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
301 omx_err = m_omx_tunnel_image_fx.Establish();
302 if(omx_err != OMX_ErrorNone)
304 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_image_fx.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
308 omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting);
309 if (omx_err != OMX_ErrorNone)
311 CLog::Log(LOGERROR, "%s::%s - m_omx_image_fx.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
316 omx_err = m_omx_tunnel_sched.Establish();
317 if(omx_err != OMX_ErrorNone)
319 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_sched.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
323 omx_err = m_omx_sched.SetStateForComponent(OMX_StateExecuting);
324 if (omx_err != OMX_ErrorNone)
326 CLog::Log(LOGERROR, "%s::%s - m_omx_sched.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
330 omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting);
331 if (omx_err != OMX_ErrorNone)
333 CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
337 m_settings_changed = true;
341 bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE deinterlace, bool hdmi_clock_sync)
343 CSingleLock lock (m_critSection);
346 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
347 std::string decoder_name;
348 m_settings_changed = false;
349 m_setStartTime = true;
352 m_res_callback = NULL;
354 m_video_codec_name = "";
355 m_codingType = OMX_VIDEO_CodingUnused;
357 m_decoded_width = hints.width;
358 m_decoded_height = hints.height;
360 m_hdmi_clock_sync = hdmi_clock_sync;
361 m_submitted_eos = false;
362 m_failed_eos = false;
364 if(hints.extrasize > 0 && hints.extradata != NULL)
366 m_extrasize = hints.extrasize;
367 m_extradata = (uint8_t *)malloc(m_extrasize);
368 memcpy(m_extradata, hints.extradata, hints.extrasize);
373 case AV_CODEC_ID_H264:
375 switch(hints.profile)
377 case FF_PROFILE_H264_BASELINE:
378 // (role name) video_decoder.avc
379 // H.264 Baseline profile
380 decoder_name = OMX_H264BASE_DECODER;
381 m_codingType = OMX_VIDEO_CodingAVC;
382 m_video_codec_name = "omx-h264";
384 case FF_PROFILE_H264_MAIN:
385 // (role name) video_decoder.avc
386 // H.264 Main profile
387 decoder_name = OMX_H264MAIN_DECODER;
388 m_codingType = OMX_VIDEO_CodingAVC;
389 m_video_codec_name = "omx-h264";
391 case FF_PROFILE_H264_HIGH:
392 // (role name) video_decoder.avc
393 // H.264 Main profile
394 decoder_name = OMX_H264HIGH_DECODER;
395 m_codingType = OMX_VIDEO_CodingAVC;
396 m_video_codec_name = "omx-h264";
398 case FF_PROFILE_UNKNOWN:
399 decoder_name = OMX_H264HIGH_DECODER;
400 m_codingType = OMX_VIDEO_CodingAVC;
401 m_video_codec_name = "omx-h264";
404 decoder_name = OMX_H264HIGH_DECODER;
405 m_codingType = OMX_VIDEO_CodingAVC;
406 m_video_codec_name = "omx-h264";
411 case AV_CODEC_ID_MPEG4:
412 // (role name) video_decoder.mpeg4
413 // MPEG-4, DivX 4/5 and Xvid compatible
414 decoder_name = OMX_MPEG4_DECODER;
415 m_codingType = OMX_VIDEO_CodingMPEG4;
416 m_video_codec_name = "omx-mpeg4";
418 case AV_CODEC_ID_MPEG1VIDEO:
419 case AV_CODEC_ID_MPEG2VIDEO:
420 // (role name) video_decoder.mpeg2
422 decoder_name = OMX_MPEG2V_DECODER;
423 m_codingType = OMX_VIDEO_CodingMPEG2;
424 m_video_codec_name = "omx-mpeg2";
426 case AV_CODEC_ID_H263:
427 // (role name) video_decoder.mpeg4
428 // MPEG-4, DivX 4/5 and Xvid compatible
429 decoder_name = OMX_MPEG4_DECODER;
430 m_codingType = OMX_VIDEO_CodingMPEG4;
431 m_video_codec_name = "omx-h263";
433 case AV_CODEC_ID_VP6:
434 // this form is encoded upside down
437 case AV_CODEC_ID_VP6F:
438 case AV_CODEC_ID_VP6A:
439 // (role name) video_decoder.vp6
441 decoder_name = OMX_VP6_DECODER;
442 m_codingType = OMX_VIDEO_CodingVP6;
443 m_video_codec_name = "omx-vp6";
445 case AV_CODEC_ID_VP8:
446 // (role name) video_decoder.vp8
448 decoder_name = OMX_VP8_DECODER;
449 m_codingType = OMX_VIDEO_CodingVP8;
450 m_video_codec_name = "omx-vp8";
452 case AV_CODEC_ID_THEORA:
453 // (role name) video_decoder.theora
455 decoder_name = OMX_THEORA_DECODER;
456 m_codingType = OMX_VIDEO_CodingTheora;
457 m_video_codec_name = "omx-theora";
459 case AV_CODEC_ID_MJPEG:
460 case AV_CODEC_ID_MJPEGB:
461 // (role name) video_decoder.mjpg
463 decoder_name = OMX_MJPEG_DECODER;
464 m_codingType = OMX_VIDEO_CodingMJPEG;
465 m_video_codec_name = "omx-mjpeg";
467 case AV_CODEC_ID_VC1:
468 case AV_CODEC_ID_WMV3:
469 // (role name) video_decoder.vc1
471 decoder_name = OMX_VC1_DECODER;
472 m_codingType = OMX_VIDEO_CodingWMV;
473 m_video_codec_name = "omx-vc1";
476 CLog::Log(LOGERROR, "COMXVideo::Open : Video codec unknown: %x", hints.codec);
480 m_deinterlace_request = deinterlace;
482 if(!m_omx_decoder.Initialize(decoder_name, OMX_IndexParamVideoInit))
489 m_omx_clock = m_av_clock->GetOMXClock();
491 if(m_omx_clock->GetComponent() == NULL)
498 omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle);
499 if (omx_err != OMX_ErrorNone)
501 CLog::Log(LOGERROR, "COMXVideo::Open m_omx_decoder.SetStateForComponent\n");
505 OMX_VIDEO_PARAM_PORTFORMATTYPE formatType;
506 OMX_INIT_STRUCTURE(formatType);
507 formatType.nPortIndex = m_omx_decoder.GetInputPort();
508 formatType.eCompressionFormat = m_codingType;
510 if (hints.fpsscale > 0 && hints.fpsrate > 0)
512 formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale;
516 formatType.xFramerate = 25 * (1<<16);
519 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType);
520 if(omx_err != OMX_ErrorNone)
523 OMX_PARAM_PORTDEFINITIONTYPE portParam;
524 OMX_INIT_STRUCTURE(portParam);
525 portParam.nPortIndex = m_omx_decoder.GetInputPort();
527 omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam);
528 if(omx_err != OMX_ErrorNone)
530 CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err);
534 portParam.nPortIndex = m_omx_decoder.GetInputPort();
535 bool small_mem = g_RBP.GetArmMem() < 256;
536 portParam.nBufferCountActual = small_mem ? VIDEO_BUFFERS:2*VIDEO_BUFFERS;
537 portParam.format.video.nFrameWidth = m_decoded_width;
538 portParam.format.video.nFrameHeight = m_decoded_height;
540 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam);
541 if(omx_err != OMX_ErrorNone)
543 CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err);
547 // request portsettingschanged on aspect ratio change
548 OMX_CONFIG_REQUESTCALLBACKTYPE notifications;
549 OMX_INIT_STRUCTURE(notifications);
550 notifications.nPortIndex = m_omx_decoder.GetOutputPort();
551 notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio;
552 notifications.bEnable = OMX_TRUE;
554 omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications);
555 if (omx_err != OMX_ErrorNone)
557 CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err);
561 OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam;
562 OMX_INIT_STRUCTURE(concanParam);
563 if(g_advancedSettings.m_omxDecodeStartWithValidFrame)
564 concanParam.bStartWithValidFrame = OMX_TRUE;
566 concanParam.bStartWithValidFrame = OMX_FALSE;
568 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam);
569 if(omx_err != OMX_ErrorNone)
571 CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmVideoDecodeErrorConcealment omx_err(0x%08x)\n", omx_err);
575 if (m_deinterlace_request != VS_DEINTERLACEMODE_OFF)
577 // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2).
578 OMX_PARAM_U32TYPE extra_buffers;
579 OMX_INIT_STRUCTURE(extra_buffers);
580 extra_buffers.nU32 = 3;
582 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers);
583 if(omx_err != OMX_ErrorNone)
585 CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err);
591 // broadcom omx entension:
592 // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images.
593 // In this mode the incoming timestamps get used without re-ordering on output images.
596 OMX_CONFIG_BOOLEANTYPE timeStampMode;
597 OMX_INIT_STRUCTURE(timeStampMode);
598 timeStampMode.bEnabled = OMX_TRUE;
600 omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode);
601 if (omx_err != OMX_ErrorNone)
603 CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err);
608 if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize))
610 OMX_NALSTREAMFORMATTYPE nalStreamFormat;
611 OMX_INIT_STRUCTURE(nalStreamFormat);
612 nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort();
613 nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes;
615 omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat);
616 if (omx_err != OMX_ErrorNone)
618 CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamNalStreamFormatSelect error (0%08x)\n", omx_err);
624 // Alloc buffers for the omx intput port.
625 omx_err = m_omx_decoder.AllocInputBuffers();
626 if (omx_err != OMX_ErrorNone)
628 CLog::Log(LOGERROR, "COMXVideo::Open AllocOMXInputBuffers error (0%08x)\n", omx_err);
632 omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
633 if (omx_err != OMX_ErrorNone)
635 CLog::Log(LOGERROR, "COMXVideo::Open error m_omx_decoder.SetStateForComponent\n");
639 if(!SendDecoderConfig())
643 m_drop_state = false;
645 switch(hints.orientation)
648 m_transform = OMX_DISPLAY_ROT90;
651 m_transform = OMX_DISPLAY_ROT180;
654 m_transform = OMX_DISPLAY_ROT270;
657 m_transform = OMX_DISPLAY_ROT0;
661 m_transform = OMX_DISPLAY_MIRROR_ROT180;
663 if(m_omx_decoder.BadState())
667 "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n",
668 CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(),
669 m_deinterlace_request, m_hdmi_clock_sync);
675 void COMXVideo::Close()
677 CSingleLock lock (m_critSection);
678 m_omx_tunnel_clock.Deestablish();
679 m_omx_tunnel_decoder.Deestablish();
681 m_omx_tunnel_image_fx.Deestablish();
682 m_omx_tunnel_sched.Deestablish();
684 m_omx_decoder.FlushInput();
686 m_omx_sched.Deinitialize();
687 m_omx_decoder.Deinitialize();
689 m_omx_image_fx.Deinitialize();
690 m_omx_render.Deinitialize();
699 m_video_codec_name = "";
700 m_deinterlace = false;
704 m_res_callback = NULL;
707 void COMXVideo::SetDropState(bool bDrop)
709 m_drop_state = bDrop;
712 unsigned int COMXVideo::GetFreeSpace()
714 CSingleLock lock (m_critSection);
715 return m_omx_decoder.GetInputBufferSpace();
718 unsigned int COMXVideo::GetSize()
720 CSingleLock lock (m_critSection);
721 return m_omx_decoder.GetInputBufferSize();
724 int COMXVideo::Decode(uint8_t *pData, int iSize, double pts)
726 CSingleLock lock (m_critSection);
727 OMX_ERRORTYPE omx_err;
729 if( m_drop_state || !m_is_open )
732 unsigned int demuxer_bytes = (unsigned int)iSize;
733 uint8_t *demuxer_content = pData;
735 if (demuxer_content && demuxer_bytes > 0)
740 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500);
741 if(omx_buffer == NULL)
743 CLog::Log(LOGERROR, "OMXVideo::Decode timeout\n");
747 omx_buffer->nFlags = 0;
748 omx_buffer->nOffset = 0;
752 omx_buffer->nFlags |= OMX_BUFFERFLAG_STARTTIME;
753 CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE);
754 m_setStartTime = false;
756 if(pts == DVD_NOPTS_VALUE)
757 omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
759 omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts);
760 omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
761 memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);
763 demuxer_bytes -= omx_buffer->nFilledLen;
764 demuxer_content += omx_buffer->nFilledLen;
766 if(demuxer_bytes == 0)
767 omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
772 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
773 if (omx_err == OMX_ErrorNone)
775 //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize);
780 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
785 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finally failed\n", CLASSNAME, __func__);
790 omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0);
791 if (omx_err == OMX_ErrorNone)
793 if(!PortSettingsChanged())
795 CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err);
799 omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0);
800 if (omx_err == OMX_ErrorNone)
802 if(!PortSettingsChanged())
804 CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err);
815 void COMXVideo::Reset(void)
817 CSingleLock lock (m_critSection);
821 m_setStartTime = true;
822 m_omx_decoder.FlushInput();
824 m_omx_image_fx.FlushInput();
827 ///////////////////////////////////////////////////////////////////////////////////////////
828 void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect)
830 CSingleLock lock (m_critSection);
834 OMX_CONFIG_DISPLAYREGIONTYPE configDisplay;
836 OMX_INIT_STRUCTURE(configDisplay);
837 configDisplay.nPortIndex = m_omx_render.GetInputPort();
838 configDisplay.fullscreen = OMX_FALSE;
839 configDisplay.noaspect = OMX_TRUE;
841 configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT);
842 configDisplay.dest_rect.x_offset = (int)(DestRect.x1+0.5f);
843 configDisplay.dest_rect.y_offset = (int)(DestRect.y1+0.5f);
844 configDisplay.dest_rect.width = (int)(DestRect.Width()+0.5f);
845 configDisplay.dest_rect.height = (int)(DestRect.Height()+0.5f);
847 configDisplay.src_rect.x_offset = (int)(SrcRect.x1+0.5f);
848 configDisplay.src_rect.y_offset = (int)(SrcRect.y1+0.5f);
849 configDisplay.src_rect.width = (int)(SrcRect.Width()+0.5f);
850 configDisplay.src_rect.height = (int)(SrcRect.Height()+0.5f);
852 configDisplay.fullscreen = configDisplay.dest_rect.width == 0 || configDisplay.dest_rect.width == 0 ? OMX_TRUE : OMX_FALSE;
854 m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay);
856 CLog::Log(LOGDEBUG, "dest_rect.x_offset %d dest_rect.y_offset %d dest_rect.width %d dest_rect.height %d\n",
857 configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset,
858 configDisplay.dest_rect.width, configDisplay.dest_rect.height);
861 int COMXVideo::GetInputBufferSize()
863 CSingleLock lock (m_critSection);
864 return m_omx_decoder.GetInputBufferSize();
867 void COMXVideo::SubmitEOS()
869 CSingleLock lock (m_critSection);
873 m_submitted_eos = true;
874 m_failed_eos = false;
876 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
877 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000);
879 if(omx_buffer == NULL)
881 CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
886 omx_buffer->nOffset = 0;
887 omx_buffer->nFilledLen = 0;
888 omx_buffer->nTimeStamp = ToOMXTime(0LL);
890 omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
892 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
893 if (omx_err != OMX_ErrorNone)
895 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
898 CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
901 bool COMXVideo::IsEOS()
903 CSingleLock lock (m_critSection);
906 if (!m_failed_eos && !m_omx_render.IsEOS())
910 CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
911 m_submitted_eos = false;