ffmpegVideoCursor.cxx 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file ffmpegVideoCursor.cxx
  10. * @author jyelon
  11. * @date 2007-08-01
  12. */
  13. #include "ffmpegVideoCursor.h"
  14. #include "config_ffmpeg.h"
  15. #include "pStatCollector.h"
  16. #include "pStatTimer.h"
  17. #include "mutexHolder.h"
  18. #include "reMutexHolder.h"
  19. #include "ffmpegVideo.h"
  20. #include "bamReader.h"
  21. extern "C" {
  22. #include "libavcodec/avcodec.h"
  23. #include "libavformat/avformat.h"
  24. #include "libavutil/pixdesc.h"
  25. #ifdef HAVE_SWSCALE
  26. #include "libswscale/swscale.h"
  27. #endif
  28. }
  29. ReMutex FfmpegVideoCursor::_av_lock;
  30. TypeHandle FfmpegVideoCursor::_type_handle;
  31. TypeHandle FfmpegVideoCursor::FfmpegBuffer::_type_handle;
  32. PStatCollector FfmpegVideoCursor::_fetch_buffer_pcollector("*:FFMPEG Video Decoding:Fetch");
  33. PStatCollector FfmpegVideoCursor::_seek_pcollector("*:FFMPEG Video Decoding:Seek");
  34. PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Video to BGR");
  35. #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 32, 100)
  36. #define AV_PIX_FMT_FLAG_ALPHA PIX_FMT_ALPHA
  37. #endif
  38. /**
  39. * This constructor is only used when reading from a bam file.
  40. */
  41. FfmpegVideoCursor::
  42. FfmpegVideoCursor() :
  43. _max_readahead_frames(0),
  44. _thread_priority(ffmpeg_thread_priority),
  45. _lock("FfmpegVideoCursor::_lock"),
  46. _action_cvar(_lock),
  47. _thread_status(TS_stopped),
  48. _seek_frame(0),
  49. _packet(nullptr),
  50. _format_ctx(nullptr),
  51. _video_ctx(nullptr),
  52. _convert_ctx(nullptr),
  53. _pixel_format((int)AV_PIX_FMT_NONE),
  54. _video_index(-1),
  55. _frame(nullptr),
  56. _frame_out(nullptr),
  57. _eof_known(false)
  58. {
  59. }
  60. /**
  61. * Specifies the source of the video cursor. This is normally called only by
  62. * the constructor or when reading from a bam file.
  63. */
  64. void FfmpegVideoCursor::
  65. init_from(FfmpegVideo *source) {
  66. nassertv(_thread == nullptr && _thread_status == TS_stopped);
  67. nassertv(source != nullptr);
  68. _source = source;
  69. _filename = _source->get_filename();
  70. if (!open_stream()) {
  71. cleanup();
  72. return;
  73. }
  74. ReMutexHolder av_holder(_av_lock);
  75. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
  76. _frame = av_frame_alloc();
  77. _frame_out = av_frame_alloc();
  78. #else
  79. _frame = avcodec_alloc_frame();
  80. _frame_out = avcodec_alloc_frame();
  81. #endif
  82. if ((_frame == nullptr)||(_frame_out == nullptr)) {
  83. cleanup();
  84. return;
  85. }
  86. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
  87. _packet = av_packet_alloc();
  88. #else
  89. _packet = new AVPacket;
  90. av_init_packet(_packet);
  91. #endif
  92. fetch_packet(0);
  93. fetch_frame(-1);
  94. _initial_dts = _begin_frame;
  95. _current_frame = -1;
  96. _eof_known = false;
  97. _eof_frame = 0;
  98. // Check if we got an alpha format. Please note that some video codecs
  99. // (eg. libvpx) change the pix_fmt after decoding the first frame, which is
  100. // why we didn't do this earlier.
  101. switch (_video_ctx->pix_fmt) {
  102. case AV_PIX_FMT_GRAY8:
  103. _num_components = 1;
  104. _pixel_format = (int)AV_PIX_FMT_GRAY8;
  105. break;
  106. case AV_PIX_FMT_YA8:
  107. _num_components = 2;
  108. _pixel_format = (int)AV_PIX_FMT_YA8;
  109. break;
  110. default:
  111. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(_video_ctx->pix_fmt);
  112. if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0) {
  113. _num_components = 4;
  114. _pixel_format = (int)AV_PIX_FMT_BGRA;
  115. } else {
  116. _num_components = 3;
  117. _pixel_format = (int)AV_PIX_FMT_BGR24;
  118. }
  119. break;
  120. }
  121. #ifdef HAVE_SWSCALE
  122. nassertv(_convert_ctx == nullptr);
  123. _convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt,
  124. _size_x, _size_y, (AVPixelFormat)_pixel_format,
  125. SWS_BILINEAR | SWS_PRINT_INFO, nullptr, nullptr, nullptr);
  126. #endif // HAVE_SWSCALE
  127. #ifdef HAVE_THREADS
  128. set_max_readahead_frames(ffmpeg_max_readahead_frames);
  129. #endif // HAVE_THREADS
  130. }
  131. /**
  132. *
  133. */
  134. FfmpegVideoCursor::
  135. FfmpegVideoCursor(FfmpegVideo *src) :
  136. _max_readahead_frames(0),
  137. _thread_priority(ffmpeg_thread_priority),
  138. _lock("FfmpegVideoCursor::_lock"),
  139. _action_cvar(_lock),
  140. _thread_status(TS_stopped),
  141. _seek_frame(0),
  142. _packet(nullptr),
  143. _format_ctx(nullptr),
  144. _video_ctx(nullptr),
  145. _convert_ctx(nullptr),
  146. _video_index(-1),
  147. _frame(nullptr),
  148. _frame_out(nullptr),
  149. _eof_known(false)
  150. {
  151. init_from(src);
  152. }
  153. /**
  154. *
  155. */
  156. FfmpegVideoCursor::
  157. ~FfmpegVideoCursor() {
  158. cleanup();
  159. }
  160. /**
  161. * Specifies the maximum number of frames that a sub-thread will attempt to
  162. * read ahead of the current frame. Setting this to a nonzero allows the
  163. * video decoding to take place in a sub-thread, which smoothes out the video
  164. * decoding time by spreading it evenly over several frames. Set this number
  165. * larger to increase the buffer between the currently visible frame and the
  166. * first undecoded frame; set it smaller to reduce memory consumption.
  167. *
  168. * Setting this to zero forces the video to be decoded in the main thread. If
  169. * threading is not available in the Panda build, this value is always zero.
  170. */
  171. void FfmpegVideoCursor::
  172. set_max_readahead_frames(int max_readahead_frames) {
  173. #ifndef HAVE_THREADS
  174. if (max_readahead_frames > 0) {
  175. ffmpeg_cat.warning()
  176. << "Couldn't set max_readahead_frames to " << max_readahead_frames
  177. << ": threading not available.\n";
  178. max_readahead_frames = 0;
  179. }
  180. #endif // HAVE_THREADS
  181. _max_readahead_frames = max_readahead_frames;
  182. if (_max_readahead_frames > 0) {
  183. if (_thread_status == TS_stopped) {
  184. start_thread();
  185. }
  186. } else {
  187. if (_thread_status != TS_stopped) {
  188. stop_thread();
  189. }
  190. }
  191. }
  192. /**
  193. * Returns the maximum number of frames that a sub-thread will attempt to read
  194. * ahead of the current frame. See set_max_readahead_frames().
  195. */
  196. int FfmpegVideoCursor::
  197. get_max_readahead_frames() const {
  198. return _max_readahead_frames;
  199. }
  200. /**
  201. * Changes the thread priority of the thread that decodes the ffmpeg video
  202. * stream (if max_readahead_frames is nonzero). Normally you shouldn't mess
  203. * with this, but there may be special cases where a precise balance of CPU
  204. * utilization between the main thread and the various ffmpeg service threads
  205. * may be needed.
  206. */
  207. void FfmpegVideoCursor::
  208. set_thread_priority(ThreadPriority thread_priority) {
  209. if (_thread_priority != thread_priority) {
  210. _thread_priority = thread_priority;
  211. if (is_thread_started()) {
  212. stop_thread();
  213. start_thread();
  214. }
  215. }
  216. }
  217. /**
  218. * Returns the current thread priority of the thread that decodes the ffmpeg
  219. * video stream (if max_readahead_frames is nonzero). See
  220. * set_thread_priority().
  221. */
  222. ThreadPriority FfmpegVideoCursor::
  223. get_thread_priority() const {
  224. return _thread_priority;
  225. }
  226. /**
  227. * Explicitly starts the ffmpeg decoding thread after it has been stopped by a
  228. * call to stop_thread(). The thread is normally started automatically, so
  229. * there is no need to call this method unless you have previously called
  230. * stop_thread() for some reason.
  231. */
  232. void FfmpegVideoCursor::
  233. start_thread() {
  234. MutexHolder holder(_lock);
  235. if (_thread_status == TS_stopped && _max_readahead_frames > 0) {
  236. // Get a unique name for the thread's sync name.
  237. ostringstream strm;
  238. strm << (void *)this;
  239. _sync_name = strm.str();
  240. // Create and start the thread object.
  241. _thread_status = TS_wait;
  242. _thread = new GenericThread(_filename.get_basename(), _sync_name, st_thread_main, this);
  243. if (!_thread->start(_thread_priority, true)) {
  244. // Couldn't start the thread.
  245. _thread = nullptr;
  246. _thread_status = TS_stopped;
  247. }
  248. }
  249. }
  250. /**
  251. * Explicitly stops the ffmpeg decoding thread. There is normally no reason
  252. * to do this unless you want to maintain precise control over what threads
  253. * are consuming CPU resources. Calling this method will make the video
  254. * update in the main thread, regardless of the setting of
  255. * max_readahead_frames, until you call start_thread() again.
  256. */
  257. void FfmpegVideoCursor::
  258. stop_thread() {
  259. if (_thread_status != TS_stopped) {
  260. PT(GenericThread) thread = _thread;
  261. {
  262. MutexHolder holder(_lock);
  263. if (_thread_status != TS_stopped) {
  264. _thread_status = TS_shutdown;
  265. }
  266. _action_cvar.notify();
  267. _thread = nullptr;
  268. }
  269. // Now that we've released the lock, we can join the thread.
  270. thread->join();
  271. }
  272. // This is a good time to clean up all of the allocated frame objects. It's
  273. // not really necessary to be holding the lock, since the thread is gone,
  274. // but we'll grab it anyway just in case someone else starts the thread up
  275. // again.
  276. MutexHolder holder(_lock);
  277. _readahead_frames.clear();
  278. }
  279. /**
  280. * Returns true if the thread has been started, false if not. This will
  281. * always return false if max_readahead_frames is 0.
  282. */
  283. bool FfmpegVideoCursor::
  284. is_thread_started() const {
  285. return (_thread_status != TS_stopped);
  286. }
  287. /**
  288. * See MovieVideoCursor::set_time().
  289. */
  290. bool FfmpegVideoCursor::
  291. set_time(double timestamp, int loop_count) {
  292. int frame = (int)(timestamp / _video_timebase + 0.5);
  293. if (_eof_known) {
  294. if (loop_count == 0) {
  295. frame = frame % (_eof_frame + 1);
  296. } else {
  297. int last_frame = (_eof_frame + 1) * loop_count;
  298. if (frame < last_frame) {
  299. frame = frame % (_eof_frame + 1);
  300. } else {
  301. frame = _eof_frame;
  302. }
  303. }
  304. }
  305. // No point in trying to position before the first frame.
  306. frame = max(frame, _initial_dts);
  307. if (ffmpeg_cat.is_spam() && frame != _current_frame) {
  308. ffmpeg_cat.spam()
  309. << "set_time(" << timestamp << "): " << frame
  310. << ", loop_count = " << loop_count << "\n";
  311. }
  312. _current_frame = frame;
  313. if (_current_frame_buffer != nullptr) {
  314. // If we've previously returned a frame, don't bother asking for a next
  315. // one if that frame is still valid.
  316. return (_current_frame >= _current_frame_buffer->_end_frame ||
  317. _current_frame < _current_frame_buffer->_begin_frame);
  318. }
  319. // If our last request didn't return a frame, try again.
  320. return true;
  321. }
  322. /**
  323. * See MovieVideoCursor::fetch_buffer.
  324. */
  325. PT(MovieVideoCursor::Buffer) FfmpegVideoCursor::
  326. fetch_buffer() {
  327. MutexHolder holder(_lock);
  328. // If there was an error at any point, just return NULL.
  329. if (_format_ctx == nullptr) {
  330. return nullptr;
  331. }
  332. PT(FfmpegBuffer) frame;
  333. if (_thread_status == TS_stopped) {
  334. // Non-threaded case. Just get the next frame directly.
  335. advance_to_frame(_current_frame);
  336. if (_frame_ready) {
  337. frame = do_alloc_frame();
  338. export_frame(frame);
  339. }
  340. } else {
  341. // Threaded case. Wait for the thread to serve up the required frames.
  342. if (!_readahead_frames.empty()) {
  343. frame = _readahead_frames.front();
  344. _readahead_frames.pop_front();
  345. _action_cvar.notify();
  346. while (frame->_end_frame < _current_frame && !_readahead_frames.empty()) {
  347. // This frame is too old. Discard it.
  348. if (ffmpeg_cat.is_debug()) {
  349. ffmpeg_cat.debug()
  350. << "ffmpeg for " << _filename.get_basename()
  351. << " at frame " << _current_frame << ", discarding frame at "
  352. << frame->_begin_frame << "\n";
  353. }
  354. frame = _readahead_frames.front();
  355. _readahead_frames.pop_front();
  356. }
  357. if (frame->_begin_frame > _current_frame) {
  358. // This frame is too new. Empty all remaining frames and seek
  359. // backwards.
  360. if (ffmpeg_cat.is_debug()) {
  361. ffmpeg_cat.debug()
  362. << "ffmpeg for " << _filename.get_basename()
  363. << " at frame " << _current_frame << ", encountered too-new frame at "
  364. << frame->_begin_frame << "\n";
  365. }
  366. do_clear_all_frames();
  367. if (_thread_status == TS_wait || _thread_status == TS_seek || _thread_status == TS_readahead) {
  368. _thread_status = TS_seek;
  369. _seek_frame = _current_frame;
  370. _action_cvar.notify();
  371. }
  372. }
  373. }
  374. if (frame == nullptr || frame->_end_frame < _current_frame) {
  375. // No frame available, or the frame is too old. Seek.
  376. if (_thread_status == TS_wait || _thread_status == TS_seek || _thread_status == TS_readahead) {
  377. _thread_status = TS_seek;
  378. _seek_frame = _current_frame;
  379. _action_cvar.notify();
  380. }
  381. }
  382. }
  383. if (frame != nullptr) {
  384. bool too_old = (frame->_end_frame < _current_frame && !ffmpeg_show_seek_frames);
  385. bool too_new = frame->_begin_frame > _current_frame;
  386. if (too_old || too_new) {
  387. // The frame is too old or too new. Just recycle it.
  388. frame = nullptr;
  389. }
  390. }
  391. if (frame != nullptr) {
  392. _current_frame_buffer = frame;
  393. if (ffmpeg_cat.is_debug()) {
  394. ffmpeg_cat.debug()
  395. << "ffmpeg for " << _filename.get_basename()
  396. << " at frame " << _current_frame << ", returning frame at "
  397. << frame->_begin_frame << "\n";
  398. }
  399. } else {
  400. if (ffmpeg_cat.is_debug()) {
  401. ffmpeg_cat.debug()
  402. << "ffmpeg for " << _filename.get_basename()
  403. << " at frame " << _current_frame << ", returning NULL\n";
  404. }
  405. }
  406. return frame.p();
  407. }
  408. /**
  409. * May be called by a derived class to allocate a new Buffer object.
  410. */
  411. PT(MovieVideoCursor::Buffer) FfmpegVideoCursor::
  412. make_new_buffer() {
  413. PT(FfmpegBuffer) frame = new FfmpegBuffer(size_x() * size_y() * get_num_components(), _video_timebase);
  414. return frame.p();
  415. }
  416. /**
  417. * Opens the stream for the first time, or when needed internally.
  418. */
  419. bool FfmpegVideoCursor::
  420. open_stream() {
  421. nassertr(!_ffvfile.is_open(), false);
  422. // Hold the global lock while we open the file and create avcodec objects.
  423. ReMutexHolder av_holder(_av_lock);
  424. if (!_source->get_subfile_info().is_empty()) {
  425. // Read a subfile.
  426. if (!_ffvfile.open_subfile(_source->get_subfile_info())) {
  427. ffmpeg_cat.info()
  428. << "Couldn't open " << _source->get_subfile_info() << "\n";
  429. close_stream();
  430. return false;
  431. }
  432. } else {
  433. // Read a filename.
  434. if (!_ffvfile.open_vfs(_filename)) {
  435. ffmpeg_cat.info()
  436. << "Couldn't open " << _filename << "\n";
  437. close_stream();
  438. return false;
  439. }
  440. }
  441. nassertr(_format_ctx == nullptr, false);
  442. _format_ctx = _ffvfile.get_format_context();
  443. nassertr(_format_ctx != nullptr, false);
  444. if (avformat_find_stream_info(_format_ctx, nullptr) < 0) {
  445. ffmpeg_cat.info()
  446. << "Couldn't find stream info\n";
  447. close_stream();
  448. return false;
  449. }
  450. nassertr(_video_ctx == nullptr, false);
  451. // As of libavformat version 57.41.100, AVStream.codec is deprecated in favor
  452. // of AVStream.codecpar. Fortunately, the two structures have
  453. // similarly-named members, so we can just switch out the declaration.
  454. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100)
  455. AVCodecParameters *codecpar;
  456. #else
  457. AVCodecContext *codecpar;
  458. #endif
  459. // Find the video stream
  460. AVStream *stream = nullptr;
  461. for (int i = 0; i < (int)_format_ctx->nb_streams; ++i) {
  462. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100)
  463. codecpar = _format_ctx->streams[i]->codecpar;
  464. #else
  465. codecpar = _format_ctx->streams[i]->codec;
  466. #endif
  467. if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
  468. _video_index = i;
  469. stream = _format_ctx->streams[i];
  470. break;
  471. }
  472. }
  473. if (stream == nullptr) {
  474. ffmpeg_cat.info()
  475. << "Couldn't find stream\n";
  476. close_stream();
  477. return false;
  478. }
  479. _video_timebase = av_q2d(stream->time_base);
  480. _min_fseek = (int)(3.0 / _video_timebase);
  481. AVCodec *pVideoCodec = nullptr;
  482. if (ffmpeg_prefer_libvpx) {
  483. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0)
  484. if (codecpar->codec_id == AV_CODEC_ID_VP9) {
  485. pVideoCodec = avcodec_find_decoder_by_name("libvpx-vp9");
  486. } else
  487. #endif
  488. if (codecpar->codec_id == AV_CODEC_ID_VP8) {
  489. pVideoCodec = avcodec_find_decoder_by_name("libvpx");
  490. }
  491. }
  492. if (pVideoCodec == nullptr) {
  493. pVideoCodec = avcodec_find_decoder(codecpar->codec_id);
  494. }
  495. if (pVideoCodec == nullptr) {
  496. ffmpeg_cat.info()
  497. << "Couldn't find codec\n";
  498. close_stream();
  499. return false;
  500. }
  501. _video_ctx = avcodec_alloc_context3(pVideoCodec);
  502. if (_video_ctx == nullptr) {
  503. ffmpeg_cat.info()
  504. << "Couldn't allocate _video_ctx\n";
  505. close_stream();
  506. return false;
  507. }
  508. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100)
  509. avcodec_parameters_to_context(_video_ctx, codecpar);
  510. #else
  511. avcodec_copy_context(_video_ctx, codecpar);
  512. #endif
  513. if (avcodec_open2(_video_ctx, pVideoCodec, nullptr) < 0) {
  514. ffmpeg_cat.info()
  515. << "Couldn't open codec\n";
  516. close_stream();
  517. return false;
  518. }
  519. _size_x = _video_ctx->width;
  520. _size_y = _video_ctx->height;
  521. _num_components = 3;
  522. _length = (double)_format_ctx->duration / (double)AV_TIME_BASE;
  523. _can_seek = true;
  524. _can_seek_fast = true;
  525. return true;
  526. }
  527. /**
  528. * Closes the stream, during cleanup or when needed internally.
  529. */
  530. void FfmpegVideoCursor::
  531. close_stream() {
  532. // Hold the global lock while we free avcodec objects.
  533. ReMutexHolder av_holder(_av_lock);
  534. if ((_video_ctx)&&(_video_ctx->codec)) {
  535. avcodec_close(_video_ctx);
  536. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0)
  537. avcodec_free_context(&_video_ctx);
  538. #else
  539. delete _video_ctx;
  540. #endif
  541. }
  542. _video_ctx = nullptr;
  543. _ffvfile.close();
  544. _format_ctx = nullptr;
  545. _video_index = -1;
  546. }
  547. /**
  548. * Reset to a standard inactive state.
  549. */
  550. void FfmpegVideoCursor::
  551. cleanup() {
  552. stop_thread();
  553. close_stream();
  554. ReMutexHolder av_holder(_av_lock);
  555. #ifdef HAVE_SWSCALE
  556. if (_convert_ctx != nullptr) {
  557. sws_freeContext(_convert_ctx);
  558. }
  559. _convert_ctx = nullptr;
  560. #endif // HAVE_SWSCALE
  561. if (_frame) {
  562. av_free(_frame);
  563. _frame = nullptr;
  564. }
  565. if (_frame_out) {
  566. _frame_out->data[0] = nullptr;
  567. av_free(_frame_out);
  568. _frame_out = nullptr;
  569. }
  570. if (_packet) {
  571. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
  572. av_packet_free(&_packet);
  573. #else
  574. if (_packet->data) {
  575. av_free_packet(_packet);
  576. }
  577. delete _packet;
  578. _packet = nullptr;
  579. #endif
  580. }
  581. }
  582. /**
  583. * The thread main function, static version (for passing to GenericThread).
  584. */
  585. void FfmpegVideoCursor::
  586. st_thread_main(void *self) {
  587. ((FfmpegVideoCursor *)self)->thread_main();
  588. }
  589. /**
  590. * The thread main function.
  591. */
  592. void FfmpegVideoCursor::
  593. thread_main() {
  594. if (ffmpeg_cat.is_spam()) {
  595. ffmpeg_cat.spam()
  596. << "ffmpeg thread for " << _filename.get_basename() << " starting.\n";
  597. }
  598. // First, push the first frame onto the readahead queue.
  599. if (_frame_ready) {
  600. PT(FfmpegBuffer) frame = do_alloc_frame();
  601. export_frame(frame);
  602. MutexHolder holder(_lock);
  603. _readahead_frames.push_back(frame);
  604. }
  605. // Now repeatedly wait for something interesting to do, until we're told to
  606. // shut down.
  607. MutexHolder holder(_lock);
  608. while (_thread_status != TS_shutdown) {
  609. nassertv(_thread_status != TS_stopped);
  610. _action_cvar.wait();
  611. while (do_poll()) {
  612. // Keep doing stuff as long as there's something to do.
  613. _lock.release();
  614. PStatClient::thread_tick(_sync_name);
  615. Thread::consider_yield();
  616. _lock.acquire();
  617. }
  618. }
  619. _thread_status = TS_stopped;
  620. if (ffmpeg_cat.is_spam()) {
  621. ffmpeg_cat.spam()
  622. << "ffmpeg thread for " << _filename.get_basename() << " stopped.\n";
  623. }
  624. }
  625. /**
  626. * Called within the sub-thread. Assumes the lock is already held. If there
  627. * is something for the thread to do, does it and returns true. If there is
  628. * nothing for the thread to do, returns false.
  629. */
  630. bool FfmpegVideoCursor::
  631. do_poll() {
  632. switch (_thread_status) {
  633. case TS_stopped:
  634. case TS_seeking:
  635. // This shouldn't be possible while the thread is running.
  636. nassertr(false, false);
  637. return false;
  638. case TS_wait:
  639. // The video hasn't started playing yet.
  640. return false;
  641. case TS_readahead:
  642. if ((int)_readahead_frames.size() < _max_readahead_frames) {
  643. // Time to read the next frame.
  644. PT(FfmpegBuffer) frame = do_alloc_frame();
  645. nassertr(frame != nullptr, false);
  646. _lock.release();
  647. fetch_frame(-1);
  648. if (_frame_ready) {
  649. export_frame(frame);
  650. _lock.acquire();
  651. _readahead_frames.push_back(frame);
  652. } else {
  653. // No frame.
  654. _lock.acquire();
  655. }
  656. return true;
  657. }
  658. // No room for the next frame yet. Wait for more.
  659. return false;
  660. case TS_seek:
  661. // Seek to a specific frame.
  662. {
  663. int seek_frame = _seek_frame;
  664. _thread_status = TS_seeking;
  665. PT(FfmpegBuffer) frame = do_alloc_frame();
  666. nassertr(frame != nullptr, false);
  667. _lock.release();
  668. advance_to_frame(seek_frame);
  669. if (_frame_ready) {
  670. export_frame(frame);
  671. _lock.acquire();
  672. do_clear_all_frames();
  673. _readahead_frames.push_back(frame);
  674. } else {
  675. _lock.acquire();
  676. do_clear_all_frames();
  677. }
  678. if (_thread_status == TS_seeking) {
  679. // After seeking, we automatically transition to readahead.
  680. _thread_status = TS_readahead;
  681. }
  682. }
  683. return true;
  684. case TS_shutdown:
  685. // Time to stop the thread.
  686. return false;
  687. }
  688. return false;
  689. }
  690. /**
  691. * Allocates a new Buffer object. Assumes the lock is held.
  692. */
  693. PT(FfmpegVideoCursor::FfmpegBuffer) FfmpegVideoCursor::
  694. do_alloc_frame() {
  695. PT(Buffer) buffer = make_new_buffer();
  696. return (FfmpegBuffer *)buffer.p();
  697. }
  698. /**
  699. * Empties the entire readahead_frames queue. Assumes the lock is held.
  700. */
  701. void FfmpegVideoCursor::
  702. do_clear_all_frames() {
  703. _readahead_frames.clear();
  704. }
  705. /**
  706. * Called within the sub-thread. Fetches a video packet and stores it in the
  707. * packet0 buffer. Sets packet_frame to the packet's timestamp. If a packet
  708. * could not be read, the packet is cleared and the packet_frame is set to the
  709. * specified default value. Returns true on failure (such as the end of the
  710. * video), or false on success.
  711. */
  712. bool FfmpegVideoCursor::
  713. fetch_packet(int default_frame) {
  714. if (ffmpeg_global_lock) {
  715. ReMutexHolder av_holder(_av_lock);
  716. return do_fetch_packet(default_frame);
  717. } else {
  718. return do_fetch_packet(default_frame);
  719. }
  720. }
  721. /**
  722. * As above, with the ffmpeg global lock held (if configured on).
  723. */
  724. bool FfmpegVideoCursor::
  725. do_fetch_packet(int default_frame) {
  726. if (_packet->data) {
  727. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
  728. av_packet_unref(_packet);
  729. #else
  730. av_free_packet(_packet);
  731. #endif
  732. }
  733. while (av_read_frame(_format_ctx, _packet) >= 0) {
  734. if (_packet->stream_index == _video_index) {
  735. _packet_frame = _packet->dts;
  736. return false;
  737. }
  738. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
  739. av_packet_unref(_packet);
  740. #else
  741. av_free_packet(_packet);
  742. #endif
  743. }
  744. _packet->data = nullptr;
  745. if (!_eof_known && default_frame != 0) {
  746. _eof_frame = _packet_frame;
  747. _eof_known = true;
  748. }
  749. if (ffmpeg_cat.is_spam()) {
  750. if (_eof_known) {
  751. ffmpeg_cat.spam()
  752. << "end of video at frame " << _eof_frame << "\n";
  753. } else {
  754. ffmpeg_cat.spam()
  755. << "end of video\n";
  756. }
  757. }
  758. _packet_frame = default_frame;
  759. return true;
  760. }
  761. /**
  762. * Called within the sub-thread. Slides forward until the indicated frame,
  763. * then fetches a frame from the stream and stores it in the frame buffer.
  764. * Sets _begin_frame and _end_frame to indicate the extents of the frame.
  765. * Sets _frame_ready true to indicate a frame is now available, or false if it
  766. * is not (for instance, because the end of the video was reached).
  767. */
  768. void FfmpegVideoCursor::
  769. fetch_frame(int frame) {
  770. PStatTimer timer(_fetch_buffer_pcollector);
  771. int finished = 0;
  772. if (_packet_frame <= frame) {
  773. finished = 0;
  774. // Get the next packet. The first packet beyond the frame we're looking
  775. // for marks the point to stop.
  776. while (_packet_frame <= frame) {
  777. PStatTimer timer(_seek_pcollector);
  778. // Decode the previous packet, and get the next one.
  779. decode_frame(finished);
  780. _begin_frame = _packet_frame;
  781. if (fetch_packet(frame)) {
  782. _end_frame = _packet_frame;
  783. _frame_ready = false;
  784. return;
  785. }
  786. }
  787. } else {
  788. // Just get the next frame.
  789. finished = 0;
  790. while (!finished && _packet->data) {
  791. decode_frame(finished);
  792. _begin_frame = _packet_frame;
  793. fetch_packet(_begin_frame + 1);
  794. }
  795. }
  796. _end_frame = _packet_frame;
  797. _frame_ready = true;
  798. }
  799. /**
  800. * Called within the sub-thread. Decodes the data in the specified packet
  801. * into _frame.
  802. */
  803. void FfmpegVideoCursor::
  804. decode_frame(int &finished) {
  805. if (ffmpeg_global_lock) {
  806. ReMutexHolder av_holder(_av_lock);
  807. do_decode_frame(finished);
  808. } else {
  809. do_decode_frame(finished);
  810. }
  811. }
  812. /**
  813. * As above, with the ffmpeg global lock held (if configured on).
  814. */
  815. void FfmpegVideoCursor::
  816. do_decode_frame(int &finished) {
  817. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100)
  818. // While the audio cursor has a really nice async loop for decoding, we
  819. // don't really do that much with video since we're already delegated to
  820. // another thread here. This is just to silence the deprecation warning
  821. // on avcodec_decode_video2.
  822. avcodec_send_packet(_video_ctx, _packet);
  823. int ret = avcodec_receive_frame(_video_ctx, _frame);
  824. finished = (ret == 0);
  825. #else
  826. avcodec_decode_video2(_video_ctx, _frame, &finished, _packet);
  827. #endif
  828. }
  829. /**
  830. * Called within the sub-thread. Seeks to a target location. Afterward, the
  831. * packet_frame is guaranteed to be less than or equal to the specified frame.
  832. */
  833. void FfmpegVideoCursor::
  834. seek(int frame, bool backward) {
  835. PStatTimer timer(_seek_pcollector);
  836. if (ffmpeg_support_seek) {
  837. if (ffmpeg_global_lock) {
  838. ReMutexHolder av_holder(_av_lock);
  839. do_seek(frame, backward);
  840. } else {
  841. do_seek(frame, backward);
  842. }
  843. } else {
  844. // If seeking isn't supported, close-and-reopen.
  845. if (backward) {
  846. reset_stream();
  847. }
  848. }
  849. }
  850. /**
  851. * As above, with the ffmpeg global lock held (if configured on). Also only
  852. * if ffmpeg-support-seek is on.
  853. */
  854. void FfmpegVideoCursor::
  855. do_seek(int frame, bool backward) {
  856. int64_t target_ts = (int64_t)frame;
  857. if (target_ts < (int64_t)(_initial_dts)) {
  858. // Attempts to seek before the first packet will fail.
  859. target_ts = _initial_dts;
  860. }
  861. int flags = 0;
  862. if (backward) {
  863. flags = AVSEEK_FLAG_BACKWARD;
  864. }
  865. if (av_seek_frame(_format_ctx, _video_index, target_ts, flags) < 0) {
  866. if (ffmpeg_cat.is_spam()) {
  867. ffmpeg_cat.spam()
  868. << "Seek failure.\n";
  869. }
  870. if (backward) {
  871. // Now try to seek forward.
  872. reset_stream();
  873. seek(frame, false);
  874. return;
  875. }
  876. // Try a binary search to get a little closer.
  877. if (binary_seek(_initial_dts, frame, frame, 1) < 0) {
  878. if (ffmpeg_cat.is_spam()) {
  879. ffmpeg_cat.spam()
  880. << "Seek double failure.\n";
  881. }
  882. reset_stream();
  883. return;
  884. }
  885. }
  886. fetch_packet(0);
  887. fetch_frame(-1);
  888. }
  889. /**
  890. * Casts about within the stream for a reasonably-close frame to seek to.
  891. * We're trying to get as close as possible to target_frame.
  892. */
  893. int FfmpegVideoCursor::
  894. binary_seek(int min_frame, int max_frame, int target_frame, int num_iterations) {
  895. int try_frame = (min_frame + max_frame) / 2;
  896. if (num_iterations > 5 || try_frame >= max_frame) {
  897. // Success.
  898. return 0;
  899. }
  900. if (av_seek_frame(_format_ctx, _video_index, try_frame, AVSEEK_FLAG_BACKWARD) < 0) {
  901. // Failure. Try lower.
  902. if (binary_seek(min_frame, try_frame - 1, target_frame, num_iterations + 1) < 0) {
  903. return -1;
  904. }
  905. } else {
  906. // Success. Try higher.
  907. if (binary_seek(try_frame + 1, max_frame, target_frame, num_iterations + 1) < 0) {
  908. return -1;
  909. }
  910. }
  911. return 0;
  912. }
  913. /**
  914. * Resets the stream to its initial, first-opened state by closing and re-
  915. * opening it.
  916. */
  917. void FfmpegVideoCursor::
  918. reset_stream() {
  919. if (ffmpeg_cat.is_spam()) {
  920. ffmpeg_cat.spam()
  921. << "Resetting ffmpeg stream.\n";
  922. }
  923. close_stream();
  924. if (!open_stream()) {
  925. ffmpeg_cat.error()
  926. << "Stream error, invalidating movie.\n";
  927. cleanup();
  928. return;
  929. }
  930. fetch_packet(0);
  931. fetch_frame(-1);
  932. }
  933. /**
  934. * Called within the sub-thread. Advance until the specified frame is in the
  935. * export buffer.
  936. */
  937. void FfmpegVideoCursor::
  938. advance_to_frame(int frame) {
  939. PStatTimer timer(_fetch_buffer_pcollector);
  940. if (frame < _begin_frame) {
  941. // Frame is in the past.
  942. if (ffmpeg_cat.is_spam()) {
  943. ffmpeg_cat.spam()
  944. << "Seeking backward to " << frame << " from " << _begin_frame << "\n";
  945. }
  946. seek(frame, true);
  947. if (_begin_frame > frame) {
  948. if (ffmpeg_cat.is_spam()) {
  949. ffmpeg_cat.spam()
  950. << "Ended up at " << _begin_frame << ", not far enough back!\n";
  951. }
  952. reset_stream();
  953. if (ffmpeg_cat.is_spam()) {
  954. ffmpeg_cat.spam()
  955. << "Reseek to 0, got " << _begin_frame << "\n";
  956. }
  957. }
  958. if (frame > _end_frame) {
  959. if (ffmpeg_cat.is_spam()) {
  960. ffmpeg_cat.spam()
  961. << "Now sliding forward to " << frame << " from " << _begin_frame << "\n";
  962. }
  963. fetch_frame(frame);
  964. }
  965. } else if (frame < _end_frame) {
  966. // Frame is in the present: already have the frame.
  967. if (ffmpeg_cat.is_spam()) {
  968. ffmpeg_cat.spam()
  969. << "Currently have " << frame << " within " << _begin_frame << " .. " << _end_frame << "\n";
  970. }
  971. } else if (frame < _end_frame + _min_fseek) {
  972. // Frame is in the near future.
  973. if (ffmpeg_cat.is_spam()) {
  974. ffmpeg_cat.spam()
  975. << "Sliding forward to " << frame << " from " << _begin_frame << "\n";
  976. }
  977. fetch_frame(frame);
  978. } else {
  979. // Frame is in the far future. Seek forward, then read. There's a danger
  980. // here: because keyframes are spaced unpredictably, trying to seek
  981. // forward could actually move us backward in the stream! This must be
  982. // avoided. So the rule is, try the seek. If it hurts us by moving us
  983. // backward, we increase the minimum threshold distance for forward-
  984. // seeking in the future.
  985. if (ffmpeg_cat.is_spam()) {
  986. ffmpeg_cat.spam()
  987. << "Jumping forward to " << frame << " from " << _begin_frame << "\n";
  988. }
  989. int base = _begin_frame;
  990. seek(frame, false);
  991. if (_begin_frame < base) {
  992. _min_fseek += (base - _begin_frame);
  993. if (ffmpeg_cat.is_spam()) {
  994. ffmpeg_cat.spam()
  995. << "Wrong way! Increasing _min_fseek to " << _min_fseek << "\n";
  996. }
  997. }
  998. if (frame > _end_frame) {
  999. if (ffmpeg_cat.is_spam()) {
  1000. ffmpeg_cat.spam()
  1001. << "Correcting, sliding forward to " << frame << " from " << _begin_frame << "\n";
  1002. }
  1003. fetch_frame(frame);
  1004. }
  1005. }
  1006. if (ffmpeg_cat.is_spam()) {
  1007. ffmpeg_cat.spam()
  1008. << "Wanted " << frame << ", got " << _begin_frame << "\n";
  1009. }
  1010. }
  1011. /**
  1012. * Called within the sub-thread. Exports the contents of the frame buffer
  1013. * into the indicated target buffer.
  1014. */
  1015. void FfmpegVideoCursor::
  1016. export_frame(FfmpegBuffer *buffer) {
  1017. PStatTimer timer(_export_frame_pcollector);
  1018. if (!_frame_ready) {
  1019. // No frame data ready, just fill with black.
  1020. if (ffmpeg_cat.is_spam()) {
  1021. ffmpeg_cat.spam()
  1022. << "ffmpeg for " << _filename.get_basename()
  1023. << ", no frame available.\n";
  1024. }
  1025. memset(buffer->_block, 0, buffer->_block_size);
  1026. return;
  1027. }
  1028. _frame_out->data[0] = buffer->_block + ((_size_y - 1) * _size_x * _num_components);
  1029. _frame_out->linesize[0] = _size_x * -_num_components;
  1030. buffer->_begin_frame = _begin_frame;
  1031. buffer->_end_frame = _end_frame;
  1032. if (ffmpeg_global_lock) {
  1033. ReMutexHolder av_holder(_av_lock);
  1034. #ifdef HAVE_SWSCALE
  1035. nassertv(_convert_ctx != nullptr && _frame != nullptr && _frame_out != nullptr);
  1036. sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
  1037. #else
  1038. img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
  1039. (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
  1040. #endif
  1041. } else {
  1042. #ifdef HAVE_SWSCALE
  1043. nassertv(_convert_ctx != nullptr && _frame != nullptr && _frame_out != nullptr);
  1044. sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
  1045. #else
  1046. img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
  1047. (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
  1048. #endif
  1049. }
  1050. }
  1051. /**
  1052. * Tells the BamReader how to create objects of type FfmpegVideo.
  1053. */
  1054. void FfmpegVideoCursor::
  1055. register_with_read_factory() {
  1056. BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
  1057. }
  1058. /**
  1059. * Writes the contents of this object to the datagram for shipping out to a
  1060. * Bam file.
  1061. */
  1062. void FfmpegVideoCursor::
  1063. write_datagram(BamWriter *manager, Datagram &dg) {
  1064. MovieVideoCursor::write_datagram(manager, dg);
  1065. // No need to write any additional data here--all of it comes implicitly
  1066. // from the underlying MovieVideo, which we process in finalize().
  1067. }
  1068. /**
  1069. * Called by the BamReader to perform any final actions needed for setting up
  1070. * the object after all objects have been read and all pointers have been
  1071. * completed.
  1072. */
  1073. void FfmpegVideoCursor::
  1074. finalize(BamReader *) {
  1075. if (_source != nullptr) {
  1076. FfmpegVideo *video;
  1077. DCAST_INTO_V(video, _source);
  1078. init_from(video);
  1079. }
  1080. }
  1081. /**
  1082. * This function is called by the BamReader's factory when a new object of
  1083. * type FfmpegVideo is encountered in the Bam file. It should create the
  1084. * FfmpegVideo and extract its information from the file.
  1085. */
  1086. TypedWritable *FfmpegVideoCursor::
  1087. make_from_bam(const FactoryParams &params) {
  1088. FfmpegVideoCursor *video = new FfmpegVideoCursor;
  1089. DatagramIterator scan;
  1090. BamReader *manager;
  1091. parse_params(params, scan, manager);
  1092. video->fillin(scan, manager);
  1093. return video;
  1094. }
  1095. /**
  1096. * This internal function is called by make_from_bam to read in all of the
  1097. * relevant data from the BamFile for the new FfmpegVideo.
  1098. */
  1099. void FfmpegVideoCursor::
  1100. fillin(DatagramIterator &scan, BamReader *manager) {
  1101. MovieVideoCursor::fillin(scan, manager);
  1102. // The MovieVideoCursor gets the underlying MovieVideo pointer. We need a
  1103. // finalize callback so we can initialize ourselves once that has been read
  1104. // completely.
  1105. manager->register_finalize(this);
  1106. }
  1107. /**
  1108. * Used to sort different buffers to ensure they correspond to the same source
  1109. * frame, particularly important when synchronizing the different pages of a
  1110. * multi-page texture.
  1111. *
  1112. * Returns 0 if the two buffers are of the same frame, <0 if this one comes
  1113. * earlier than the other one, and >0 if the other one comes earlier.
  1114. */
  1115. int FfmpegVideoCursor::FfmpegBuffer::
  1116. compare_timestamp(const Buffer *other) const {
  1117. const FfmpegBuffer *fother;
  1118. DCAST_INTO_R(fother, other, 0);
  1119. if (_end_frame * _video_timebase <= fother->_begin_frame * fother->_video_timebase) {
  1120. return -1;
  1121. } else if (_begin_frame * _video_timebase >= fother->_end_frame * fother->_video_timebase) {
  1122. return 1;
  1123. }
  1124. return 0;
  1125. }
  1126. /**
  1127. * Returns the nearest timestamp value of this particular buffer. Ideally,
  1128. * MovieVideoCursor::set_time() for this timestamp would return this buffer
  1129. * again. This need be defined only if compare_timestamp() is also defined.
  1130. */
  1131. double FfmpegVideoCursor::FfmpegBuffer::
  1132. get_timestamp() const {
  1133. int mid_frame = (_begin_frame + _end_frame - 1) / 2;
  1134. return mid_frame * _video_timebase;
  1135. }