MythTV  master
privatedecoder_omx.cpp
Go to the documentation of this file.
1 #include "privatedecoder_omx.h"
2 
3 #include <algorithm>
4 #include <cassert>
5 #include <cstddef>
6 
7 #include <OMX_Video.h>
8 #ifdef USING_BROADCOM
9 #include <OMX_Broadcom.h>
10 #endif
11 
12 #include <QMutexLocker>
13 
14 extern "C" {
15 #include "libavutil/pixdesc.h"
16 #include "libavcodec/avcodec.h"
17 #include "libavutil/imgutils.h"
18 }
19 
20 #include "avformatdecoder.h"
21 #include "mythcorecontext.h"
22 #include "mythlogging.h"
23 #include "omxcontext.h"
24 #include "mythavutil.h"
25 
26 using namespace omxcontext;
27 
28 
29 #define LOC QString("DOMX:%1 ").arg(m_videc.Id())
30 
31 // Stringize a macro
32 #define _STR(s) #s
33 #define STR(s) _STR(s)
34 
35 // VideoFrame <> OMX_BUFFERHEADERTYPE
36 #define FRAMESETHDR(f,h) ((f)->priv[2] = reinterpret_cast<unsigned char* >(h))
37 #define FRAMESETHDRNONE(f) ((f)->priv[2] = nullptr)
38 #define FRAME2HDR(f) ((OMX_BUFFERHEADERTYPE*)((f)->priv[2]))
39 #define FRAMESETREF(f,r) ((f)->priv[1] = reinterpret_cast<unsigned char* >(r))
40 #define FRAMESETREFNONE(f) ((f)->priv[1] = nullptr)
41 #define FRAME2REF(f) ((AVBufferRef*)((f)->priv[1]))
42 #define HDR2FRAME(h) ((VideoFrame*)((h)->pAppPrivate))
43 
44 // Component name
45 #ifdef USING_BELLAGIO
46 # define VIDEO_DECODE "" // Not implemented
47 #else
48 # define VIDEO_DECODE "video_decode"
49 #endif
50 
51 /*
52  * Types
53  */
54 
55 
56 /*
57  * Module data
58  */
59 QString const PrivateDecoderOMX::s_name("openmax");
60 
61 
62 /*
63  * Prototypes
64  */
65 static const char *H264Profile2String(int profile);
66 
67 
68 /*
69  * Functions
70  */
71 
72 // Convert PTS <> OMX ticks
73 static inline OMX_TICKS Pts2Ticks(AVStream *stream, int64_t pts)
74 {
75  if (pts == AV_NOPTS_VALUE)
76  return S64_TO_TICKS(0);
77 
78  return S64_TO_TICKS( int64_t(
79  (av_q2d(stream->time_base) * pts)* OMX_TICKS_PER_SECOND) );
80 }
81 
82 static inline int64_t Ticks2Pts(AVStream *stream, OMX_TICKS ticks)
83 {
84  return int64_t( (TICKS_TO_S64(ticks) /
85  av_q2d(stream->time_base)) / OMX_TICKS_PER_SECOND );
86 }
87 
88 // static
90 {
91  opts.decoders->append(s_name);
92  (*opts.equiv_decoders)[s_name].append("nuppel");
93  (*opts.equiv_decoders)[s_name].append("ffmpeg");
94  (*opts.equiv_decoders)[s_name].append("dummy");
95 }
96 
98  m_videc(gCoreContext->GetSetting("OMXVideoDecode", VIDEO_DECODE), *this),
99  m_filter(nullptr), m_bStartTime(false),
100  m_avctx(nullptr),
101  m_lock(QMutex::Recursive), m_bSettingsChanged(false),
102  m_bSettingsHaveChanged(false)
103 {
104  if (OMX_ErrorNone != m_videc.Init(OMX_IndexParamVideoInit))
105  return;
106 
107  if (!m_videc.IsValid())
108  return;
109 
110  // Show default port definitions and video formats supported
111  for (unsigned port = 0; port < m_videc.Ports(); ++port)
112  {
113  m_videc.ShowPortDef(port, LOG_DEBUG);
114 #if 0
115  m_videc.ShowFormats(port, LOG_DEBUG);
116 #endif
117  }
118 }
119 
120 // virtual
122 {
123  // Must shutdown the decoder now before our state becomes invalid.
124  // When the decoder dtor is called our state has already been destroyed.
125  m_videc.Shutdown();
126 
127  if (m_filter)
128  av_bitstream_filter_close(m_filter);
129 }
130 
131 // virtual
133 {
134  return s_name;
135 }
136 
137 // pure virtual
138 bool PrivateDecoderOMX::Init(const QString &decoder, PlayerFlags flags,
139  AVCodecContext *avctx)
140 {
141  if (decoder != s_name || !(flags & kDecodeAllowEXT) || !avctx)
142  return false;
143 
144  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + __func__ + QString(
145  "(decoder=%1 flags=%2) - begin").arg(decoder).arg(flags));
146 
147  if (getenv("NO_OPENMAX"))
148  {
149  LOG(VB_PLAYBACK, LOG_NOTICE, LOC + "OpenMAX decoder disabled");
150  return false;
151  }
152 
153  if (!m_videc.IsValid())
154  {
155  LOG(VB_GENERAL, LOG_ERR, LOC + "No video decoder");
156  return false;
157  }
158 
159  if (m_videc.Ports() < 2)
160  {
161  LOG(VB_GENERAL, LOG_ERR, LOC + "No video decoder ports");
162  return false;
163  }
164 
165  OMX_VIDEO_CODINGTYPE type = OMX_VIDEO_CodingUnused;
166  switch (avctx->codec_id)
167  {
168  case AV_CODEC_ID_MPEG1VIDEO:
169  case AV_CODEC_ID_MPEG2VIDEO:
170  type = OMX_VIDEO_CodingMPEG2;
171  break;
172  case AV_CODEC_ID_H263:
173  case AV_CODEC_ID_H263P:
174  case AV_CODEC_ID_H263I:
175  type = OMX_VIDEO_CodingH263;
176  break;
177  case AV_CODEC_ID_RV10:
178  case AV_CODEC_ID_RV20:
179  case AV_CODEC_ID_RV30:
180  case AV_CODEC_ID_RV40:
181  type = OMX_VIDEO_CodingRV;
182  break;
183  case AV_CODEC_ID_MJPEG:
184  case AV_CODEC_ID_MJPEGB:
185  type = OMX_VIDEO_CodingMJPEG;
186  break;
187  case AV_CODEC_ID_MPEG4:
188  type = OMX_VIDEO_CodingMPEG4;
189  break;
190  case AV_CODEC_ID_WMV1:
191  case AV_CODEC_ID_WMV2:
192  case AV_CODEC_ID_WMV3:
193  type = OMX_VIDEO_CodingWMV;
194  break;
195  case AV_CODEC_ID_H264:
196  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Codec H264 %1")
197  .arg(H264Profile2String(avctx->profile)) );
198  type = OMX_VIDEO_CodingAVC;
199  break;
200 #ifdef OMX_AUDIO_CodingTheora_Supported
201  case AV_CODEC_ID_THEORA:
202  type = OMX_VIDEO_CodingTheora;
203  break;
204 #endif
205 #ifdef OMX_AUDIO_CodingVP6_Supported
206  case AV_CODEC_ID_VP3:
207  case AV_CODEC_ID_VP5:
208  case AV_CODEC_ID_VP6:
209  case AV_CODEC_ID_VP6F:
210  case AV_CODEC_ID_VP6A:
211  type = OMX_VIDEO_CodingVP6;
212  break;
213 #endif
214 #ifdef OMX_AUDIO_CodingVP8_Supported
215  case AV_CODEC_ID_VP8:
216  type = OMX_VIDEO_CodingVP8;
217  break;
218 #endif
219 #ifdef OMX_AUDIO_CodingVP9_Supported
220  case AV_CODEC_ID_VP9:
221  type = OMX_VIDEO_CodingVP9;
222  break;
223 #endif
224 #ifdef OMX_AUDIO_CodingMVC_Supported
225  case AV_CODEC_ID_MVC1:
226  case AV_CODEC_ID_MVC2:
227  type = OMX_VIDEO_CodingMVC;
228  break;
229 #endif
230  default:
231  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Codec %1 not supported")
232  .arg(ff_codec_id_string(avctx->codec_id)));
233  return false;
234  }
235 
236  // Set input format
237  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Codec %1 => %2")
238  .arg(ff_codec_id_string(avctx->codec_id)).arg(Coding2String(type)));
239 
240  OMX_VIDEO_PARAM_PORTFORMATTYPE fmt;
241  OMX_DATA_INIT(fmt);
242  fmt.nPortIndex = m_videc.Base();
243  fmt.eCompressionFormat = type; // OMX_VIDEO_CodingAutoDetect gives error
244  fmt.eColorFormat = OMX_COLOR_FormatUnused;
245  OMX_ERRORTYPE e = m_videc.SetParameter(OMX_IndexParamVideoPortFormat, &fmt);
246  if (e != OMX_ErrorNone)
247  {
248  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
249  "Set input IndexParamVideoPortFormat error %1")
250  .arg(Error2String(e)));
251  return false;
252  }
253 
254  if (type == OMX_VIDEO_CodingAVC)
255  {
256  if (SetNalType(avctx) != OMX_ErrorNone)
257  {
258  if (avctx->extradata_size > 0 && avctx->extradata[0] == 1)
259  {
260  // Install s/w filter to convert mp4 to annex B
261  if (!CreateFilter(avctx))
262  return false;
263  }
264  }
265  }
266 
267  // Check output port default pixel format
268  switch (m_videc.PortDef(1).format.video.eColorFormat)
269  {
270  case OMX_COLOR_FormatYUV420Planar:
271  case OMX_COLOR_FormatYUV420PackedPlanar: // Broadcom default
272  break;
273 
274  default:
275  // Set output pixel format
276  fmt.nPortIndex = m_videc.Base() + 1;
277  fmt.eCompressionFormat = OMX_VIDEO_CodingUnused;
278  fmt.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
279  e = m_videc.SetParameter(OMX_IndexParamVideoPortFormat, &fmt);
280  if (e != OMX_ErrorNone)
281  {
282  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
283  "Set output IndexParamVideoPortFormat error %1")
284  .arg(Error2String(e)));
285  return false;
286  }
287  break;
288  }
289  avctx->pix_fmt = AV_PIX_FMT_YUV420P; // == FMT_YV12
290 
291  // Update input buffers (default is 20 preset in OMX)
292  m_videc.GetPortDef(0);
293  OMX_PARAM_PORTDEFINITIONTYPE &indef = m_videc.PortDef(0);
294  OMX_U32 inputBuffers
295  = OMX_U32(gCoreContext->GetNumSetting("OmxInputBuffers", 30));
296  if (inputBuffers > 0U
297  && inputBuffers != indef.nBufferCountActual
298  && inputBuffers > indef.nBufferCountMin)
299  {
300  indef.nBufferCountActual = inputBuffers;
301  e = m_videc.SetParameter(OMX_IndexParamPortDefinition, &indef);
302  if (e != OMX_ErrorNone)
303  {
304  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
305  "Set input IndexParamPortDefinition error %1")
306  .arg(Error2String(e)));
307  return false;
308  }
309  }
310  m_videc.GetPortDef(0);
311  m_videc.ShowPortDef(0, LOG_INFO);
312 
313  // Ensure at least 2 output buffers
314  OMX_PARAM_PORTDEFINITIONTYPE &def = m_videc.PortDef(1);
315  if (def.nBufferCountActual < 2U ||
316  def.nBufferCountActual < def.nBufferCountMin)
317  {
318  def.nBufferCountActual = std::max(OMX_U32(2), def.nBufferCountMin);
319  e = m_videc.SetParameter(OMX_IndexParamPortDefinition, &def);
320  if (e != OMX_ErrorNone)
321  {
322  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
323  "Set output IndexParamPortDefinition error %1")
324  .arg(Error2String(e)));
325  return false;
326  }
327  }
328  m_videc.GetPortDef(0);
329  m_videc.ShowPortDef(1, LOG_INFO);
330 
331  // Goto OMX_StateIdle & allocate all buffers
332  // This generates an error if fmt.eCompressionFormat is not supported
334  e = m_videc.SetState(OMX_StateIdle, 500, &cb);
335  if (e != OMX_ErrorNone)
336  {
337  // NB The RPi requires a license file for MPEG decoding.
338  if (type == OMX_VIDEO_CodingMPEG2)
339  LOG(VB_GENERAL, LOG_WARNING, LOC +
340  "NB MPEG2 decoding requires a license file");
341  return false;
342  }
343 
344  m_bSettingsHaveChanged = false;
345 
346  // Goto OMX_StateExecuting
347  e = m_videc.SetState(OMX_StateExecuting, 500);
348  if (e != OMX_ErrorNone)
349  return false;
350 
351  e = FillOutputBuffers();
352  if (e != OMX_ErrorNone)
353  return false;
354 
355  // The decoder is now ready for input
356  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + __func__ + " - end");
357  return true;
358 }
359 
360 // Setup H264 decoder for NAL type
361 OMX_ERRORTYPE PrivateDecoderOMX::SetNalType(AVCodecContext *avctx)
362 {
363 #ifdef USING_BROADCOM
364  OMX_NALSTREAMFORMATTYPE fmt;
365  OMX_DATA_INIT(fmt);
366  fmt.nPortIndex = m_videc.Base();
367 
368  OMX_ERRORTYPE e = m_videc.GetParameter(
369  OMX_INDEXTYPE(OMX_IndexParamNalStreamFormatSupported), &fmt);
370  if (e != OMX_ErrorNone)
371  {
372  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
373  "Get ParamNalStreamFormatSupported error %1")
374  .arg(Error2String(e)));
375  if (avctx->extradata_size == 0 || avctx->extradata[0] != 1)
376  return OMX_ErrorNone; // Annex B, no filter needed
377  return e;
378  }
379 
380  static bool s_bReported;
381  if (!s_bReported)
382  {
383  s_bReported = true;
384  QStringList list;
385  if (fmt.eNaluFormat & OMX_NaluFormatStartCodes)
386  list << "StartCodes (Annex B)";
387  if (fmt.eNaluFormat & OMX_NaluFormatOneNaluPerBuffer)
388  list << "OneNaluPerBuffer";
389  if (fmt.eNaluFormat & OMX_NaluFormatOneByteInterleaveLength)
390  list << "OneByteInterleaveLength";
391  if (fmt.eNaluFormat & OMX_NaluFormatTwoByteInterleaveLength)
392  list << "TwoByteInterleaveLength";
393  if (fmt.eNaluFormat & OMX_NaluFormatFourByteInterleaveLength)
394  list << "FourByteInterleaveLength";
395  LOG(VB_PLAYBACK, LOG_INFO, LOC + "NalStreamFormatSupported: " +
396  list.join(", "));
397  }
398 
399  OMX_NALUFORMATSTYPE type;
400  QString naluFormat;
401  if (avctx->extradata_size >= 5 && avctx->extradata[0] == 1)
402  {
403  // AVCC NALs (mp4 stream)
404  int n = 1 + (avctx->extradata[4] & 0x3);
405  switch (n)
406  {
407  case 1:
408  type = OMX_NaluFormatOneByteInterleaveLength;
409  naluFormat = "OneByteInterleaveLength";
410  break;
411  case 2:
412  type = OMX_NaluFormatTwoByteInterleaveLength;
413  naluFormat = "TwoByteInterleaveLength";
414  break;
415  case 4:
416  type = OMX_NaluFormatFourByteInterleaveLength;
417  naluFormat = "FourByteInterleaveLength";
418  break;
419  default:
420  return OMX_ErrorUnsupportedSetting;
421  }
422  }
423  else
424  {
425  type = OMX_NaluFormatStartCodes; // Annex B
426  naluFormat = "StartCodes";
427  }
428 
429  fmt.eNaluFormat = OMX_NALUFORMATSTYPE(fmt.eNaluFormat & type);
430  if (!fmt.eNaluFormat)
431  {
432  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Unsupported NAL stream format " +
433  naluFormat);
434  return OMX_ErrorUnsupportedSetting;
435  }
436 
437  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "NAL stream format: " + naluFormat);
438 
439  e = m_videc.SetParameter(OMX_INDEXTYPE(OMX_IndexParamNalStreamFormatSelect), &fmt);
440  if (e != OMX_ErrorNone)
441  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
442  "Set ParamNalStreamFormatSelect(%1) error %2")
443  .arg(naluFormat).arg(Error2String(e)));
444  return e;
445 #else
446  if (avctx->extradata_size == 0 || avctx->extradata[0] != 1)
447  return OMX_ErrorNone; // Annex B, no filter needed
448 
449  return OMX_ErrorUnsupportedSetting;
450 #endif //USING_BROADCOM
451 }
452 
453 
454 // Create an h264_mp4toannexb conversion filter
455 bool PrivateDecoderOMX::CreateFilter(AVCodecContext *avctx)
456 {
457  // Check NAL size
458  if (avctx->extradata_size < 5)
459  {
460  LOG(VB_PLAYBACK, LOG_ERR, LOC + "AVCC extradata_size too small");
461  return false;
462  }
463 
464  int n = 1 + (avctx->extradata[4] & 0x3);
465  switch (n)
466  {
467  case 1:
468  case 2:
469  case 4:
470  break;
471  default:
472  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid NAL size (%1)")
473  .arg(n));
474  return false;
475  }
476 
477  if (m_filter)
478  return true;
479 
480  m_filter = av_bitstream_filter_init("h264_mp4toannexb");
481  if (!m_filter)
482  {
483  LOG(VB_PLAYBACK, LOG_ERR, LOC +
484  "Failed to create h264_mp4toannexb filter");
485  return false;
486  }
487 
488  LOG(VB_GENERAL, LOG_INFO, LOC + "Installed h264_mp4toannexb filter");
489  return true;
490 }
491 
492 // OMX_StateIdle callback
493 OMX_ERRORTYPE PrivateDecoderOMX::AllocBuffersCB()
494 {
495  assert(m_ibufs_sema.available() == 0);
496  assert(m_ibufs.isEmpty());
497  assert(m_obufs_sema.available() == 0);
498  assert(m_obufs.isEmpty());
499 
500  // Allocate input buffers
501  int index = 0;
502  const OMX_PARAM_PORTDEFINITIONTYPE &def = m_videc.PortDef(index);
503  OMX_U32 uBufs = def.nBufferCountActual;
504  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(
505  "Allocate %1 of %2 byte input buffer(s)")
506  .arg(uBufs).arg(def.nBufferSize));
507  while (uBufs--)
508  {
509  OMX_BUFFERHEADERTYPE *hdr;
510  OMX_ERRORTYPE e = OMX_AllocateBuffer(m_videc.Handle(), &hdr,
511  m_videc.Base() + index, this, def.nBufferSize);
512  if (e != OMX_ErrorNone)
513  {
514  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
515  "OMX_AllocateBuffer error %1").arg(Error2String(e)) );
516  return e;
517  }
518  if (hdr->nSize != sizeof(OMX_BUFFERHEADERTYPE))
519  {
520  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_AllocateBuffer header mismatch");
521  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
522  return OMX_ErrorVersionMismatch;
523  }
524  if (hdr->nVersion.nVersion != OMX_VERSION)
525  {
526  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_AllocateBuffer version mismatch");
527  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
528  return OMX_ErrorVersionMismatch;
529  }
530  hdr->nFilledLen = 0;
531  hdr->nOffset = 0;
532  m_lock.lock();
533  m_ibufs.append(hdr);
534  m_lock.unlock();
535  m_ibufs_sema.release();
536  }
537 
538  // Allocate output buffers
539  return AllocOutputBuffersCB();
540 }
541 
542 // Start filling the output buffers
544 {
545  while (m_obufs_sema.tryAcquire())
546  {
547  m_lock.lock();
548  assert(!m_obufs.isEmpty());
549  OMX_BUFFERHEADERTYPE *hdr = m_obufs.takeFirst();
550  m_lock.unlock();
551 
552  hdr->nFlags = 0;
553  hdr->nFilledLen = 0;
554  OMX_ERRORTYPE e = OMX_FillThisBuffer(m_videc.Handle(), hdr);
555  if (e != OMX_ErrorNone)
556  {
557  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
558  "OMX_FillThisBuffer error %1").arg(Error2String(e)) );
559  m_lock.lock();
560  m_obufs.append(hdr);
561  m_lock.unlock();
562  m_obufs_sema.release();
563  return e;
564  }
565  }
566 
567  return OMX_ErrorNone;
568 }
569 
570 // Deallocate output buffers
571 // OMX_CommandPortDisable callback
573 {
574  const int index = 1;
575  while (m_obufs_sema.tryAcquire(1, !m_videc.IsCommandComplete() ? 100 : 0) )
576  {
577  m_lock.lock();
578  assert(!m_obufs.isEmpty());
579  OMX_BUFFERHEADERTYPE *hdr = m_obufs.takeFirst();
580  m_lock.unlock();
581 
582  VideoFrame *frame = HDR2FRAME(hdr);
583  if (frame && FRAME2HDR(frame) == hdr)
584  {
585  FRAMESETHDRNONE(frame);
586 
587  AVBufferRef *ref = FRAME2REF(frame);
588  if (ref)
589  {
590  FRAMESETREFNONE(frame);
591  av_buffer_unref(&ref);
592  }
593  }
594 
595  OMX_ERRORTYPE e = OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
596  if (e != OMX_ErrorNone)
597  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
598  "OMX_FreeBuffer 0x%1 error %2")
599  .arg(quintptr(hdr),0,16).arg(Error2String(e)));
600  }
601  assert(m_obufs.isEmpty());
602  assert(m_obufs_sema.available() == 0);
603  return OMX_ErrorNone;
604 }
605 
606 // Allocate output buffers
607 // OMX_CommandPortEnable callback
609 {
610  assert(m_obufs_sema.available() == 0);
611  assert(m_obufs.isEmpty());
612 
613  const int index = 1;
614  const OMX_PARAM_PORTDEFINITIONTYPE *pdef = &m_videc.PortDef(index);
615  OMX_U32 uBufs = pdef->nBufferCountActual;
616  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(
617  "Allocate %1 of %2 byte output buffer(s)")
618  .arg(uBufs).arg(pdef->nBufferSize));
619  while (uBufs--)
620  {
621  OMX_BUFFERHEADERTYPE *hdr;
622  OMX_ERRORTYPE e = OMX_AllocateBuffer(m_videc.Handle(), &hdr,
623  m_videc.Base() + index, nullptr, pdef->nBufferSize);
624  if (e != OMX_ErrorNone)
625  {
626  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
627  "OMX_AllocateBuffer error %1").arg(Error2String(e)) );
628  return e;
629  }
630  if (hdr->nSize != sizeof(OMX_BUFFERHEADERTYPE))
631  {
632  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_AllocateBuffer header mismatch");
633  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
634  return OMX_ErrorVersionMismatch;
635  }
636  if (hdr->nVersion.nVersion != OMX_VERSION)
637  {
638  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_AllocateBuffer version mismatch");
639  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
640  return OMX_ErrorVersionMismatch;
641  }
642  hdr->nFilledLen = 0;
643  hdr->nOffset = 0;
644  m_obufs.append(hdr);
645  m_obufs_sema.release();
646  }
647 
648  return OMX_ErrorNone;
649 }
650 
651 // Use VideoOutput buffers
652 // OMX_CommandPortEnable callback
653 OMX_ERRORTYPE PrivateDecoderOMX::UseBuffersCB()
654 {
655  assert(m_obufs_sema.available() == 0);
656  assert(m_obufs.isEmpty());
657  assert(m_avctx);
658 
659  const int index = 1;
660  const OMX_PARAM_PORTDEFINITIONTYPE &def = m_videc.PortDef(index);
661  OMX_U32 uBufs = def.nBufferCountActual;
662 
663  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(
664  "Use %1 of %2 byte output buffer(s)")
665  .arg(uBufs).arg(def.nBufferSize));
666 
667  OMX_ERRORTYPE e = OMX_ErrorNone;
668 
669  while (uBufs--)
670  {
671  MythAVFrame picture;
672  if (m_avctx->get_buffer2(m_avctx, picture, 0) < 0)
673  {
674  LOG(VB_PLAYBACK, LOG_ERR, LOC + __func__ + " no video frames");
675  return OMX_ErrorOverflow;
676  }
677 
678  VideoFrame *frame = (VideoFrame*)picture->opaque;
679  assert(frame);
680 
681  OMX_BUFFERHEADERTYPE *hdr;
682  e = OMX_UseBuffer(m_videc.Handle(), &hdr, m_videc.Base() + index, frame,
683  def.nBufferSize, frame->buf);
684  if (e != OMX_ErrorNone)
685  {
686  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
687  "OMX_UseBuffer error %1").arg(Error2String(e)) );
688  return e;
689  }
690  if (hdr->nSize != sizeof(OMX_BUFFERHEADERTYPE))
691  {
692  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_UseBuffer header mismatch");
693  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
694  return OMX_ErrorVersionMismatch;
695  }
696  if (hdr->nVersion.nVersion != OMX_VERSION)
697  {
698  LOG(VB_PLAYBACK, LOG_ERR, LOC + "OMX_UseBuffer version mismatch");
699  OMX_FreeBuffer(m_videc.Handle(), m_videc.Base() + index, hdr);
700  return OMX_ErrorVersionMismatch;
701  }
702 
703  assert(frame == HDR2FRAME(hdr));
704  FRAMESETHDR(frame, hdr);
705  FRAMESETREF(frame, picture->buf[0]);
706  picture->buf[0] = nullptr;
707 
708  hdr->nFilledLen = 0;
709  hdr->nOffset = 0;
710 
711  m_obufs.append(hdr);
712  m_obufs_sema.release();
713  }
714 
715  return e;
716 }
717 
718 // pure virtual
720 {
721  if (!m_videc.IsValid())
722  return false;
723 
724  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + __func__ + " - begin");
725 
726  m_bStartTime = false;
727 
728  // Flush input
729  OMX_ERRORTYPE e;
730  e = m_videc.SendCommand(OMX_CommandFlush, m_videc.Base(), nullptr, 50);
731  if (e != OMX_ErrorNone)
732  return false;
733 
734  // Flush output
735  e = m_videc.SendCommand(OMX_CommandFlush, m_videc.Base() + 1, nullptr, 50);
736  if (e != OMX_ErrorNone)
737  return false;
738 
739  if (m_avctx && m_avctx->get_buffer2)
740  {
741  // Request new buffers when GetFrame is next called
742  QMutexLocker lock(&m_lock);
743  m_bSettingsChanged = true;
744  }
745  else
746  {
747  // Re-submit the empty output buffers
749  }
750 
751  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + __func__ + " - end");
752  return true;
753 }
754 
755 // pure virtual
757  AVStream *stream,
758  AVFrame *picture,
759  int *got_picture_ptr,
760  AVPacket *pkt)
761 {
762  if (!m_videc.IsValid())
763  return -1;
764 
765  if (!stream)
766  return -1;
767 
768  // Check for a decoded frame
769  int ret = GetBufferedFrame(stream, picture);
770  if (ret < 0)
771  return ret;
772  if (ret > 0)
773  *got_picture_ptr = 1;
774 
775  // Check for OMX_EventPortSettingsChanged notification
776  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
777  if (SettingsChanged(avctx) != OMX_ErrorNone)
778  {
779  // PGB If there was an error, discard this packet
780  *got_picture_ptr = 0;
781  return -1;
782  }
783 
784  // PGB If settings have changed, discard this one packet
785  QMutexLocker lock(&m_lock);
787  {
788  m_bSettingsHaveChanged = false;
789  *got_picture_ptr = 0;
790  return -1;
791  }
792 
793  // Submit a packet for decoding
794  lock.unlock();
795  return (pkt && pkt->size) ? ProcessPacket(stream, pkt) : 0;
796 }
797 
798 // Submit a packet for decoding
799 int PrivateDecoderOMX::ProcessPacket(AVStream *stream, AVPacket *pkt)
800 {
801  uint8_t *buf = pkt->data, *free_buf = nullptr;
802  int size = pkt->size;
803  int ret = pkt->size;
804 
805  // Convert h264_mp4toannexb
806  if (m_filter)
807  {
808  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
809  int outbuf_size = 0;
810  uint8_t *outbuf = nullptr;
811  int res = av_bitstream_filter_filter(m_filter, avctx, nullptr, &outbuf,
812  &outbuf_size, buf, size, 0);
813  if (res <= 0)
814  {
815  static int count;
816  if (++count == 1)
817  LOG(VB_GENERAL, LOG_ERR, LOC +
818  QString("Failed to convert packet (%1)").arg(res));
819  if (count > 200)
820  count = 0;
821  }
822 
823  if (outbuf && outbuf_size > 0)
824  {
825  size = outbuf_size;
826  buf = free_buf = outbuf;
827  }
828  }
829 
830  // size is typically 50000 - 70000 but occasionally as low as 2500
831  // or as high as 360000
832  while (size > 0)
833  {
834  if (!m_ibufs_sema.tryAcquire(1, 100))
835  {
836  LOG(VB_GENERAL, LOG_ERR, LOC + __func__ +
837  " Ran out of OMX input buffers, see OmxInputBuffers setting.");
838  ret = 0;
839  break;
840  }
841  int freebuffers = m_ibufs_sema.available();
842  if (freebuffers < 2)
843  LOG(VB_PLAYBACK, LOG_WARNING, LOC + __func__ +
844  QString(" Free OMX input buffers = %1, see OmxInputBuffers setting.")
845  .arg(freebuffers));
846  m_lock.lock();
847  assert(!m_ibufs.isEmpty());
848  OMX_BUFFERHEADERTYPE *hdr = m_ibufs.takeFirst();
849  m_lock.unlock();
850 
851  int free = int(hdr->nAllocLen) - int(hdr->nFilledLen + hdr->nOffset);
852  int cnt = (free > size) ? size : free;
853  memcpy(&hdr->pBuffer[hdr->nOffset + hdr->nFilledLen], buf, cnt);
854  hdr->nFilledLen += cnt;
855  buf += cnt;
856  size -= cnt;
857 
858  hdr->nTimeStamp = Pts2Ticks(stream, pkt->pts);
859  if (!m_bStartTime && (pkt->flags & AV_PKT_FLAG_KEY))
860  {
861  m_bStartTime = true;
862  hdr->nFlags = OMX_BUFFERFLAG_STARTTIME;
863  }
864  else
865  hdr->nFlags = 0;
866 
867  LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + QString(
868  "EmptyThisBuffer len=%1 tc=%2uS (pts %3)")
869  .arg(hdr->nFilledLen).arg(TICKS_TO_S64(hdr->nTimeStamp))
870  .arg(pkt->pts) );
871 
872  OMX_ERRORTYPE e = OMX_EmptyThisBuffer(m_videc.Handle(), hdr);
873  if (e != OMX_ErrorNone)
874  {
875  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
876  "OMX_EmptyThisBuffer error %1").arg(Error2String(e)) );
877  m_lock.lock();
878  m_ibufs.append(hdr);
879  m_lock.unlock();
880  m_ibufs_sema.release();
881  ret = -1;
882  break;
883  }
884  }
885 
886  if (free_buf)
887  av_freep(&free_buf);
888 
889  return ret;
890 }
891 
892 // Dequeue decoded buffer
893 int PrivateDecoderOMX::GetBufferedFrame(AVStream *stream, AVFrame *picture)
894 {
895  if (!picture)
896  return -1;
897 
898  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
899  if (!avctx)
900  return -1;
901 
902  if (!m_obufs_sema.tryAcquire())
903  return 0;
904 
905  m_lock.lock();
906  assert(!m_obufs.isEmpty());
907  OMX_BUFFERHEADERTYPE *hdr = m_obufs.takeFirst();
908  m_lock.unlock();
909 
910  OMX_U32 nFlags = hdr->nFlags;
911  if (nFlags & ~OMX_BUFFERFLAG_ENDOFFRAME)
912  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
913  QString("Decoded frame flags=%1").arg(HeaderFlags(nFlags)) );
914 
915  if (avctx->pix_fmt < 0)
916  avctx->pix_fmt = AV_PIX_FMT_YUV420P; // == FMT_YV12
917 
918  int ret = 1; // Assume success
919  if (hdr->nFilledLen == 0)
920  {
921  // This happens after an EventBufferFlag EOS
922  ret = 0;
923  }
924  else if (avctx->get_buffer2(avctx, picture, 0) < 0)
925  {
926  LOG(VB_GENERAL, LOG_ERR, LOC +
927  "Decoded frame available but no video buffers");
928  ret = 0;
929  }
930  else
931  {
932  VideoFrame vf;
933  VideoFrameType frametype = FMT_YV12;
934  AVPixelFormat out_fmt = AV_PIX_FMT_YUV420P; // == FMT_YV12
935  AVPixelFormat in_fmt = AV_PIX_FMT_NONE;
936  int pitches[3]; // Y, U, & V pitches
937  int offsets[3]; // Y, U, & V offsets
938  unsigned char *buf = nullptr;
939 
940  const OMX_VIDEO_PORTDEFINITIONTYPE &vdef = m_videc.PortDef(1).format.video;
941  switch (vdef.eColorFormat)
942  {
943  case OMX_COLOR_FormatYUV420Planar:
944  case OMX_COLOR_FormatYUV420PackedPlanar: // Broadcom default
945  pitches[0] = vdef.nStride;
946  pitches[1] = pitches[2] = vdef.nStride >> 1;
947  offsets[0] = 0;
948  offsets[1] = vdef.nStride * vdef.nSliceHeight;
949  offsets[2] = offsets[1] + (offsets[1] >> 2);
950  in_fmt = AV_PIX_FMT_YUV420P;
951  break;
952 
953  case OMX_COLOR_Format16bitRGB565:
954  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Format %1 broken")
955  .arg(Format2String(vdef.eColorFormat)) );
956  in_fmt = AV_PIX_FMT_RGB565LE;
957  out_fmt = AV_PIX_FMT_RGBA;
958  frametype = FMT_RGBA32;
959  break;
960 
961  default:
962  LOG(VB_GENERAL, LOG_ERR, LOC + QString(
963  "Unsupported frame type: %1")
964  .arg(Format2String(vdef.eColorFormat)) );
965  break;
966  }
967 
968  picture->reordered_opaque = Ticks2Pts(stream, hdr->nTimeStamp);
969 
970  VideoFrame *frame = HDR2FRAME(hdr);
971 
972  if (frame && FRAME2HDR(frame) == hdr)
973  {
974  frame->bpp = bitsperpixel(frametype);
975  frame->codec = frametype;
976  frame->width = vdef.nFrameWidth;
977  frame->height = vdef.nFrameHeight;
978  memcpy(frame->offsets, offsets, sizeof frame->offsets);
979  memcpy(frame->pitches, pitches, sizeof frame->pitches);
980 
981  VideoFrame *frame2 = (VideoFrame*)picture->opaque;
982  OMX_BUFFERHEADERTYPE *hdr2 = FRAME2HDR(frame2);
983  if (hdr2 && HDR2FRAME(hdr2) == frame2)
984  {
985  // The new frame has an associated hdr so use that
986  hdr = hdr2;
987  }
988  else
989  {
990  // Re-use the current header with the new frame
991  assert(unsigned(frame2->size) >= hdr->nAllocLen);
992  hdr->pBuffer = frame2->buf;
993  hdr->pAppPrivate = frame2;
994  assert(frame2 == HDR2FRAME(hdr));
995  FRAMESETHDR(frame2, hdr);
996  }
997 
998  FRAMESETREF(frame2, picture->buf[0]);
999 
1000  // Indicate the buffered frame from the completed OMX buffer
1001  picture->buf[0] = FRAME2REF(frame);
1002  FRAMESETREFNONE(frame);
1003  picture->opaque = frame;
1004  }
1005  else if (in_fmt == avctx->pix_fmt)
1006  {
1007  // Prepare to copy the OMX buffer
1008  init(&vf, frametype, &hdr->pBuffer[hdr->nOffset],
1009  vdef.nFrameWidth, vdef.nFrameHeight, hdr->nFilledLen,
1010  pitches, offsets);
1011  }
1012  else if (in_fmt != AV_PIX_FMT_NONE)
1013  {
1014  int in_width = vdef.nStride;
1015  int in_height = vdef.nSliceHeight;
1016  int out_width = (vdef.nFrameWidth + 15) & (~0xf);
1017  int out_height = vdef.nFrameHeight;
1018  int size = ((bitsperpixel(frametype) * out_width) / 8) * out_height;
1019  uint8_t* src = &hdr->pBuffer[hdr->nOffset];
1020 
1021  buf = (unsigned char*)av_malloc(size);
1022  init(&vf, frametype, buf, out_width, out_height, size);
1023 
1024  AVFrame img_in, img_out;
1025  av_image_fill_arrays(img_out.data, img_out.linesize,
1026  vf.buf, out_fmt, out_width,
1027  out_height, IMAGE_ALIGN);
1028  av_image_fill_arrays(img_in.data, img_in.linesize,
1029  src, in_fmt, in_width, in_height, IMAGE_ALIGN);
1030 
1031  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Converting %1 to %2")
1032  .arg(av_pix_fmt_desc_get(in_fmt)->name)
1033  .arg(av_pix_fmt_desc_get(out_fmt)->name) );
1034  m_copyCtx.Copy(&img_out, out_fmt, &img_in, in_fmt, in_width, in_height);
1035  }
1036  else
1037  {
1038  ret = 0;
1039  }
1040 
1041  if (ret)
1042  {
1043 #ifdef OMX_BUFFERFLAG_INTERLACED
1044  if (nFlags & OMX_BUFFERFLAG_INTERLACED)
1045  picture->interlaced_frame = 1;
1046  else
1047 #endif
1048  picture->interlaced_frame = 0;
1049 #ifdef OMX_BUFFERFLAG_TOP_FIELD_FIRST
1050  if (nFlags & OMX_BUFFERFLAG_TOP_FIELD_FIRST)
1051  picture->top_field_first = 1;
1052  else
1053 #endif
1054  picture->top_field_first = 0;
1055  picture->repeat_pict = 0;
1056  if (!frame)
1057  {
1058  // Copy OMX buffer to the frame provided
1059  copy((VideoFrame*)picture->opaque, &vf);
1060  }
1061  }
1062 
1063  av_freep(&buf);
1064  }
1065 
1066  hdr->nFlags = 0;
1067  hdr->nFilledLen = 0;
1068  OMX_ERRORTYPE e = OMX_FillThisBuffer(m_videc.Handle(), hdr);
1069  if (e != OMX_ErrorNone)
1070  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
1071  "OMX_FillThisBuffer reQ error %1").arg(Error2String(e)) );
1072 
1073  return ret;
1074 }
1075 
1076 // Handle the port settings changed notification
1077 OMX_ERRORTYPE PrivateDecoderOMX::SettingsChanged(AVCodecContext *avctx)
1078 {
1079  QMutexLocker lock(&m_lock);
1080 
1081  // Check for errors notified in EventCB
1082  OMX_ERRORTYPE e = m_videc.LastError();
1083  if (e != OMX_ErrorNone)
1084  {
1085  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("SettingsChanged error %1")
1086  .arg(Error2String(e)));
1087  return e;
1088  }
1089 
1090  if (!m_bSettingsChanged)
1091  return OMX_ErrorNone;
1092 
1093  lock.unlock();
1094 
1095  LOG(VB_PLAYBACK, LOG_INFO, LOC + __func__ + " - begin");
1096 
1097  const int index = 1; // Output port index
1098 
1099  // Disable output port and free output buffers
1101  e = m_videc.PortDisable(index, 500, &cb);
1102  if (e != OMX_ErrorNone)
1103  return e;
1104 
1105  assert(m_obufs_sema.available() == 0);
1106  assert(m_obufs.isEmpty());
1107 
1108  // Update the output port definition to get revised buffer no. and size
1109  e = m_videc.GetPortDef(index);
1110  if (e != OMX_ErrorNone)
1111  return e;
1112 
1113  // Log the new port definition
1114  m_videc.ShowPortDef(index, LOG_INFO);
1115 
1116  // Set output format
1117  // Broadcom doc says OMX_COLOR_Format16bitRGB565 also supported
1118  OMX_VIDEO_PARAM_PORTFORMATTYPE fmt;
1119  OMX_DATA_INIT(fmt);
1120  fmt.nPortIndex = m_videc.Base() + index;
1121  fmt.eCompressionFormat = OMX_VIDEO_CodingUnused;
1122  fmt.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; // default
1123  e = m_videc.SetParameter(OMX_IndexParamVideoPortFormat, &fmt);
1124  if (e != OMX_ErrorNone)
1125  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
1126  "SetParameter IndexParamVideoPortFormat error %1")
1127  .arg(Error2String(e)));
1128 
1129 #ifdef USING_BROADCOM
1130  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_INFO))
1131  {
1132  OMX_CONFIG_POINTTYPE aspect;
1133  e = GetAspect(aspect, index);
1134  if (e == OMX_ErrorNone)
1135  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Pixel aspect x/y = %1/%2")
1136  .arg(aspect.nX).arg(aspect.nY) );
1137  }
1138 #endif
1139 
1140  ComponentCB PrivateDecoderOMX::*allocBuffers =
1141  &PrivateDecoderOMX::AllocOutputBuffersCB; // -> member fn
1142  if ((m_avctx = avctx) && avctx->get_buffer2)
1143  {
1144  // Use the video output buffers directly
1145  allocBuffers = &PrivateDecoderOMX::UseBuffersCB;
1146  }
1147 
1148  // Re-enable output port and allocate new output buffers
1149  OMXComponentCB<PrivateDecoderOMX> cb2(this, allocBuffers);
1150  e = m_videc.PortEnable(index, 500, &cb2);
1151  if (e != OMX_ErrorNone)
1152  return e;
1153 
1154  // Submit the new output buffers
1155  e = FillOutputBuffers();
1156  if (e != OMX_ErrorNone)
1157  return e;
1158 
1159  lock.relock();
1160  m_bSettingsChanged = false;
1161  m_bSettingsHaveChanged = true;
1162  lock.unlock();
1163 
1164  LOG(VB_PLAYBACK, LOG_INFO, LOC + __func__ + " - end");
1165  return OMX_ErrorNone;
1166 }
1167 
1168 // virtual
1170 {
1171  QMutexLocker lock(&m_lock);
1172  return !m_obufs.isEmpty();
1173 }
1174 
1175 #ifdef USING_BROADCOM
1176 OMX_ERRORTYPE PrivateDecoderOMX::GetAspect(
1177  OMX_CONFIG_POINTTYPE &point, int index) const
1178 {
1179  OMX_DATA_INIT(point);
1180  point.nPortIndex = m_videc.Base() + index;
1181  OMX_ERRORTYPE e = m_videc.GetParameter(OMX_IndexParamBrcmPixelAspectRatio,
1182  &point);
1183  if (e != OMX_ErrorNone)
1184  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
1185  "IndexParamBrcmPixelAspectRatio error %1").arg(Error2String(e)));
1186  return e;
1187 }
1188 #endif
1189 
1190 #ifdef USING_BROADCOM
1191 OMX_ERRORTYPE PrivateDecoderOMX::GetInterlace(
1192  OMX_CONFIG_INTERLACETYPE &interlace, int index) const
1193 {
1194  OMX_DATA_INIT(interlace);
1195  interlace.nPortIndex = m_videc.Base() + index;
1196  OMX_ERRORTYPE e = m_videc.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
1197  if (e != OMX_ErrorNone)
1198  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
1199  "IndexConfigCommonInterlace error %1").arg(Error2String(e)));
1200  return e;
1201 }
1202 #endif // USING_BROADCOM
1203 
1204 // virtual
1205 OMX_ERRORTYPE PrivateDecoderOMX::Event(OMXComponent &cmpnt, OMX_EVENTTYPE eEvent,
1206  OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
1207 {
1208  switch(eEvent)
1209  {
1210  case OMX_EventPortSettingsChanged:
1211  if (nData1 != m_videc.Base() + 1)
1212  break;
1213 
1214  if (m_lock.tryLock(500))
1215  {
1216  m_bSettingsChanged = true;
1217  m_lock.unlock();
1218  }
1219  else
1220  {
1221  LOG(VB_GENERAL, LOG_CRIT, LOC +
1222  "EventPortSettingsChanged deadlock");
1223  }
1224  return OMX_ErrorNone;
1225 
1226  default:
1227  break;
1228  }
1229 
1230  return OMXComponentCtx::Event(cmpnt, eEvent, nData1, nData2, pEventData);
1231 }
1232 
1233 // virtual
1235  OMXComponent& /*cmpnt*/, OMX_BUFFERHEADERTYPE *hdr)
1236 {
1237  assert(hdr->nSize == sizeof(OMX_BUFFERHEADERTYPE));
1238  assert(hdr->nVersion.nVersion == OMX_VERSION);
1239  hdr->nFilledLen = 0;
1240  if (m_lock.tryLock(1000))
1241  {
1242  m_ibufs.append(hdr);
1243  m_lock.unlock();
1244  m_ibufs_sema.release();
1245  }
1246  else
1247  LOG(VB_GENERAL, LOG_CRIT, LOC + "EmptyBufferDone deadlock");
1248  return OMX_ErrorNone;
1249 }
1250 
1251 // virtual
1253  OMXComponent& /*cmpnt*/, OMX_BUFFERHEADERTYPE *hdr)
1254 {
1255  assert(hdr->nSize == sizeof(OMX_BUFFERHEADERTYPE));
1256  assert(hdr->nVersion.nVersion == OMX_VERSION);
1257  if (m_lock.tryLock(1000))
1258  {
1259  m_obufs.append(hdr);
1260  m_lock.unlock();
1261  m_obufs_sema.release();
1262  }
1263  else
1264  LOG(VB_GENERAL, LOG_CRIT, LOC + "FillBufferDone deadlock");
1265  return OMX_ErrorNone;
1266 }
1267 
1268 // virtual
1270 {
1271  // Free all output buffers
1273 
1274  // Free all input buffers
1275  while (m_ibufs_sema.tryAcquire())
1276  {
1277  m_lock.lock();
1278  assert(!m_ibufs.isEmpty());
1279  OMX_BUFFERHEADERTYPE *hdr = m_ibufs.takeFirst();
1280  m_lock.unlock();
1281 
1282  OMX_ERRORTYPE e = OMX_FreeBuffer(m_videc.Handle(), m_videc.Base(), hdr);
1283  if (e != OMX_ErrorNone)
1284  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString(
1285  "OMX_FreeBuffer 0x%1 error %2")
1286  .arg(quintptr(hdr),0,16).arg(Error2String(e)));
1287  }
1288 }
1289 
1290 #define CASE2STR(f) case f: return STR(f)
1291 #define CASE2STR_(f) case f: return #f
1292 
1293 static const char *H264Profile2String(int profile)
1294 {
1295  switch (profile)
1296  {
1297  CASE2STR_(FF_PROFILE_H264_BASELINE);
1298  CASE2STR_(FF_PROFILE_H264_MAIN);
1299  CASE2STR_(FF_PROFILE_H264_EXTENDED);
1300  CASE2STR_(FF_PROFILE_H264_HIGH);
1301  CASE2STR_(FF_PROFILE_H264_HIGH_10);
1302  CASE2STR_(FF_PROFILE_H264_HIGH_10_INTRA);
1303  CASE2STR_(FF_PROFILE_H264_HIGH_422);
1304  CASE2STR_(FF_PROFILE_H264_HIGH_422_INTRA);
1305  CASE2STR_(FF_PROFILE_H264_HIGH_444_PREDICTIVE);
1306  CASE2STR_(FF_PROFILE_H264_HIGH_444_INTRA);
1307  CASE2STR_(FF_PROFILE_H264_CAVLC_444);
1308  }
1309  static char buf[32];
1310  return strcpy(buf, qPrintable(QString("Profile 0x%1").arg(profile)));
1311 }
1312 /* EOF */
OMX_ERRORTYPE GetConfig(OMX_INDEXTYPE type, OMX_PTR p) const
Definition: omxcontext.h:73
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
#define CASE2STR_(f)
int ProcessPacket(AVStream *, AVPacket *)
PlayerFlags
Definition: mythplayer.h:88
#define VIDEO_DECODE
int Copy(VideoFrame *dst, const VideoFrame *src)
Definition: mythavutil.cpp:200
QList< OMX_BUFFERHEADERTYPE * > m_ibufs
OMX_U32 Base() const
Definition: omxcontext.h:48
MythAVCopy m_copyCtx
struct AVFrame AVFrame
bool Reset(void) override
bool IsValid() const
Definition: omxcontext.h:43
bool CreateFilter(AVCodecContext *)
const OMX_PARAM_PORTDEFINITIONTYPE & PortDef(unsigned index=0) const
Definition: omxcontext.cpp:297
static int64_t Ticks2Pts(AVStream *stream, OMX_TICKS ticks)
static int bitsperpixel(VideoFrameType type)
Definition: mythframe.h:267
OMX_ERRORTYPE Event(OMXComponent &, OMX_EVENTTYPE, OMX_U32, OMX_U32, OMX_PTR) override
OMXComponentCtx.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define S64_TO_TICKS(n)
Definition: omxcontext.h:181
ComponentCB UseBuffersCB
int GetFrame(AVStream *stream, AVFrame *picture, int *got_picture_ptr, AVPacket *pkt) override
OMX_ERRORTYPE EmptyBufferDone(OMXComponent &, OMX_BUFFERHEADERTYPE *) override
ComponentCB AllocBuffersCB
enum FrameType_ VideoFrameType
OMX_ERRORTYPE LastError()
Definition: omxcontext.cpp:570
long long copy(QFile &dst, QFile &src, uint block_size)
Copies src file to dst file.
OMX_ERRORTYPE SetNalType(AVCodecContext *)
void ShowPortDef(unsigned index=0, LogLevel_t=LOG_INFO, uint64_t=VB_PLAYBACK) const
Definition: omxcontext.cpp:309
AVCodecContext * m_avctx
bool Init(const QString &decoder, PlayerFlags flags, AVCodecContext *avctx) override
static void GetDecoders(render_opts &opts)
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
OMX_ERRORTYPE PortEnable(unsigned index=0, int ms=-1, OMXComponentAbstractCB *cb=nullptr)
Definition: omxcontext.h:76
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
ComponentCB FreeOutputBuffersCB
MythCodecMap * gCodecMap
This global variable contains the MythCodecMap instance for the app.
Definition: mythavutil.cpp:381
OMX_ERRORTYPE Init(OMX_INDEXTYPE)
Definition: omxcontext.cpp:218
OMX_ERRORTYPE SetState(OMX_STATETYPE state, int ms=-1, OMXComponentAbstractCB *cb=nullptr)
Definition: omxcontext.cpp:457
static QString const s_name
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:24
int height
Definition: mythframe.h:42
const char * Coding2String(OMX_VIDEO_CODINGTYPE eCompressionFormat)
Definition: omxcontext.cpp:792
ComponentCB AllocOutputBuffersCB
void ReleaseBuffers(OMXComponent &) override
OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE type, OMX_PTR p) const
Definition: omxcontext.h:68
QString GetName(void) override
#define FRAMESETREF(f, r)
void Shutdown()
Definition: omxcontext.cpp:185
void OMX_DATA_INIT(T &s)
Definition: omxcontext.h:162
QList< OMX_BUFFERHEADERTYPE * > m_obufs
const char * name
Definition: ParseText.cpp:328
#define TICKS_TO_S64(n)
Definition: omxcontext.h:180
AVCodecContext * getCodecContext(const AVStream *, const AVCodec *pCodec=nullptr, bool nullCodec=false)
Definition: mythavutil.cpp:392
void * av_malloc(unsigned int size)
OMX_ERRORTYPE PortDisable(unsigned index=0, int ms=-1, OMXComponentAbstractCB *cb=nullptr)
Definition: omxcontext.h:79
#define FRAMESETHDRNONE(f)
#define HDR2FRAME(h)
static OMX_TICKS Pts2Ticks(AVStream *stream, int64_t pts)
virtual OMX_ERRORTYPE Event(OMXComponent &, OMX_EVENTTYPE, OMX_U32, OMX_U32, OMX_PTR)
OMXComponentCtx.
Definition: omxcontext.cpp:660
OMX_ERRORTYPE FillOutputBuffers()
int GetNumSetting(const QString &key, int defaultval=0)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define assert(x)
OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE type, OMX_PTR p)
Definition: omxcontext.h:66
#define FRAME2REF(f)
QString HeaderFlags(OMX_U32 nFlags)
OMX_ERRORTYPE FillBufferDone(OMXComponent &, OMX_BUFFERHEADERTYPE *) override
const char * Error2String(OMX_ERRORTYPE eError)
static void init(VideoFrame *vf, VideoFrameType _codec, unsigned char *_buf, int _width, int _height, int _size, const int *p=nullptr, const int *o=nullptr, float _aspect=-1.0F, double _rate=-1.0F, int _aligned=64)
Definition: mythframe.h:115
OMX_ERRORTYPE ComponentCB()
static const char * H264Profile2String(int profile)
#define FRAMESETREFNONE(f)
#define FRAME2HDR(f)
bool IsCommandComplete() const
Definition: omxcontext.h:58
bool HasBufferedFrames(void) override
MythAVFrame little utility class that act as a safe way to allocate an AVFrame which can then be allo...
Definition: mythavutil.h:42
OMX_ERRORTYPE SettingsChanged(AVCodecContext *)
AVBitStreamFilterContext * m_filter
OMX_ERRORTYPE GetAspect(OMX_CONFIG_POINTTYPE &, int index) const
unsigned char * buf
Definition: mythframe.h:39
OMX_ERRORTYPE GetPortDef(unsigned index=0)
Definition: omxcontext.cpp:274
#define LOC
OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE cmd, OMX_U32 nParam=0, void *pCmdData=nullptr, int ms=-1, OMXComponentAbstractCB *cb=nullptr)
Definition: omxcontext.cpp:493
int GetBufferedFrame(AVStream *, AVFrame *)
unsigned Ports() const
Definition: omxcontext.h:49
void ShowFormats(unsigned index=0, LogLevel_t=LOG_INFO, uint64_t=VB_PLAYBACK) const
Definition: omxcontext.cpp:438
#define FRAMESETHDR(f, h)
const char * Format2String(OMX_COLOR_FORMATTYPE eColorFormat)
Definition: omxcontext.cpp:922
#define OMX_VERSION
Definition: omxcontext.h:158
OMX_HANDLETYPE Handle() const
Definition: omxcontext.h:44
VideoFrameType codec
Definition: mythframe.h:38