read_thread.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "read_thread.h"
  2. #include "AVPlayer2/playercontroller.h"
  3. #include <QLoggingCategory>
  4. Q_LOGGING_CATEGORY(playerControllerReadThread, "player.controller.ReadThread")
  5. extern int infinite_buffer;
  6. extern int64_t start_time;
  7. static int64_t duration = AV_NOPTS_VALUE;
  8. ReadThread::ReadThread(VideoState* pState)
  9. : m_pPlayData(pState)
  10. {
  11. qCDebug(playerControllerReadThread) << "[ReadThread] constructed, pState:" << (void*) pState;
  12. }
  13. ReadThread::~ReadThread()
  14. {
  15. qCDebug(playerControllerReadThread) << "[ReadThread] destructed.";
  16. stop();
  17. join();
  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. if (!is)
  33. return ret;
  34. pkt = av_packet_alloc();
  35. if (!pkt) {
  36. av_log(nullptr, AV_LOG_FATAL, "Could not allocate packet.\n");
  37. ret = AVERROR(ENOMEM);
  38. return ret;
  39. }
  40. qCDebug(playerControllerReadThread) << "[ReadThread] loop_read start, file:"
  41. << (is && is->ic ? is->ic->url : "null");
  42. is->read_thread_exit = 0;
  43. for (;;) {
  44. if (isExit()) {
  45. qCDebug(playerControllerReadThread) << "[ReadThread] m_exit set, break.";
  46. break;
  47. }
  48. if (is->abort_request) {
  49. qCDebug(playerControllerReadThread) << "[ReadThread] abort_request set, break.";
  50. break;
  51. }
  52. if (is->paused != is->last_paused) {
  53. is->last_paused = is->paused;
  54. if (is->paused)
  55. is->read_pause_return = av_read_pause(is->ic);
  56. else
  57. av_read_play(is->ic);
  58. }
  59. if (is->seek_req) {
  60. qCDebug(playerControllerReadThread)
  61. << "[ReadThread] seek_req, seek_pos:" << is->seek_pos
  62. << ", seek_rel:" << is->seek_rel << ", seek_flags:" << is->seek_flags;
  63. int64_t seek_target = is->seek_pos;
  64. int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2 : INT64_MIN;
  65. int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2 : INT64_MAX;
  66. ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
  67. if (ret < 0) {
  68. av_log(nullptr, AV_LOG_ERROR, "%s: error while seeking\n", is->ic->url);
  69. qCWarning(playerControllerReadThread)
  70. << "[ReadThread] avformat_seek_file failed, ret:" << ret;
  71. } else {
  72. qCDebug(playerControllerReadThread)
  73. << "[ReadThread] avformat_seek_file success, flush queues.";
  74. if (is->audio_stream >= 0)
  75. packet_queue_flush(&is->audioq);
  76. if (is->subtitle_stream >= 0)
  77. packet_queue_flush(&is->subtitleq);
  78. if (is->video_stream >= 0)
  79. packet_queue_flush(&is->videoq);
  80. if (is->seek_flags & AVSEEK_FLAG_BYTE) {
  81. set_clock(&is->extclk, NAN, 0);
  82. } else {
  83. set_clock(&is->extclk, seek_target / (double) AV_TIME_BASE, 0);
  84. }
  85. }
  86. is->seek_req = 0;
  87. is->queue_attachments_req = 1;
  88. is->eof = 0;
  89. if (is->paused)
  90. step_to_next_frame(is);
  91. }
  92. if (is->queue_attachments_req) {
  93. qCDebug(playerControllerReadThread)
  94. << "[ReadThread] queue_attachments_req, video_st:" << (void*) is->video_st;
  95. if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
  96. ret = av_packet_ref(pkt, &is->video_st->attached_pic);
  97. if (ret < 0)
  98. break;
  99. packet_queue_put(&is->videoq, pkt);
  100. packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
  101. }
  102. is->queue_attachments_req = 0;
  103. }
  104. /* if the queue are full, no need to read more */
  105. if (infinite_buffer < 1
  106. && (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
  107. || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq)
  108. && stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq)
  109. && stream_has_enough_packets(is->subtitle_st,
  110. is->subtitle_stream,
  111. &is->subtitleq)))) {
  112. qCDebug(playerControllerReadThread)
  113. << "[ReadThread] queues full, waiting... audioq:" << is->audioq.size
  114. << ", videoq:" << is->videoq.size << ", subtitleq:" << is->subtitleq.size;
  115. std::unique_lock<std::mutex> lock(m_mutex);
  116. m_cv.wait_for(lock, std::chrono::milliseconds(10), [this, is] { return isExit() || is->abort_request; });
  117. continue;
  118. }
  119. if (!is->paused
  120. && (!is->audio_st
  121. || (is->auddec.finished == is->audioq.serial
  122. && frame_queue_nb_remaining(&is->sampq) == 0))
  123. && (!is->video_st
  124. || (is->viddec.finished == is->videoq.serial
  125. && frame_queue_nb_remaining(&is->pictq) == 0))) {
  126. if (is->loop) {
  127. stream_seek(is, 0, 0, 0);
  128. } else {
  129. // autoexit
  130. break;
  131. }
  132. }
  133. ret = av_read_frame(is->ic, pkt);
  134. if (ret < 0) {
  135. char buf[256] = {0};
  136. av_strerror(ret, buf, 256);
  137. qCWarning(playerControllerReadThread)
  138. << "[ReadThread] av_read_frame failed, ret:" << ret << ", eof:" << is->eof
  139. << ", pb_error:" << (is->ic->pb ? is->ic->pb->error : 0)
  140. << "error:" << QString::fromUtf8(buf);
  141. if ((ret == AVERROR_EOF || avio_feof(is->ic->pb)) && !is->eof) {
  142. qCDebug(playerControllerReadThread) << "[ReadThread] EOF reached, send null packets.";
  143. if (is->video_stream >= 0)
  144. packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
  145. if (is->audio_stream >= 0)
  146. packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream);
  147. if (is->subtitle_stream >= 0)
  148. packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream);
  149. is->eof = 1;
  150. // if (is->loop) {
  151. // stream_seek(is, 0, 0, 0);
  152. // } else {
  153. // is->eof = 1;
  154. // break; // added for auto exit read thread
  155. // }
  156. }
  157. if (is->ic->pb && is->ic->pb->error) {
  158. qCWarning(playerControllerReadThread) << "[ReadThread] IO error detected.";
  159. break;
  160. }
  161. std::unique_lock<std::mutex> lock(m_mutex);
  162. m_cv.wait_for(lock, std::chrono::milliseconds(10), [this, is] { return isExit() || is->abort_request; });
  163. continue;
  164. } else {
  165. is->eof = 0;
  166. qCDebug(playerControllerReadThread)
  167. << "[ReadThread] av_read_frame success, stream_index:" << pkt->stream_index
  168. << ", pts:" << pkt->pts;
  169. }
  170. /* check if packet is in play range specified by user, then queue, otherwise discard */
  171. stream_start_time = is->ic->streams[pkt->stream_index]->start_time;
  172. pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
  173. pkt_in_play_range = duration == AV_NOPTS_VALUE
  174. || (pkt_ts
  175. - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0))
  176. * av_q2d(is->ic->streams[pkt->stream_index]->time_base)
  177. - (double) (start_time != AV_NOPTS_VALUE ? start_time : 0)
  178. / 1000000
  179. <= ((double) duration / 1000000);
  180. if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
  181. qCDebug(playerControllerReadThread) << "[ReadThread] put audio packet, pts:" << pkt->pts;
  182. packet_queue_put(&is->audioq, pkt);
  183. } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
  184. && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
  185. qCDebug(playerControllerReadThread) << "[ReadThread] put video packet, pts:" << pkt->pts;
  186. packet_queue_put(&is->videoq, pkt);
  187. } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
  188. qCDebug(playerControllerReadThread) << "[ReadThread] put subtitle packet, pts:" << pkt->pts;
  189. packet_queue_put(&is->subtitleq, pkt);
  190. } else {
  191. qCDebug(playerControllerReadThread)
  192. << "[ReadThread] drop packet, stream_index:" << pkt->stream_index;
  193. av_packet_unref(pkt);
  194. }
  195. }
  196. qCWarning(playerControllerReadThread)
  197. << "[ReadThread] loop_read about to exit, eof:" << is->eof
  198. << ", audioq.size:" << is->audioq.size << ", videoq.size:" << is->videoq.size
  199. << ", subtitleq.size:" << is->subtitleq.size << ", abort_request:" << is->abort_request
  200. << ", m_exit:" << (m_exit ? m_exit->load() : -1);
  201. qCDebug(playerControllerReadThread) << "[ReadThread] loop_read exit, set read_thread_exit = -1";
  202. is->read_thread_exit = -1;
  203. if (!is->ic)
  204. avformat_close_input(&is->ic);
  205. av_packet_free(&pkt);
  206. return 0;
  207. }
  208. void ReadThread::run()
  209. {
  210. qCDebug(playerControllerReadThread) << "[ReadThread] run start";
  211. int ret = loop_read();
  212. qCDebug(playerControllerReadThread) << "[ReadThread] run end, loop_read ret:" << ret;
  213. // 可加日志输出
  214. }