video_state.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. // ***********************************************************/
  2. // video_state.cpp
  3. //
  4. // Copy Right @ Steven Huang. All rights reserved.
  5. //
  6. // A/V synchronization state. This code is referenced
  7. // from ffplay.c in Ffmpeg library.
  8. // ***********************************************************/
  9. #include "video_state.h"
  10. int infinite_buffer = -1;
  11. int64_t start_time = AV_NOPTS_VALUE;
  12. static enum AVPixelFormat hw_pix_fmt;
  13. VideoStateData::VideoStateData(bool use_hardware, bool loop_play)
  14. : m_bUseHardware(use_hardware), m_bLoopPlay(loop_play)
  15. {
  16. }
  17. VideoStateData::~VideoStateData()
  18. {
  19. close_hardware();
  20. delete_video_state();
  21. }
  22. void VideoStateData::delete_video_state()
  23. {
  24. if (m_pState)
  25. {
  26. stream_close(m_pState);
  27. m_pState = nullptr;
  28. }
  29. }
  30. VideoState* VideoStateData::get_state() const
  31. {
  32. return m_pState;
  33. }
  34. bool VideoStateData::is_hardware_decode() const
  35. {
  36. return m_bHardwareSuccess;
  37. }
  38. int VideoStateData::create_video_state(const char* filename)
  39. {
  40. int ret = -1;
  41. if (!filename || !filename[0])
  42. {
  43. qDebug("filename is invalid, please select a valid media file.");
  44. return ret;
  45. }
  46. m_pState = stream_open(filename);
  47. if (!m_pState)
  48. {
  49. qDebug("stream_open failed!");
  50. return ret;
  51. }
  52. return open_media(m_pState);
  53. }
  54. void VideoStateData::print_state() const
  55. {
  56. if (const auto is = m_pState)
  57. {
  58. qDebug("[VideoState]PacketQueue(v:%p,a:%p,s:%p)", &is->videoq, &is->audioq, &is->subtitleq);
  59. qDebug("[VideoState]FrameQueue(v:%p,a:%p,s:%p)", &is->pictq, &is->sampq, &is->subpq);
  60. qDebug("[VideoState]Decoder(v:%p,a:%p,s:%p)", &is->viddec, &is->auddec, &is->subdec);
  61. qDebug("[VideoState]Clock(v:%p,a:%p,s:%p)", &is->vidclk, &is->audclk, &is->extclk);
  62. }
  63. }
  64. int VideoStateData::open_media(VideoState* is)
  65. {
  66. assert(is);
  67. int err;
  68. uint i;
  69. int ret = -1;
  70. int st_index[AVMEDIA_TYPE_NB];
  71. AVFormatContext* ic = nullptr;
  72. const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
  73. memset(st_index, -1, sizeof(st_index));
  74. is->eof = 0;
  75. ic = avformat_alloc_context();
  76. if (!ic)
  77. {
  78. av_log(nullptr, AV_LOG_FATAL, "Could not allocate context.\n");
  79. ret = AVERROR(ENOMEM);
  80. goto fail;
  81. }
  82. ic->interrupt_callback.callback = nullptr; // decode_interrupt_cb;
  83. ic->interrupt_callback.opaque = is;
  84. err = avformat_open_input(&ic, is->filename, is->iformat, nullptr);
  85. if (err < 0)
  86. {
  87. av_log(nullptr, AV_LOG_FATAL, "failed to open %s: %d", is->filename, err);
  88. ret = -1;
  89. goto fail;
  90. }
  91. is->ic = ic;
  92. //ic->flags |= AVFMT_FLAG_GENPTS; // gen pts
  93. av_format_inject_global_side_data(ic);
  94. //AVDictionary** opts = setup_find_stream_info_opts(ic, codec_opts);
  95. //int orig_nb_streams = ic->nb_streams;
  96. err = avformat_find_stream_info(ic, nullptr);
  97. if (err < 0)
  98. {
  99. av_log(nullptr, AV_LOG_WARNING, "%s: could not find codec parameters\n", is->filename);
  100. ret = -1;
  101. goto fail;
  102. }
  103. if (ic->pb)
  104. ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use
  105. // avio_feof() to test for the end
  106. // if (seek_by_bytes < 0)
  107. // seek_by_bytes = (ic->iformat->flags & AVFMT_TS_DISCONT) &&
  108. //strcmp("ogg", ic->iformat->name);
  109. //is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
  110. is->max_frame_duration = 2.0;
  111. /* if seeking requested, we execute it */
  112. if (start_time != AV_NOPTS_VALUE)
  113. {
  114. int64_t timestamp;
  115. timestamp = start_time;
  116. /* add the stream start time */
  117. if (ic->start_time != AV_NOPTS_VALUE)
  118. timestamp += ic->start_time;
  119. ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
  120. if (ret < 0)
  121. {
  122. av_log(nullptr, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n", is->filename, (double)timestamp / AV_TIME_BASE);
  123. }
  124. }
  125. is->realtime = is_realtime(ic);
  126. av_dump_format(ic, 0, is->filename, 0);
  127. for (i = 0; i < ic->nb_streams; i++)
  128. {
  129. AVStream* st = ic->streams[i];
  130. enum AVMediaType type = st->codecpar->codec_type;
  131. st->discard = AVDISCARD_ALL;
  132. if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
  133. if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
  134. st_index[type] = i;
  135. }
  136. for (i = 0; i < AVMEDIA_TYPE_NB; i++)
  137. {
  138. if (wanted_stream_spec[i] && st_index[i] == -1)
  139. {
  140. av_log(nullptr, AV_LOG_ERROR, "Stream specifier %s does not match any %s stream\n",
  141. wanted_stream_spec[i], av_get_media_type_string(AVMediaType(i)));
  142. st_index[i] = INT_MAX;
  143. }
  144. }
  145. st_index[AVMEDIA_TYPE_VIDEO] = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, st_index[AVMEDIA_TYPE_VIDEO], -1, nullptr, 0);
  146. st_index[AVMEDIA_TYPE_AUDIO] = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, st_index[AVMEDIA_TYPE_AUDIO],
  147. st_index[AVMEDIA_TYPE_VIDEO], nullptr, 0);
  148. st_index[AVMEDIA_TYPE_SUBTITLE] = av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE, st_index[AVMEDIA_TYPE_SUBTITLE],
  149. (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ? st_index[AVMEDIA_TYPE_AUDIO] : st_index[AVMEDIA_TYPE_VIDEO]), nullptr, 0);
  150. /* open the streams */
  151. if (st_index[AVMEDIA_TYPE_VIDEO] >= 0)
  152. {
  153. stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
  154. }
  155. if (st_index[AVMEDIA_TYPE_AUDIO] >= 0)
  156. {
  157. stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
  158. }
  159. if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0)
  160. {
  161. stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
  162. }
  163. if (is->video_stream < 0 && is->audio_stream < 0)
  164. {
  165. av_log(nullptr, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n", is->filename);
  166. ret = -1;
  167. goto fail;
  168. }
  169. if (infinite_buffer < 0 && is->realtime)
  170. infinite_buffer = 1;
  171. return 0;
  172. fail:
  173. if (ic && !is->ic)
  174. avformat_close_input(&ic);
  175. return ret;
  176. }
  177. VideoState* VideoStateData::stream_open(const char* filename, const AVInputFormat* iformat)
  178. {
  179. VideoState* is = nullptr;
  180. int startup_volume = 100;
  181. int av_sync_type = AV_SYNC_AUDIO_MASTER;
  182. is = (VideoState*)av_mallocz(sizeof(VideoState));
  183. if (!is)
  184. return nullptr;
  185. is->last_video_stream = is->video_stream = -1;
  186. is->last_audio_stream = is->audio_stream = -1;
  187. is->last_subtitle_stream = is->subtitle_stream = -1;
  188. is->filename = av_strdup(filename);
  189. if (!is->filename)
  190. goto fail;
  191. is->iformat = iformat;
  192. is->ytop = 0;
  193. is->xleft = 0;
  194. /* start video display */
  195. if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
  196. goto fail;
  197. if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
  198. goto fail;
  199. if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
  200. goto fail;
  201. if (packet_queue_init(&is->videoq) < 0 ||
  202. packet_queue_init(&is->audioq) < 0 ||
  203. packet_queue_init(&is->subtitleq) < 0)
  204. goto fail;
  205. if (!(is->continue_read_thread = new QWaitCondition()))
  206. {
  207. av_log(nullptr, AV_LOG_FATAL, "new QWaitCondition() failed!\n");
  208. goto fail;
  209. }
  210. init_clock(&is->vidclk, &is->videoq.serial);
  211. init_clock(&is->audclk, &is->audioq.serial);
  212. init_clock(&is->extclk, &is->extclk.serial);
  213. is->audio_clock_serial = -1;
  214. if (startup_volume < 0)
  215. av_log(nullptr, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
  216. if (startup_volume > 100)
  217. av_log(nullptr, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
  218. startup_volume = av_clip(startup_volume, 0, 100);
  219. startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
  220. is->audio_volume = startup_volume;
  221. is->muted = 0;
  222. is->av_sync_type = av_sync_type;
  223. // is->read_tid = m_pReadThreadId;
  224. is->read_thread_exit = -1;
  225. is->loop = int(m_bLoopPlay);
  226. is->threads = {nullptr};
  227. #if USE_AVFILTER_AUDIO
  228. is->audio_speed = 1.0;
  229. #endif
  230. return is;
  231. fail:
  232. stream_close(is);
  233. return nullptr;
  234. }
  235. void VideoStateData::threads_setting(VideoState* is, const Threads& threads)
  236. {
  237. if (!is)
  238. return;
  239. assert(!is->threads.read_tid);
  240. assert(!is->threads.video_decode_tid);
  241. assert(!is->threads.audio_decode_tid);
  242. assert(!is->threads.video_play_tid);
  243. assert(!is->threads.audio_play_tid);
  244. assert(!is->threads.subtitle_decode_tid);
  245. is->threads = threads;
  246. }
  247. void VideoStateData::read_thread_exit_wait(VideoState* is)
  248. {
  249. if (!is)
  250. return;
  251. if (is->read_thread_exit != 0)
  252. return;
  253. if (is->threads.read_tid)
  254. {
  255. av_log(nullptr, AV_LOG_INFO, "read thread wait before!\n");
  256. is->threads.read_tid->wait();
  257. av_log(nullptr, AV_LOG_INFO, "read thread wait after!\n");
  258. is->threads.read_tid = nullptr;
  259. }
  260. }
  261. void VideoStateData::threads_exit_wait(VideoState* is)
  262. {
  263. if (!is)
  264. return;
  265. if (is->threads.video_play_tid)
  266. {
  267. is->threads.video_play_tid->wait();
  268. is->threads.video_play_tid = nullptr;
  269. }
  270. if (is->threads.audio_play_tid)
  271. {
  272. is->threads.audio_play_tid->wait();
  273. is->threads.audio_play_tid = nullptr;
  274. }
  275. if (is->threads.video_decode_tid)
  276. {
  277. is->threads.video_decode_tid->wait();
  278. is->threads.video_decode_tid = nullptr;
  279. }
  280. if (is->threads.audio_decode_tid)
  281. {
  282. is->threads.audio_decode_tid->wait();
  283. is->threads.audio_decode_tid = nullptr;
  284. }
  285. if (is->threads.subtitle_decode_tid)
  286. {
  287. is->threads.subtitle_decode_tid->wait();
  288. is->threads.subtitle_decode_tid = nullptr;
  289. }
  290. }
  291. void VideoStateData::stream_close(VideoState* is)
  292. {
  293. assert(is);
  294. is->abort_request = 1;
  295. read_thread_exit_wait(is);
  296. // if (is->read_thread_exit == 0)
  297. //{
  298. // // SDL_WaitThread(is->read_tid, nullptr);
  299. // //((QThread*)(is->read_tid))->wait();
  300. // /*if (m_pReadThreadId)
  301. // m_pReadThreadId->wait();*/
  302. //}
  303. /* close each stream */
  304. if (is->audio_stream >= 0)
  305. stream_component_close(is, is->audio_stream);
  306. if (is->video_stream >= 0)
  307. stream_component_close(is, is->video_stream);
  308. if (is->subtitle_stream >= 0)
  309. stream_component_close(is, is->subtitle_stream);
  310. threads_exit_wait(is); // read and decode threads exit here.
  311. avformat_close_input(&is->ic);
  312. packet_queue_destroy(&is->videoq);
  313. packet_queue_destroy(&is->audioq);
  314. packet_queue_destroy(&is->subtitleq);
  315. /* free all pictures */
  316. frame_queue_destory(&is->pictq);
  317. frame_queue_destory(&is->sampq);
  318. frame_queue_destory(&is->subpq);
  319. if (is->continue_read_thread)
  320. {
  321. delete is->continue_read_thread;
  322. is->continue_read_thread = nullptr;
  323. }
  324. // SDL_DestroyCond(is->continue_read_thread);
  325. sws_freeContext(is->img_convert_ctx);
  326. sws_freeContext(is->sub_convert_ctx);
  327. av_free(is->filename);
  328. /*if (is->vis_texture)
  329. SDL_DestroyTexture(is->vis_texture);
  330. if (is->vid_texture)
  331. SDL_DestroyTexture(is->vid_texture);
  332. if (is->sub_texture)
  333. SDL_DestroyTexture(is->sub_texture);*/
  334. av_free(is);
  335. }
  336. static enum AVPixelFormat get_hw_format(AVCodecContext* ctx, const enum AVPixelFormat* pix_fmts)
  337. {
  338. for (const enum AVPixelFormat* p = pix_fmts; *p != -1; p++)
  339. {
  340. if (*p == hw_pix_fmt)
  341. return *p;
  342. }
  343. fprintf(stderr, "Failed to get HW surface format, codec_id=%d\n", (int)ctx->codec_id);
  344. return AV_PIX_FMT_NONE;
  345. }
  346. // static int hw_decoder_init(AVCodecContext* ctx, const enum AVHWDeviceType
  347. // type)
  348. //{
  349. // int err = 0;
  350. //
  351. // if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type, nullptr,
  352. //nullptr, 0)) < 0) { fprintf(stderr, "Failed to create specified HW
  353. //device.\n"); return err;
  354. // }
  355. //
  356. // ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
  357. //
  358. // return err;
  359. //}
  360. int VideoStateData::hw_decoder_init(AVCodecContext* ctx, const enum AVHWDeviceType type)
  361. {
  362. int err = 0;
  363. if ((err = av_hwdevice_ctx_create(&m_hw_device_ctx, type, nullptr, nullptr, 0)) < 0)
  364. {
  365. fprintf(stderr, "Failed to create specified HW device.\n");
  366. return err;
  367. }
  368. ctx->hw_device_ctx = av_buffer_ref(m_hw_device_ctx);
  369. return err;
  370. }
  371. bool VideoStateData::open_hardware(AVCodecContext* avctx, const AVCodec* codec, const char* device)
  372. {
  373. enum AVHWDeviceType type = get_hwdevice(device);
  374. hw_pix_fmt = get_hwdevice_decoder(codec, type);
  375. avctx->get_format = get_hw_format;
  376. if (hw_decoder_init(avctx, type) < 0)
  377. return false;
  378. return true;
  379. }
  380. void VideoStateData::close_hardware()
  381. {
  382. av_buffer_unref(&m_hw_device_ctx);
  383. }
  384. int VideoStateData::stream_component_open(VideoState* is, int stream_index)
  385. {
  386. assert(is);
  387. AVFormatContext* ic = is->ic;
  388. AVCodecContext* avctx;
  389. const AVCodec* codec;
  390. AVDictionary* opts = nullptr;
  391. // const AVDictionaryEntry* t = nullptr;
  392. int sample_rate, nb_channels;
  393. AVChannelLayout ch_layout = {0};
  394. // int64_t
  395. int format;
  396. int ret = 0;
  397. int stream_lowres = 0;
  398. if (stream_index < 0 || ((unsigned int)stream_index) >= ic->nb_streams)
  399. return -1;
  400. avctx = avcodec_alloc_context3(nullptr);
  401. if (!avctx)
  402. return AVERROR(ENOMEM);
  403. ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
  404. if (ret < 0)
  405. goto fail;
  406. avctx->pkt_timebase = ic->streams[stream_index]->time_base;
  407. codec = avcodec_find_decoder(avctx->codec_id);
  408. switch (avctx->codec_type)
  409. {
  410. case AVMEDIA_TYPE_AUDIO:
  411. is->last_audio_stream = stream_index;
  412. break;
  413. case AVMEDIA_TYPE_SUBTITLE:
  414. is->last_subtitle_stream = stream_index;
  415. break;
  416. case AVMEDIA_TYPE_VIDEO:
  417. is->last_video_stream = stream_index;
  418. if (m_bUseHardware)
  419. {
  420. m_bHardwareSuccess = false;
  421. const char* hardware_device = "dxva2"; // device = <vaapi|vdpau|dxva2|d3d11va>
  422. ret = open_hardware(avctx, codec, hardware_device);
  423. if (!ret)
  424. {
  425. qWarning("hardware-accelerated opened failed, device:%s", hardware_device);
  426. goto fail;
  427. }
  428. qInfo("hardware-accelerated opened, device:%s", hardware_device);
  429. m_bHardwareSuccess = true;
  430. }
  431. break;
  432. }
  433. if (!codec)
  434. {
  435. av_log(nullptr, AV_LOG_WARNING, "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
  436. ret = AVERROR(EINVAL);
  437. goto fail;
  438. }
  439. avctx->codec_id = codec->id;
  440. if (stream_lowres > codec->max_lowres)
  441. {
  442. av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n", codec->max_lowres);
  443. stream_lowres = codec->max_lowres;
  444. }
  445. avctx->lowres = stream_lowres;
  446. // avctx->flags2 |= AV_CODEC_FLAG2_FAST;
  447. /*opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
  448. if (!av_dict_get(opts, "threads", NULL, 0))
  449. av_dict_set(&opts, "threads", "auto", 0);
  450. if (stream_lowres)
  451. av_dict_set_int(&opts, "lowres", stream_lowres, 0);*/
  452. if ((ret = avcodec_open2(avctx, codec, &opts)) < 0)
  453. {
  454. goto fail;
  455. }
  456. is->eof = 0;
  457. ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
  458. switch (avctx->codec_type)
  459. {
  460. case AVMEDIA_TYPE_AUDIO:
  461. #if USE_AVFILTER_AUDIO
  462. {
  463. AVFilterContext* sink;
  464. // const char* afilters =
  465. // "aresample=8000,aformat=sample_fmts=s16:channel_layouts=mono"; //
  466. // "atempo=2"; const char* afilters = nullptr; const char* afilters =
  467. // "atempo=2.0";
  468. is->audio_filter_src.freq = avctx->sample_rate;
  469. is->audio_filter_src.ch_layout.nb_channels = avctx->ch_layout.nb_channels; // avctx->channels;
  470. is->audio_filter_src.ch_layout = avctx->ch_layout; // avctx->channel_layout
  471. is->audio_filter_src.fmt = avctx->sample_fmt;
  472. if ((ret = configure_audio_filters(is, is->afilters, 0)) < 0)
  473. goto fail;
  474. sink = is->out_audio_filter;
  475. sample_rate = av_buffersink_get_sample_rate(sink);
  476. nb_channels = av_buffersink_get_channels(sink);
  477. // channel_layout = av_buffersink_get_channel_layout(sink);
  478. format = av_buffersink_get_format(sink);
  479. AVChannelLayout chn_layout;
  480. av_buffersink_get_ch_layout(sink, &chn_layout);
  481. qDebug("afilter sink: sample rate:%d, chn:%d, fmt:%d, chn_layout:%d", sample_rate, nb_channels, format, chn_layout.u);
  482. }
  483. #else
  484. sample_rate = avctx->sample_rate;
  485. ret = av_channel_layout_copy(&ch_layout, &avctx->ch_layout);
  486. if (ret < 0)
  487. goto fail;
  488. #endif
  489. /* prepare audio output */
  490. /*if ((ret = audio_open(is, chn_layout, nb_channels, sample_rate,
  491. &is->audio_tgt)) < 0) goto fail;
  492. is->audio_src = is->audio_tgt;*/
  493. is->audio_stream = stream_index;
  494. is->audio_st = ic->streams[stream_index];
  495. if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)))
  496. {
  497. is->auddec.start_pts = is->audio_st->start_time;
  498. is->auddec.start_pts_tb = is->audio_st->time_base;
  499. }
  500. m_bHasAudio = true;
  501. m_avctxAudio = avctx;
  502. break;
  503. case AVMEDIA_TYPE_VIDEO:
  504. is->video_stream = stream_index;
  505. is->video_st = ic->streams[stream_index];
  506. m_bHasVideo = true;
  507. m_avctxVideo = avctx;
  508. break;
  509. case AVMEDIA_TYPE_SUBTITLE:
  510. is->subtitle_stream = stream_index;
  511. is->subtitle_st = ic->streams[stream_index];
  512. m_bHasSubtitle = true;
  513. m_avctxSubtitle = avctx;
  514. break;
  515. default:
  516. break;
  517. }
  518. goto out;
  519. fail:
  520. avcodec_free_context(&avctx);
  521. out:
  522. av_dict_free(&opts);
  523. return ret;
  524. }
  525. void VideoStateData::stream_component_close(VideoState* is, int stream_index)
  526. {
  527. assert(is);
  528. AVFormatContext* ic = is->ic;
  529. AVCodecParameters* codecpar;
  530. if (stream_index < 0 || ((unsigned int)stream_index) >= ic->nb_streams)
  531. return;
  532. codecpar = ic->streams[stream_index]->codecpar;
  533. switch (codecpar->codec_type)
  534. {
  535. case AVMEDIA_TYPE_AUDIO:
  536. decoder_abort(&is->auddec, &is->sampq);
  537. // SDL_CloseAudioDevice(audio_dev);
  538. decoder_destroy(&is->auddec);
  539. // swr_free(&is->swr_ctx);
  540. // av_freep(&is->audio_buf1);
  541. // is->audio_buf1_size = 0;
  542. // is->audio_buf = nullptr;
  543. /*if (is->rdft) {
  544. av_rdft_end(is->rdft);
  545. av_freep(&is->rdft_data);
  546. is->rdft = nullptr;
  547. is->rdft_bits = 0;
  548. }*/
  549. break;
  550. case AVMEDIA_TYPE_VIDEO:
  551. decoder_abort(&is->viddec, &is->pictq);
  552. decoder_destroy(&is->viddec);
  553. break;
  554. case AVMEDIA_TYPE_SUBTITLE:
  555. decoder_abort(&is->subdec, &is->subpq);
  556. decoder_destroy(&is->subdec);
  557. break;
  558. default:
  559. qDebug("Not handled yet.......code type:%d", codecpar->codec_type);
  560. break;
  561. }
  562. ic->streams[stream_index]->discard = AVDISCARD_ALL;
  563. switch (codecpar->codec_type)
  564. {
  565. case AVMEDIA_TYPE_AUDIO:
  566. is->audio_st = nullptr;
  567. is->audio_stream = -1;
  568. break;
  569. case AVMEDIA_TYPE_VIDEO:
  570. is->video_st = nullptr;
  571. is->video_stream = -1;
  572. break;
  573. case AVMEDIA_TYPE_SUBTITLE:
  574. is->subtitle_st = nullptr;
  575. is->subtitle_stream = -1;
  576. break;
  577. default:
  578. break;
  579. }
  580. }
  581. bool VideoStateData::has_video() const
  582. {
  583. return m_bHasVideo;
  584. }
  585. bool VideoStateData::has_audio() const
  586. {
  587. return m_bHasAudio;
  588. }
  589. bool VideoStateData::has_subtitle() const
  590. {
  591. return m_bHasSubtitle;
  592. }
  593. AVCodecContext* VideoStateData::get_contex(AVMediaType type) const
  594. {
  595. AVCodecContext* pCtx = nullptr;
  596. switch (type)
  597. {
  598. case AVMEDIA_TYPE_AUDIO:
  599. pCtx = m_avctxAudio;
  600. break;
  601. case AVMEDIA_TYPE_VIDEO:
  602. pCtx = m_avctxVideo;
  603. break;
  604. case AVMEDIA_TYPE_SUBTITLE:
  605. pCtx = m_avctxSubtitle;
  606. break;
  607. default:
  608. break;
  609. }
  610. return pCtx;
  611. }
  612. enum AVHWDeviceType VideoStateData::get_hwdevice(const char* device) const
  613. {
  614. // device = <vaapi|vdpau|dxva2|d3d11va>
  615. enum AVHWDeviceType type = av_hwdevice_find_type_by_name(device);
  616. if (type == AV_HWDEVICE_TYPE_NONE)
  617. {
  618. av_log(nullptr, AV_LOG_WARNING, "Device type %s is not supported.\n", device);
  619. av_log(nullptr, AV_LOG_INFO, "Available device types:");
  620. while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
  621. av_log(nullptr, AV_LOG_INFO, " %s", av_hwdevice_get_type_name(type));
  622. av_log(nullptr, AV_LOG_INFO, "\n");
  623. return AV_HWDEVICE_TYPE_NONE;
  624. }
  625. return type;
  626. }
  627. enum AVPixelFormat VideoStateData::get_hwdevice_decoder(const AVCodec* decoder, enum AVHWDeviceType type) const
  628. {
  629. if (!decoder || AV_HWDEVICE_TYPE_NONE == type)
  630. return AV_PIX_FMT_NONE;
  631. for (int i = 0;; i++)
  632. {
  633. const AVCodecHWConfig* config = avcodec_get_hw_config(decoder, i);
  634. if (!config)
  635. {
  636. av_log(nullptr, AV_LOG_WARNING, "Decoder %s does not support device type %s.\n", decoder->name, av_hwdevice_get_type_name(type));
  637. return AV_PIX_FMT_NONE;
  638. }
  639. if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && config->device_type == type)
  640. {
  641. return config->pix_fmt;
  642. }
  643. }
  644. return AV_PIX_FMT_NONE;
  645. }