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 
101 uint VideoBuffers::GetNumBuffers(int PixelFormat, int MaxReferenceFrames, bool Decoder /*=false*/)
102 {
103  uint refs = static_cast<uint>(MaxReferenceFrames);
104  switch (PixelFormat)
105  {
106  case FMT_DXVA2: return 30;
107  // It is currrently unclear whether VTB just happy with a smaller buffer size
108  // or needs reference frames plus headroom - use the latter for now.
109  case FMT_VTB: return refs + 8;
110  // Max 16 ref frames, 12 headroom and allocate 2 extra in the VAAPI frames
111  // context for additional references held by the VPP deinterlacer (i.e.
112  // prevent buffer starvation in the decoder)
113  // This covers the 'worst case' samples.
114  case FMT_VAAPI: return Decoder ? (refs + 14) : (refs + 12);
115  case FMT_VDPAU: return refs + 12;
116  // Copyback of hardware frames. These decoders are buffering internally
117  // already - so no need for a large presentation buffer
118  case FMT_NONE: return 8; // NOLINT(bugprone-branch-clone)
119  // As for copyback, these decoders buffer internally
120  case FMT_NVDEC: return 8;
121  case FMT_MEDIACODEC: return 8;
122  case FMT_MMAL: return 8;
123  // the default number of output buffers in FFmpeg v4l2_m2m.h is 6
124  case FMT_DRMPRIME: return 6;
125  // Standard software decode
126  case FMT_YV12: return refs + 14;
127  default: break;
128  }
129  return 30;
130 }
131 
133 {
134  DeleteBuffers();
135 }
136 
154 void VideoBuffers::Init(uint NumDecode, bool ExtraForPause,
155  uint NeedFree, uint NeedPrebufferNormal,
156  uint NeedPrebufferSmall)
157 {
158  QMutexLocker locker(&m_globalLock);
159 
160  Reset();
161 
162  uint numcreate = NumDecode + ((ExtraForPause) ? 1 : 0);
163 
164  // make a big reservation, so that things that depend on
165  // pointer to VideoFrames work even after a few push_backs
166  m_buffers.reserve(max(numcreate, (uint)128));
167 
168  m_buffers.resize(numcreate);
169  for (uint i = 0; i < numcreate; i++)
170  {
171  memset(At(i), 0, sizeof(VideoFrame));
172  At(i)->codec = FMT_NONE;
173  At(i)->interlaced_frame = -1;
174  At(i)->top_field_first = 1;
175  m_vbufferMap[At(i)] = i;
176  }
177 
178  m_needFreeFrames = NeedFree;
179  m_needPrebufferFrames = NeedPrebufferNormal;
180  m_needPrebufferFramesNormal = NeedPrebufferNormal;
181  m_needPrebufferFramesSmall = NeedPrebufferSmall;
182  m_createdPauseFrame = ExtraForPause;
183 
185  Enqueue(kVideoBuffer_pause, At(numcreate - 1));
186 
187  for (uint i = 0; i < NumDecode; i++)
190 }
191 
193  MythCodecID CodecID)
194 {
195  QMutexLocker locker(&m_globalLock);
196  for (auto & buffer : m_buffers)
197  SetDeinterlacingFlags(buffer, Single, Double, CodecID);
198 }
199 
208  MythDeintType Double, MythCodecID CodecID)
209 {
210  static const MythDeintType kDriver = DEINT_ALL & ~(DEINT_CPU | DEINT_SHADER);
211  static const MythDeintType kShader = DEINT_ALL & ~(DEINT_CPU | DEINT_DRIVER);
212  static const MythDeintType kSoftware = DEINT_ALL & ~(DEINT_SHADER | DEINT_DRIVER);
213  Frame.deinterlace_single = Single;
214  Frame.deinterlace_double = Double;
215 
216  if (codec_is_copyback(CodecID))
217  {
218  if (codec_is_vaapi_dec(CodecID) || codec_is_nvdec_dec(CodecID))
219  Frame.deinterlace_allowed = kSoftware | kShader | kDriver;
220  else // VideoToolBox, MediaCodec and VDPAU copyback
221  Frame.deinterlace_allowed = kSoftware | kShader;
222  }
223  else if (FMT_DRMPRIME == Frame.codec)
224  { // NOLINT(bugprone-branch-clone)
225  Frame.deinterlace_allowed = kShader; // No driver deint - if RGBA frames are returned, shaders will be disabled
226  }
227  else if (FMT_MMAL == Frame.codec)
228  {
229  Frame.deinterlace_allowed = kShader; // No driver deint yet (TODO) and YUV frames returned
230  }
231  else if (FMT_VTB == Frame.codec)
232  {
233  Frame.deinterlace_allowed = kShader; // No driver deint and YUV frames returned
234  }
235  else if (FMT_NVDEC == Frame.codec)
236  {
237  Frame.deinterlace_allowed = kShader | kDriver; // YUV frames and decoder deint
238  }
239  else if (FMT_VDPAU == Frame.codec)
240  { // NOLINT(bugprone-branch-clone)
241  Frame.deinterlace_allowed = kDriver; // No YUV frames for shaders
242  }
243  else if (FMT_VAAPI == Frame.codec)
244  {
245  Frame.deinterlace_allowed = kDriver; // DRM will allow shader if no VPP
246  }
247  else
248  {
249  Frame.deinterlace_allowed = kSoftware | kShader;
250  }
251 }
252 
258 {
259  QMutexLocker locker(&m_globalLock);
260  m_available.clear();
261  m_used.clear();
262  m_limbo.clear();
263  m_finished.clear();
264  m_decode.clear();
265  m_pause.clear();
266  m_displayed.clear();
267  m_vbufferMap.clear();
268 }
269 
275 {
276  QMutexLocker locker(&m_globalLock);
278 }
279 
281 {
282  if (format_is_hw(Frame->codec))
283  {
284  auto* ref = reinterpret_cast<AVBufferRef*>(Frame->priv[0]);
285  if (ref != nullptr)
286  av_buffer_unref(&ref);
287  Frame->buf = Frame->priv[0] = nullptr;
288 
289  if (format_is_hwframes(Frame->codec))
290  {
291  ref = reinterpret_cast<AVBufferRef*>(Frame->priv[1]);
292  if (ref != nullptr)
293  av_buffer_unref(&ref);
294  Frame->priv[1] = nullptr;
295  }
296  }
297  (void)Frame;
298 }
299 
301 {
302  QMutexLocker locker(&m_globalLock);
303  VideoFrame *frame = nullptr;
304 
305  // Try to get a frame not being used by the decoder
306  for (size_t i = 0; i < m_available.size(); i++)
307  {
308  frame = m_available.dequeue();
309  if (m_decode.contains(frame))
310  m_available.enqueue(frame);
311  else
312  break;
313  }
314 
315  while (frame && m_used.contains(frame))
316  {
317  LOG(VB_PLAYBACK, LOG_NOTICE,
318  QString("GetNextFreeFrame() served a busy frame %1. Dropping. %2")
319  .arg(DebugString(frame, true)).arg(GetStatus()));
320  frame = m_available.dequeue();
321  }
322 
323  if (frame)
324  SafeEnqueue(EnqueueTo, frame);
325  return frame;
326 }
327 
333 {
334  for (uint tries = 1; true; tries++)
335  {
337  if (frame)
338  return frame;
339 
340  if (tries >= TRY_LOCK_SPINS)
341  {
342  LOG(VB_GENERAL, LOG_ERR, QString("GetNextFreeFrame: "
343  "available:%1 used:%2 limbo:%3 pause:%4 displayed:%5 decode:%6 finished:%7")
344  .arg(m_available.size()).arg(m_used.size()).arg(m_limbo.size())
345  .arg(m_pause.size()).arg(m_displayed.size()).arg(m_decode.size())
346  .arg(m_finished.size()));
347  LOG(VB_GENERAL, LOG_ERR,
348  QString("GetNextFreeFrame() unable to "
349  "lock frame %1 times. Discarding Frames.")
350  .arg(TRY_LOCK_SPINS));
351  DiscardFrames(true);
352  continue;
353  }
354 
355  if (tries && !(tries % TRY_LOCK_SPINS_BEFORE_WARNING))
356  {
357  LOG(VB_PLAYBACK, LOG_NOTICE,
358  QString("GetNextFreeFrame() TryLock has "
359  "spun %1 times, this is a lot.").arg(tries));
360  }
361  std::this_thread::sleep_for(std::chrono::microseconds(TRY_LOCK_SPIN_WAIT));
362  }
363 
364  return nullptr;
365 }
366 
374 {
375  QMutexLocker locker(&m_globalLock);
376 
379  //non directrendering frames are ffmpeg handled
380  if (Frame->directrendering != 0)
383 }
384 
391 {
392  QMutexLocker locker(&m_globalLock);
393  if (m_limbo.contains(Frame))
395 
396  // if decoder didn't release frame and the buffer is getting released by
397  // the decoder assume that the frame is lost and return to available
398  if (!m_decode.contains(Frame))
399  {
402  }
403 
404  // remove from decode queue since the decoder is finished
405  while (m_decode.contains(Frame))
407 }
408 
414 {
415  QMutexLocker locker(&m_globalLock);
417 }
418 
424 {
425  QMutexLocker locker(&m_globalLock);
426 
427  if(m_used.contains(Frame))
429 
431 
432  // check if any finished frames are no longer used by decoder and return to available
434  for (auto & it : ula)
435  {
436  if (!m_decode.contains(it))
437  {
441  }
442  }
443 }
444 
451 {
452  QMutexLocker locker(&m_globalLock);
455 }
456 
458 {
459  QMutexLocker locker(&m_globalLock);
460  frame_queue_t *queue = nullptr;
461  if (Type == kVideoBuffer_avail)
462  queue = &m_available;
463  else if (Type == kVideoBuffer_used)
464  queue = &m_used;
465  else if (Type == kVideoBuffer_displayed)
466  queue = &m_displayed;
467  else if (Type == kVideoBuffer_limbo)
468  queue = &m_limbo;
469  else if (Type == kVideoBuffer_pause)
470  queue = &m_pause;
471  else if (Type == kVideoBuffer_decode)
472  queue = &m_decode;
473  else if (Type == kVideoBuffer_finished)
474  queue = &m_finished;
475  return queue;
476 }
477 
479 {
480  QMutexLocker locker(&m_globalLock);
481  const frame_queue_t *queue = nullptr;
482  if (Type == kVideoBuffer_avail)
483  queue = &m_available;
484  else if (Type == kVideoBuffer_used)
485  queue = &m_used;
486  else if (Type == kVideoBuffer_displayed)
487  queue = &m_displayed;
488  else if (Type == kVideoBuffer_limbo)
489  queue = &m_limbo;
490  else if (Type == kVideoBuffer_pause)
491  queue = &m_pause;
492  else if (Type == kVideoBuffer_decode)
493  queue = &m_decode;
494  else if (Type == kVideoBuffer_finished)
495  queue = &m_finished;
496  return queue;
497 }
498 
500 {
501  return &m_buffers[FrameNum];
502 }
503 
504 const VideoFrame* VideoBuffers::At(uint FrameNum) const
505 {
506  return &m_buffers[FrameNum];
507 }
508 
510 {
511  QMutexLocker locker(&m_globalLock);
512  frame_queue_t *queue = Queue(Type);
513  if (!queue)
514  return nullptr;
515  return queue->dequeue();
516 }
517 
519 {
520  QMutexLocker locker(&m_globalLock);
521  frame_queue_t *queue = Queue(Type);
522  if (!queue)
523  return nullptr;
524  if (!queue->empty())
525  return queue->head();
526  return nullptr;
527 }
528 
530 {
531  QMutexLocker locker(&m_globalLock);
532  frame_queue_t *queue = Queue(Type);
533  if (!queue)
534  return nullptr;
535  if (!queue->empty())
536  return queue->tail();
537  return nullptr;
538 }
539 
541 {
542  if (!Frame)
543  return;
544  frame_queue_t *queue = Queue(Type);
545  if (!queue)
546  return;
547  m_globalLock.lock();
548  queue->remove(Frame);
549  queue->enqueue(Frame);
550  if (Type == kVideoBuffer_pause)
551  Frame->pause_frame = 1;
552  m_globalLock.unlock();
553 }
554 
556 {
557  if (!Frame)
558  return;
559 
560  QMutexLocker locker(&m_globalLock);
561  if ((Type & kVideoBuffer_avail) == kVideoBuffer_avail)
563  if ((Type & kVideoBuffer_used) == kVideoBuffer_used)
567  if ((Type & kVideoBuffer_limbo) == kVideoBuffer_limbo)
569  if ((Type & kVideoBuffer_pause) == kVideoBuffer_pause)
575 }
576 
578 {
579  QMutexLocker locker(&m_globalLock);
580  Count = (Count <= 0) ? Size(Source) : Count;
581  for (uint i=0; i<(uint)Count; i++)
582  {
583  VideoFrame *frame = Dequeue(Source);
584  if (frame)
585  Enqueue(Dest, frame);
586  }
587 }
588 
590 {
591  if (!Frame)
592  return;
593  QMutexLocker locker(&m_globalLock);
595  Enqueue(Type, Frame);
596 }
597 
599 {
600  m_globalLock.lock();
601  frame_queue_t *queue = Queue(Type);
602  if (queue)
603  return queue->begin();
604  return m_available.begin();
605 }
606 
608 {
609  m_globalLock.unlock();
610 }
611 
613 {
614  QMutexLocker locker(&m_globalLock);
615  frame_queue_t *queue = Queue(Type);
616  return (queue ? queue->end() : m_available.end());
617 }
618 
620 {
621  QMutexLocker locker(&m_globalLock);
622  const frame_queue_t *queue = Queue(Type);
623  if (queue)
624  return queue->size();
625  return 0;
626 }
627 
629 {
630  QMutexLocker locker(&m_globalLock);
631  const frame_queue_t *queue = Queue(Type);
632  if (queue)
633  return queue->contains(Frame);
634  return false;
635 }
636 
638 {
640  {
641  LOG(VB_GENERAL, LOG_ERR, "GetScratchFrame() called, but not allocated");
642  return nullptr;
643  }
644 
645  QMutexLocker locker(&m_globalLock);
646  return Head(kVideoBuffer_pause);
647 }
648 
650 {
651  return At(m_vpos);
652 }
653 
655 {
656  return At(m_rpos);
657 }
658 
660 {
662  {
663  LOG(VB_GENERAL, LOG_ERR,
664  "SetLastShownFrameToScratch() called but no pause frame");
665  return;
666  }
667 
669  m_rpos = m_vbufferMap[pause];
670 }
671 
673 {
674  return Size(kVideoBuffer_used);
675 }
676 
678 {
679  return Size(kVideoBuffer_avail);
680 }
681 
683 {
685 }
686 
688 {
690 }
691 
693 {
694  return At(m_vpos);
695 }
696 
698 {
699  return At(m_rpos);
700 }
701 
703 {
704  return m_buffers.size();
705 }
706 
711 void VideoBuffers::DiscardFrames(bool NextFrameIsKeyFrame)
712 {
713  QMutexLocker locker(&m_globalLock);
714  LOG(VB_PLAYBACK, LOG_INFO, QString("VideoBuffers::DiscardFrames(%1): %2")
715  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
716 
717  if (!NextFrameIsKeyFrame)
718  {
719  frame_queue_t ula(m_used);
720  for (auto & it : ula)
721  DiscardFrame(it);
722  LOG(VB_PLAYBACK, LOG_INFO,
723  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
724  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
725  return;
726  }
727 
728  // Remove inheritence of all frames not in displayed or pause
729  frame_queue_t ula(m_used);
730  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
731  ula.insert(ula.end(), m_available.begin(), m_available.end());
732  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
734 
735  // Discard frames
736  frame_queue_t discards(m_used);
737  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
738  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
739  for (it = discards.begin(); it != discards.end(); ++it)
740  DiscardFrame(*it);
741 
742  // Verify that things are kosher
743  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
744  {
745  for (uint i=0; i < Size(); i++)
746  {
747  if (!m_available.contains(At(i)) &&
748  !m_pause.contains(At(i)) &&
749  !m_displayed.contains(At(i)))
750  {
751  // This message is DEBUG because it does occur
752  // after Reset is called.
753  // That happens when failing over from OpenGL
754  // to another method, if QT painter is selected.
755  LOG(VB_GENERAL, LOG_DEBUG,
756  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
757  "in available, pause, or displayed %3")
758  .arg(DebugString(At(i), true)).arg((long long)At(i))
759  .arg(GetStatus()));
760  DiscardFrame(At(i));
761  }
762  }
763  }
764 
765  // Make sure frames used by decoder are last...
766  // This is for libmpeg2 which still uses the frames after a reset.
767  for (it = m_decode.begin(); it != m_decode.end(); ++it)
768  Remove(kVideoBuffer_all, *it);
769  for (it = m_decode.begin(); it != m_decode.end(); ++it)
770  m_available.enqueue(*it);
771  m_decode.clear();
772 
773  LOG(VB_PLAYBACK, LOG_INFO,
774  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
775  .arg(NextFrameIsKeyFrame).arg(GetStatus()));
776 }
777 
787 {
788  {
789  QMutexLocker locker(&m_globalLock);
790 
791  for (uint i = 0; i < Size(); i++)
792  At(i)->timecode = 0;
793 
794  for (uint i = 0; (i < Size()) && (m_used.count() > 1); i++)
795  {
796  VideoFrame *buffer = At(i);
797  if (m_used.contains(buffer) && !m_decode.contains(buffer))
798  {
799  m_used.remove(buffer);
800  m_available.enqueue(buffer);
801  ReleaseDecoderResources(buffer);
802  }
803  }
804 
805  if (m_used.count() > 0)
806  {
807  for (uint i = 0; i < Size(); i++)
808  {
809  VideoFrame *buffer = At(i);
810  if (m_used.contains(buffer) && !m_decode.contains(buffer))
811  {
812  m_used.remove(buffer);
813  m_available.enqueue(buffer);
814  ReleaseDecoderResources(buffer);
815  m_vpos = m_vbufferMap[buffer];
816  m_rpos = m_vpos;
817  break;
818  }
819  }
820  }
821  else
822  {
823  m_vpos = m_rpos = 0;
824  }
825  }
826 }
827 
828 bool VideoBuffers::CreateBuffers(VideoFrameType Type, QSize Size, bool ExtraForPause,
829  uint NeedFree, uint NeedprebufferNormal,
830  uint NeedPrebufferSmall, int MaxReferenceFrames)
831 {
832  Init(GetNumBuffers(Type, MaxReferenceFrames), ExtraForPause, NeedFree, NeedprebufferNormal,
833  NeedPrebufferSmall);
834  return CreateBuffers(Type, Size.width(), Size.height());
835 }
836 
837 bool VideoBuffers::CreateBuffers(VideoFrameType Type, int Width, int Height)
838 {
839  bool success = true;
840 
841  // Hardware buffers with no allocated memory
842  if (format_is_hw(Type))
843  {
844  for (uint i = 0; i < Size(); i++)
845  success &= CreateBuffer(Width, Height, i, nullptr, Type);
846  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 empty %2 (%3x%4) video buffers")
847  .arg(Size()).arg(format_description(Type)).arg(Width).arg(Height));
848  return success;
849  }
850 
851  // Software buffers
852  size_t bufsize = GetBufferSize(Type, Width, Height);
853  for (uint i = 0; i < Size(); i++)
854  {
855  unsigned char *data = GetAlignedBuffer(bufsize);
856  if (!data)
857  LOG(VB_GENERAL, LOG_CRIT, "Failed to allocate video buffer memory");
858  init(&m_buffers[i], Type, data, Width, Height, static_cast<int>(bufsize));
859  success &= (m_buffers[i].buf != nullptr);
860  }
861 
862  Clear();
863  LOG(VB_PLAYBACK, LOG_INFO, QString("Created %1 %2 (%3x%4) video buffers")
864  .arg(Size()).arg(format_description(Type)).arg(Width).arg(Height));
865  return success;
866 }
867 
868 bool VideoBuffers::CreateBuffer(int Width, int Height, uint Number,
869  void* Data, VideoFrameType Format)
870 {
871  if (Number >= Size())
872  return false;
873  init(&m_buffers[Number], Format, (unsigned char*)Data, Width, Height, 0);
874  return true;
875 }
876 
878 {
879  next_dbg_str = 0;
880  for (uint i = 0; i < Size(); i++)
881  av_freep(&(m_buffers[i].buf));
882 }
883 
885  int Width, int Height)
886 {
887  if (!Frame)
888  return false;
889  if (format_is_hw(Type) || format_is_hw(Frame->codec))
890  {
891  LOG(VB_GENERAL, LOG_ERR, "Cannot re-initialise a hardware buffer");
892  return false;
893  }
894 
895  // Find the frame
896  VideoFrameType old = Frame->codec;
897  size_t size = GetBufferSize(Type, Width, Height);
898  unsigned char *buf = Frame->buf;
899  bool newbuf = false;
900  if ((Frame->size != static_cast<int>(size)) || !buf)
901  {
902  // Free existing buffer
903  av_freep(&buf);
904  Frame->buf = nullptr;
905 
906  // Initialise new
907  buf = GetAlignedBuffer(size);
908  if (!buf)
909  {
910  LOG(VB_GENERAL, LOG_ERR, "Failed to reallocate frame buffer");
911  return false;
912  }
913  newbuf = true;
914  }
915 
916  LOG(VB_PLAYBACK, LOG_INFO, QString("Reallocated frame %1 %2x%3->%4 %5x%6 (New buffer: %7)")
917  .arg(format_description(old)).arg(Frame->width).arg(Frame->height)
918  .arg(format_description(Type)).arg(Width).arg(Height)
919  .arg(newbuf));
920  MythDeintType singler = Frame->deinterlace_single;
921  MythDeintType doubler = Frame->deinterlace_double;
922  init(Frame, Type, buf, Width, Height, static_cast<int>(size));
923  // retain deinterlacer settings and update restrictions based on new frame type
924  SetDeinterlacingFlags(*Frame, singler, doubler, CodecID);
925  clear(Frame);
926  return true;
927 }
928 
929 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num);
930 
931 QString VideoBuffers::GetStatus(uint Num) const
932 {
933  if (Num == 0)
934  Num = Size();
935 
936  QString str("");
937  if (m_globalLock.tryLock())
938  {
939  int count = Size();
940  unsigned long long a = to_bitmap(m_available, count);
941  unsigned long long u = to_bitmap(m_used, count);
942  unsigned long long d = to_bitmap(m_displayed, count);
943  unsigned long long l = to_bitmap(m_limbo, count);
944  unsigned long long p = to_bitmap(m_pause, count);
945  unsigned long long f = to_bitmap(m_finished, count);
946  unsigned long long x = to_bitmap(m_decode, count);
947  for (uint i = 0; i < Num; i++)
948  {
949  unsigned long long mask = 1ULL << i;
950  QString tmp("");
951  if (a & mask)
952  tmp += (x & mask) ? "a" : "A";
953  if (u & mask)
954  tmp += (x & mask) ? "u" : "U";
955  if (d & mask)
956  tmp += (x & mask) ? "d" : "D";
957  if (l & mask)
958  tmp += (x & mask) ? "l" : "L";
959  if (p & mask)
960  tmp += (x & mask) ? "p" : "P";
961  if (f & mask)
962  tmp += (x & mask) ? "f" : "F";
963  if (0 == tmp.length())
964  str += " ";
965  else if (1 == tmp.length())
966  str += tmp;
967  else
968  str += "(" + tmp + ")";
969  }
970  m_globalLock.unlock();
971  }
972  else
973  {
974  for (uint i = 0; i < Num; i++)
975  str += " ";
976  }
977  return str;
978 }
979 
980 void VideoBuffers::Clear(uint FrameNum)
981 {
982  clear(At(FrameNum));
983 }
984 
986 {
987  for (uint i = 0; i < Size(); i++)
988  Clear(i);
989 }
990 
991 /*******************************
992  ** Debugging functions below **
993  *******************************/
994 
995 #define DBG_STR_ARR_SIZE 40
997 {
998  "A ", " B ", " C ", " D ",
999  " E ", " F ", " G ", " H", // 8
1000  "a ", " b ", " c ", " d ",
1001  " e ", " f ", " g ", " h", // 16
1002  "0 ", " 1 ", " 2 ", " 3 ",
1003  " 4 ", " 5 ", " 6 ", " 7", // 24
1004  "I ", " J ", " K ", " L ",
1005  " M ", " N ", " O ", " P", // 32
1006  "i ", " j ", " k ", " l ",
1007  " m ", " n ", " o ", " p", // 40
1008 };
1010 {
1011  "A","B","C","D","E","F","G","H", // 8
1012  "a","b","c","d","e","f","g","h", // 16
1013  "0","1","2","3","4","5","6","7", // 24
1014  "I","J","K","L","M","N","O","P", // 32
1015  "i","j","k","l","m","n","o","p", // 40
1016 };
1017 
1018 map<const VideoFrame *, int> dbg_str;
1019 
1020 static int DebugNum(const VideoFrame *Frame)
1021 {
1022  auto it = dbg_str.find(Frame);
1023  if (it == dbg_str.end())
1024  return dbg_str[Frame] = next_dbg_str++;
1025  return it->second;
1026 }
1027 
1028 const QString& DebugString(const VideoFrame *Frame, bool Short)
1029 {
1030  if (Short)
1033 }
1034 
1035 const QString& DebugString(uint FrameNum, bool Short)
1036 {
1037  return ((Short) ? dbg_str_arr_short : dbg_str_arr)[FrameNum];
1038 }
1039 
1040 static unsigned long long to_bitmap(const frame_queue_t& Queue, int Num)
1041 {
1042  unsigned long long bitmap = 0;
1043  for (auto *it : Queue)
1044  {
1045  int shift = DebugNum(it) % Num;
1046  bitmap |= 1ULL << shift;
1047  }
1048  return bitmap;
1049 }
void ClearAfterSeek(void)
Clear used frames after seeking.
frame_queue_t * Queue(BufferType Type)
uint m_needPrebufferFramesNormal
Definition: videobuffers.h:124
BufferType
Definition: videobuffers.h:27
void Reset(void)
Resets the class so that Init may be called again.
vbuffer_map_t m_vbufferMap
Definition: videobuffers.h:119
void ReleaseFrame(VideoFrame *Frame)
Frame is ready to be for filtering or OSD application.
void Clear(void)
VideoFrame * At(uint FrameNum)
void SetLastShownFrameToScratch(void)
frame_queue_t m_limbo
Definition: videobuffers.h:114
QString GetStatus(uint Num=0) const
long long timecode
Definition: mythframe.h:149
typename deque< VideoFrame * >::iterator iterator
Definition: mythdeque.h:44
MythCodecID
Definition: mythcodecid.h:10
VideoFrame * Dequeue(BufferType Type)
static void ReleaseDecoderResources(VideoFrame *Frame)
T tail()
Returns item at tail of list. O(1).
Definition: mythdeque.h:91
uint m_needPrebufferFramesSmall
Definition: videobuffers.h:125
frame_queue_t m_used
Definition: videobuffers.h:113
bool Contains(BufferType Type, VideoFrame *Frame) const
VideoFrameType codec
Definition: mythframe.h:138
int top_field_first
1 if top field is first.
Definition: mythframe.h:153
uint m_needPrebufferFrames
Definition: videobuffers.h:123
#define codec_is_copyback(id)
Definition: mythcodecid.h:344
uint ValidVideoFrames(void) const
VideoFrameType
Definition: mythframe.h:23
frame_queue_t m_decode
Definition: videobuffers.h:117
static unsigned char * GetAlignedBuffer(size_t Size)
Definition: mythframe.h:676
T head()
Returns item at head of list. O(1).
Definition: mythdeque.h:82
void SafeEnqueue(BufferType Type, VideoFrame *Frame)
int interlaced_frame
1 if interlaced.
Definition: mythframe.h:152
void DoneDisplayingFrame(VideoFrame *Frame)
Removes frame from used queue and adds it to the available list.
size_type count() const
Returns size of list. O(1).
Definition: mythdeque.h:79
static guint32 * tmp
Definition: goom_core.c:35
void enqueue(T d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:42
void Init(uint NumDecode, bool ExtraForPause, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall)
Creates buffers and sets various buffer management parameters.
static bool ReinitBuffer(VideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
frame_queue_t m_available
Definition: videobuffers.h:112
bool EnoughFreeFrames(void) const
MythDeintType
Definition: mythframe.h:120
frame_queue_t m_displayed
Definition: videobuffers.h:116
map< const VideoFrame *, int > dbg_str
#define codec_is_nvdec_dec(id)
Definition: mythcodecid.h:330
void SetPrebuffering(bool Normal)
Sets prebuffering state to normal, or small.
bool m_createdPauseFrame
Definition: videobuffers.h:126
frame_vector_t m_buffers
Definition: videobuffers.h:120
void SetDeinterlacing(MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
const QString & DebugString(const VideoFrame *Frame, bool Short)
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:846
VideoFrame * GetLastShownFrame(void)
void Remove(BufferType Type, VideoFrame *Frame)
static int format_is_hw(VideoFrameType Type)
Definition: mythframe.h:72
static const uint16_t * d
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:32
void Requeue(BufferType Dest, BufferType Source, int Count=1)
#define codec_is_vaapi_dec(id)
Definition: mythcodecid.h:313
static unsigned long long to_bitmap(const frame_queue_t &Queue, int Num)
void StartDisplayingFrame(void)
Sets rpos to index of videoframe at head of used queue.
void DiscardFrame(VideoFrame *Frame)
Frame is ready to be reused by decoder.
frame_queue_t::iterator BeginLock(BufferType Type)
bool contains(T const &item) const
Returns true if item is in list. O(n).
Definition: mythdeque.h:75
VideoFrame * GetNextFreeFrame(BufferType EnqueueTo=kVideoBuffer_limbo)
Gets a frame from available buffers list.
void DeLimboFrame(VideoFrame *Frame)
If the frame is still in the limbo state it is added to the available queue.
unsigned int uint
Definition: compat.h:140
bool CreateBuffers(VideoFrameType Type, QSize Size, bool ExtraForPause, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall, int MaxReferenceFrames=16)
#define TRY_LOCK_SPINS
#define DBG_STR_ARR_SIZE
static void init(VideoFrame *vf, VideoFrameType _codec, unsigned char *_buf, int _width, int _height, int _size, const int *p=nullptr, const int *o=nullptr, float _aspect=-1.0F, double _rate=-1.0F, int _aligned=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.h:230
frame_queue_t m_finished
Definition: videobuffers.h:118
VideoFrame * GetLastDecodedFrame(void)
virtual ~VideoBuffers()
VideoFrame * GetNextFreeFrameInternal(BufferType EnqueueTo)
VideoFrame * GetScratchFrame(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static uint GetNumBuffers(int PixelFormat, int MaxReferenceFrames=16, bool Decoder=false)
uint Size(void) const
uint m_needFreeFrames
Definition: videobuffers.h:122
static int format_is_hwframes(VideoFrameType Type)
Definition: mythframe.h:80
QString dbg_str_arr[DBG_STR_ARR_SIZE]
static int DebugNum(const VideoFrame *Frame)
void DiscardFrames(bool NextFrameIsKeyFrame)
Mark all used frames as ready to be reused, this is for seek.
const char * format_description(VideoFrameType Type)
Definition: mythframe.cpp:33
static size_t GetBufferSize(VideoFrameType Type, int Width, int Height, int Aligned=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.h:655
frame_queue_t m_pause
Definition: videobuffers.h:115
static void SetDeinterlacingFlags(VideoFrame &Frame, MythDeintType Single, MythDeintType Double, MythCodecID CodecID)
Set the appropriate flags for single and double rate deinterlacing.
int next_dbg_str
QString dbg_str_arr_short[DBG_STR_ARR_SIZE]
bool EnoughDecodedFrames(void) const
void remove(T const item)
Removes any item from list. O(n).
Definition: mythdeque.h:67
QMutex m_globalLock
Definition: videobuffers.h:129
#define TRY_LOCK_SPINS_BEFORE_WARNING
VideoFrame * Head(BufferType Type)
frame_queue_t::iterator End(BufferType Type)
void Enqueue(BufferType Type, VideoFrame *Frame)
VideoFrame * Tail(BufferType Type)
#define TRY_LOCK_SPIN_WAIT
void DeleteBuffers(void)
uint FreeVideoFrames(void) const
bool CreateBuffer(int Width, int Height, uint Number, void *Data, VideoFrameType Format)