video_play_thread.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. // ***********************************************************/
  2. // video_play_thread.cpp
  3. //
  4. // Copy Right @ Steven Huang. All rights reserved.
  5. //
  6. // Video play thread. This section includes key code for
  7. // synchronizing video frames and audio using pts/dts,
  8. // as well as subtitle processing.
  9. // ***********************************************************/
  10. #include "video_play_thread.h"
  11. #include "AVPlayer2/playercontroller.h"
  12. #include <QLoggingCategory>
  13. Q_LOGGING_CATEGORY(playerControllerVideoPlayThread, "player.controller.VideoPlayThread")
  14. extern int framedrop;
  15. const QRegularExpression VideoPlayThread::m_assFilter = QRegularExpression("{\\\\.*?}");
  16. const QRegularExpression VideoPlayThread::m_assNewLineReplacer = QRegularExpression("\\\\n|\\\\N");
  17. Q_DECLARE_METATYPE(AVFrame*)
  18. VideoPlayThread::VideoPlayThread(VideoState* pState)
  19. : m_pState(pState)
  20. {
  21. qRegisterMetaType<AVFrame*>();
  22. }
  23. VideoPlayThread::~VideoPlayThread()
  24. {
  25. final_resample_param();
  26. }
  27. void VideoPlayThread::stop()
  28. {
  29. *m_exit = true;
  30. m_cv.notify_all();
  31. }
  32. void VideoPlayThread::run()
  33. {
  34. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] run start, m_pState:" << (void*)m_pState;
  35. assert(m_pState);
  36. VideoState* is = m_pState;
  37. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] VideoState* is:" << (void*)is << ", abort_request:" << is->abort_request;
  38. double remaining_time = 0.0;
  39. int loop_count = 0;
  40. for (;;) {
  41. if (m_exit && *m_exit) {
  42. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] m_exit set, exit.";
  43. break;
  44. }
  45. if (is->abort_request) {
  46. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] abort_request set, exit.";
  47. break;
  48. }
  49. if (is->eof && frame_queue_nb_remaining(&is->pictq) == 0) {
  50. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] eof且队列空,退出线程";
  51. break; // 线程退出
  52. }
  53. if (is->paused) {
  54. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] paused, wait.";
  55. std::unique_lock<std::mutex> lock(m_mutex);
  56. m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return m_exit && *m_exit; });
  57. continue;
  58. }
  59. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] call video_refresh, loop:" << loop_count << ", pictq size:" << (is ? is->pictq.size : -1) << ", remaining_time:" << remaining_time;
  60. if (remaining_time > 0.0)
  61. av_usleep((int64_t) (remaining_time * 1000000.0));
  62. remaining_time = REFRESH_RATE;
  63. if ((!is->paused || is->force_refresh)) {
  64. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] call video_refresh, loop:" << loop_count++;
  65. video_refresh(is, &remaining_time);
  66. }
  67. }
  68. qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] run end, abort_request:" << is->abort_request
  69. << ", m_exit:" << (m_exit ? m_exit->load() : -1);
  70. }
  71. void VideoPlayThread::video_refresh(VideoState* is, double* remaining_time)
  72. {
  73. double time;
  74. Frame *sp, *sp2;
  75. if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
  76. check_external_clock_speed(is);
  77. if (is->video_st) {
  78. retry:
  79. // ffplay方案:eof且只剩最后一帧时,消耗掉最后一帧
  80. if (is->eof && frame_queue_nb_remaining(&is->pictq) == 1) {
  81. frame_queue_next(&is->pictq);
  82. // 这里可以考虑发信号通知播放结束
  83. return;
  84. }
  85. if (frame_queue_nb_remaining(&is->pictq) == 0) {
  86. // nothing to do, no picture to display in the queue
  87. *remaining_time = REFRESH_RATE;
  88. } else {
  89. double last_duration, duration, delay;
  90. Frame *vp, *lastvp;
  91. /* dequeue the picture */
  92. lastvp = frame_queue_peek_last(&is->pictq);
  93. vp = frame_queue_peek(&is->pictq);
  94. if (vp->serial != is->videoq.serial) {
  95. frame_queue_next(&is->pictq);
  96. goto retry;
  97. }
  98. if (lastvp->serial != vp->serial)
  99. is->frame_timer = av_gettime_relative() / 1000000.0;
  100. if (is->paused)
  101. goto display;
  102. /* compute nominal last_duration */
  103. last_duration = vp_duration(is, lastvp, vp);
  104. delay = compute_target_delay(last_duration, is);
  105. time = av_gettime_relative() / 1000000.0;
  106. if (time < is->frame_timer + delay) {
  107. *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
  108. goto display;
  109. }
  110. is->frame_timer += delay;
  111. if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
  112. is->frame_timer = time;
  113. is->pictq.mutex->lock();
  114. if (!isnan(vp->pts))
  115. update_video_pts(is, vp->pts, vp->pos, vp->serial);
  116. is->pictq.mutex->unlock();
  117. if (frame_queue_nb_remaining(&is->pictq) > 1) {
  118. Frame* nextvp = frame_queue_peek_next(&is->pictq);
  119. duration = vp_duration(is, vp, nextvp);
  120. if (!is->step
  121. && (framedrop > 0
  122. || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER))
  123. && time > is->frame_timer + duration) {
  124. is->frame_drops_late++;
  125. frame_queue_next(&is->pictq);
  126. goto retry;
  127. }
  128. }
  129. if (is->subtitle_st) {
  130. while (frame_queue_nb_remaining(&is->subpq) > 0) {
  131. sp = frame_queue_peek(&is->subpq);
  132. if (frame_queue_nb_remaining(&is->subpq) > 1)
  133. sp2 = frame_queue_peek_next(&is->subpq);
  134. else
  135. sp2 = nullptr;
  136. if (sp->serial != is->subtitleq.serial
  137. || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
  138. || (sp2
  139. && is->vidclk.pts
  140. > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) {
  141. #if 0
  142. if (sp->uploaded) {
  143. int i;
  144. for (i = 0; i < sp->sub.num_rects; i++) {
  145. AVSubtitleRect* sub_rect = sp->sub.rects[i];
  146. /*uint8_t* pixels;
  147. int pitch, j;
  148. if (!SDL_LockTexture(is->sub_texture, (SDL_Rect*)sub_rect, (void**)&pixels, &pitch)) {
  149. for (j = 0; j < sub_rect->h; j++, pixels += pitch)
  150. memset(pixels, 0, sub_rect->w << 2);
  151. SDL_UnlockTexture(is->sub_texture);
  152. }*/
  153. }
  154. }
  155. #endif
  156. frame_queue_next(&is->subpq);
  157. } else {
  158. break;
  159. }
  160. }
  161. }
  162. frame_queue_next(&is->pictq);
  163. is->force_refresh = 1;
  164. if (is->step && !is->paused)
  165. toggle_pause(is, !is->step);
  166. }
  167. display:
  168. /* display picture */
  169. if (is->force_refresh && is->pictq.rindex_shown)
  170. video_display(is);
  171. }
  172. is->force_refresh = 0;
  173. }
  174. void VideoPlayThread::video_display(VideoState* is)
  175. {
  176. if (is->audio_st && false) {
  177. // video_audio_display(is);
  178. } else if (is->video_st) {
  179. video_image_display(is);
  180. }
  181. }
  182. #if 0
  183. void VideoPlayThread::video_audio_display(VideoState* s)
  184. {
  185. int64_t audio_callback_time = 0;
  186. int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
  187. int ch, channels, h, h2;
  188. int64_t time_diff;
  189. int rdft_bits, nb_freq;
  190. for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
  191. ;
  192. nb_freq = 1 << (rdft_bits - 1);
  193. /* compute display index : center on currently output samples */
  194. channels = s->audio_tgt.channels;
  195. nb_display_channels = channels;
  196. if (!s->paused) {
  197. int data_used = (2 * nb_freq);
  198. n = 2 * channels;
  199. delay = s->audio_write_buf_size;
  200. delay /= n;
  201. /* to be more precise, we take into account the time spent since
  202. the last buffer computation */
  203. if (audio_callback_time) {
  204. time_diff = av_gettime_relative() - audio_callback_time;
  205. delay -= (time_diff * s->audio_tgt.freq) / 1000000;
  206. }
  207. delay += 2 * data_used;
  208. if (delay < data_used)
  209. delay = data_used;
  210. i_start = x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
  211. /*if (s->show_mode == SHOW_MODE_WAVES) {
  212. h = INT_MIN;
  213. for (i = 0; i < 1000; i += channels) {
  214. int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
  215. int a = s->sample_array[idx];
  216. int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
  217. int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
  218. int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
  219. int score = a - d;
  220. if (h < score && (b ^ c) < 0) {
  221. h = score;
  222. i_start = idx;
  223. }
  224. }
  225. }*/
  226. s->last_i_start = i_start;
  227. }
  228. else {
  229. i_start = s->last_i_start;
  230. }
  231. #if 0
  232. if (s->show_mode == SHOW_MODE_WAVES) {
  233. SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
  234. /* total height for one channel */
  235. h = s->height / nb_display_channels;
  236. /* graph height / 2 */
  237. h2 = (h * 9) / 20;
  238. for (ch = 0; ch < nb_display_channels; ch++) {
  239. i = i_start + ch;
  240. y1 = s->ytop + ch * h + (h / 2); /* position of center line */
  241. for (x = 0; x < s->width; x++) {
  242. y = (s->sample_array[i] * h2) >> 15;
  243. if (y < 0) {
  244. y = -y;
  245. ys = y1 - y;
  246. }
  247. else {
  248. ys = y1;
  249. }
  250. fill_rectangle(s->xleft + x, ys, 1, y);
  251. i += channels;
  252. if (i >= SAMPLE_ARRAY_SIZE)
  253. i -= SAMPLE_ARRAY_SIZE;
  254. }
  255. }
  256. SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
  257. for (ch = 1; ch < nb_display_channels; ch++) {
  258. y = s->ytop + ch * h;
  259. fill_rectangle(s->xleft, y, s->width, 1);
  260. }
  261. }
  262. else {
  263. if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
  264. return;
  265. if (s->xpos >= s->width)
  266. s->xpos = 0;
  267. nb_display_channels = FFMIN(nb_display_channels, 2);
  268. if (rdft_bits != s->rdft_bits) {
  269. av_rdft_end(s->rdft);
  270. av_free(s->rdft_data);
  271. s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
  272. s->rdft_bits = rdft_bits;
  273. s->rdft_data = av_malloc_array(nb_freq, 4 * sizeof(*s->rdft_data));
  274. }
  275. if (!s->rdft || !s->rdft_data) {
  276. av_log(nullptr, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
  277. s->show_mode = SHOW_MODE_WAVES;
  278. }
  279. else {
  280. FFTSample* data[2];
  281. SDL_Rect rect = { .x = s->xpos, .y = 0, .w = 1, .h = s->height };
  282. uint32_t* pixels;
  283. int pitch;
  284. for (ch = 0; ch < nb_display_channels; ch++) {
  285. data[ch] = s->rdft_data + 2 * nb_freq * ch;
  286. i = i_start + ch;
  287. for (x = 0; x < 2 * nb_freq; x++) {
  288. double w = (x - nb_freq) * (1.0 / nb_freq);
  289. data[ch][x] = s->sample_array[i] * (1.0 - w * w);
  290. i += channels;
  291. if (i >= SAMPLE_ARRAY_SIZE)
  292. i -= SAMPLE_ARRAY_SIZE;
  293. }
  294. av_rdft_calc(s->rdft, data[ch]);
  295. }
  296. /* Least efficient way to do this, we should of course
  297. * directly access it but it is more than fast enough. */
  298. if (!SDL_LockTexture(s->vis_texture, &rect, (void**)&pixels, &pitch)) {
  299. pitch >>= 2;
  300. pixels += pitch * s->height;
  301. for (y = 0; y < s->height; y++) {
  302. double w = 1 / sqrt(nb_freq);
  303. int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
  304. int b = (nb_display_channels == 2) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
  305. : a;
  306. a = FFMIN(a, 255);
  307. b = FFMIN(b, 255);
  308. pixels -= pitch;
  309. *pixels = (a << 16) + (b << 8) + ((a + b) >> 1);
  310. }
  311. SDL_UnlockTexture(s->vis_texture);
  312. }
  313. SDL_RenderCopy(renderer, s->vis_texture, nullptr, nullptr);
  314. }
  315. if (!s->paused)
  316. s->xpos++;
  317. }
  318. #endif
  319. }
  320. #endif
  321. void VideoPlayThread::video_image_display(VideoState* is)
  322. {
  323. Frame* sp = nullptr;
  324. Frame* vp = frame_queue_peek_last(&is->pictq);
  325. Video_Resample* pResample = &m_Resample;
  326. if (frame_queue_nb_remaining(&is->subpq) > 0) {
  327. sp = frame_queue_peek(&is->subpq);
  328. if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
  329. if (!sp->uploaded) {
  330. // uint8_t* pixels[4];
  331. // int pitch[4];
  332. if (!sp->width || !sp->height) {
  333. sp->width = vp->width;
  334. sp->height = vp->height;
  335. }
  336. // if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888,
  337. // sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0) return;
  338. #if 1
  339. for (unsigned int i = 0; i < sp->sub.num_rects; i++) {
  340. AVSubtitleRect* sub_rect = sp->sub.rects[i];
  341. if (sub_rect->type == SUBTITLE_ASS) {
  342. qDebug("subtitle[%d], format:%d, type:%d, text:%s, flags:%d",
  343. i,
  344. sp->sub.format,
  345. sub_rect->type,
  346. sub_rect->text,
  347. sub_rect->flags);
  348. // QString ass = QString::fromUtf8(sub_rect->ass);
  349. QString ass = QString::fromLocal8Bit(
  350. QString::fromStdString(sub_rect->ass).toUtf8());
  351. QStringList assList = ass.split(",");
  352. if (assList.size() > 8) {
  353. ass = assList[8];
  354. qDebug("ass: %s", qUtf8Printable(ass));
  355. parse_subtitle_ass(ass);
  356. }
  357. } else {
  358. qWarning("not handled yet, type:%d", sub_rect->type);
  359. }
  360. }
  361. #else
  362. for (i = 0; i < sp->sub.num_rects; i++) {
  363. AVSubtitleRect* sub_rect = sp->sub.rects[i];
  364. sub_rect->x = av_clip(sub_rect->x, 0, sp->width);
  365. sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
  366. sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
  367. sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
  368. is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
  369. sub_rect->w,
  370. sub_rect->h,
  371. AV_PIX_FMT_PAL8,
  372. sub_rect->w,
  373. sub_rect->h,
  374. AV_PIX_FMT_BGRA,
  375. 0,
  376. nullptr,
  377. nullptr,
  378. nullptr);
  379. if (!is->sub_convert_ctx) {
  380. av_log(nullptr, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
  381. return;
  382. }
  383. #if 1
  384. sws_scale(is->sub_convert_ctx,
  385. (const uint8_t* const*) sub_rect->data,
  386. sub_rect->linesize,
  387. 0,
  388. sub_rect->h,
  389. pixels,
  390. pitch);
  391. #else
  392. if (!SDL_LockTexture(is->sub_texture,
  393. (SDL_Rect*) sub_rect,
  394. (void**) pixels,
  395. pitch)) {
  396. sws_scale(is->sub_convert_ctx,
  397. (const uint8_t* const*) sub_rect->data,
  398. sub_rect->linesize,
  399. 0,
  400. sub_rect->h,
  401. pixels,
  402. pitch);
  403. SDL_UnlockTexture(is->sub_texture);
  404. }
  405. #endif
  406. }
  407. #endif
  408. sp->uploaded = 1;
  409. }
  410. } else {
  411. sp = nullptr;
  412. }
  413. }
  414. AVFrame* pFrameRGB = pResample->pFrameRGB; // dst
  415. AVCodecContext* pVideoCtx = is->viddec.avctx;
  416. AVFrame* pFrame = vp->frame;
  417. // AVPixelFormat fmt = (AVPixelFormat)pFrame->format; // 0
  418. // const char* fmt_name = av_get_pix_fmt_name(fmt);
  419. // AVHWFramesContext* ctx =
  420. // (AVHWFramesContext*)pVideoCtx->hw_frames_ctx->data; AVPixelFormat sw_fmt =
  421. // ctx->sw_format;
  422. // qDebug("frame w:%d,h:%d, pts:%lld, dts:%lld", pVideoCtx->width,
  423. // pVideoCtx->height, pFrame->pts, pFrame->pkt_dts);
  424. // TODO: 不转换
  425. sws_scale(pResample->sws_ctx,
  426. (uint8_t const* const*) pFrame->data,
  427. pFrame->linesize,
  428. 0,
  429. pVideoCtx->height,
  430. pFrameRGB->data,
  431. pFrameRGB->linesize);
  432. // QImage img(pVideoCtx->width, pVideoCtx->height, QImage::Format_RGB888);
  433. // for (int y = 0; y < pVideoCtx->height; ++y) {
  434. // memcpy(img.scanLine(y),
  435. // pFrameRGB->data[0] + y * pFrameRGB->linesize[0],
  436. // pVideoCtx->width * 3);
  437. // }
  438. // emit frame_ready(img);
  439. if (m_onFrameReady) m_onFrameReady(pFrameRGB);
  440. }
  441. bool VideoPlayThread::init_resample_param(AVCodecContext* pVideo, bool bHardware)
  442. {
  443. Video_Resample* pResample = &m_Resample;
  444. if (pVideo) {
  445. enum AVPixelFormat pix_fmt = pVideo->pix_fmt; // frame format after decode
  446. if (bHardware)
  447. pix_fmt = AV_PIX_FMT_NV12;
  448. struct SwsContext* sws_ctx
  449. = sws_getContext(pVideo->width,
  450. pVideo->height,
  451. pix_fmt, // AV_PIX_FMT_YUV420P
  452. pVideo->width,
  453. pVideo->height,
  454. AV_PIX_FMT_RGB24, // sws_scale destination color scheme
  455. SWS_BILINEAR,
  456. nullptr,
  457. nullptr,
  458. nullptr);
  459. AVFrame* pFrameRGB = av_frame_alloc();
  460. if (!pFrameRGB) {
  461. printf("Could not allocate rgb frame.\n");
  462. return false;
  463. }
  464. pFrameRGB->width = pVideo->width;
  465. pFrameRGB->height = pVideo->height;
  466. pFrameRGB->format = AV_PIX_FMT_RGB24;
  467. int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pVideo->width, pVideo->height, 32);
  468. uint8_t* const buffer_RGB = (uint8_t*) av_malloc(numBytes * sizeof(uint8_t));
  469. if (!buffer_RGB) {
  470. printf("Could not allocate buffer.\n");
  471. return false;
  472. }
  473. av_image_fill_arrays(pFrameRGB->data,
  474. pFrameRGB->linesize,
  475. buffer_RGB,
  476. AV_PIX_FMT_RGB24,
  477. pVideo->width,
  478. pVideo->height,
  479. 32);
  480. pResample->sws_ctx = sws_ctx;
  481. pResample->pFrameRGB = pFrameRGB;
  482. pResample->buffer_RGB = buffer_RGB;
  483. return true;
  484. }
  485. return false;
  486. }
  487. void VideoPlayThread::final_resample_param()
  488. {
  489. Video_Resample* pResample = &m_Resample;
  490. // Free video resample context
  491. sws_freeContext(pResample->sws_ctx);
  492. // Free the RGB image
  493. av_free(pResample->buffer_RGB);
  494. av_frame_free(&pResample->pFrameRGB);
  495. av_free(pResample->pFrameRGB);
  496. }
  497. void VideoPlayThread::parse_subtitle_ass(const QString& text)
  498. {
  499. QString str = text;
  500. str.remove(m_assFilter);
  501. str.replace(m_assNewLineReplacer, "\n");
  502. str = str.trimmed();
  503. // emit subtitle_ready(str);
  504. if (m_onSubtitleReady) m_onSubtitleReady(str);
  505. }