MythTV  master
videobuffers.cpp
Go to the documentation of this file.
1 // Copyright (c) 2005, Daniel Thor Kristjansson
2 // based on earlier work in MythTV's videout_xvmc.cpp
3 
4 // MythTV
5 #include "mythconfig.h"
6 #include "mythcontext.h"
7 #include "fourcc.h"
8 #include "compat.h"
9 #include "mythlogging.h"
10 #include "mythcodecid.h"
11 #include "videobuffers.h"
12 
13 // FFmpeg
14 extern "C" {
15 #include "libavcodec/avcodec.h"
16 }
17 
18 // Std
19 #include <chrono>
20 #include <thread>
21 
22 #define TRY_LOCK_SPINS 2000
23 #define TRY_LOCK_SPINS_BEFORE_WARNING 9999
24 #define TRY_LOCK_SPIN_WAIT 1000 /* usec */
25 
26 int next_dbg_str = 0;
27 
37 static inline void ReleaseDecoderResources(VideoFrame *Frame, vector<AVBufferRef *> &Discards)
38 {
39  if (format_is_hw(Frame->codec))
40  {
41  auto* ref = reinterpret_cast<AVBufferRef*>(Frame->priv[0]);
42  if (ref != nullptr)
43  Discards.push_back(ref);
44  Frame->buf = Frame->priv[0] = nullptr;
45 
46  if (format_is_hwframes(Frame->codec))
47  {
48  ref = reinterpret_cast<AVBufferRef*>(Frame->priv[1]);
49  if (ref != nullptr)
50  Discards.push_back(ref);
51  Frame->priv[1] = nullptr;
52  }
53  }
54 }
55 
56 static inline void DoDiscard(vector<AVBufferRef *> &Discards)
57 {
58  for (auto * it : Discards)
59  av_buffer_unref(&it);
60 }
61 
135 uint VideoBuffers::GetNumBuffers(int PixelFormat, int MaxReferenceFrames, bool Decoder /*=false*/)
136 {
137  uint refs = static_cast<uint>(MaxReferenceFrames);
138  switch (PixelFormat)
139  {
140  case FMT_DXVA2: return 30;
141  // It is currrently unclear whether VTB just happy with a smaller buffer size
142  // or needs reference frames plus headroom - use the latter for now.
143  case FMT_VTB: return refs + 8;
144  // Max 16 ref frames, 12 headroom and allocate 2 extra in the VAAPI frames
145  // context for additional references held by the VPP deinterlacer (i.e.
146  // prevent buffer starvation in the decoder)
147  // This covers the 'worst case' samples.
148  case FMT_VAAPI: return Decoder ? (refs + 14) : (refs + 12);
149  case FMT_VDPAU: return refs + 12;
150  // Copyback of hardware frames. These decoders are buffering internally
151  // already - so no need for a large presentation buffer
152  case FMT_NONE: return 8; // NOLINT(bugprone-branch-clone)
153  // As for copyback, these decoders buffer internally
154  case FMT_NVDEC: return 8;
155  case FMT_MEDIACODEC: return 8;
156  case FMT_MMAL: return 8;
157  // the default number of output buffers in FFmpeg v4l2_m2m.h is 6
158  case FMT_DRMPRIME: return 6;
159  // Standard software decode
160  case FMT_YV12: return refs + 14;
161  default: break;
162  }
163  return 30;
164 }
165 
167 {
168  DeleteBuffers();
169 }
170 
188 void VideoBuffers::Init(uint NumDecode, bool ExtraForPause,
189  uint NeedFree, uint NeedPrebufferNormal,
190  uint NeedPrebufferSmall)
191 {
192  QMutexLocker locker(&m_globalLock);
193 
194  Reset();
195 
196  uint numcreate = NumDecode + ((ExtraForPause) ? 1 : 0);
197 
198  // make a big reservation, so that things that depend on
199  // pointer to VideoFrames work even after a few push_backs
200  m_buffers.reserve(max(numcreate, (uint)128));
201 
202  m_buffers.resize(numcreate);
203  for (uint i = 0; i < numcreate; i++)
204  {
205  memset(At(i), 0, sizeof(VideoFrame));
206  At(i)->codec = FMT_NONE;
207  At(i)->interlaced_frame = -1;
208  At(i)->top_field_first = true;
209  m_vbufferMap[At(i)] = i;
210  }
211 
212  m_needFreeFrames = NeedFree;
213  m_needPrebufferFrames = NeedPrebufferNormal;
214  m_needPrebufferFramesNormal = NeedPrebufferNormal;
215  m_needPrebufferFramesSmall = NeedPrebufferSmall;
216  m_createdPauseFrame = ExtraForPause;
217 
219  Enqueue(kVideoBuffer_pause, At(numcreate - 1));
220 
221  for (uint i = 0; i < NumDecode; i++)
224 }
225 
227  MythCodecID CodecID)
228 {
229  QMutexLocker locker(&m_globalLock);
230  for (auto & buffer : m_buffers)
231  SetDeinterlacingFlags(buffer, Single, Double, CodecID);
232 }
233 
242  MythDeintType Double, MythCodecID CodecID)
243 {
244  static const MythDeintType kDriver = DEINT_ALL & ~(DEINT_CPU | DEINT_SHADER);
245  static const MythDeintType kShader = DEINT_ALL & ~(DEINT_CPU | DEINT_DRIVER);
246  static const MythDeintType kSoftware = DEINT_ALL & ~(DEINT_SHADER | DEINT_DRIVER);
247  Frame.deinterlace_single = Single;
248  Frame.deinterlace_double = Double;
249 
250  if (codec_is_copyback(CodecID))
251  {
252  if (codec_is_vaapi_dec(CodecID) || codec_is_nvdec_dec(CodecID))
253  Frame.deinterlace_allowed = kSoftware | kShader | kDriver;
254  else // VideoToolBox, MediaCodec and VDPAU copyback
255  Frame.deinterlace_allowed = kSoftware | kShader;
256  }
257  else if (FMT_DRMPRIME == Frame.codec)
258  { // NOLINT(bugprone-branch-clone)
259  Frame.deinterlace_allowed = kShader; // No driver deint - if RGBA frames are returned, shaders will be disabled
260  }
261  else if (FMT_MMAL == Frame.codec)
262  {
263  Frame.deinterlace_allowed = kShader; // No driver deint yet (TODO) and YUV frames returned
264  }
265  else if (FMT_VTB == Frame.codec)
266  {
267  Frame.deinterlace_allowed = kShader; // No driver deint and YUV frames returned
268  }
269  else if (FMT_NVDEC == Frame.codec)
270  {
271  Frame.deinterlace_allowed = kShader | kDriver; // YUV frames and decoder deint
272  }
273  else if (FMT_VDPAU == Frame.codec)
274  { // NOLINT(bugprone-branch-clone)
275  Frame.deinterlace_allowed = kDriver; // No YUV frames for shaders
276  }
277  else if (FMT_VAAPI == Frame.codec)
278  {
279  Frame.deinterlace_allowed = kDriver; // DRM will allow shader if no VPP
280  }
281  else
282  {
283  Frame.deinterlace_allowed = kSoftware | kShader;
284  }
285 }
286 
292 {
293  QMutexLocker locker(&m_globalLock);
294  m_available.clear();
295  m_used.clear();
296  m_limbo.clear();
297  m_finished.clear();
298  m_decode.clear();
299  m_pause.clear();
300  m_displayed.clear();
301  m_vbufferMap.clear();
302 }
303 
309 {
310  QMutexLocker locker(&m_globalLock);
312 }
313 
315 {
316  QMutexLocker locker(&m_globalLock);
317  VideoFrame *frame = nullptr;
318 
319  // Try to get a frame not being used by the decoder
320  for (size_t i = 0; i < m_available.size(); i++)
321  {
322  frame = m_available.dequeue();
323  if (m_decode.contains(frame))
324  m_available.enqueue(frame);
325  else
326  break;
327  }
328 
329  while (frame && m_used.contains(frame))
330  {
331  LOG(VB_PLAYBACK, LOG_NOTICE,
332  QString("GetNextFreeFrame() served a busy frame %1. Dropping. %2")
333  .arg(DebugString(frame, true)).arg(GetStatus()));
334  frame = m_available.dequeue();
335  }
336 
337  if (frame)
338  SafeEnqueue(EnqueueTo, frame);
339  return frame;
340 }
341 
347 {
348  for (uint tries = 1; true; tries++)
349  {
351  if (frame)
352  return frame;
353 
354  if (tries >= TRY_LOCK_SPINS)
355  {
356  LOG(VB_GENERAL, LOG_ERR, QString("GetNextFreeFrame: "
357  "available:%1 used:%2 limbo:%3 pause:%4 displayed:%5 decode:%6 finished:%7")
358  .arg(m_available.size()).arg(m_used.size()).arg(m_limbo.size())
359  .arg(m_pause.size()).arg(m_displayed.size()).arg(m_decode.size())
360  .arg(m_finished.size()));
361  LOG(VB_GENERAL, LOG_ERR,
362  QString("GetNextFreeFrame() unable to "
363  "lock frame %1 times. Discarding Frames.")
364  .arg(TRY_LOCK_SPINS));
365  DiscardFrames(true);
366  continue;
367  }
368 
369  if (tries && !(tries % TRY_LOCK_SPINS_BEFORE_WARNING))
370  {
371  LOG(VB_PLAYBACK, LOG_NOTICE,
372  QString("GetNextFreeFrame() TryLock has "
373  "spun %1 times, this is a lot.").arg(tries));
374  }
375  std::this_thread::sleep_for(std::chrono::microseconds(TRY_LOCK_SPIN_WAIT));
376  }
377 
378  return nullptr;
379 }
380 
388 {
389  QMutexLocker locker(&m_globalLock);
390 
393  //non directrendering frames are ffmpeg handled
394  if (Frame->directrendering)
397 }
398 
405 {
406  vector<AVBufferRef*> discards;
407 
408  m_globalLock.lock();
409 
410  if (m_limbo.contains(Frame))
412 
413  // if decoder didn't release frame and the buffer is getting released by
414  // the decoder assume that the frame is lost and return to available
415  if (!m_decode.contains(Frame))
416  {
417  ReleaseDecoderResources(Frame, discards);
419  }
420 
421  // remove from decode queue since the decoder is finished
422  while (m_decode.contains(Frame))
424 
425  m_globalLock.unlock();
426 
427  DoDiscard(discards);
428 }
429 
435 {
436  QMutexLocker locker(&m_globalLock);
438 }
439 
445 {
446  vector<AVBufferRef*> discards;
447 
448  m_globalLock.lock();
449 
450  if(m_used.contains(Frame))
452 
454 
455  // check if any finished frames are no longer used by decoder and return to available
457  for (auto & it : ula)
458  {
459  if (!m_decode.contains(it))
460  {
462  ReleaseDecoderResources(it, discards);
464  }
465  }
466 
467  m_globalLock.unlock();
468 
469  DoDiscard(discards);
470 }
471 
478 {
479  vector<AVBufferRef*> discards;
480  m_globalLock.lock();
481  ReleaseDecoderResources(Frame, discards);
483  m_globalLock.unlock();
484  DoDiscard(discards);
485 }
486 
488 {
489  vector<AVBufferRef*> discards;
490 
491  m_globalLock.lock();
492  while (Size(kVideoBuffer_pause))
493  {
495  ReleaseDecoderResources(frame, discards);
497  }
498  m_globalLock.unlock();
499 
500  DoDiscard(discards);
501 }
502 
509 bool VideoBuffers::DiscardAndRecreate(MythCodecID CodecID, QSize VideoDim, int References)
510 {
511  bool result = false;
512  vector<AVBufferRef*> refs;
513 
514  m_globalLock.lock();
515  LOG(VB_PLAYBACK, LOG_INFO, QString("DiscardAndRecreate: %1").arg(GetStatus()));
516 
517  // Remove pause frames (cutdown version of DiscardPauseFrames)
518  while (Size(kVideoBuffer_pause))
519  {
521  ReleaseDecoderResources(frame, refs);
523  }
524 
525  // See DiscardFrames
526  frame_queue_t ula(m_used);
527  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
528  ula.insert(ula.end(), m_available.begin(), m_available.end());
529  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
530 
531  frame_queue_t discards(m_used);
532  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
533  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
534  for (auto & discard : discards)
535  {
536  ReleaseDecoderResources(discard, refs);
538  }
539 
540  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
541  {
542  for (uint i = 0; i < Size(); i++)
543  {
544  if (!m_available.contains(At(i)) && !m_pause.contains(At(i)) &&
545  !m_displayed.contains(At(i)))
546  {
547  LOG(VB_GENERAL, LOG_INFO,
548  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
549  "in available, pause, or displayed %3")
550  .arg(DebugString(At(i), true)).arg(reinterpret_cast<long long>(At(i)))
551  .arg(GetStatus()));
552  ReleaseDecoderResources(At(i), refs);
554  }
555  }
556  }
557 
558  for (auto & it : m_decode)
560  for (auto & it : m_decode)
561  m_available.enqueue(it);
562  m_decode.clear();
563 
564  DeleteBuffers();
565  Reset();
566 
567  // Recreate - see MythVideoOutputOpenGL::CreateBuffers
568  if (codec_is_copyback(CodecID))
569  {
570  Init(VideoBuffers::GetNumBuffers(FMT_NONE), false, 1, 4, 2);
571  result = CreateBuffers(FMT_YV12, VideoDim.width(), VideoDim.height());
572  }
573  else if (codec_is_mediacodec(CodecID))
574  {
575  result = CreateBuffers(FMT_MEDIACODEC, VideoDim, false, 1, 2, 2);
576  }
577  else if (codec_is_vaapi(CodecID))
578  {
579  result = CreateBuffers(FMT_VAAPI, VideoDim, false, 2, 1, 4, References);
580  }
581  else if (codec_is_vtb(CodecID))
582  {
583  result = CreateBuffers(FMT_VTB, VideoDim, false, 1, 4, 2);
584  }
585  else if (codec_is_vdpau(CodecID))
586  {
587  result = CreateBuffers(FMT_VDPAU, VideoDim, false, 2, 1, 4, References);
588  }
589  else if (codec_is_nvdec(CodecID))
590  {
591  result = CreateBuffers(FMT_NVDEC, VideoDim, false, 2, 1, 4);
592  }
593  else if (codec_is_mmal(CodecID))
594  {
595  result = CreateBuffers(FMT_MMAL, VideoDim, false, 2, 1, 4);
596  }
597  else if (codec_is_v4l2(CodecID) || codec_is_drmprime(CodecID))
598  {
599  result = CreateBuffers(FMT_DRMPRIME, VideoDim, false, 2, 1, 4);
600  }
601  else
602  {
603  result = CreateBuffers(FMT_YV12, VideoDim, false, 1, 8, 4, References);
604  }
605 
606  LOG(VB_PLAYBACK, LOG_INFO, QString("DiscardAndRecreate: %1").arg(GetStatus()));
607  m_globalLock.unlock();
608 
609  // and finally release references now that the lock is released
610  DoDiscard(refs);
611  return result;
612 }
613 
615 {
616  QMutexLocker locker(&m_globalLock);
617  frame_queue_t *queue = nullptr;
618  if (Type == kVideoBuffer_avail)
619  queue = &m_available;
620  else if (Type == kVideoBuffer_used)
621  queue = &m_used;
622  else if (Type == kVideoBuffer_displayed)
623  queue = &m_displayed;
624  else if (Type == kVideoBuffer_limbo)
625  queue = &m_limbo;
626  else if (Type == kVideoBuffer_pause)
627  queue = &m_pause;
628  else if (Type == kVideoBuffer_decode)
629  queue = &m_decode;
630  else if (Type == kVideoBuffer_finished)
631  queue = &m_finished;
632  return queue;
633 }
634 
636 {
637  QMutexLocker locker(&m_globalLock);
638  const frame_queue_t *queue = nullptr;
639  if (Type == kVideoBuffer_avail)
640  queue = &m_available;
641  else if (Type == kVideoBuffer_used)
642  queue = &m_used;
643  else if (Type == kVideoBuffer_displayed)
644  queue = &m_displayed;
645  else if (Type == kVideoBuffer_limbo)
646  queue = &m_limbo;
647  else if (Type == kVideoBuffer_pause)
648  queue = &m_pause;
649  else if (Type == kVideoBuffer_decode)
650  queue = &m_decode;
651  else if (Type == kVideoBuffer_finished)
652  queue = &m_finished;
653  return queue;
654 }
655 
657 {
658  return &m_buffers[FrameNum];
659 }
660 
661 const VideoFrame* VideoBuffers::At(uint FrameNum) const
662 {
663  return &m_buffers[FrameNum];
664 }
665 
667 {
668  QMutexLocker locker(&m_globalLock);
669  frame_queue_t *queue = Queue(Type);
670  if (!queue)
671  return nullptr;
672  return queue->dequeue();
673 }
674 
676 {
677  QMutexLocker locker(&m_globalLock);
678  frame_queue_t *queue = Queue(Type);
679  if (!queue)
680  return nullptr;
681  if (!queue->empty())
682  return queue->head();
683  return nullptr;
684 }
685 
687 {
688  QMutexLocker locker(&m_globalLock);
689  frame_queue_t *queue = Queue(Type);
690  if (!queue)
691  return nullptr;
692  if (!queue->empty())
693  return queue->tail();
694  return nullptr;
695 }
696 
698 {
699  if (!Frame)
700  return;
701  frame_queue_t *queue = Queue(Type);
702  if (!queue)
703  return;
704  m_globalLock.lock();
705  queue->remove(Frame);
706  queue->enqueue(Frame);
707  if (Type == kVideoBuffer_pause)
708  Frame->pause_frame = true;
709  m_globalLock.unlock();
710 }
711 
713 {
714  if (!Frame)
715  return;
716 
717  QMutexLocker locker(&m_globalLock);
718  if ((Type & kVideoBuffer_avail) == kVideoBuffer_avail)
720  if ((Type & kVideoBuffer_used) == kVideoBuffer_used)
724  if ((Type & kVideoBuffer_limbo) == kVideoBuffer_limbo)
726  if ((Type & kVideoBuffer_pause) == kVideoBuffer_pause)
732 }
733 
735 {
736  QMutexLocker locker(&m_globalLock);
737  Count = (Count <= 0) ? Size(Source) : Count;
738  for (uint i=0; i<(uint)Count; i++)
739  {
740  VideoFrame *frame = Dequeue(Source);
741  if (frame)
742  Enqueue(Dest, frame);
743  }
744 }
745 
747 {
748  if (!Frame)
749  return;
750  QMutexLocker locker(&m_globalLock);
752  Enqueue(Type, Frame);
753 }
754 
761 {
762  m_globalLock.lock();
763  frame_queue_t *queue = Queue(Type);
764  if (queue)
765  return queue->begin();
766  return m_available.begin();
767 }
768 
770 {
771  m_globalLock.unlock();
772 }
773 
775 {
776  QMutexLocker locker(&m_globalLock);
777  frame_queue_t *queue = Queue(Type);
778  return (queue ? queue->end() : m_available.end());
779 }
780 
782 {
783  QMutexLocker locker(&m_globalLock);
784  const frame_queue_t *queue = Queue(Type);
785  if (queue)
786  return queue->size();
787  return 0;
788 }
789 
791 {
792  QMutexLocker locker(&m_globalLock);
793  const frame_queue_t *queue = Queue(Type);
794  if (queue)
795  return queue->contains(Frame);
796  return false;
797 }
798 
800 {
802  {
803  LOG(VB_GENERAL, LOG_ERR, "GetScratchFrame() called, but not allocated");
804  return nullptr;
805  }
806 
807  QMutexLocker locker(&m_globalLock);
808  return Head(kVideoBuffer_pause);
809 }
810 
812 {
813  return At(m_vpos);
814 }
815 
817 {
818  return At(m_rpos);
819 }
820 
822 {
824  {
825  LOG(VB_GENERAL, LOG_ERR,
826  "SetLastShownFrameToScratch() called but no pause frame");
827  return;
828  }
829 
831  m_rpos = m_vbufferMap[pause];
832 }
833 
835 {
836  return Size(kVideoBuffer_used);
837 }
838 
840 {
841  return Size(kVideoBuffer_avail);
842 }
843 
845 {
847 }
848 
850 {
852 }
853 
855 {
856  return At(m_vpos);
857 }
858 
860 {
861  return At(m_rpos);
862 }
863 
865 {
866  return m_buffers.size();
867 }
868 
873 void VideoBuffers::DiscardFrames(bool NextFrameIsKeyFrame)
874 {
875  vector<AVBufferRef*> refs;
876  m_globalLock.lock();
877  LOG(VB_PLAYBACK, LOG_INFO, QString("VideoBuffers::DiscardFrames(%1): %2")
878  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
879 
880  if (!NextFrameIsKeyFrame)
881  {
882  frame_queue_t ula(m_used);
883  for (auto & it : ula)
884  {
885  ReleaseDecoderResources(it, refs);
887  }
888  LOG(VB_PLAYBACK, LOG_INFO,
889  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
890  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
891  m_globalLock.unlock();
892  DoDiscard(refs);
893  return;
894  }
895 
896  // Remove inheritence of all frames not in displayed or pause
897  frame_queue_t ula(m_used);
898  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
899  ula.insert(ula.end(), m_available.begin(), m_available.end());
900  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
902 
903  // Discard frames
904  frame_queue_t discards(m_used);
905  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
906  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
907  for (it = discards.begin(); it != discards.end(); ++it)
908  {
909  ReleaseDecoderResources(*it, refs);
911  }
912 
913  // Verify that things are kosher
914  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
915  {
916  for (uint i = 0; i < Size(); i++)
917  {
918  if (!m_available.contains(At(i)) && !m_pause.contains(At(i)) &&
919  !m_displayed.contains(At(i)))
920  {
921  // This message is DEBUG because it does occur
922  // after Reset is called.
923  // That happens when failing over from OpenGL
924  // to another method, if QT painter is selected.
925  LOG(VB_GENERAL, LOG_DEBUG,
926  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
927  "in available, pause, or displayed %3")
928  .arg(DebugString(At(i), true)).arg((long long)At(i))
929  .arg(GetStatus()));
930  ReleaseDecoderResources(At(i), refs);
932  }
933  }
934  }
935 
936  // Make sure frames used by decoder are last...
937  // This is for libmpeg2 which still uses the frames after a reset.
938  for (it = m_decode.begin(); it != m_decode.end(); ++it)
939  Remove(kVideoBuffer_all, *it);
940  for (it = m_decode.begin(); it != m_decode.end(); ++it)
941  m_available.enqueue(*it);
942  m_decode.clear();
943 
944  LOG(VB_PLAYBACK, LOG_INFO,
945  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
946  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
947 
948  m_globalLock.unlock();
949  DoDiscard(refs);
950 }
951 
961 {
962  vector<AVBufferRef*> discards;
963  {
964  QMutexLocker locker(&m_globalLock);
965 
966  for (uint i = 0; i < Size(); i++)
967  At(i)->timecode = 0;
968 
969  for (uint i = 0; (i < Size()) && (m_used.count() > 1); i++)
970  {
971  VideoFrame *buffer = At(i);
972  if (m_used.contains(buffer) && !m_decode.contains(buffer))
973  {
974  m_used.remove(buffer);
975  m_available.enqueue(buffer);
976  ReleaseDecoderResources(buffer, discards);
977  }
978  }
979 
980  if (m_used.count() > 0)
981  {
982  for (uint i = 0; i < Size(); i++)
983  {
984  VideoFrame *buffer = At(i);
985  if (m_used.contains(buffer) && !m_decode.contains(buffer))
986  {
987  m_used.remove(buffer);
988  m_available.enqueue(buffer);
989  ReleaseDecoderResources(buffer, discards);
990  m_vpos = m_vbufferMap[buffer];
991  m_rpos = m_vpos;
992  break;
993  }
994  }
995  }
996  else
997  {
998  m_vpos = m_rpos = 0;
999  }
1000  }
1001 
1002  DoDiscard(discards);
1003 }
1004 
1005 bool VideoBuffers::CreateBuffers(VideoFrameType Type, QSize Size, bool ExtraForPause,
1006  uint NeedFree, uint NeedprebufferNormal,
1007  uint NeedPrebufferSmall, int MaxReferenceFrames)
1008 {
1009  Init(GetNumBuffers(Type, MaxReferenceFrames), ExtraForPause, NeedFree, NeedprebufferNormal,
1010  NeedPrebufferSmall);
1011  return CreateBuffers(Type, Size.width(), Size.height());
1012 }
1013 
1014 bool VideoBuffers::CreateBuffers(VideoFrameType Type, int Width, int Height)
1015 {
1016  bool success = true;
1017 
1018  // Hardware buffers with no allocated memory
1019  if (format_is_hw(Type))
1020  {
1021  for (uint i = 0; i < Size(); i++)
1022  success &= CreateBuffer(Width, Height, i, nullptr, Type);
1023  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 empty %2 (%3x%4) video buffers")
1024  .arg(Size()).arg(format_description(Type)).arg(Width).arg(Height));
1025  return success;
1026  }
1027 
1028  // Software buffers
1029  size_t bufsize = GetBufferSize(Type, Width, Height);
1030  for (uint i = 0; i < Size(); i++)
1031  {
1032  unsigned char *data = GetAlignedBuffer(bufsize);
1033  if (!data)
1034  LOG(VB_GENERAL, LOG_CRIT, "Failed to allocate video buffer memory");
1035  init(&m_buffers[i], Type, data, Width, Height, static_cast<int>(bufsize));
1036  success &= (m_buffers[i].buf != nullptr);
1037  }
1038 
1039  Clear();
1040  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 %2 (%3x%4) video buffers")
1041  .arg(Size()).arg(format_description(Type)).arg(Width).arg(Height));
1042  return success;
1043 }
1044 
1045 bool VideoBuffers::CreateBuffer(int Width, int Height, uint Number,
1046  void* Data, VideoFrameType Format)
1047 {
1048  if (Number >= Size())
1049  return false;
1050  init(&m_buffers[Number], Format, (unsigned char*)Data, Width, Height, 0);
1051  return true;
1052 }
1053 
1055 {
1056  next_dbg_str = 0;
1057  for (uint i = 0; i < Size(); i++)
1058  av_freep(&(m_buffers[i].buf));
1059 }
1060 
1062  int Width, int Height)
1063 {
1064  if (!Frame)
1065  return false;
1066  if (format_is_hw(Type) || format_is_hw(Frame->codec))
1067  {
1068  LOG(VB_GENERAL, LOG_ERR, "Cannot re-initialise a hardware buffer");
1069  return false;
1070  }
1071 
1072  // Find the frame
1073  VideoFrameType old = Frame->codec;
1074  size_t size = GetBufferSize(Type, Width, Height);
1075  unsigned char *buf = Frame->buf;
1076  bool newbuf = false;
1077  if ((Frame->size != static_cast<int>(size)) || !buf)
1078  {
1079  // Free existing buffer
1080  av_freep(&buf);
1081  Frame->buf = nullptr;
1082 
1083  // Initialise new
1084  buf = GetAlignedBuffer(size);
1085  if (!buf)
1086  {
1087  LOG(VB_GENERAL, LOG_ERR, "Failed to reallocate frame buffer");
1088  return false;
1089  }
1090  newbuf = true;
1091  }
1092 
1093  LOG(VB_PLAYBACK, LOG_INFO, QString("Reallocated frame %1 %2x%3->%4 %5x%6 (New buffer: %7)")
1094  .arg(format_description(old)).arg(Frame->width).arg(Frame->height)
1095  .arg(format_description(Type)).arg(Width).arg(Height)
1096  .arg(newbuf));
1097  MythDeintType singler = Frame->deinterlace_single;
1098  MythDeintType doubler = Frame->deinterlace_double;
1099  init(Frame, Type, buf, Width, Height, static_cast<int>(size));
1100  // retain deinterlacer settings and update restrictions based on new frame type
1101  SetDeinterlacingFlags(*Frame, singler, doubler, CodecID);
1102  clear(Frame);
1103  return true;
1104 }
1105 
1106 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num);
1107 
1108 QString VideoBuffers::GetStatus(uint Num) const
1109 {
1110  if (Num == 0)
1111  Num = Size();
1112 
1113  QString str("");
1114  if (m_globalLock.tryLock())
1115  {
1116  int count = Size();
1117  unsigned long long a = to_bitmap(m_available, count);
1118  unsigned long long u = to_bitmap(m_used, count);
1119  unsigned long long d = to_bitmap(m_displayed, count);
1120  unsigned long long l = to_bitmap(m_limbo, count);
1121  unsigned long long p = to_bitmap(m_pause, count);
1122  unsigned long long f = to_bitmap(m_finished, count);
1123  unsigned long long x = to_bitmap(m_decode, count);
1124  for (uint i = 0; i < Num; i++)
1125  {
1126  unsigned long long mask = 1ULL << i;
1127  QString tmp("");
1128  if (a & mask)
1129  tmp += (x & mask) ? "a" : "A";
1130  if (u & mask)
1131  tmp += (x & mask) ? "u" : "U";
1132  if (d & mask)
1133  tmp += (x & mask) ? "d" : "D";
1134  if (l & mask)
1135  tmp += (x & mask) ? "l" : "L";
1136  if (p & mask)
1137  tmp += (x & mask) ? "p" : "P";
1138  if (f & mask)
1139  tmp += (x & mask) ? "f" : "F";
1140  if (0 == tmp.length())
1141  str += " ";
1142  else if (1 == tmp.length())
1143  str += tmp;
1144  else
1145  str += "(" + tmp + ")";
1146  }
1147  m_globalLock.unlock();
1148  }
1149  else
1150  {
1151  for (uint i = 0; i < Num; i++)
1152  str += " ";
1153  }
1154  return str;
1155 }
1156 
1158 {
1159  clear(At(FrameNum));
1160 }
1161 
1163 {
1164  for (uint i = 0; i < Size(); i++)
1165  Clear(i);
1166 }
1167 
1168 /*******************************
1169  ** Debugging functions below **
1170  *******************************/
1171 
1172 #define DBG_STR_ARR_SIZE 40
1174 {
1175  "A ", " B ", " C ", " D ",
1176  " E ", " F ", " G ", " H", // 8
1177  "a ", " b ", " c ", " d ",
1178  " e ", " f ", " g ", " h", // 16
1179  "0 ", " 1 ", " 2 ", " 3 ",
1180  " 4 ", " 5 ", " 6 ", " 7", // 24
1181  "I ", " J ", " K ", " L ",
1182  " M ", " N ", " O ", " P", // 32
1183  "i ", " j ", " k ", " l ",
1184  " m ", " n ", " o ", " p", // 40
1185 };
1187 {
1188  "A","B","C","D","E","F","G","H", // 8
1189  "a","b","c","d","e","f","g","h", // 16
1190  "0","1","2","3","4","5","6","7", // 24
1191  "I","J","K","L","M","N","O","P", // 32
1192  "i","j","k","l","m","n","o","p", // 40
1193 };
1194 
1195 map<const VideoFrame *, int> dbg_str;
1196 
1197 static int DebugNum(const VideoFrame *Frame)
1198 {
1199  auto it = dbg_str.find(Frame);
1200  if (it == dbg_str.end())
1201  return dbg_str[Frame] = next_dbg_str++;
1202  return it->second;
1203 }
1204 
1205 const QString& DebugString(const VideoFrame *Frame, bool Short)
1206 {
1207  if (Short)
1210 }
1211 
1212 const QString& DebugString(uint FrameNum, bool Short)
1213 {
1214  return ((Short) ? dbg_str_arr_short : dbg_str_arr)[FrameNum];
1215 }
1216 
1217 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num)
1218 {
1219  unsigned long long bitmap = 0;
1220  for (auto *it : Queue)
1221  {
1222  int shift = DebugNum(it) % Num;
1223  bitmap |= 1ULL << shift;
1224  }
1225  return bitmap;
1226 }
MythDeque::remove
void remove(T const item)
Removes any item from list. O(n).
Definition: mythdeque.h:67
VideoBuffers::m_createdPauseFrame
bool m_createdPauseFrame
Definition: videobuffers.h:127
FMT_MEDIACODEC
@ FMT_MEDIACODEC
Definition: mythframe.h:65
DebugNum
static int DebugNum(const VideoFrame *Frame)
Definition: videobuffers.cpp:1197
codec_is_copyback
#define codec_is_copyback(id)
Definition: mythcodecid.h:344
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:129
VideoBuffers::ValidVideoFrames
uint ValidVideoFrames(void) const
Definition: videobuffers.cpp:834
kVideoBuffer_avail
@ kVideoBuffer_avail
Definition: videobuffers.h:29
VideoBuffers::Size
uint Size(void) const
Definition: videobuffers.cpp:864
VideoBuffers::Contains
bool Contains(BufferType Type, VideoFrame *Frame) const
Definition: videobuffers.cpp:790
GetBufferSize
static size_t GetBufferSize(VideoFrameType Type, int Width, int Height, int Aligned=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.h:658
VideoBuffers::Tail
VideoFrame * Tail(BufferType Type)
Definition: videobuffers.cpp:686
VideoBuffers::Remove
void Remove(BufferType Type, VideoFrame *Frame)
Definition: videobuffers.cpp:712
FMT_VTB
@ FMT_VTB
Definition: mythframe.h:66
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:128
VideoBuffers::m_available
frame_queue_t m_available
Definition: videobuffers.h:113
VideoBuffers::m_needPrebufferFrames
uint m_needPrebufferFrames
Definition: videobuffers.h:124
kCodec_NONE
@ kCodec_NONE
Definition: mythcodecid.h:14
FMT_DRMPRIME
@ FMT_DRMPRIME
Definition: mythframe.h:68
kVideoBuffer_decode
@ kVideoBuffer_decode
Definition: videobuffers.h:35
VideoBuffers::m_needPrebufferFramesNormal
uint m_needPrebufferFramesNormal
Definition: videobuffers.h:125
d
static const uint16_t * d
Definition: iso6937tables.cpp:1025
Frame
Definition: zmdefines.h:93
VideoFrame::timecode
long long timecode
Definition: mythframe.h:150
VideoBuffers::EnoughDecodedFrames
bool EnoughDecodedFrames(void) const
Definition: videobuffers.cpp:849
codec_is_nvdec
#define codec_is_nvdec(id)
Definition: mythcodecid.h:328
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:123
VideoBuffers::ReinitBuffer
static bool ReinitBuffer(VideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
Definition: videobuffers.cpp:1061
arg
arg(title).arg(filename).arg(doDelete))
VideoBuffers::DoneDisplayingFrame
void DoneDisplayingFrame(VideoFrame *Frame)
Definition: videobuffers.cpp:444
VideoBuffers::SetDeinterlacing
void SetDeinterlacing(MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
Definition: videobuffers.cpp:226
VideoBuffers::DiscardAndRecreate
bool DiscardAndRecreate(MythCodecID CodecID, QSize VideoDim, int References)
Discard all buffers and recreate.
Definition: videobuffers.cpp:509
VideoBuffers::m_limbo
frame_queue_t m_limbo
Definition: videobuffers.h:115
codec_is_vdpau
#define codec_is_vdpau(id)
Definition: mythcodecid.h:298
MythDate::Format
Format
Definition: mythdate.h:12
VideoBuffers::At
VideoFrame * At(uint FrameNum)
Definition: videobuffers.cpp:656
codec_is_mmal
#define codec_is_mmal(id)
Definition: mythcodecid.h:341
VideoBuffers::End
frame_queue_t::iterator End(BufferType Type)
Definition: videobuffers.cpp:774
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
kVideoBuffer_finished
@ kVideoBuffer_finished
Definition: videobuffers.h:34
DEINT_ALL
@ DEINT_ALL
Definition: mythframe.h:130
VideoFrame
Definition: mythframe.h:137
TRY_LOCK_SPIN_WAIT
#define TRY_LOCK_SPIN_WAIT
Definition: videobuffers.cpp:24
MythDeque::tail
T tail()
Returns item at tail of list. O(1).
Definition: mythdeque.h:92
VideoBuffers::DeLimboFrame
void DeLimboFrame(VideoFrame *Frame)
Definition: videobuffers.cpp:404
VideoBuffers::CreateBuffer
bool CreateBuffer(int Width, int Height, uint Number, void *Data, VideoFrameType Format)
Definition: videobuffers.cpp:1045
VideoBuffers::CreateBuffers
bool CreateBuffers(VideoFrameType Type, QSize Size, bool ExtraForPause, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall, int MaxReferenceFrames=16)
Definition: videobuffers.cpp:1005
VideoBuffers::DiscardFrame
void DiscardFrame(VideoFrame *Frame)
Definition: videobuffers.cpp:477
format_is_hwframes
static bool format_is_hwframes(VideoFrameType Type)
Definition: mythframe.h:81
VideoBuffers::SetDeinterlacingFlags
static void SetDeinterlacingFlags(VideoFrame &Frame, MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
Set the appropriate flags for single and double rate deinterlacing.
Definition: videobuffers.cpp:241
VideoFrame::codec
VideoFrameType codec
Definition: mythframe.h:139
VideoBuffers::SafeEnqueue
void SafeEnqueue(BufferType Type, VideoFrame *Frame)
Definition: videobuffers.cpp:746
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
dbg_str
map< const VideoFrame *, int > dbg_str
Definition: videobuffers.cpp:1195
VideoBuffers::m_vpos
uint m_vpos
Definition: videobuffers.h:129
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:26
VideoBuffers::m_pause
frame_queue_t m_pause
Definition: videobuffers.h:116
VideoBuffers::m_buffers
frame_vector_t m_buffers
Definition: videobuffers.h:121
TRY_LOCK_SPINS_BEFORE_WARNING
#define TRY_LOCK_SPINS_BEFORE_WARNING
Definition: videobuffers.cpp:23
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:127
videobuffers.h
MythCodecID
MythCodecID
Definition: mythcodecid.h:10
Decoder
Definition: decoder.h:65
format_is_hw
static bool format_is_hw(VideoFrameType Type)
Definition: mythframe.h:73
VideoBuffers::m_displayed
frame_queue_t m_displayed
Definition: videobuffers.h:117
mythlogging.h
codec_is_mediacodec
#define codec_is_mediacodec(id)
Definition: mythcodecid.h:323
Source
Definition: channelsettings.cpp:68
VideoFrame::interlaced_frame
int interlaced_frame
1 if interlaced. 0 if not interlaced. -1 if unknown.
Definition: mythframe.h:153
VideoBuffers::~VideoBuffers
virtual ~VideoBuffers()
Definition: videobuffers.cpp:166
VideoBuffers::m_vbufferMap
vbuffer_map_t m_vbufferMap
Definition: videobuffers.h:120
VideoBuffers::GetLastDecodedFrame
VideoFrame * GetLastDecodedFrame(void)
Definition: videobuffers.cpp:811
hardwareprofile.config.p
p
Definition: config.py:33
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:28
VideoBuffers::GetNextFreeFrameInternal
VideoFrame * GetNextFreeFrameInternal(BufferType EnqueueTo)
Definition: videobuffers.cpp:314
VideoBuffers::m_globalLock
QMutex m_globalLock
Definition: videobuffers.h:130
compat.h
VideoBuffers::EnoughFreeFrames
bool EnoughFreeFrames(void) const
Definition: videobuffers.cpp:844
VideoBuffers::m_finished
frame_queue_t m_finished
Definition: videobuffers.h:119
VideoBuffers::Queue
frame_queue_t * Queue(BufferType Type)
Definition: videobuffers.cpp:614
ReleaseDecoderResources
static void ReleaseDecoderResources(VideoFrame *Frame, vector< AVBufferRef * > &Discards)
Store AVBufferRef's for later disposal.
Definition: videobuffers.cpp:37
VideoBuffers::StartDisplayingFrame
void StartDisplayingFrame(void)
Definition: videobuffers.cpp:434
VideoBuffers::GetNextFreeFrame
VideoFrame * GetNextFreeFrame(BufferType EnqueueTo=kVideoBuffer_limbo)
Gets a frame from available buffers list.
Definition: videobuffers.cpp:346
VideoBuffers::GetScratchFrame
VideoFrame * GetScratchFrame(void)
Definition: videobuffers.cpp:799
VideoBuffers::SetLastShownFrameToScratch
void SetLastShownFrameToScratch(void)
Definition: videobuffers.cpp:821
mythcodecid.h
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:846
VideoFrame::top_field_first
bool top_field_first
true if top field is first.
Definition: mythframe.h:154
kVideoBuffer_all
@ kVideoBuffer_all
Definition: videobuffers.h:36
VideoBuffers::Init
void Init(uint NumDecode, bool ExtraForPause, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall)
Creates buffers and sets various buffer management parameters.
Definition: videobuffers.cpp:188
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:600
VideoBuffers::Reset
void Reset(void)
Definition: videobuffers.cpp:291
VideoBuffers::m_needFreeFrames
uint m_needFreeFrames
Definition: videobuffers.h:123
init
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=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.h:232
uint
unsigned int uint
Definition: compat.h:140
VideoBuffers::GetLastShownFrame
VideoFrame * GetLastShownFrame(void)
Definition: videobuffers.cpp:816
VideoBuffers::BeginLock
frame_queue_t::iterator BeginLock(BufferType Type)
Lock the video buffers.
Definition: videobuffers.cpp:760
FMT_NVDEC
@ FMT_NVDEC
Definition: mythframe.h:67
codec_is_drmprime
#define codec_is_drmprime(id)
Definition: mythcodecid.h:296
dbg_str_arr
QString dbg_str_arr[DBG_STR_ARR_SIZE]
Definition: videobuffers.cpp:1173
kVideoBuffer_limbo
@ kVideoBuffer_limbo
Definition: videobuffers.h:30
VideoBuffers::EndLock
void EndLock()
Definition: videobuffers.cpp:769
VideoBuffers::DiscardPauseFrames
void DiscardPauseFrames(void)
Definition: videobuffers.cpp:487
kVideoBuffer_pause
@ kVideoBuffer_pause
Definition: videobuffers.h:32
dbg_str_arr_short
QString dbg_str_arr_short[DBG_STR_ARR_SIZE]
Definition: videobuffers.cpp:1186
kVideoBuffer_displayed
@ kVideoBuffer_displayed
Definition: videobuffers.h:33
VideoBuffers::Dequeue
VideoFrame * Dequeue(BufferType Type)
Definition: videobuffers.cpp:666
MythDeintType
MythDeintType
Definition: mythframe.h:121
VideoBuffers::m_used
frame_queue_t m_used
Definition: videobuffers.h:114
FMT_VDPAU
@ FMT_VDPAU
Definition: mythframe.h:61
kVideoBuffer_used
@ kVideoBuffer_used
Definition: videobuffers.h:31
DBG_STR_ARR_SIZE
#define DBG_STR_ARR_SIZE
Definition: videobuffers.cpp:1172
next_dbg_str
int next_dbg_str
Definition: videobuffers.cpp:26
codec_is_vaapi_dec
#define codec_is_vaapi_dec(id)
Definition: mythcodecid.h:313
codec_is_vaapi
#define codec_is_vaapi(id)
Definition: mythcodecid.h:311
DebugString
const QString & DebugString(const VideoFrame *Frame, bool Short)
Definition: videobuffers.cpp:1205
FMT_DXVA2
@ FMT_DXVA2
Definition: mythframe.h:63
MythDeque< VideoFrame * >
codec_is_nvdec_dec
#define codec_is_nvdec_dec(id)
Definition: mythcodecid.h:330
VideoBuffers::SetPrebuffering
void SetPrebuffering(bool Normal)
Definition: videobuffers.cpp:308
VideoBuffers::ClearAfterSeek
void ClearAfterSeek(void)
Clear used frames after seeking.
Definition: videobuffers.cpp:960
mythcontext.h
codec_is_v4l2
#define codec_is_v4l2(id)
Definition: mythcodecid.h:338
VideoBuffers::m_rpos
uint m_rpos
Definition: videobuffers.h:128
MythDeque::head
T head()
Returns item at head of list. O(1).
Definition: mythdeque.h:83
VideoBuffers::FreeVideoFrames
uint FreeVideoFrames(void) const
Definition: videobuffers.cpp:839
FMT_MMAL
@ FMT_MMAL
Definition: mythframe.h:64
VideoBuffers::Clear
void Clear(void)
Definition: videobuffers.cpp:1162
VideoFrameType
VideoFrameType
Definition: mythframe.h:24
FMT_VAAPI
@ FMT_VAAPI
Definition: mythframe.h:62
codec_is_vtb
#define codec_is_vtb(id)
Definition: mythcodecid.h:333
TRY_LOCK_SPINS
#define TRY_LOCK_SPINS
Definition: videobuffers.cpp:22
MythDeque::contains
bool contains(T const &item) const
Returns true if item is in list. O(n).
Definition: mythdeque.h:76
to_bitmap
static unsigned long long to_bitmap(const frame_queue_t &Queue, int Num)
Definition: videobuffers.cpp:1217
VideoBuffers::DiscardFrames
void DiscardFrames(bool NextFrameIsKeyFrame)
Definition: videobuffers.cpp:873
MythDeque::enqueue
void enqueue(T d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:42
DoDiscard
static void DoDiscard(vector< AVBufferRef * > &Discards)
Definition: videobuffers.cpp:56
MythDeque::dequeue
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:32
VideoBuffers::Requeue
void Requeue(BufferType Dest, BufferType Source, int Count=1)
Definition: videobuffers.cpp:734
format_description
const char * format_description(VideoFrameType Type)
Definition: mythframe.cpp:33
GetAlignedBuffer
static unsigned char * GetAlignedBuffer(size_t Size)
Definition: mythframe.h:679
VideoBuffers::GetStatus
QString GetStatus(uint Num=0) const
Definition: videobuffers.cpp:1108
MythDeque::count
size_type count() const
Returns size of list. O(1).
Definition: mythdeque.h:80
VideoBuffers::Enqueue
void Enqueue(BufferType Type, VideoFrame *Frame)
Definition: videobuffers.cpp:697
VideoBuffers::GetNumBuffers
static uint GetNumBuffers(int PixelFormat, int MaxReferenceFrames=16, bool Decoder=false)
Definition: videobuffers.cpp:135
VideoBuffers::m_needPrebufferFramesSmall
uint m_needPrebufferFramesSmall
Definition: videobuffers.h:126
VideoBuffers::DeleteBuffers
void DeleteBuffers(void)
Definition: videobuffers.cpp:1054
VideoBuffers::Head
VideoFrame * Head(BufferType Type)
Definition: videobuffers.cpp:675
VideoBuffers::m_decode
frame_queue_t m_decode
Definition: videobuffers.h:118
fourcc.h
BufferType
BufferType
Definition: videobuffers.h:27
VideoBuffers::ReleaseFrame
void ReleaseFrame(VideoFrame *Frame)
Definition: videobuffers.cpp:387
MythDeque< VideoFrame * >::iterator
typename deque< VideoFrame * >::iterator iterator
Definition: mythdeque.h:44