frame.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "frame.h"
  2. #include "player.h"
  3. void frame_queue_unref_item(frame_t *vp)
  4. {
  5. av_frame_unref(vp->frame);
  6. }
  7. int frame_queue_init(frame_queue_t *f, packet_queue_t *pktq, int max_size, int keep_last)
  8. {
  9. memset(f, 0, sizeof(frame_queue_t));
  10. if (!(f->frame_mutex = SDL_CreateMutex())) {
  11. return AVERROR(ENOMEM);
  12. }
  13. if (!(f->frame_cond = SDL_CreateCond())) {
  14. return AVERROR(ENOMEM);
  15. }
  16. f->pktq = pktq;
  17. f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
  18. f->keep_last = !!keep_last;
  19. for (int i = 0; i < f->max_size; i++) {
  20. if (!(f->queue[i].frame = av_frame_alloc())) {
  21. return AVERROR(ENOMEM);
  22. }
  23. }
  24. return 0;
  25. }
  26. void frame_queue_destory(frame_queue_t *f)
  27. {
  28. for (int i = 0; i < f->max_size; i++) {
  29. frame_t *vp = &f->queue[i];
  30. frame_queue_unref_item(vp);
  31. av_frame_free(&vp->frame);
  32. }
  33. SDL_DestroyMutex(f->frame_mutex);
  34. SDL_DestroyCond(f->frame_cond);
  35. }
  36. void frame_queue_signal(frame_queue_t *f)
  37. {
  38. SDL_LockMutex(f->frame_mutex);
  39. SDL_CondSignal(f->frame_cond);
  40. SDL_UnlockMutex(f->frame_mutex);
  41. }
  42. frame_t *frame_queue_peek(frame_queue_t *f)
  43. {
  44. return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
  45. }
  46. frame_t *frame_queue_peek_next(frame_queue_t *f)
  47. {
  48. return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
  49. }
  50. // 取出此帧进行播放,只读取不删除,不删除是因为此帧需要缓存下来供下一次使用。播放后,此帧变为上一帧
  51. frame_t *frame_queue_peek_last(frame_queue_t *f)
  52. {
  53. return &f->queue[f->rindex];
  54. }
  55. // 向队列尾部申请一个可写的帧空间,若无空间可写,则等待
  56. frame_t *frame_queue_peek_writable(frame_queue_t *f)
  57. {
  58. /* wait until we have space to put a new frame */
  59. SDL_LockMutex(f->frame_mutex);
  60. while (f->size >= f->max_size && !f->pktq->abort_flag) {
  61. SDL_CondWait(f->frame_cond, f->frame_mutex);
  62. }
  63. SDL_UnlockMutex(f->frame_mutex);
  64. if (f->pktq->abort_flag) {
  65. return NULL;
  66. }
  67. return &f->queue[f->windex];
  68. }
  69. // 从队列头部读取一帧,只读取不删除,若无帧可读则等待
  70. frame_t *frame_queue_peek_readable(frame_queue_t *f)
  71. {
  72. /* wait until we have a readable a new frame */
  73. bool bexit = false;
  74. SDL_LockMutex(f->frame_mutex);
  75. while (f->size - f->rindex_shown <= 0 && !f->pktq->abort_flag) {
  76. SDL_CondWait(f->frame_cond, f->frame_mutex);
  77. }
  78. SDL_UnlockMutex(f->frame_mutex);
  79. if (f->pktq->abort_flag || bexit) {
  80. return NULL;
  81. }
  82. return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
  83. }
  84. // 向队列尾部压入一帧,只更新计数与写指针,因此调用此函数前应将帧数据写入队列相应位置
  85. void frame_queue_push(frame_queue_t *f)
  86. {
  87. if (++f->windex == f->max_size) {
  88. f->windex = 0;
  89. }
  90. SDL_LockMutex(f->frame_mutex);
  91. f->size++;
  92. SDL_CondSignal(f->frame_cond);
  93. SDL_UnlockMutex(f->frame_mutex);
  94. }
  95. // 读指针(rindex)指向的帧已显示,删除此帧,注意不读取直接删除。读指针加1
  96. void frame_queue_next(frame_queue_t *f)
  97. {
  98. if (f->keep_last && !f->rindex_shown) {
  99. f->rindex_shown = 1;
  100. return;
  101. }
  102. frame_queue_unref_item(&f->queue[f->rindex]);
  103. if (++f->rindex == f->max_size) {
  104. f->rindex = 0;
  105. }
  106. SDL_LockMutex(f->frame_mutex);
  107. f->size--;
  108. SDL_CondSignal(f->frame_cond);
  109. SDL_UnlockMutex(f->frame_mutex);
  110. }
  111. // frame_queue中未显示的帧数
  112. /* return the number of undisplayed frames in the queue */
  113. int frame_queue_nb_remaining(frame_queue_t *f)
  114. {
  115. return f->size - f->rindex_shown;
  116. }
  117. /* return last shown position */
  118. int64_t frame_queue_last_pos(frame_queue_t *f)
  119. {
  120. frame_t *fp = &f->queue[f->rindex];
  121. if (f->rindex_shown && fp->serial == f->pktq->serial) {
  122. return fp->pos;
  123. }
  124. else {
  125. return -1;
  126. }
  127. }