2222extern " C" {
2323 #include " libavcodec/avcodec.h"
2424 #include " libavformat/avformat.h"
25+ #include " libavutil/pixdesc.h"
2526#ifdef HAVE_SWSCALE
2627 #include " libswscale/swscale.h"
2728#endif
@@ -35,11 +36,16 @@ PStatCollector FfmpegVideoCursor::_fetch_buffer_pcollector("*:FFMPEG Video Decod
3536PStatCollector FfmpegVideoCursor::_seek_pcollector (" *:FFMPEG Video Decoding:Seek" );
3637PStatCollector FfmpegVideoCursor::_export_frame_pcollector (" *:FFMPEG Convert Video to BGR" );
3738
38-
3939#if LIBAVFORMAT_VERSION_MAJOR < 53
4040 #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
4141#endif
4242
43+ #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100)
44+ #define AV_PIX_FMT_NONE PIX_FMT_NONE
45+ #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
46+ #define AV_PIX_FMT_BGRA PIX_FMT_BGRA
47+ #endif
48+
4349/* *
4450 * This constructor is only used when reading from a bam file.
4551 */
@@ -55,6 +61,7 @@ FfmpegVideoCursor() :
5561 _format_ctx(NULL ),
5662 _video_ctx(NULL ),
5763 _convert_ctx(NULL ),
64+ _pixel_format(AV_PIX_FMT_NONE),
5865 _video_index(-1 ),
5966 _frame(NULL ),
6067 _frame_out(NULL ),
@@ -80,17 +87,6 @@ init_from(FfmpegVideo *source) {
8087
8188 ReMutexHolder av_holder (_av_lock);
8289
83- #ifdef HAVE_SWSCALE
84- nassertv (_convert_ctx == NULL );
85- _convert_ctx = sws_getContext (_size_x, _size_y, _video_ctx->pix_fmt ,
86- #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 74, 100)
87- _size_x, _size_y, AV_PIX_FMT_BGR24,
88- #else
89- _size_x, _size_y, PIX_FMT_BGR24,
90- #endif
91- SWS_BILINEAR | SWS_PRINT_INFO, NULL , NULL , NULL );
92- #endif // HAVE_SWSCALE
93-
9490#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
9591 _frame = av_frame_alloc ();
9692 _frame_out = av_frame_alloc ();
@@ -115,6 +111,25 @@ init_from(FfmpegVideo *source) {
115111 _eof_known = false ;
116112 _eof_frame = 0 ;
117113
114+ // Check if we got an alpha format. Please note that some video codecs
115+ // (eg. libvpx) change the pix_fmt after decoding the first frame, which is
116+ // why we didn't do this earlier.
117+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get (_video_ctx->pix_fmt );
118+ if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0 ) {
119+ _num_components = 4 ;
120+ _pixel_format = AV_PIX_FMT_BGRA;
121+ } else {
122+ _num_components = 3 ;
123+ _pixel_format = AV_PIX_FMT_BGR24;
124+ }
125+
126+ #ifdef HAVE_SWSCALE
127+ nassertv (_convert_ctx == NULL );
128+ _convert_ctx = sws_getContext (_size_x, _size_y, _video_ctx->pix_fmt ,
129+ _size_x, _size_y, _pixel_format,
130+ SWS_BILINEAR | SWS_PRINT_INFO, NULL , NULL , NULL );
131+ #endif // HAVE_SWSCALE
132+
118133#ifdef HAVE_THREADS
119134 set_max_readahead_frames (ffmpeg_max_readahead_frames);
120135#endif // HAVE_THREADS
@@ -495,7 +510,17 @@ open_stream() {
495510 return false ;
496511 }
497512
498- AVCodec *pVideoCodec = avcodec_find_decoder (_video_ctx->codec_id );
513+ AVCodec *pVideoCodec = NULL ;
514+ if (ffmpeg_prefer_libvpx) {
515+ if (_video_ctx->codec_id == AV_CODEC_ID_VP9) {
516+ pVideoCodec = avcodec_find_decoder_by_name (" libvpx-vp9" );
517+ } else if (_video_ctx->codec_id == AV_CODEC_ID_VP8) {
518+ pVideoCodec = avcodec_find_decoder_by_name (" libvpx" );
519+ }
520+ }
521+ if (pVideoCodec == NULL ) {
522+ pVideoCodec = avcodec_find_decoder (_video_ctx->codec_id );
523+ }
499524 if (pVideoCodec == NULL ) {
500525 ffmpeg_cat.info ()
501526 << " Couldn't find codec\n " ;
@@ -515,7 +540,7 @@ open_stream() {
515540
516541 _size_x = _video_ctx->width ;
517542 _size_y = _video_ctx->height ;
518- _num_components = 3 ; // Don't know how to implement RGBA movies yet.
543+ _num_components = 3 ;
519544 _length = (double )_format_ctx->duration / (double )AV_TIME_BASE;
520545 _can_seek = true ;
521546 _can_seek_fast = true ;
@@ -1075,8 +1100,8 @@ export_frame(FfmpegBuffer *buffer) {
10751100 return ;
10761101 }
10771102
1078- _frame_out->data [0 ] = buffer->_block + ((_size_y - 1 ) * _size_x * 3 );
1079- _frame_out->linesize [0 ] = _size_x * -3 ;
1103+ _frame_out->data [0 ] = buffer->_block + ((_size_y - 1 ) * _size_x * _num_components );
1104+ _frame_out->linesize [0 ] = _size_x * -_num_components ;
10801105 buffer->_begin_frame = _begin_frame;
10811106 buffer->_end_frame = _end_frame;
10821107
@@ -1086,15 +1111,15 @@ export_frame(FfmpegBuffer *buffer) {
10861111 nassertv (_convert_ctx != NULL && _frame != NULL && _frame_out != NULL );
10871112 sws_scale (_convert_ctx, _frame->data , _frame->linesize , 0 , _size_y, _frame_out->data , _frame_out->linesize );
10881113#else
1089- img_convert ((AVPicture *)_frame_out, PIX_FMT_BGR24 ,
1114+ img_convert ((AVPicture *)_frame_out, _pixel_format ,
10901115 (AVPicture *)_frame, _video_ctx->pix_fmt , _size_x, _size_y);
10911116#endif
10921117 } else {
10931118#ifdef HAVE_SWSCALE
10941119 nassertv (_convert_ctx != NULL && _frame != NULL && _frame_out != NULL );
10951120 sws_scale (_convert_ctx, _frame->data , _frame->linesize , 0 , _size_y, _frame_out->data , _frame_out->linesize );
10961121#else
1097- img_convert ((AVPicture *)_frame_out, PIX_FMT_BGR24 ,
1122+ img_convert ((AVPicture *)_frame_out, _pixel_format ,
10981123 (AVPicture *)_frame, _video_ctx->pix_fmt , _size_x, _size_y);
10991124#endif
11001125 }
0 commit comments