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