frame.cpp 3.8 KB

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