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