read_thread.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // ***********************************************************/
  2. // read_thread.cpp
  3. //
  4. // Copy Right @ Steven Huang. All rights reserved.
  5. //
  6. // read packets thread.
  7. // ***********************************************************/
  8. #include "read_thread.h"
  9. extern int infinite_buffer;
  10. extern int64_t start_time;
  11. static int64_t duration = AV_NOPTS_VALUE;
  12. ReadThread::ReadThread(QObject* parent, VideoState* pState)
  13. : QThread(parent), m_pPlayData(pState)
  14. {
  15. }
  16. ReadThread::~ReadThread()
  17. {
  18. }
  19. void ReadThread::set_video_state(VideoState* pState)
  20. {
  21. assert(pState);
  22. m_pPlayData = pState;
  23. }
  24. int ReadThread::loop_read()
  25. {
  26. int ret = -1;
  27. VideoState* is = m_pPlayData;
  28. AVPacket* pkt = nullptr;
  29. int pkt_in_play_range = 0;
  30. int64_t stream_start_time = 0;
  31. int64_t pkt_ts = 0;
  32. // AVFormatContext* pFormatCtx = is->ic;
  33. assert(is);
  34. // assert(pFormatCtx);
  35. if (!is)
  36. return ret;
  37. pkt = av_packet_alloc();
  38. if (!pkt)
  39. {
  40. av_log(nullptr, AV_LOG_FATAL, "Could not allocate packet.\n");
  41. ret = AVERROR(ENOMEM);
  42. return ret;
  43. }
  44. is->read_thread_exit = 0;
  45. for (;;)
  46. {
  47. if (is->abort_request)
  48. break;
  49. if (is->paused != is->last_paused)
  50. {
  51. is->last_paused = is->paused;
  52. if (is->paused)
  53. is->read_pause_return = av_read_pause(is->ic);
  54. else
  55. av_read_play(is->ic);
  56. }
  57. if (is->seek_req)
  58. {
  59. int64_t seek_target = is->seek_pos;
  60. int64_t seek_min =
  61. is->seek_rel > 0 ? seek_target - is->seek_rel + 2 : INT64_MIN;
  62. int64_t seek_max =
  63. is->seek_rel < 0 ? seek_target - is->seek_rel - 2 : INT64_MAX;
  64. // FIXME the +-2 is due to rounding being not done in the correct
  65. // direction in generation
  66. // of the seek_pos/seek_rel variables
  67. ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max,
  68. is->seek_flags);
  69. if (ret < 0)
  70. {
  71. av_log(nullptr, AV_LOG_ERROR, "%s: error while seeking\n", is->ic->url);
  72. }
  73. else
  74. {
  75. if (is->audio_stream >= 0)
  76. packet_queue_flush(&is->audioq);
  77. if (is->subtitle_stream >= 0)
  78. packet_queue_flush(&is->subtitleq);
  79. if (is->video_stream >= 0)
  80. packet_queue_flush(&is->videoq);
  81. if (is->seek_flags & AVSEEK_FLAG_BYTE)
  82. {
  83. set_clock(&is->extclk, NAN, 0);
  84. }
  85. else
  86. {
  87. set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
  88. }
  89. }
  90. is->seek_req = 0;
  91. is->queue_attachments_req = 1;
  92. is->eof = 0;
  93. if (is->paused)
  94. step_to_next_frame(is);
  95. }
  96. if (is->queue_attachments_req)
  97. {
  98. if (is->video_st &&
  99. is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)
  100. {
  101. ret = av_packet_ref(pkt, &is->video_st->attached_pic);
  102. if (ret < 0)
  103. break;
  104. packet_queue_put(&is->videoq, pkt);
  105. packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
  106. }
  107. is->queue_attachments_req = 0;
  108. }
  109. /* if the queue are full, no need to read more */
  110. if (infinite_buffer < 1 &&
  111. (is->audioq.size + is->videoq.size + is->subtitleq.size >
  112. MAX_QUEUE_SIZE ||
  113. (stream_has_enough_packets(is->audio_st, is->audio_stream,
  114. &is->audioq) &&
  115. stream_has_enough_packets(is->video_st, is->video_stream,
  116. &is->videoq) &&
  117. stream_has_enough_packets(is->subtitle_st, is->subtitle_stream,
  118. &is->subtitleq))))
  119. {
  120. /* wait 10 ms */
  121. m_waitMutex.lock();
  122. // SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
  123. is->continue_read_thread->wait(&m_waitMutex, 10);
  124. m_waitMutex.unlock();
  125. continue;
  126. }
  127. ret = av_read_frame(is->ic, pkt);
  128. if (ret < 0)
  129. {
  130. if ((ret == AVERROR_EOF || avio_feof(is->ic->pb)) && !is->eof)
  131. {
  132. if (is->video_stream >= 0)
  133. packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
  134. if (is->audio_stream >= 0)
  135. packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream);
  136. if (is->subtitle_stream >= 0)
  137. packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream);
  138. if (is->loop)
  139. {
  140. stream_seek(is, 0, 0, 0);
  141. }
  142. else
  143. {
  144. is->eof = 1;
  145. break; // added for auto exit read thread
  146. }
  147. }
  148. if (is->ic->pb && is->ic->pb->error)
  149. {
  150. break;
  151. }
  152. m_waitMutex.lock();
  153. is->continue_read_thread->wait(&m_waitMutex, 10);
  154. m_waitMutex.unlock();
  155. continue;
  156. }
  157. else
  158. {
  159. is->eof = 0;
  160. }
  161. /* check if packet is in play range specified by user, then queue, otherwise
  162. * discard */
  163. stream_start_time = is->ic->streams[pkt->stream_index]->start_time;
  164. pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
  165. pkt_in_play_range =
  166. duration == AV_NOPTS_VALUE ||
  167. (pkt_ts -
  168. (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
  169. av_q2d(is->ic->streams[pkt->stream_index]->time_base) -
  170. (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) /
  171. 1000000 <=
  172. ((double)duration / 1000000);
  173. if (pkt->stream_index == is->audio_stream && pkt_in_play_range)
  174. {
  175. packet_queue_put(&is->audioq, pkt);
  176. }
  177. else if (pkt->stream_index == is->video_stream && pkt_in_play_range &&
  178. !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC))
  179. {
  180. packet_queue_put(&is->videoq, pkt);
  181. }
  182. else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range)
  183. {
  184. packet_queue_put(&is->subtitleq, pkt);
  185. }
  186. else
  187. {
  188. av_packet_unref(pkt);
  189. }
  190. // print_state_info(is);
  191. }
  192. is->read_thread_exit = -1;
  193. av_packet_free(&pkt);
  194. return 0;
  195. }
  196. void ReadThread::run()
  197. {
  198. int ret = loop_read();
  199. if (ret < 0)
  200. {
  201. qDebug("-------- Read packets thread exit, with error=%d\n", ret);
  202. }
  203. else
  204. {
  205. qDebug("-------- Read packets thread exit.");
  206. }
  207. }