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(MythVideoFrame *Frame, std::vector<AVBufferRef *> &Discards)
38 {
40  {
41  auto* ref = reinterpret_cast<AVBufferRef*>(Frame->m_priv[0]);
42  if (ref != nullptr)
43  Discards.push_back(ref);
44  Frame->m_buffer = Frame->m_priv[0] = nullptr;
45 
47  {
48  ref = reinterpret_cast<AVBufferRef*>(Frame->m_priv[1]);
49  if (ref != nullptr)
50  Discards.push_back(ref);
51  Frame->m_priv[1] = nullptr;
52  }
53  }
54 }
55 
56 static inline void DoDiscard(const std::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 
175 void VideoBuffers::Init(uint NumDecode, uint NeedFree,
176  uint NeedPrebufferNormal, uint NeedPrebufferSmall)
177 {
178  QMutexLocker locker(&m_globalLock);
179 
180  Reset();
181 
182  // make a big reservation, so that things that depend on
183  // pointer to VideoFrames work even after a few push_backs
184  m_buffers.reserve(std::max(NumDecode, 128U));
185  m_buffers.resize(NumDecode);
186  for (uint i = 0; i < NumDecode; i++)
187  m_vbufferMap[At(i)] = i;
188 
189  m_needFreeFrames = NeedFree;
190  m_needPrebufferFrames = NeedPrebufferNormal;
191  m_needPrebufferFramesNormal = NeedPrebufferNormal;
192  m_needPrebufferFramesSmall = NeedPrebufferSmall;
193 
194  for (uint i = 0; i < NumDecode; i++)
197 }
198 
200  MythCodecID CodecID)
201 {
202  QMutexLocker locker(&m_globalLock);
203  for (auto & buffer : m_buffers)
204  SetDeinterlacingFlags(buffer, Single, Double, CodecID);
205 }
206 
215  MythDeintType Double, MythCodecID CodecID)
216 {
217  static const MythDeintType kDriver = DEINT_ALL & ~(DEINT_CPU | DEINT_SHADER);
218  static const MythDeintType kShader = DEINT_ALL & ~(DEINT_CPU | DEINT_DRIVER);
219  static const MythDeintType kSoftware = DEINT_ALL & ~(DEINT_SHADER | DEINT_DRIVER);
220  Frame.m_deinterlaceSingle = Single;
221  Frame.m_deinterlaceDouble = Double;
222 
223  if (codec_is_copyback(CodecID))
224  {
225  if (codec_is_vaapi_dec(CodecID) || codec_is_nvdec_dec(CodecID))
226  Frame.m_deinterlaceAllowed = kSoftware | kShader | kDriver;
227  else // VideoToolBox, MediaCodec and VDPAU copyback
228  Frame.m_deinterlaceAllowed = kSoftware | kShader;
229  }
230  else if (FMT_DRMPRIME == Frame.m_type)
231  { // NOLINT(bugprone-branch-clone)
232  Frame.m_deinterlaceAllowed = kShader; // No driver deint - if RGBA frames are returned, shaders will be disabled
233  }
234  else if (FMT_MMAL == Frame.m_type)
235  {
236  Frame.m_deinterlaceAllowed = kShader; // No driver deint yet (TODO) and YUV frames returned
237  }
238  else if (FMT_VTB == Frame.m_type)
239  {
240  Frame.m_deinterlaceAllowed = kShader; // No driver deint and YUV frames returned
241  }
242  else if (FMT_NVDEC == Frame.m_type)
243  {
244  Frame.m_deinterlaceAllowed = kShader | kDriver; // YUV frames and decoder deint
245  }
246  else if (FMT_VDPAU == Frame.m_type)
247  { // NOLINT(bugprone-branch-clone)
248  Frame.m_deinterlaceAllowed = kDriver; // No YUV frames for shaders
249  }
250  else if (FMT_VAAPI == Frame.m_type)
251  {
252  Frame.m_deinterlaceAllowed = kDriver; // DRM will allow shader if no VPP
253  }
254  else
255  {
256  Frame.m_deinterlaceAllowed = kSoftware | kShader;
257  }
258 }
259 
265 {
266  QMutexLocker locker(&m_globalLock);
267  m_available.clear();
268  m_used.clear();
269  m_limbo.clear();
270  m_finished.clear();
271  m_decode.clear();
272  m_pause.clear();
273  m_displayed.clear();
274  m_vbufferMap.clear();
275 }
276 
282 {
283  QMutexLocker locker(&m_globalLock);
285 }
286 
288 {
289  QMutexLocker locker(&m_globalLock);
290  MythVideoFrame *frame = nullptr;
291 
292  // Try to get a frame not being used by the decoder
293  for (size_t i = 0; i < m_available.size(); i++)
294  {
295  frame = m_available.dequeue();
296  if (m_decode.contains(frame))
297  m_available.enqueue(frame);
298  else
299  break;
300  }
301 
302  while (frame && m_used.contains(frame))
303  {
304  LOG(VB_PLAYBACK, LOG_NOTICE,
305  QString("GetNextFreeFrame() served a busy frame %1. Dropping. %2")
306  .arg(DebugString(frame, true)).arg(GetStatus()));
307  frame = m_available.dequeue();
308  }
309 
310  if (frame)
311  SafeEnqueue(EnqueueTo, frame);
312  return frame;
313 }
314 
320 {
321  for (uint tries = 1; true; tries++)
322  {
324  if (frame)
325  return frame;
326 
327  if (tries >= TRY_LOCK_SPINS)
328  {
329  LOG(VB_GENERAL, LOG_ERR, QString("GetNextFreeFrame: "
330  "available:%1 used:%2 limbo:%3 pause:%4 displayed:%5 decode:%6 finished:%7")
331  .arg(m_available.size()).arg(m_used.size()).arg(m_limbo.size())
332  .arg(m_pause.size()).arg(m_displayed.size()).arg(m_decode.size())
333  .arg(m_finished.size()));
334  LOG(VB_GENERAL, LOG_ERR,
335  QString("GetNextFreeFrame() unable to "
336  "lock frame %1 times. Discarding Frames.")
337  .arg(TRY_LOCK_SPINS));
338  DiscardFrames(true);
339  continue;
340  }
341 
342  if (tries && !(tries % TRY_LOCK_SPINS_BEFORE_WARNING))
343  {
344  LOG(VB_PLAYBACK, LOG_NOTICE,
345  QString("GetNextFreeFrame() TryLock has "
346  "spun %1 times, this is a lot.").arg(tries));
347  }
348  std::this_thread::sleep_for(std::chrono::microseconds(TRY_LOCK_SPIN_WAIT));
349  }
350 
351  return nullptr;
352 }
353 
361 {
362  QMutexLocker locker(&m_globalLock);
363 
366  //non directrendering frames are ffmpeg handled
367  if (Frame->m_directRendering)
370 }
371 
378 {
379  std::vector<AVBufferRef*> discards;
380 
381  m_globalLock.lock();
382 
383  if (m_limbo.contains(Frame))
385 
386  // if decoder didn't release frame and the buffer is getting released by
387  // the decoder assume that the frame is lost and return to available
388  if (!m_decode.contains(Frame))
389  {
390  ReleaseDecoderResources(Frame, discards);
392  }
393 
394  // remove from decode queue since the decoder is finished
395  while (m_decode.contains(Frame))
397 
398  m_globalLock.unlock();
399 
400  DoDiscard(discards);
401 }
402 
408 {
409  QMutexLocker locker(&m_globalLock);
411 }
412 
418 {
419  std::vector<AVBufferRef*> discards;
420 
421  m_globalLock.lock();
422 
423  if(m_used.contains(Frame))
425 
427 
428  // check if any finished frames are no longer used by decoder and return to available
430  for (auto & it : ula)
431  {
432  if (!m_decode.contains(it))
433  {
435  ReleaseDecoderResources(it, discards);
437  }
438  }
439 
440  m_globalLock.unlock();
441 
442  DoDiscard(discards);
443 }
444 
451 {
452  std::vector<AVBufferRef*> discards;
453  m_globalLock.lock();
454  ReleaseDecoderResources(Frame, discards);
456  m_globalLock.unlock();
457  DoDiscard(discards);
458 }
459 
461 {
462  std::vector<AVBufferRef*> discards;
463 
464  m_globalLock.lock();
465  while (Size(kVideoBuffer_pause))
466  {
468  ReleaseDecoderResources(frame, discards);
470  }
471  m_globalLock.unlock();
472 
473  DoDiscard(discards);
474 }
475 
482 bool VideoBuffers::DiscardAndRecreate(MythCodecID CodecID, QSize VideoDim, int References)
483 {
484  bool result = false;
485  std::vector<AVBufferRef*> refs;
486 
487  m_globalLock.lock();
488  LOG(VB_PLAYBACK, LOG_INFO, QString("DiscardAndRecreate: %1").arg(GetStatus()));
489 
490  // Remove pause frames (cutdown version of DiscardPauseFrames)
491  while (Size(kVideoBuffer_pause))
492  {
494  ReleaseDecoderResources(frame, refs);
496  }
497 
498  // See DiscardFrames
499  frame_queue_t ula(m_used);
500  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
501  ula.insert(ula.end(), m_available.begin(), m_available.end());
502  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
503 
504  frame_queue_t discards(m_used);
505  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
506  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
507  for (auto & discard : discards)
508  {
509  ReleaseDecoderResources(discard, refs);
511  }
512 
513  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
514  {
515  for (uint i = 0; i < Size(); i++)
516  {
517  if (!m_available.contains(At(i)) && !m_pause.contains(At(i)) &&
518  !m_displayed.contains(At(i)))
519  {
520  LOG(VB_GENERAL, LOG_INFO,
521  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
522  "in available, pause, or displayed %3")
523  .arg(DebugString(At(i), true)).arg(reinterpret_cast<long long>(At(i)))
524  .arg(GetStatus()));
525  ReleaseDecoderResources(At(i), refs);
527  }
528  }
529  }
530 
531  for (auto & it : m_decode)
533  for (auto & it : m_decode)
534  m_available.enqueue(it);
535  m_decode.clear();
536 
537  Reset();
538 
539  // Recreate - see MythVideoOutputOpenGL::CreateBuffers
540  if (codec_is_copyback(CodecID))
541  {
543  result = CreateBuffers(FMT_YV12, VideoDim.width(), VideoDim.height());
544  }
545  else if (codec_is_mediacodec(CodecID))
546  {
547  result = CreateBuffers(FMT_MEDIACODEC, VideoDim, 1, 2, 2);
548  }
549  else if (codec_is_vaapi(CodecID))
550  {
551  result = CreateBuffers(FMT_VAAPI, VideoDim, 2, 1, 4, References);
552  }
553  else if (codec_is_vtb(CodecID))
554  {
555  result = CreateBuffers(FMT_VTB, VideoDim, 1, 4, 2);
556  }
557  else if (codec_is_vdpau(CodecID))
558  {
559  result = CreateBuffers(FMT_VDPAU, VideoDim, 2, 1, 4, References);
560  }
561  else if (codec_is_nvdec(CodecID))
562  {
563  result = CreateBuffers(FMT_NVDEC, VideoDim, 2, 1, 4);
564  }
565  else if (codec_is_mmal(CodecID))
566  {
567  result = CreateBuffers(FMT_MMAL, VideoDim, 2, 1, 4);
568  }
569  else if (codec_is_v4l2(CodecID) || codec_is_drmprime(CodecID))
570  {
571  result = CreateBuffers(FMT_DRMPRIME, VideoDim, 2, 1, 4);
572  }
573  else
574  {
575  result = CreateBuffers(FMT_YV12, VideoDim, 1, 8, 4, References);
576  }
577 
578  LOG(VB_PLAYBACK, LOG_INFO, QString("DiscardAndRecreate: %1").arg(GetStatus()));
579  m_globalLock.unlock();
580 
581  // and finally release references now that the lock is released
582  DoDiscard(refs);
583  return result;
584 }
585 
587 {
588  QMutexLocker locker(&m_globalLock);
589  frame_queue_t *queue = nullptr;
590  if (Type == kVideoBuffer_avail)
591  queue = &m_available;
592  else if (Type == kVideoBuffer_used)
593  queue = &m_used;
594  else if (Type == kVideoBuffer_displayed)
595  queue = &m_displayed;
596  else if (Type == kVideoBuffer_limbo)
597  queue = &m_limbo;
598  else if (Type == kVideoBuffer_pause)
599  queue = &m_pause;
600  else if (Type == kVideoBuffer_decode)
601  queue = &m_decode;
602  else if (Type == kVideoBuffer_finished)
603  queue = &m_finished;
604  return queue;
605 }
606 
608 {
609  QMutexLocker locker(&m_globalLock);
610  const frame_queue_t *queue = nullptr;
611  if (Type == kVideoBuffer_avail)
612  queue = &m_available;
613  else if (Type == kVideoBuffer_used)
614  queue = &m_used;
615  else if (Type == kVideoBuffer_displayed)
616  queue = &m_displayed;
617  else if (Type == kVideoBuffer_limbo)
618  queue = &m_limbo;
619  else if (Type == kVideoBuffer_pause)
620  queue = &m_pause;
621  else if (Type == kVideoBuffer_decode)
622  queue = &m_decode;
623  else if (Type == kVideoBuffer_finished)
624  queue = &m_finished;
625  return queue;
626 }
627 
629 {
630  return &m_buffers[FrameNum];
631 }
632 
633 const MythVideoFrame* VideoBuffers::At(uint FrameNum) const
634 {
635  return &m_buffers[FrameNum];
636 }
637 
639 {
640  QMutexLocker locker(&m_globalLock);
641  frame_queue_t *queue = Queue(Type);
642  if (!queue)
643  return nullptr;
644  return queue->dequeue();
645 }
646 
648 {
649  QMutexLocker locker(&m_globalLock);
650  frame_queue_t *queue = Queue(Type);
651  if (!queue)
652  return nullptr;
653  if (!queue->empty())
654  return queue->head();
655  return nullptr;
656 }
657 
659 {
660  QMutexLocker locker(&m_globalLock);
661  frame_queue_t *queue = Queue(Type);
662  if (!queue)
663  return nullptr;
664  if (!queue->empty())
665  return queue->tail();
666  return nullptr;
667 }
668 
670 {
671  if (!Frame)
672  return;
673  frame_queue_t *queue = Queue(Type);
674  if (!queue)
675  return;
676  m_globalLock.lock();
677  queue->remove(Frame);
678  queue->enqueue(Frame);
679  if (Type == kVideoBuffer_pause)
680  Frame->m_pauseFrame = true;
681  m_globalLock.unlock();
682 }
683 
685 {
686  if (!Frame)
687  return;
688 
689  QMutexLocker locker(&m_globalLock);
690  if ((Type & kVideoBuffer_avail) == kVideoBuffer_avail)
692  if ((Type & kVideoBuffer_used) == kVideoBuffer_used)
696  if ((Type & kVideoBuffer_limbo) == kVideoBuffer_limbo)
698  if ((Type & kVideoBuffer_pause) == kVideoBuffer_pause)
704 }
705 
707 {
708  QMutexLocker locker(&m_globalLock);
709  Count = (Count <= 0) ? Size(Source) : Count;
710  for (uint i=0; i<(uint)Count; i++)
711  {
712  MythVideoFrame *frame = Dequeue(Source);
713  if (frame)
714  Enqueue(Dest, frame);
715  }
716 }
717 
719 {
720  if (!Frame)
721  return;
722  QMutexLocker locker(&m_globalLock);
724  Enqueue(Type, Frame);
725 }
726 
733 {
734  m_globalLock.lock();
735  frame_queue_t *queue = Queue(Type);
736  if (queue)
737  return queue->begin();
738  return m_available.begin();
739 }
740 
742 {
743  m_globalLock.unlock();
744 }
745 
747 {
748  QMutexLocker locker(&m_globalLock);
749  frame_queue_t *queue = Queue(Type);
750  return (queue ? queue->end() : m_available.end());
751 }
752 
754 {
755  QMutexLocker locker(&m_globalLock);
756  const frame_queue_t *queue = Queue(Type);
757  if (queue)
758  return queue->size();
759  return 0;
760 }
761 
763 {
764  QMutexLocker locker(&m_globalLock);
765  const frame_queue_t *queue = Queue(Type);
766  if (queue)
767  return queue->contains(Frame);
768  return false;
769 }
770 
772 {
773  return At(m_vpos);
774 }
775 
777 {
778  return At(m_rpos);
779 }
780 
782 {
783  return Size(kVideoBuffer_used);
784 }
785 
787 {
788  return Size(kVideoBuffer_avail);
789 }
790 
792 {
794 }
795 
797 {
799 }
800 
802 {
803  return At(m_vpos);
804 }
805 
807 {
808  return At(m_rpos);
809 }
810 
812 {
813  return m_buffers.size();
814 }
815 
820 void VideoBuffers::DiscardFrames(bool NextFrameIsKeyFrame)
821 {
822  std::vector<AVBufferRef*> refs;
823  m_globalLock.lock();
824  LOG(VB_PLAYBACK, LOG_INFO, QString("VideoBuffers::DiscardFrames(%1): %2")
825  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
826 
827  if (!NextFrameIsKeyFrame)
828  {
829  frame_queue_t ula(m_used);
830  for (auto & it : ula)
831  {
832  ReleaseDecoderResources(it, refs);
834  }
835  LOG(VB_PLAYBACK, LOG_INFO,
836  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
837  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
838  m_globalLock.unlock();
839  DoDiscard(refs);
840  return;
841  }
842 
843  // Remove inheritence of all frames not in displayed or pause
844  frame_queue_t ula(m_used);
845  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
846  ula.insert(ula.end(), m_available.begin(), m_available.end());
847  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
849 
850  // Discard frames
851  frame_queue_t discards(m_used);
852  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
853  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
854  for (it = discards.begin(); it != discards.end(); ++it)
855  {
856  ReleaseDecoderResources(*it, refs);
858  }
859 
860  // Verify that things are kosher
861  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
862  {
863  for (uint i = 0; i < Size(); i++)
864  {
865  if (!m_available.contains(At(i)) && !m_pause.contains(At(i)) &&
866  !m_displayed.contains(At(i)))
867  {
868  // This message is DEBUG because it does occur
869  // after Reset is called.
870  // That happens when failing over from OpenGL
871  // to another method, if QT painter is selected.
872  LOG(VB_GENERAL, LOG_DEBUG,
873  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
874  "in available, pause, or displayed %3")
875  .arg(DebugString(At(i), true)).arg((long long)At(i))
876  .arg(GetStatus()));
877  ReleaseDecoderResources(At(i), refs);
879  }
880  }
881  }
882 
883  // Make sure frames used by decoder are last...
884  // This is for libmpeg2 which still uses the frames after a reset.
885  for (it = m_decode.begin(); it != m_decode.end(); ++it)
886  Remove(kVideoBuffer_all, *it);
887  for (it = m_decode.begin(); it != m_decode.end(); ++it)
888  m_available.enqueue(*it);
889  m_decode.clear();
890 
891  LOG(VB_PLAYBACK, LOG_INFO,
892  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
893  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
894 
895  m_globalLock.unlock();
896  DoDiscard(refs);
897 }
898 
908 {
909  std::vector<AVBufferRef*> discards;
910  {
911  QMutexLocker locker(&m_globalLock);
912 
913  for (uint i = 0; i < Size(); i++)
914  At(i)->m_timecode = 0;
915 
916  for (uint i = 0; (i < Size()) && (m_used.count() > 1); i++)
917  {
918  MythVideoFrame *buffer = At(i);
919  if (m_used.contains(buffer) && !m_decode.contains(buffer))
920  {
921  m_used.remove(buffer);
922  m_available.enqueue(buffer);
923  ReleaseDecoderResources(buffer, discards);
924  }
925  }
926 
927  if (m_used.count() > 0)
928  {
929  for (uint i = 0; i < Size(); i++)
930  {
931  MythVideoFrame *buffer = At(i);
932  if (m_used.contains(buffer) && !m_decode.contains(buffer))
933  {
934  m_used.remove(buffer);
935  m_available.enqueue(buffer);
936  ReleaseDecoderResources(buffer, discards);
937  m_vpos = m_vbufferMap[buffer];
938  m_rpos = m_vpos;
939  break;
940  }
941  }
942  }
943  else
944  {
945  m_vpos = m_rpos = 0;
946  }
947  }
948 
949  DoDiscard(discards);
950 }
951 
953  uint NeedFree, uint NeedprebufferNormal,
954  uint NeedPrebufferSmall, int MaxReferenceFrames)
955 {
956  Init(GetNumBuffers(Type, MaxReferenceFrames), NeedFree, NeedprebufferNormal, NeedPrebufferSmall);
957  return CreateBuffers(Type, Size.width(), Size.height());
958 }
959 
960 bool VideoBuffers::CreateBuffers(VideoFrameType Type, int Width, int Height)
961 {
962  bool success = true;
963 
964  // Hardware buffers with no allocated memory
966  {
967  for (uint i = 0; i < Size(); i++)
968  m_buffers[i].Init(Type, Width, Height);
969  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 empty %2 (%3x%4) video buffers")
970  .arg(Size()).arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
971  return true;
972  }
973 
974  // Software buffers
975  for (uint i = 0; i < Size(); i++)
976  {
977  m_buffers[i].Init(Type, Width, Height);
978  m_buffers[i].ClearBufferToBlank();
979  success &= m_buffers[i].m_dummy || (m_buffers[i].m_buffer != nullptr);
980  }
981 
982  // workaround null buffers for audio only (remove when these buffers aren't used)
983  if (!success && (Width < 1 || Height < 1))
984  success = true;
985 
986  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 %2 (%3x%4) video buffers")
987  .arg(Size()).arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
988  return success;
989 }
990 
992  int Width, int Height)
993 {
994  if (!Frame)
995  return false;
996 
998  {
999  LOG(VB_GENERAL, LOG_ERR, "Cannot re-initialise a hardware buffer");
1000  return false;
1001  }
1002 
1003  VideoFrameType old = Frame->m_type;
1004  LOG(VB_PLAYBACK, LOG_INFO, QString("Reallocating frame %1 %2x%3->%4 %5x%6")
1005  .arg(MythVideoFrame::FormatDescription(old)).arg(Frame->m_width).arg(Frame->m_height)
1006  .arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
1007 
1008  MythDeintType singler = Frame->m_deinterlaceSingle;
1009  MythDeintType doubler = Frame->m_deinterlaceDouble;
1010  Frame->Init(Type, Width, Height);
1011  Frame->ClearBufferToBlank();
1012 
1013  // retain deinterlacer settings and update restrictions based on new frame type
1014  SetDeinterlacingFlags(*Frame, singler, doubler, CodecID);
1015  return true;
1016 }
1017 
1018 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num);
1019 
1020 QString VideoBuffers::GetStatus(uint Num) const
1021 {
1022  if (Num == 0)
1023  Num = Size();
1024 
1025  QString str("");
1026  if (m_globalLock.tryLock())
1027  {
1028  int count = Size();
1029  unsigned long long a = to_bitmap(m_available, count);
1030  unsigned long long u = to_bitmap(m_used, count);
1031  unsigned long long d = to_bitmap(m_displayed, count);
1032  unsigned long long l = to_bitmap(m_limbo, count);
1033  unsigned long long p = to_bitmap(m_pause, count);
1034  unsigned long long f = to_bitmap(m_finished, count);
1035  unsigned long long x = to_bitmap(m_decode, count);
1036  for (uint i = 0; i < Num; i++)
1037  {
1038  unsigned long long mask = 1ULL << i;
1039  QString tmp("");
1040  if (a & mask)
1041  tmp += (x & mask) ? "a" : "A";
1042  if (u & mask)
1043  tmp += (x & mask) ? "u" : "U";
1044  if (d & mask)
1045  tmp += (x & mask) ? "d" : "D";
1046  if (l & mask)
1047  tmp += (x & mask) ? "l" : "L";
1048  if (p & mask)
1049  tmp += (x & mask) ? "p" : "P";
1050  if (f & mask)
1051  tmp += (x & mask) ? "f" : "F";
1052  if (0 == tmp.length())
1053  str += " ";
1054  else if (1 == tmp.length())
1055  str += tmp;
1056  else
1057  str += "(" + tmp + ")";
1058  }
1059  m_globalLock.unlock();
1060  }
1061  else
1062  {
1063  for (uint i = 0; i < Num; i++)
1064  str += " ";
1065  }
1066  return str;
1067 }
1068 
1069 /*******************************
1070  ** Debugging functions below **
1071  *******************************/
1072 
1073 #define DBG_STR_ARR_SIZE 40
1074 const std::array<const QString,DBG_STR_ARR_SIZE> dbg_str_arr
1075 {
1076  "A ", " B ", " C ", " D ",
1077  " E ", " F ", " G ", " H", // 8
1078  "a ", " b ", " c ", " d ",
1079  " e ", " f ", " g ", " h", // 16
1080  "0 ", " 1 ", " 2 ", " 3 ",
1081  " 4 ", " 5 ", " 6 ", " 7", // 24
1082  "I ", " J ", " K ", " L ",
1083  " M ", " N ", " O ", " P", // 32
1084  "i ", " j ", " k ", " l ",
1085  " m ", " n ", " o ", " p", // 40
1086 };
1087 const std::array<const QString,DBG_STR_ARR_SIZE> dbg_str_arr_short
1088 {
1089  "A","B","C","D","E","F","G","H", // 8
1090  "a","b","c","d","e","f","g","h", // 16
1091  "0","1","2","3","4","5","6","7", // 24
1092  "I","J","K","L","M","N","O","P", // 32
1093  "i","j","k","l","m","n","o","p", // 40
1094 };
1095 
1096 std::map<const MythVideoFrame *, int> dbg_str;
1097 
1098 static int DebugNum(const MythVideoFrame *Frame)
1099 {
1100  auto it = dbg_str.find(Frame);
1101  if (it == dbg_str.end())
1102  return dbg_str[Frame] = next_dbg_str++;
1103  return it->second;
1104 }
1105 
1106 const QString& DebugString(const MythVideoFrame *Frame, bool Short)
1107 {
1108  if (Short)
1111 }
1112 
1113 const QString& DebugString(uint FrameNum, bool Short)
1114 {
1115  return ((Short) ? dbg_str_arr_short : dbg_str_arr)[FrameNum];
1116 }
1117 
1118 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num)
1119 {
1120  unsigned long long bitmap = 0;
1121  for (auto *it : Queue)
1122  {
1123  int shift = DebugNum(it) % Num;
1124  bitmap |= 1ULL << shift;
1125  }
1126  return bitmap;
1127 }
MythDeque::remove
void remove(T const item)
Removes any item from list. O(n).
Definition: mythdeque.h:67
FMT_MEDIACODEC
@ FMT_MEDIACODEC
Definition: mythframe.h:56
codec_is_copyback
#define codec_is_copyback(id)
Definition: mythcodecid.h:344
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:70
VideoBuffers::ValidVideoFrames
uint ValidVideoFrames(void) const
Definition: videobuffers.cpp:781
DebugNum
static int DebugNum(const MythVideoFrame *Frame)
Definition: videobuffers.cpp:1098
kVideoBuffer_avail
@ kVideoBuffer_avail
Definition: videobuffers.h:28
VideoBuffers::ReleaseFrame
void ReleaseFrame(MythVideoFrame *Frame)
Frame is ready to be for filtering or OSD application.
Definition: videobuffers.cpp:360
VideoBuffers::Size
uint Size(void) const
Definition: videobuffers.cpp:811
VideoBuffers::Head
MythVideoFrame * Head(BufferType Type)
Definition: videobuffers.cpp:647
VideoBuffers::Tail
MythVideoFrame * Tail(BufferType Type)
Definition: videobuffers.cpp:658
FMT_VTB
@ FMT_VTB
Definition: mythframe.h:57
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:69
VideoBuffers::m_available
frame_queue_t m_available
Definition: videobuffers.h:105
VideoBuffers::m_needPrebufferFrames
uint m_needPrebufferFrames
Definition: videobuffers.h:116
kCodec_NONE
@ kCodec_NONE
Definition: mythcodecid.h:14
MythVideoFrame::HardwareFramesFormat
static bool HardwareFramesFormat(VideoFrameType Type)
Definition: mythframe.h:416
FMT_DRMPRIME
@ FMT_DRMPRIME
Definition: mythframe.h:59
VideoBuffers::Remove
void Remove(BufferType Type, MythVideoFrame *Frame)
Definition: videobuffers.cpp:684
VideoBuffers::GetNextFreeFrame
MythVideoFrame * GetNextFreeFrame(BufferType EnqueueTo=kVideoBuffer_limbo)
Gets a frame from available buffers list.
Definition: videobuffers.cpp:319
kVideoBuffer_decode
@ kVideoBuffer_decode
Definition: videobuffers.h:34
VideoBuffers::m_needPrebufferFramesNormal
uint m_needPrebufferFramesNormal
Definition: videobuffers.h:117
Frame
Definition: zmdefines.h:94
VideoBuffers::EnoughDecodedFrames
bool EnoughDecodedFrames(void) const
Definition: videobuffers.cpp:796
codec_is_nvdec
#define codec_is_nvdec(id)
Definition: mythcodecid.h:328
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:64
arg
arg(title).arg(filename).arg(doDelete))
VideoBuffers::SetDeinterlacing
void SetDeinterlacing(MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
Definition: videobuffers.cpp:199
VideoBuffers::DiscardAndRecreate
bool DiscardAndRecreate(MythCodecID CodecID, QSize VideoDim, int References)
Discard all buffers and recreate.
Definition: videobuffers.cpp:482
VideoBuffers::m_limbo
frame_queue_t m_limbo
Definition: videobuffers.h:107
codec_is_vdpau
#define codec_is_vdpau(id)
Definition: mythcodecid.h:298
VideoBuffers::Dequeue
MythVideoFrame * Dequeue(BufferType Type)
Definition: videobuffers.cpp:638
codec_is_mmal
#define codec_is_mmal(id)
Definition: mythcodecid.h:341
VideoBuffers::End
frame_queue_t::iterator End(BufferType Type)
Definition: videobuffers.cpp:746
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
VideoBuffers::SetDeinterlacingFlags
static void SetDeinterlacingFlags(MythVideoFrame &Frame, MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
Set the appropriate flags for single and double rate deinterlacing.
Definition: videobuffers.cpp:214
MythVideoFrame::HardwareFormat
static bool HardwareFormat(VideoFrameType Type)
Definition: mythframe.h:408
kVideoBuffer_finished
@ kVideoBuffer_finished
Definition: videobuffers.h:33
DEINT_ALL
@ DEINT_ALL
Definition: mythframe.h:71
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
dbg_str
std::map< const MythVideoFrame *, int > dbg_str
Definition: videobuffers.cpp:1096
VideoBuffers::GetNextFreeFrameInternal
MythVideoFrame * GetNextFreeFrameInternal(BufferType EnqueueTo)
Definition: videobuffers.cpp:287
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MythVideoFrame::m_timecode
long long m_timecode
Definition: mythframe.h:122
VideoBuffers::m_vpos
uint m_vpos
Definition: videobuffers.h:120
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:17
VideoBuffers::m_pause
frame_queue_t m_pause
Definition: videobuffers.h:108
VideoBuffers::m_buffers
frame_vector_t m_buffers
Definition: videobuffers.h:113
TRY_LOCK_SPINS_BEFORE_WARNING
#define TRY_LOCK_SPINS_BEFORE_WARNING
Definition: videobuffers.cpp:23
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:68
videobuffers.h
MythCodecID
MythCodecID
Definition: mythcodecid.h:11
Decoder
Definition: decoder.h:66
VideoBuffers::m_displayed
frame_queue_t m_displayed
Definition: videobuffers.h:109
mythlogging.h
codec_is_mediacodec
#define codec_is_mediacodec(id)
Definition: mythcodecid.h:323
Source
Definition: channelsettings.cpp:69
VideoBuffers::m_vbufferMap
vbuffer_map_t m_vbufferMap
Definition: videobuffers.h:112
VideoBuffers::Contains
bool Contains(BufferType Type, MythVideoFrame *Frame) const
Definition: videobuffers.cpp:762
hardwareprofile.config.p
p
Definition: config.py:33
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:19
VideoBuffers::m_globalLock
QMutex m_globalLock
Definition: videobuffers.h:121
compat.h
VideoBuffers::EnoughFreeFrames
bool EnoughFreeFrames(void) const
Definition: videobuffers.cpp:791
VideoBuffers::m_finished
frame_queue_t m_finished
Definition: videobuffers.h:111
VideoBuffers::Queue
frame_queue_t * Queue(BufferType Type)
Definition: videobuffers.cpp:586
VideoBuffers::StartDisplayingFrame
void StartDisplayingFrame(void)
Sets rpos to index of videoframe at head of used queue.
Definition: videobuffers.cpp:407
ReleaseDecoderResources
static void ReleaseDecoderResources(MythVideoFrame *Frame, std::vector< AVBufferRef * > &Discards)
Store AVBufferRef's for later disposal.
Definition: videobuffers.cpp:37
mythcodecid.h
kVideoBuffer_all
@ kVideoBuffer_all
Definition: videobuffers.h:35
dbg_str_arr
const std::array< const QString, DBG_STR_ARR_SIZE > dbg_str_arr
Definition: videobuffers.cpp:1075
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:603
VideoBuffers::Reset
void Reset(void)
Resets the class so that Init may be called again.
Definition: videobuffers.cpp:264
VideoBuffers::m_needFreeFrames
uint m_needFreeFrames
Definition: videobuffers.h:115
uint
unsigned int uint
Definition: compat.h:140
VideoBuffers::BeginLock
frame_queue_t::iterator BeginLock(BufferType Type)
Lock the video buffers.
Definition: videobuffers.cpp:732
FMT_NVDEC
@ FMT_NVDEC
Definition: mythframe.h:58
codec_is_drmprime
#define codec_is_drmprime(id)
Definition: mythcodecid.h:296
kVideoBuffer_limbo
@ kVideoBuffer_limbo
Definition: videobuffers.h:29
VideoBuffers::EndLock
void EndLock()
Definition: videobuffers.cpp:741
VideoBuffers::DiscardPauseFrames
void DiscardPauseFrames(void)
Definition: videobuffers.cpp:460
kVideoBuffer_pause
@ kVideoBuffer_pause
Definition: videobuffers.h:31
kVideoBuffer_displayed
@ kVideoBuffer_displayed
Definition: videobuffers.h:32
VideoBuffers::GetLastShownFrame
MythVideoFrame * GetLastShownFrame(void)
Definition: videobuffers.cpp:776
MythDeintType
MythDeintType
Definition: mythframe.h:63
VideoBuffers::DiscardFrame
void DiscardFrame(MythVideoFrame *Frame)
Frame is ready to be reused by decoder.
Definition: videobuffers.cpp:450
VideoBuffers::m_used
frame_queue_t m_used
Definition: videobuffers.h:106
MythVideoFrame::FormatDescription
static QString FormatDescription(VideoFrameType Type)
Definition: mythframe.cpp:363
VideoBuffers::Enqueue
void Enqueue(BufferType Type, MythVideoFrame *Frame)
Definition: videobuffers.cpp:669
FMT_VDPAU
@ FMT_VDPAU
Definition: mythframe.h:52
kVideoBuffer_used
@ kVideoBuffer_used
Definition: videobuffers.h:30
DBG_STR_ARR_SIZE
#define DBG_STR_ARR_SIZE
Definition: videobuffers.cpp:1073
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
FMT_DXVA2
@ FMT_DXVA2
Definition: mythframe.h:54
MythDeque< MythVideoFrame * >
VideoBuffers::GetLastDecodedFrame
MythVideoFrame * GetLastDecodedFrame(void)
Definition: videobuffers.cpp:771
codec_is_nvdec_dec
#define codec_is_nvdec_dec(id)
Definition: mythcodecid.h:330
VideoBuffers::SetPrebuffering
void SetPrebuffering(bool Normal)
Sets prebuffering state to normal, or small.
Definition: videobuffers.cpp:281
VideoBuffers::ClearAfterSeek
void ClearAfterSeek(void)
Clear used frames after seeking.
Definition: videobuffers.cpp:907
mythcontext.h
VideoBuffers::DoneDisplayingFrame
void DoneDisplayingFrame(MythVideoFrame *Frame)
Removes frame from used queue and adds it to the available list.
Definition: videobuffers.cpp:417
codec_is_v4l2
#define codec_is_v4l2(id)
Definition: mythcodecid.h:338
VideoBuffers::m_rpos
uint m_rpos
Definition: videobuffers.h:119
MythDeque::head
T head()
Returns item at head of list. O(1).
Definition: mythdeque.h:83
VideoBuffers::SafeEnqueue
void SafeEnqueue(BufferType Type, MythVideoFrame *Frame)
Definition: videobuffers.cpp:718
DoDiscard
static void DoDiscard(const std::vector< AVBufferRef * > &Discards)
Definition: videobuffers.cpp:56
VideoBuffers::FreeVideoFrames
uint FreeVideoFrames(void) const
Definition: videobuffers.cpp:786
DebugString
const QString & DebugString(const MythVideoFrame *Frame, bool Short)
Definition: videobuffers.cpp:1106
VideoBuffers::ReinitBuffer
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
Definition: videobuffers.cpp:991
FMT_MMAL
@ FMT_MMAL
Definition: mythframe.h:55
VideoFrameType
VideoFrameType
Definition: mythframe.h:16
FMT_VAAPI
@ FMT_VAAPI
Definition: mythframe.h:53
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:1118
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
MythVideoFrame
Definition: mythframe.h:83
VideoBuffers::DiscardFrames
void DiscardFrames(bool NextFrameIsKeyFrame)
Mark all used frames as ready to be reused, this is for seek.
Definition: videobuffers.cpp:820
MythDeque::enqueue
void enqueue(T d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:42
VideoBuffers::DeLimboFrame
void DeLimboFrame(MythVideoFrame *Frame)
If the frame is still in the limbo state it is added to the available queue.
Definition: videobuffers.cpp:377
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:706
dbg_str_arr_short
const std::array< const QString, DBG_STR_ARR_SIZE > dbg_str_arr_short
Definition: videobuffers.cpp:1088
VideoBuffers::CreateBuffers
bool CreateBuffers(VideoFrameType Type, QSize Size, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall, int MaxReferenceFrames=16)
Definition: videobuffers.cpp:952
VideoBuffers::At
MythVideoFrame * At(uint FrameNum)
Definition: videobuffers.cpp:628
VideoBuffers::Init
void Init(uint NumDecode, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall)
Creates buffers and sets various buffer management parameters.
Definition: videobuffers.cpp:175
VideoBuffers::GetStatus
QString GetStatus(uint Num=0) const
Definition: videobuffers.cpp:1020
MythDeque::count
size_type count() const
Returns size of list. O(1).
Definition: mythdeque.h:80
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:118
VideoBuffers::m_decode
frame_queue_t m_decode
Definition: videobuffers.h:110
fourcc.h
BufferType
BufferType
Definition: videobuffers.h:27
MythDeque< MythVideoFrame * >::iterator
typename deque< MythVideoFrame * >::iterator iterator
Definition: mythdeque.h:44