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 "libmythbase/compat.h"
10 #include "libmythbase/mythconfig.h"
12 
13 #include "fourcc.h"
14 #include "mythcodecid.h"
15 #include "videobuffers.h"
16 
17 // FFmpeg
18 extern "C" {
19 #include "libavcodec/avcodec.h"
20 }
21 
22 static constexpr uint16_t TRY_LOCK_SPINS { 2000 };
23 static constexpr uint16_t TRY_LOCK_SPINS_BEFORE_WARNING { 9999 };
24 static constexpr std::chrono::milliseconds TRY_LOCK_SPIN_WAIT { 1ms };
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), 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(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(), m_renderFormats);
544  }
545  else if (codec_is_mediacodec(CodecID))
546  {
547  result = CreateBuffers(FMT_MEDIACODEC, m_renderFormats, VideoDim, 1, 2, 2);
548  }
549  else if (codec_is_vaapi(CodecID))
550  {
551  result = CreateBuffers(FMT_VAAPI, m_renderFormats, VideoDim, 2, 1, 4, References);
552  }
553  else if (codec_is_vtb(CodecID))
554  {
555  result = CreateBuffers(FMT_VTB, m_renderFormats, VideoDim, 1, 4, 2);
556  }
557  else if (codec_is_vdpau(CodecID))
558  {
559  result = CreateBuffers(FMT_VDPAU, m_renderFormats, VideoDim, 2, 1, 4, References);
560  }
561  else if (codec_is_nvdec(CodecID))
562  {
563  result = CreateBuffers(FMT_NVDEC, m_renderFormats, VideoDim, 2, 1, 4);
564  }
565  else if (codec_is_mmal(CodecID))
566  {
567  result = CreateBuffers(FMT_MMAL, m_renderFormats, VideoDim, 2, 1, 4);
568  }
569  else if (codec_is_v4l2(CodecID) || codec_is_drmprime(CodecID))
570  {
571  result = CreateBuffers(FMT_DRMPRIME, m_renderFormats, VideoDim, 2, 1, 4);
572  }
573  else
574  {
575  result = CreateBuffers(FMT_YV12, m_renderFormats, 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  if (!Frame)
709  return;
710  QMutexLocker locker(&m_globalLock);
712  Enqueue(Type, Frame);
713 }
714 
721 {
722  m_globalLock.lock();
723  frame_queue_t *queue = Queue(Type);
724  if (queue)
725  return queue->begin();
726  return m_available.begin();
727 }
728 
730 {
731  m_globalLock.unlock();
732 }
733 
735 {
736  QMutexLocker locker(&m_globalLock);
737  frame_queue_t *queue = Queue(Type);
738  return (queue ? queue->end() : m_available.end());
739 }
740 
742 {
743  QMutexLocker locker(&m_globalLock);
744  const frame_queue_t *queue = Queue(Type);
745  if (queue)
746  return queue->size();
747  return 0;
748 }
749 
751 {
752  QMutexLocker locker(&m_globalLock);
753  const frame_queue_t *queue = Queue(Type);
754  if (queue)
755  return queue->contains(Frame);
756  return false;
757 }
758 
760 {
761  return At(m_vpos);
762 }
763 
765 {
766  return At(m_rpos);
767 }
768 
770 {
771  return Size(kVideoBuffer_used);
772 }
773 
775 {
776  return Size(kVideoBuffer_avail);
777 }
778 
780 {
782 }
783 
785 {
787 }
788 
790 {
791  return At(m_vpos);
792 }
793 
795 {
796  return At(m_rpos);
797 }
798 
800 {
801  return m_buffers.size();
802 }
803 
808 void VideoBuffers::DiscardFrames(bool NextFrameIsKeyFrame)
809 {
810  std::vector<AVBufferRef*> refs;
811  m_globalLock.lock();
812  LOG(VB_PLAYBACK, LOG_INFO, QString("VideoBuffers::DiscardFrames(%1): %2")
813  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
814 
815  if (!NextFrameIsKeyFrame)
816  {
817  frame_queue_t ula(m_used);
818  for (auto & it : ula)
819  {
820  ReleaseDecoderResources(it, refs);
822  }
823  LOG(VB_PLAYBACK, LOG_INFO,
824  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
825  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
826  m_globalLock.unlock();
827  DoDiscard(refs);
828  return;
829  }
830 
831  // Remove inheritence of all frames not in displayed or pause
832  frame_queue_t ula(m_used);
833  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
834  ula.insert(ula.end(), m_available.begin(), m_available.end());
835  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
837 
838  // Discard frames
839  frame_queue_t discards(m_used);
840  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
841  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
842  for (it = discards.begin(); it != discards.end(); ++it)
843  {
844  ReleaseDecoderResources(*it, refs);
846  }
847 
848  // Verify that things are kosher
849  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
850  {
851  for (uint i = 0; i < Size(); i++)
852  {
853  if (!m_available.contains(At(i)) && !m_pause.contains(At(i)) &&
854  !m_displayed.contains(At(i)))
855  {
856  // This message is DEBUG because it does occur
857  // after Reset is called.
858  // That happens when failing over from OpenGL
859  // to another method, if QT painter is selected.
860  LOG(VB_GENERAL, LOG_DEBUG,
861  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
862  "in available, pause, or displayed %3")
863  .arg(DebugString(At(i), true)).arg((long long)At(i))
864  .arg(GetStatus()));
865  ReleaseDecoderResources(At(i), refs);
867  }
868  }
869  }
870 
871  // Make sure frames used by decoder are last...
872  // This is for libmpeg2 which still uses the frames after a reset.
873  for (it = m_decode.begin(); it != m_decode.end(); ++it)
874  Remove(kVideoBuffer_all, *it);
875  for (it = m_decode.begin(); it != m_decode.end(); ++it)
876  m_available.enqueue(*it);
877  m_decode.clear();
878 
879  LOG(VB_PLAYBACK, LOG_INFO,
880  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
881  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
882 
883  m_globalLock.unlock();
884  DoDiscard(refs);
885 }
886 
896 {
897  std::vector<AVBufferRef*> discards;
898  {
899  QMutexLocker locker(&m_globalLock);
900 
901  for (uint i = 0; i < Size(); i++)
902  At(i)->m_timecode = 0ms;
903 
904  for (uint i = 0; (i < Size()) && (m_used.count() > 1); i++)
905  {
906  MythVideoFrame *buffer = At(i);
907  if (m_used.contains(buffer) && !m_decode.contains(buffer))
908  {
909  m_used.remove(buffer);
910  m_available.enqueue(buffer);
911  ReleaseDecoderResources(buffer, discards);
912  }
913  }
914 
915  if (m_used.count() > 0)
916  {
917  for (uint i = 0; i < Size(); i++)
918  {
919  MythVideoFrame *buffer = At(i);
920  if (m_used.contains(buffer) && !m_decode.contains(buffer))
921  {
922  m_used.remove(buffer);
923  m_available.enqueue(buffer);
924  ReleaseDecoderResources(buffer, discards);
925  m_vpos = m_vbufferMap[buffer];
926  m_rpos = m_vpos;
927  break;
928  }
929  }
930  }
931  else
932  {
933  m_vpos = m_rpos = 0;
934  }
935  }
936 
937  DoDiscard(discards);
938 }
939 
940 bool VideoBuffers::CreateBuffers(VideoFrameType Type, const VideoFrameTypes* RenderFormats, QSize Size,
941  uint NeedFree, uint NeedprebufferNormal,
942  uint NeedPrebufferSmall, int MaxReferenceFrames)
943 {
944  m_renderFormats = RenderFormats;
945  Init(GetNumBuffers(Type, MaxReferenceFrames), NeedFree, NeedprebufferNormal, NeedPrebufferSmall);
946  return CreateBuffers(Type, Size.width(), Size.height(), m_renderFormats);
947 }
948 
949 bool VideoBuffers::CreateBuffers(VideoFrameType Type, int Width, int Height, const VideoFrameTypes* RenderFormats)
950 {
951  bool success = true;
952  m_renderFormats = RenderFormats;
953 
954  // Hardware buffers with no allocated memory
956  {
957  for (uint i = 0; i < Size(); i++)
958  m_buffers[i].Init(Type, Width, Height, m_renderFormats);
959  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 empty %2 (%3x%4) video buffers")
960  .arg(Size()).arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
961  return true;
962  }
963 
964  // Software buffers
965  for (uint i = 0; i < Size(); i++)
966  {
967  m_buffers[i].Init(Type, Width, Height, m_renderFormats);
968  m_buffers[i].ClearBufferToBlank();
969  success &= m_buffers[i].m_dummy || (m_buffers[i].m_buffer != nullptr);
970  }
971 
972  // workaround null buffers for audio only (remove when these buffers aren't used)
973  if (!success && (Width < 1 || Height < 1))
974  success = true;
975 
976  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 %2 (%3x%4) video buffers")
977  .arg(Size()).arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
978  return success;
979 }
980 
982  int Width, int Height)
983 {
984  if (!Frame)
985  return false;
986 
988  {
989  LOG(VB_GENERAL, LOG_ERR, "Cannot re-initialise a hardware buffer");
990  return false;
991  }
992 
993  VideoFrameType old = Frame->m_type;
994  const auto * formats = Frame->m_renderFormats;
995  LOG(VB_PLAYBACK, LOG_INFO, QString("Reallocating frame %1 %2x%3->%4 %5x%6")
996  .arg(MythVideoFrame::FormatDescription(old)).arg(Frame->m_width).arg(Frame->m_height)
997  .arg(MythVideoFrame::FormatDescription(Type)).arg(Width).arg(Height));
998 
999  MythDeintType singler = Frame->m_deinterlaceSingle;
1000  MythDeintType doubler = Frame->m_deinterlaceDouble;
1001  Frame->Init(Type, Width, Height, formats);
1002  Frame->ClearBufferToBlank();
1003 
1004  // retain deinterlacer settings and update restrictions based on new frame type
1005  SetDeinterlacingFlags(*Frame, singler, doubler, CodecID);
1006  return true;
1007 }
1008 
1009 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num);
1010 
1011 QString VideoBuffers::GetStatus(uint Num) const
1012 {
1013  if (Num == 0)
1014  Num = Size();
1015 
1016  QString str("");
1017  if (m_globalLock.tryLock())
1018  {
1019  int count = Size();
1020  unsigned long long a = to_bitmap(m_available, count);
1021  unsigned long long u = to_bitmap(m_used, count);
1022  unsigned long long d = to_bitmap(m_displayed, count);
1023  unsigned long long l = to_bitmap(m_limbo, count);
1024  unsigned long long p = to_bitmap(m_pause, count);
1025  unsigned long long f = to_bitmap(m_finished, count);
1026  unsigned long long x = to_bitmap(m_decode, count);
1027  for (uint i = 0; i < Num; i++)
1028  {
1029  unsigned long long mask = 1ULL << i;
1030  QString tmp("");
1031  if (a & mask)
1032  tmp += (x & mask) ? "a" : "A";
1033  if (u & mask)
1034  tmp += (x & mask) ? "u" : "U";
1035  if (d & mask)
1036  tmp += (x & mask) ? "d" : "D";
1037  if (l & mask)
1038  tmp += (x & mask) ? "l" : "L";
1039  if (p & mask)
1040  tmp += (x & mask) ? "p" : "P";
1041  if (f & mask)
1042  tmp += (x & mask) ? "f" : "F";
1043  if (0 == tmp.length())
1044  str += " ";
1045  else if (1 == tmp.length())
1046  str += tmp;
1047  else
1048  str += "(" + tmp + ")";
1049  }
1050  m_globalLock.unlock();
1051  }
1052  else
1053  {
1054  for (uint i = 0; i < Num; i++)
1055  str += " ";
1056  }
1057  return str;
1058 }
1059 
1060 /*******************************
1061  ** Debugging functions below **
1062  *******************************/
1063 
1064 static constexpr size_t DBG_STR_ARR_SIZE { 40 };
1065 const std::array<const QString,DBG_STR_ARR_SIZE> dbg_str_arr
1067  "A ", " B ", " C ", " D ",
1068  " E ", " F ", " G ", " H", // 8
1069  "a ", " b ", " c ", " d ",
1070  " e ", " f ", " g ", " h", // 16
1071  "0 ", " 1 ", " 2 ", " 3 ",
1072  " 4 ", " 5 ", " 6 ", " 7", // 24
1073  "I ", " J ", " K ", " L ",
1074  " M ", " N ", " O ", " P", // 32
1075  "i ", " j ", " k ", " l ",
1076  " m ", " n ", " o ", " p", // 40
1077 };
1078 const std::array<const QString,DBG_STR_ARR_SIZE> dbg_str_arr_short
1080  "A","B","C","D","E","F","G","H", // 8
1081  "a","b","c","d","e","f","g","h", // 16
1082  "0","1","2","3","4","5","6","7", // 24
1083  "I","J","K","L","M","N","O","P", // 32
1084  "i","j","k","l","m","n","o","p", // 40
1085 };
1086 
1087 std::map<const MythVideoFrame *, int> dbg_str;
1088 
1089 static int DebugNum(const MythVideoFrame *Frame)
1090 {
1091  auto it = dbg_str.find(Frame);
1092  if (it == dbg_str.end())
1093  return dbg_str[Frame] = next_dbg_str++;
1094  return it->second;
1095 }
1096 
1097 const QString& DebugString(const MythVideoFrame *Frame, bool Short)
1098 {
1099  if (Short)
1102 }
1103 
1104 const QString& DebugString(uint FrameNum, bool Short)
1105 {
1106  return ((Short) ? dbg_str_arr_short : dbg_str_arr)[FrameNum];
1107 }
1108 
1109 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num)
1110 {
1111  unsigned long long bitmap = 0;
1112  for (auto *it : Queue)
1113  {
1114  int shift = DebugNum(it) % Num;
1115  bitmap |= 1ULL << shift;
1116  }
1117  return bitmap;
1118 }
MythDeque::remove
void remove(T const item)
Removes any item from list. O(n).
Definition: mythdeque.h:66
FMT_VTB
@ FMT_VTB
Definition: mythframe.h:61
VideoBuffers::ValidVideoFrames
uint ValidVideoFrames(void) const
Definition: videobuffers.cpp:769
FMT_VDPAU
@ FMT_VDPAU
Definition: mythframe.h:56
DebugNum
static int DebugNum(const MythVideoFrame *Frame)
Definition: videobuffers.cpp:1089
VideoBuffers::ReleaseFrame
void ReleaseFrame(MythVideoFrame *Frame)
Definition: videobuffers.cpp:360
VideoBuffers::Size
uint Size(void) const
Definition: videobuffers.cpp:799
VideoBuffers::Head
MythVideoFrame * Head(BufferType Type)
Definition: videobuffers.cpp:647
codec_is_v4l2
static bool codec_is_v4l2(MythCodecID id)
Definition: mythcodecid.h:356
VideoBuffers::Tail
MythVideoFrame * Tail(BufferType Type)
Definition: videobuffers.cpp:658
VideoBuffers::m_available
frame_queue_t m_available
Definition: videobuffers.h:103
MythCodecID
MythCodecID
Definition: mythcodecid.h:11
VideoBuffers::m_needPrebufferFrames
uint m_needPrebufferFrames
Definition: videobuffers.h:115
MythVideoFrame::HardwareFramesFormat
static bool HardwareFramesFormat(VideoFrameType Type)
Definition: mythframe.h:432
codec_is_nvdec
static bool codec_is_nvdec(MythCodecID id)
Definition: mythcodecid.h:342
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
VideoBuffers::m_needPrebufferFramesNormal
uint m_needPrebufferFramesNormal
Definition: videobuffers.h:116
VideoBuffers::m_globalLock
QRecursiveMutex m_globalLock
Definition: videobuffers.h:120
Frame
Definition: zmdefines.h:102
VideoBuffers::EnoughDecodedFrames
bool EnoughDecodedFrames(void) const
Definition: videobuffers.cpp:784
codec_is_vaapi
static bool codec_is_vaapi(MythCodecID id)
Definition: mythcodecid.h:319
codec_is_vtb
static bool codec_is_vtb(MythCodecID id)
Definition: mythcodecid.h:349
FMT_NVDEC
@ FMT_NVDEC
Definition: mythframe.h:62
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
codec_is_vaapi_dec
static bool codec_is_vaapi_dec(MythCodecID id)
Definition: mythcodecid.h:322
VideoBuffers::m_limbo
frame_queue_t m_limbo
Definition: videobuffers.h:105
VideoBuffers::Dequeue
MythVideoFrame * Dequeue(BufferType Type)
Definition: videobuffers.cpp:638
VideoBuffers::End
frame_queue_t::iterator End(BufferType Type)
Definition: videobuffers.cpp:734
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
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
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:21
MythVideoFrame::HardwareFormat
static bool HardwareFormat(VideoFrameType Type)
Definition: mythframe.h:424
kVideoBuffer_pause
@ kVideoBuffer_pause
Definition: videobuffers.h:31
DBG_STR_ARR_SIZE
static constexpr size_t DBG_STR_ARR_SIZE
Definition: videobuffers.cpp:1064
kVideoBuffer_finished
@ kVideoBuffer_finished
Definition: videobuffers.h:33
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:1087
VideoBuffers::CreateBuffers
bool CreateBuffers(VideoFrameType Type, const VideoFrameTypes *RenderFormats, QSize Size, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall, int MaxReferenceFrames=16)
Definition: videobuffers.cpp:940
kCodec_NONE
@ kCodec_NONE
Definition: mythcodecid.h:15
VideoBuffers::GetNextFreeFrameInternal
MythVideoFrame * GetNextFreeFrameInternal(BufferType EnqueueTo)
Definition: videobuffers.cpp:287
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
MythDeintType
MythDeintType
Definition: mythframe.h:66
VideoBuffers::m_vpos
uint m_vpos
Definition: videobuffers.h:119
VideoBuffers::m_pause
frame_queue_t m_pause
Definition: videobuffers.h:106
VideoBuffers::m_buffers
frame_vector_t m_buffers
Definition: videobuffers.h:111
videobuffers.h
Decoder
Definition: decoder.h:70
FMT_VAAPI
@ FMT_VAAPI
Definition: mythframe.h:57
VideoBuffers::m_displayed
frame_queue_t m_displayed
Definition: videobuffers.h:107
kVideoBuffer_displayed
@ kVideoBuffer_displayed
Definition: videobuffers.h:32
mythlogging.h
TRY_LOCK_SPINS
static constexpr uint16_t TRY_LOCK_SPINS
Definition: videobuffers.cpp:22
MythDeque< MythVideoFrame * >::iterator
typename std::deque< MythVideoFrame * >::iterator iterator
Definition: mythdeque.h:43
VideoBuffers::m_vbufferMap
vbuffer_map_t m_vbufferMap
Definition: videobuffers.h:110
VideoBuffers::Contains
bool Contains(BufferType Type, MythVideoFrame *Frame) const
Definition: videobuffers.cpp:750
hardwareprofile.config.p
p
Definition: config.py:33
DEINT_ALL
@ DEINT_ALL
Definition: mythframe.h:75
MythVideoFrame::m_timecode
std::chrono::milliseconds m_timecode
Definition: mythframe.h:130
compat.h
VideoFrameTypes
std::vector< VideoFrameType > VideoFrameTypes
Definition: mythframe.h:82
VideoBuffers::EnoughFreeFrames
bool EnoughFreeFrames(void) const
Definition: videobuffers.cpp:779
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:74
VideoBuffers::m_finished
frame_queue_t m_finished
Definition: videobuffers.h:109
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:73
formats
const std::array< const std::string, 8 > formats
Definition: vbilut.cpp:189
VideoBuffers::Queue
frame_queue_t * Queue(BufferType Type)
Definition: videobuffers.cpp:586
codec_is_nvdec_dec
static bool codec_is_nvdec_dec(MythCodecID id)
Definition: mythcodecid.h:345
VideoBuffers::StartDisplayingFrame
void StartDisplayingFrame(void)
Definition: videobuffers.cpp:407
VideoFrameType
VideoFrameType
Definition: mythframe.h:19
ReleaseDecoderResources
static void ReleaseDecoderResources(MythVideoFrame *Frame, std::vector< AVBufferRef * > &Discards)
Store AVBufferRef's for later disposal.
Definition: videobuffers.cpp:37
mythcodecid.h
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:23
FMT_DRMPRIME
@ FMT_DRMPRIME
Definition: mythframe.h:63
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:1066
VideoBuffers::Reset
void Reset(void)
Definition: videobuffers.cpp:264
TRY_LOCK_SPIN_WAIT
static constexpr std::chrono::milliseconds TRY_LOCK_SPIN_WAIT
Definition: videobuffers.cpp:24
VideoBuffers::m_needFreeFrames
uint m_needFreeFrames
Definition: videobuffers.h:114
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:68
kVideoBuffer_avail
@ kVideoBuffer_avail
Definition: videobuffers.h:28
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:72
VideoBuffers::BeginLock
frame_queue_t::iterator BeginLock(BufferType Type)
Lock the video buffers.
Definition: videobuffers.cpp:720
kVideoBuffer_decode
@ kVideoBuffer_decode
Definition: videobuffers.h:34
kVideoBuffer_used
@ kVideoBuffer_used
Definition: videobuffers.h:30
VideoBuffers::EndLock
void EndLock()
Definition: videobuffers.cpp:729
VideoBuffers::DiscardPauseFrames
void DiscardPauseFrames(void)
Definition: videobuffers.cpp:460
VideoBuffers::GetLastShownFrame
MythVideoFrame * GetLastShownFrame(void)
Definition: videobuffers.cpp:764
FMT_MMAL
@ FMT_MMAL
Definition: mythframe.h:59
VideoBuffers::DiscardFrame
void DiscardFrame(MythVideoFrame *Frame)
Definition: videobuffers.cpp:450
VideoBuffers::m_used
frame_queue_t m_used
Definition: videobuffers.h:104
MythVideoFrame::FormatDescription
static QString FormatDescription(VideoFrameType Type)
Definition: mythframe.cpp:368
TRY_LOCK_SPINS_BEFORE_WARNING
static constexpr uint16_t TRY_LOCK_SPINS_BEFORE_WARNING
Definition: videobuffers.cpp:23
VideoBuffers::Enqueue
void Enqueue(BufferType Type, MythVideoFrame *Frame)
Definition: videobuffers.cpp:669
next_dbg_str
int next_dbg_str
Definition: videobuffers.cpp:26
MythDeque< MythVideoFrame * >
codec_is_mmal
static bool codec_is_mmal(MythCodecID id)
Definition: mythcodecid.h:361
VideoBuffers::GetLastDecodedFrame
MythVideoFrame * GetLastDecodedFrame(void)
Definition: videobuffers.cpp:759
VideoBuffers::SetPrebuffering
void SetPrebuffering(bool Normal)
Definition: videobuffers.cpp:281
kVideoBuffer_limbo
@ kVideoBuffer_limbo
Definition: videobuffers.h:29
VideoBuffers::ClearAfterSeek
void ClearAfterSeek(void)
Clear used frames after seeking.
Definition: videobuffers.cpp:895
VideoBuffers::DoneDisplayingFrame
void DoneDisplayingFrame(MythVideoFrame *Frame)
Definition: videobuffers.cpp:417
VideoBuffers::m_rpos
uint m_rpos
Definition: videobuffers.h:118
codec_is_mediacodec
static bool codec_is_mediacodec(MythCodecID id)
Definition: mythcodecid.h:335
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:706
DoDiscard
static void DoDiscard(const std::vector< AVBufferRef * > &Discards)
Definition: videobuffers.cpp:56
VideoBuffers::FreeVideoFrames
uint FreeVideoFrames(void) const
Definition: videobuffers.cpp:774
DebugString
const QString & DebugString(const MythVideoFrame *Frame, bool Short)
Definition: videobuffers.cpp:1097
FMT_DXVA2
@ FMT_DXVA2
Definition: mythframe.h:58
VideoBuffers::ReinitBuffer
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
Definition: videobuffers.cpp:981
codec_is_drmprime
static bool codec_is_drmprime(MythCodecID id)
Definition: mythcodecid.h:299
codec_is_vdpau
static bool codec_is_vdpau(MythCodecID id)
Definition: mythcodecid.h:302
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
BufferType
BufferType
Definition: videobuffers.h:26
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:1109
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
MythVideoFrame
Definition: mythframe.h:87
VideoBuffers::DiscardFrames
void DiscardFrames(bool NextFrameIsKeyFrame)
Definition: videobuffers.cpp:808
VideoBuffers::DeLimboFrame
void DeLimboFrame(MythVideoFrame *Frame)
Definition: videobuffers.cpp:377
codec_is_copyback
static bool codec_is_copyback(MythCodecID id)
Definition: mythcodecid.h:366
FMT_MEDIACODEC
@ FMT_MEDIACODEC
Definition: mythframe.h:60
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:1079
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:1011
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:135
VideoBuffers::m_needPrebufferFramesSmall
uint m_needPrebufferFramesSmall
Definition: videobuffers.h:117
VideoBuffers::m_decode
frame_queue_t m_decode
Definition: videobuffers.h:108
VideoBuffers::m_renderFormats
const VideoFrameTypes * m_renderFormats
Definition: videobuffers.h:112
uint
unsigned int uint
Definition: freesurround.h:24
fourcc.h
MythDeque::enqueue
void enqueue(const T &d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:41