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 #include <chrono> // for milliseconds
5 #include <thread> // for sleep_for
6 
7 #include "mythconfig.h"
8 
9 #include "mythcontext.h"
10 #include "videobuffers.h"
11 extern "C" {
12 #include "libavcodec/avcodec.h"
13 }
14 #include "fourcc.h"
15 #include "compat.h"
16 #include "mythlogging.h"
17 
18 #define TRY_LOCK_SPINS 2000
19 #define TRY_LOCK_SPINS_BEFORE_WARNING 9999
20 #define TRY_LOCK_SPIN_WAIT 1000 /* usec */
21 
22 int next_dbg_str = 0;
23 
24 YUVInfo::YUVInfo(uint w, uint h, uint sz, const int *p, const int *o,
25  int aligned)
26  : m_width(w), m_height(h), m_size(sz)
27 {
28  // make sure all our pitches are a multiple of "aligned" bytes
29  // Needs to take into consideration that U and V channels are half
30  // the width of Y channel
31  uint width_aligned;
32 
33  if (!aligned)
34  {
35  width_aligned = m_width;
36  }
37  else
38  {
39  width_aligned = (m_width + aligned - 1) & ~(aligned - 1);
40  }
41 
42  if (p)
43  {
44  memcpy(m_pitches, p, 3 * sizeof(int));
45  }
46  else
47  {
48  m_pitches[0] = width_aligned;
49  m_pitches[1] = m_pitches[2] = (width_aligned+1) >> 1;
50  }
51 
52  if (o)
53  {
54  memcpy(m_offsets, o, 3 * sizeof(int));
55  }
56  else
57  {
58  m_offsets[0] = 0;
59  m_offsets[1] = width_aligned * m_height;
60  m_offsets[2] = m_offsets[1] + ((width_aligned+1) >> 1) * ((m_height+1) >> 1);
61  }
62 }
63 
138 {
139  DeleteBuffers();
140 }
141 
163 void VideoBuffers::Init(uint numdecode, bool extra_for_pause,
164  uint need_free, uint needprebuffer_normal,
165  uint needprebuffer_small, uint keepprebuffer)
166 {
167  QMutexLocker locker(&m_globalLock);
168 
169  Reset();
170 
171  uint numcreate = numdecode + ((extra_for_pause) ? 1 : 0);
172 
173  // make a big reservation, so that things that depend on
174  // pointer to VideoFrames work even after a few push_backs
175  m_buffers.reserve(max(numcreate, (uint)128));
176 
177  m_buffers.resize(numcreate);
178  for (uint i = 0; i < numcreate; i++)
179  {
180  memset(At(i), 0, sizeof(VideoFrame));
181  At(i)->codec = FMT_NONE;
182  At(i)->interlaced_frame = -1;
183  At(i)->top_field_first = +1;
184  m_vbufferMap[At(i)] = i;
185  }
186 
187  m_needFreeFrames = need_free;
188  m_needPrebufferFrames = needprebuffer_normal;
189  m_needPrebufferFramesNormal = needprebuffer_normal;
190  m_needPrebufferFramesSmall = needprebuffer_small;
191  m_keepPrebufferFrames = keepprebuffer;
192  m_createdPauseFrame = extra_for_pause;
193 
195  Enqueue(kVideoBuffer_pause, At(numcreate - 1));
196 
197  for (uint i = 0; i < numdecode; i++)
199 }
200 
206 {
207  QMutexLocker locker(&m_globalLock);
208 
209  // Delete ffmpeg VideoFrames so we can create
210  // a different number of buffers below
211  frame_vector_t::iterator it = m_buffers.begin();
212  for (;it != m_buffers.end(); ++it)
213  {
214  av_freep(&it->qscale_table);
215  }
216 
217  m_available.clear();
218  m_used.clear();
219  m_limbo.clear();
220  m_finished.clear();
221  m_decode.clear();
222  m_pause.clear();
223  m_displayed.clear();
224  m_vbufferMap.clear();
225 }
226 
232 {
233  QMutexLocker locker(&m_globalLock);
234  m_needPrebufferFrames = (normal) ?
236 }
237 
239 {
240  QMutexLocker locker(&m_globalLock);
241  VideoFrame *frame = nullptr;
242 
243  // Try to get a frame not being used by the decoder
244  for (size_t i = 0; i < m_available.size(); i++)
245  {
246  frame = m_available.dequeue();
247  if (m_decode.contains(frame))
248  m_available.enqueue(frame);
249  else
250  break;
251  }
252 
253  while (frame && m_used.contains(frame))
254  {
255  LOG(VB_PLAYBACK, LOG_NOTICE,
256  QString("GetNextFreeFrame() served a busy frame %1. Dropping. %2")
257  .arg(DebugString(frame, true)).arg(GetStatus()));
258  frame = m_available.dequeue();
259  }
260 
261  if (frame)
262  SafeEnqueue(enqueue_to, frame);
263 
264  return frame;
265 }
266 
274 {
275  for (uint tries = 1; true; tries++)
276  {
278 
279  if (frame)
280  return frame;
281 
282  if (tries >= TRY_LOCK_SPINS)
283  {
284  LOG(VB_GENERAL, LOG_ERR, QString("GetNextFreeFrame: "
285  "available:%1 used:%2 limbo:%3 pause:%4 displayed:%5 decode:%6 finished:%7")
286  .arg(m_available.size()).arg(m_used.size()).arg(m_limbo.size())
287  .arg(m_pause.size()).arg(m_displayed.size()).arg(m_decode.size())
288  .arg(m_finished.size()));
289  LOG(VB_GENERAL, LOG_ERR,
290  QString("GetNextFreeFrame() unable to "
291  "lock frame %1 times. Discarding Frames.")
292  .arg(TRY_LOCK_SPINS));
293  DiscardFrames(true);
294  continue;
295  }
296 
297  if (tries && !(tries % TRY_LOCK_SPINS_BEFORE_WARNING))
298  {
299  LOG(VB_PLAYBACK, LOG_NOTICE,
300  QString("GetNextFreeFrame() TryLock has "
301  "spun %1 times, this is a lot.").arg(tries));
302  }
303  std::this_thread::sleep_for(std::chrono::microseconds(TRY_LOCK_SPIN_WAIT));
304  }
305 
306  return nullptr;
307 }
308 
316 {
317  QMutexLocker locker(&m_globalLock);
318 
319  m_vpos = m_vbufferMap[frame];
320  m_limbo.remove(frame);
321  //non directrendering frames are ffmpeg handled
322  if (frame->directrendering != 0)
323  m_decode.enqueue(frame);
324  m_used.enqueue(frame);
325 }
326 
333 {
334  QMutexLocker locker(&m_globalLock);
335  if (m_limbo.contains(frame))
336  m_limbo.remove(frame);
337 
338  // if decoder didn't release frame and the buffer is getting released by
339  // the decoder assume that the frame is lost and return to available
340  if (!m_decode.contains(frame))
342 
343  // remove from decode queue since the decoder is finished
344  while (m_decode.contains(frame))
345  m_decode.remove(frame);
346 }
347 
353 {
354  QMutexLocker locker(&m_globalLock);
356 }
357 
363 {
364  QMutexLocker locker(&m_globalLock);
365 
366  if(m_used.contains(frame))
367  Remove(kVideoBuffer_used, frame);
368 
370 
371  // check if any finished frames are no longer used by decoder and return to available
373  frame_queue_t::iterator it = ula.begin();
374  for (; it != ula.end(); ++it)
375  {
376  if (!m_decode.contains(*it))
377  {
380  }
381  }
382 }
383 
390 {
391  QMutexLocker locker(&m_globalLock);
393 }
394 
396 {
397  QMutexLocker locker(&m_globalLock);
398 
399  frame_queue_t *q = nullptr;
400 
401  if (type == kVideoBuffer_avail)
402  q = &m_available;
403  else if (type == kVideoBuffer_used)
404  q = &m_used;
405  else if (type == kVideoBuffer_displayed)
406  q = &m_displayed;
407  else if (type == kVideoBuffer_limbo)
408  q = &m_limbo;
409  else if (type == kVideoBuffer_pause)
410  q = &m_pause;
411  else if (type == kVideoBuffer_decode)
412  q = &m_decode;
413  else if (type == kVideoBuffer_finished)
414  q = &m_finished;
415 
416  return q;
417 }
418 
420 {
421  QMutexLocker locker(&m_globalLock);
422 
423  const frame_queue_t *q = nullptr;
424 
425  if (type == kVideoBuffer_avail)
426  q = &m_available;
427  else if (type == kVideoBuffer_used)
428  q = &m_used;
429  else if (type == kVideoBuffer_displayed)
430  q = &m_displayed;
431  else if (type == kVideoBuffer_limbo)
432  q = &m_limbo;
433  else if (type == kVideoBuffer_pause)
434  q = &m_pause;
435  else if (type == kVideoBuffer_decode)
436  q = &m_decode;
437  else if (type == kVideoBuffer_finished)
438  q = &m_finished;
439 
440  return q;
441 }
442 
444 {
445  QMutexLocker locker(&m_globalLock);
446 
447  frame_queue_t *q = Queue(type);
448 
449  if (!q)
450  return nullptr;
451 
452  return q->dequeue();
453 }
454 
456 {
457  QMutexLocker locker(&m_globalLock);
458 
459  frame_queue_t *q = Queue(type);
460 
461  if (!q)
462  return nullptr;
463 
464  if (!q->empty())
465  return q->head();
466 
467  return nullptr;
468 }
469 
471 {
472  QMutexLocker locker(&m_globalLock);
473 
474  frame_queue_t *q = Queue(type);
475 
476  if (!q)
477  return nullptr;
478 
479  if (!q->empty())
480  return q->tail();
481 
482  return nullptr;
483 }
484 
486 {
487  if (!frame)
488  return;
489 
490  frame_queue_t *q = Queue(type);
491  if (!q)
492  return;
493 
494  m_globalLock.lock();
495  q->remove(frame);
496  q->enqueue(frame);
497  m_globalLock.unlock();
498 }
499 
501 {
502  if (!frame)
503  return;
504 
505  QMutexLocker locker(&m_globalLock);
506 
508  m_available.remove(frame);
510  m_used.remove(frame);
512  m_displayed.remove(frame);
514  m_limbo.remove(frame);
516  m_pause.remove(frame);
518  m_decode.remove(frame);
520  m_finished.remove(frame);
521 }
522 
524 {
525  QMutexLocker locker(&m_globalLock);
526 
527  num = (num <= 0) ? Size(src) : num;
528  for (uint i=0; i<(uint)num; i++)
529  {
530  VideoFrame *frame = Dequeue(src);
531  if (frame)
532  Enqueue(dst, frame);
533  }
534 }
535 
537 {
538  if (!frame)
539  return;
540 
541  QMutexLocker locker(&m_globalLock);
542 
543  Remove(kVideoBuffer_all, frame);
544  Enqueue(dst, frame);
545 }
546 
548 {
549  m_globalLock.lock();
550  frame_queue_t *q = Queue(type);
551  if (q)
552  return q->begin();
553  return m_available.begin();
554 }
555 
557 {
558  QMutexLocker locker(&m_globalLock);
559 
561  frame_queue_t *q = Queue(type);
562  if (q)
563  it = q->end();
564  else
565  it = m_available.end();
566 
567  return it;
568 }
569 
571 {
572  QMutexLocker locker(&m_globalLock);
573 
574  const frame_queue_t *q = Queue(type);
575  if (q)
576  return q->size();
577 
578  return 0;
579 }
580 
582 {
583  QMutexLocker locker(&m_globalLock);
584 
585  const frame_queue_t *q = Queue(type);
586  if (q)
587  return q->contains(frame);
588 
589  return false;
590 }
591 
593 {
595  {
596  LOG(VB_GENERAL, LOG_ERR, "GetScratchFrame() called, but not allocated");
597  }
598 
599  QMutexLocker locker(&m_globalLock);
600  return Head(kVideoBuffer_pause);
601 }
602 
604 {
606  {
607  LOG(VB_GENERAL, LOG_ERR,
608  "SetLastShownFrameToScratch() called but no pause frame");
609  return;
610  }
611 
613  m_rpos = m_vbufferMap[pause];
614 }
615 
620 void VideoBuffers::DiscardFrames(bool next_frame_keyframe)
621 {
622  QMutexLocker locker(&m_globalLock);
623  LOG(VB_PLAYBACK, LOG_INFO, QString("VideoBuffers::DiscardFrames(%1): %2")
624  .arg(next_frame_keyframe).arg(GetStatus()));
625 
626  if (!next_frame_keyframe)
627  {
628  frame_queue_t ula(m_used);
629  frame_queue_t::iterator it = ula.begin();
630  for (; it != ula.end(); ++it)
631  DiscardFrame(*it);
632  LOG(VB_PLAYBACK, LOG_INFO,
633  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
634  .arg(next_frame_keyframe).arg(GetStatus()));
635  return;
636  }
637 
638  // Remove inheritence of all frames not in displayed or pause
639  frame_queue_t ula(m_used);
640  ula.insert(ula.end(), m_limbo.begin(), m_limbo.end());
641  ula.insert(ula.end(), m_available.begin(), m_available.end());
642  ula.insert(ula.end(), m_finished.begin(), m_finished.end());
644 
645  // Discard frames
646  frame_queue_t discards(m_used);
647  discards.insert(discards.end(), m_limbo.begin(), m_limbo.end());
648  discards.insert(discards.end(), m_finished.begin(), m_finished.end());
649  for (it = discards.begin(); it != discards.end(); ++it)
650  DiscardFrame(*it);
651 
652  // Verify that things are kosher
653  if (m_available.count() + m_pause.count() + m_displayed.count() != Size())
654  {
655  for (uint i=0; i < Size(); i++)
656  {
657  if (!m_available.contains(At(i)) &&
658  !m_pause.contains(At(i)) &&
659  !m_displayed.contains(At(i)))
660  {
661  // This message is DEBUG because it does occur
662  // after Reset is called.
663  // That happens when failing over from OpenGL
664  // to another method, if QT painter is selected.
665  LOG(VB_GENERAL, LOG_DEBUG,
666  QString("VideoBuffers::DiscardFrames(): %1 (%2) not "
667  "in available, pause, or displayed %3")
668  .arg(DebugString(At(i), true)).arg((long long)At(i))
669  .arg(GetStatus()));
670  DiscardFrame(At(i));
671  }
672  }
673  }
674 
675  // Make sure frames used by decoder are last...
676  // This is for libmpeg2 which still uses the frames after a reset.
677  for (it = m_decode.begin(); it != m_decode.end(); ++it)
678  Remove(kVideoBuffer_all, *it);
679  for (it = m_decode.begin(); it != m_decode.end(); ++it)
680  m_available.enqueue(*it);
681  m_decode.clear();
682 
683  LOG(VB_PLAYBACK, LOG_INFO,
684  QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
685  .arg(next_frame_keyframe).arg(GetStatus()));
686 }
687 
689 {
690  {
691  QMutexLocker locker(&m_globalLock);
692 
693  for (uint i = 0; i < Size(); i++)
694  At(i)->timecode = 0;
695 
696  while (m_used.count() > 1)
697  {
698  VideoFrame *buffer = m_used.dequeue();
699  m_available.enqueue(buffer);
700  }
701 
702  if (m_used.count() > 0)
703  {
704  VideoFrame *buffer = m_used.dequeue();
705  m_available.enqueue(buffer);
706  m_vpos = m_vbufferMap[buffer];
707  m_rpos = m_vpos;
708  }
709  else
710  {
711  m_vpos = m_rpos = 0;
712  }
713  }
714 }
715 
716 bool VideoBuffers::CreateBuffers(VideoFrameType type, int width, int height)
717 {
718  vector<unsigned char*> bufs;
719  vector<YUVInfo> yuvinfo;
720  return CreateBuffers(type, width, height, bufs, yuvinfo);
721 }
722 
723 bool VideoBuffers::CreateBuffers(VideoFrameType type, int width, int height,
724  vector<unsigned char*> bufs,
725  vector<YUVInfo> yuvinfo)
726 {
727  if ((FMT_YV12 != type) && (FMT_YUY2 != type))
728  return false;
729 
730  bool ok = true;
731  uint buf_size = buffersize(type, width, height);
732 
733  while (bufs.size() < Size())
734  {
735  unsigned char *data = (unsigned char*)av_malloc(buf_size + 64);
736  if (!data)
737  {
738  LOG(VB_GENERAL, LOG_ERR, "Failed to allocate memory for frame.");
739  return false;
740  }
741 
742  bufs.push_back(data);
743  yuvinfo.emplace_back(width, height, buf_size, nullptr, nullptr);
744  m_allocatedArrays.push_back(data);
745  }
746 
747  for (uint i = 0; i < Size(); i++)
748  {
749  init(&m_buffers[i],
750  type, bufs[i], yuvinfo[i].m_width, yuvinfo[i].m_height,
751  max(buf_size, yuvinfo[i].m_size),
752  (const int*) yuvinfo[i].m_pitches, (const int*) yuvinfo[i].m_offsets);
753 
754  ok &= (bufs[i] != nullptr);
755  }
756 
757  Clear();
758 
759  return ok;
760 }
761 
762 static unsigned char *ffmpeg_hack = (unsigned char*)
763  "avlib should not use this private data";
764 
765 bool VideoBuffers::CreateBuffer(int width, int height, uint num, void* data,
766  VideoFrameType fmt)
767 {
768  if (num >= Size())
769  return false;
770 
771  init(&m_buffers[num], fmt, (unsigned char*)data, width, height, 0);
772  m_buffers[num].priv[0] = ffmpeg_hack;
773  m_buffers[num].priv[1] = ffmpeg_hack;
774  return true;
775 }
776 
777 uint VideoBuffers::AddBuffer(int width, int height, void* data,
778  VideoFrameType fmt)
779 {
780  QMutexLocker lock(&m_globalLock);
781 
782  uint num = Size();
783  m_buffers.resize(num + 1);
784  memset(&m_buffers[num], 0, sizeof(VideoFrame));
785  m_buffers[num].interlaced_frame = -1;
786  m_buffers[num].top_field_first = 1;
787  m_vbufferMap[At(num)] = num;
788  if (!data)
789  {
790  int size = buffersize(fmt, width, height);
791  data = av_malloc(size);
792  m_allocatedArrays.push_back((unsigned char*)data);
793  }
794  init(&m_buffers[num], fmt, (unsigned char*)data, width, height, 0);
795  m_buffers[num].priv[0] = ffmpeg_hack;
796  m_buffers[num].priv[1] = ffmpeg_hack;
798 
799  return Size();
800 }
801 
803 {
804  next_dbg_str = 0;
805  for (uint i = 0; i < Size(); i++)
806  {
807  m_buffers[i].buf = nullptr;
808 
809  av_freep(&m_buffers[i].qscale_table);
810  }
811 
812  for (size_t i = 0; i < m_allocatedArrays.size(); i++)
814  m_allocatedArrays.clear();
815 }
816 
817 static unsigned long long to_bitmap(const frame_queue_t& list, int /*n*/);
818 QString VideoBuffers::GetStatus(int n) const
819 {
820  if (n <= 0)
821  n = Size();
822 
823  QString str("");
824  if (m_globalLock.tryLock())
825  {
826  int m = Size();
827  unsigned long long a = to_bitmap(m_available, m);
828  unsigned long long u = to_bitmap(m_used, m);
829  unsigned long long d = to_bitmap(m_displayed, m);
830  unsigned long long l = to_bitmap(m_limbo, m);
831  unsigned long long p = to_bitmap(m_pause, m);
832  unsigned long long f = to_bitmap(m_finished, m);
833  unsigned long long x = to_bitmap(m_decode, m);
834  for (uint i=0; i<(uint)n; i++)
835  {
836  unsigned long long mask = 1ULL<<i;
837  QString tmp("");
838  if (a & mask)
839  tmp += (x & mask) ? "a" : "A";
840  if (u & mask)
841  tmp += (x & mask) ? "u" : "U";
842  if (d & mask)
843  tmp += (x & mask) ? "d" : "D";
844  if (l & mask)
845  tmp += (x & mask) ? "l" : "L";
846  if (p & mask)
847  tmp += (x & mask) ? "p" : "P";
848  if (f & mask)
849  tmp += (x & mask) ? "f" : "F";
850 
851  if (0 == tmp.length())
852  str += " ";
853  else if (1 == tmp.length())
854  str += tmp;
855  else
856  str += "(" + tmp + ")";
857  }
858  m_globalLock.unlock();
859  }
860  else
861  {
862  for (uint i=0; i<(uint)n; i++)
863  str += " ";
864  }
865  return str;
866 }
867 
869 {
870  clear(At(i));
871 }
872 
874 {
875  for (uint i = 0; i < Size(); i++)
876  Clear(i);
877 }
878 
879 /*******************************
880  ** Debugging functions below **
881  *******************************/
882 
883 #define DBG_STR_ARR_SIZE 40
885 {
886  "A ", " B ", " C ", " D ",
887  " E ", " F ", " G ", " H", // 8
888  "a ", " b ", " c ", " d ",
889  " e ", " f ", " g ", " h", // 16
890  "0 ", " 1 ", " 2 ", " 3 ",
891  " 4 ", " 5 ", " 6 ", " 7", // 24
892  "I ", " J ", " K ", " L ",
893  " M ", " N ", " O ", " P", // 32
894  "i ", " j ", " k ", " l ",
895  " m ", " n ", " o ", " p", // 40
896 };
898 {
899  "A","B","C","D","E","F","G","H", // 8
900  "a","b","c","d","e","f","g","h", // 16
901  "0","1","2","3","4","5","6","7", // 24
902  "I","J","K","L","M","N","O","P", // 32
903  "i","j","k","l","m","n","o","p", // 40
904 };
905 
906 map<const VideoFrame *, int> dbg_str;
907 
908 static int DebugNum(const VideoFrame *frame)
909 {
910  map<const VideoFrame *, int>::iterator it = dbg_str.find(frame);
911  if (it == dbg_str.end())
912  return dbg_str[frame] = next_dbg_str++;
913 
914  return it->second;
915 }
916 
917 const QString& DebugString(const VideoFrame *frame, bool short_str)
918 {
919  if (short_str)
921  return dbg_str_arr[DebugNum(frame) % DBG_STR_ARR_SIZE];
922 }
923 
924 const QString& DebugString(uint str_num, bool short_str)
925 {
926  return ((short_str) ? dbg_str_arr_short : dbg_str_arr)[str_num];
927 }
928 
929 static unsigned long long to_bitmap(const frame_queue_t& list, int n)
930 {
931  unsigned long long bitmap = 0;
932  frame_queue_t::const_iterator it = list.begin();
933  for (; it != list.end(); ++it)
934  {
935  int shift = DebugNum(*it) % n;
936  bitmap |= 1ULL<<shift;
937  }
938  return bitmap;
939 }
940 
941 static QString bitmap_to_string(unsigned long long bitmap)
942 {
943  QString str("");
944  for (int i=0; i<8; i++)
945  str += ((bitmap>>i)&1) ? DebugString(i, true) : " ";
946  return str;
947 }
948 
949 QString DebugString(const frame_queue_t& list)
950 {
952 }
953 
954 QString DebugString(const vector<const VideoFrame*>& list)
955 {
956  // first create a bitmap..
957  unsigned long long bitmap = 0;
958  vector<const VideoFrame*>::const_iterator it = list.begin();
959  for (; it != list.end(); ++it)
960  {
961  int shift = DebugNum(*it) % DBG_STR_ARR_SIZE;
962  bitmap |= 1ULL<<shift;
963  }
964  // then transform bitmap to string
965  return bitmap_to_string(bitmap);
966 }
void ClearAfterSeek(void)
uint m_needPrebufferFramesNormal
Definition: videobuffers.h:150
BufferType
Definition: videobuffers.h:35
uint m_pitches[3]
Definition: videobuffers.h:57
void Reset(void)
Resets the class so that Init may be called again.
vbuffer_map_t m_vbufferMap
Definition: videobuffers.h:144
void DoneDisplayingFrame(VideoFrame *frame)
Removes frame from used queue and adds it to the available list.
void Clear(void)
const QString & DebugString(const VideoFrame *frame, bool short_str)
void SetLastShownFrameToScratch(void)
void Remove(BufferType, VideoFrame *)
frame_queue_t m_limbo
Definition: videobuffers.h:139
QString GetStatus(int n=-1) const
static unsigned char * ffmpeg_hack
void SafeEnqueue(BufferType, VideoFrame *frame)
T tail()
Returns item at tail of list. O(1).
Definition: mythdeque.h:91
uint m_needPrebufferFramesSmall
Definition: videobuffers.h:151
frame_queue_t m_used
Definition: videobuffers.h:138
VideoFrame * At(uint i)
Definition: videobuffers.h:90
uint m_needPrebufferFrames
Definition: videobuffers.h:149
uint m_height
Definition: videobuffers.h:55
unsigned int uint
Definition: compat.h:140
frame_queue_t m_decode
Definition: videobuffers.h:142
T head()
Returns item at head of list. O(1).
Definition: mythdeque.h:82
void Requeue(BufferType dst, BufferType src, int num=1)
void SetPrebuffering(bool normal)
Sets prebuffering state to normal, or small.
long long timecode
Definition: mythframe.h:49
enum FrameType_ VideoFrameType
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
frame_queue_t m_available
Definition: videobuffers.h:137
frame_queue_t m_displayed
Definition: videobuffers.h:141
bool CreateBuffers(VideoFrameType type, int width, int height, vector< unsigned char * > bufs, vector< YUVInfo > yuvinfo)
map< const VideoFrame *, int > dbg_str
static QString bitmap_to_string(unsigned long long bitmap)
bool m_createdPauseFrame
Definition: videobuffers.h:153
VideoFrame * Dequeue(BufferType)
frame_queue_t::iterator end(BufferType)
uint m_keepPrebufferFrames
Definition: videobuffers.h:152
frame_vector_t m_buffers
Definition: videobuffers.h:145
uint Size() const
Definition: videobuffers.h:121
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:830
deque< VideoFrame * >::iterator iterator
Definition: mythdeque.h:44
static const uint16_t * d
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:32
void StartDisplayingFrame(void)
Sets rpos to index of videoframe at head of used queue.
bool CreateBuffer(int width, int height, uint num, void *data, VideoFrameType fmt)
bool contains(T const &item) const
Returns true if item is in list. O(n).
Definition: mythdeque.h:75
YUVInfo(uint w, uint h, uint sz, const int *p, const int *o, int aligned=64)
uint AddBuffer(int width, int height, void *data, VideoFrameType fmt)
#define TRY_LOCK_SPINS
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
#define DBG_STR_ARR_SIZE
static int DebugNum(const VideoFrame *frame)
void * av_malloc(unsigned int size)
VideoFrame * Tail(BufferType)
frame_queue_t m_finished
Definition: videobuffers.h:143
void DeLimboFrame(VideoFrame *frame)
If the frame is still in the limbo state it is added to the available queue.
virtual ~VideoBuffers()
uint m_width
Definition: videobuffers.h:54
VideoFrame * GetScratchFrame(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
int directrendering
1 if managed by FFmpeg
Definition: mythframe.h:67
void DiscardFrame(VideoFrame *frame)
Frame is ready to be reused by decoder.
uint m_needFreeFrames
Definition: videobuffers.h:148
VideoFrame * GetNextFreeFrame(BufferType enqueue_to=kVideoBuffer_limbo)
Gets a frame from available buffers list.
VideoFrame * Head(BufferType)
void ReleaseFrame(VideoFrame *frame)
Frame is ready to be for filtering or OSD application.
QString dbg_str_arr[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=64)
Definition: mythframe.h:115
static unsigned long long to_bitmap(const frame_queue_t &list, int)
void Enqueue(BufferType, VideoFrame *)
deque< VideoFrame * >::const_iterator const_iterator
Definition: mythdeque.h:45
frame_queue_t m_pause
Definition: videobuffers.h:140
frame_queue_t * Queue(BufferType type)
bool Contains(BufferType type, VideoFrame *) const
void av_free(void *ptr)
int next_dbg_str
QString dbg_str_arr_short[DBG_STR_ARR_SIZE]
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:297
int interlaced_frame
1 if interlaced.
Definition: mythframe.h:57
void remove(T const item)
Removes any item from list. O(n).
Definition: mythdeque.h:67
QMutex m_globalLock
Definition: videobuffers.h:157
#define TRY_LOCK_SPINS_BEFORE_WARNING
void Init(uint numdecode, bool extra_for_pause, uint need_free, uint needprebuffer_normal, uint needprebuffer_small, uint keepprebuffer)
Creates buffers and sets various buffer management parameters.
VideoFrame * GetNextFreeFrameInternal(BufferType enqueue_to)
frame_queue_t::iterator begin_lock(BufferType)
void DiscardFrames(bool next_frame_keyframe)
Mark all used frames as ready to be reused, this is for seek.
#define TRY_LOCK_SPIN_WAIT
void DeleteBuffers(void)
uchar_vector_t m_allocatedArrays
Definition: videobuffers.h:146
uint m_offsets[3]
Definition: videobuffers.h:58
VideoFrameType codec
Definition: mythframe.h:38