try_decode_video_frame
static int try_decode_video_frame ( AVCodecContext * codec_ctx, AVPacket * pkt, int decode)
{ int ret = 0 ; int got_frame = 0 ; AVFrame * frame = NULL ; int skip_frame = codec_ctx-> skip_frame; if ( ! avcodec_is_open ( codec_ctx) ) { const AVCodec * codec = avcodec_find_decoder ( codec_ctx-> codec_id) ; ret = avcodec_open2 ( codec_ctx, codec, NULL ) ; if ( ret < 0 ) { av_log ( codec_ctx, AV_LOG_ERROR, "Failed to open codec\n" ) ; goto end; } } frame = av_frame_alloc ( ) ; if ( ! frame) { av_log ( NULL , AV_LOG_ERROR, "Failed to allocate frame\n" ) ; goto end; } if ( ! decode && avpriv_codec_get_cap_skip_frame_fill_param ( codec_ctx-> codec) ) { codec_ctx-> skip_frame = AVDISCARD_ALL; } do { ret = avcodec_decode_video2 ( codec_ctx, frame, & got_frame, pkt) ; av_assert0 ( decode || ( ! decode && ! got_frame) ) ; if ( ret < 0 ) break ; pkt-> data += ret; pkt-> size -= ret; if ( got_frame) { break ; } } while ( pkt-> size > 0 ) ; end: codec_ctx-> skip_frame = skip_frame; av_frame_free ( & frame) ; return ret;
}
find_video_stream_info
static int find_video_stream_info ( AVFormatContext * fmt_ctx, int decode)
{ int ret = 0 ; int i, done = 0 ; AVPacket pkt; av_init_packet ( & pkt) ; while ( ! done) { AVCodecContext * codec_ctx = NULL ; AVStream * st; if ( ( ret = av_read_frame ( fmt_ctx, & pkt) ) < 0 ) { av_log ( fmt_ctx, AV_LOG_ERROR, "Failed to read frame\n" ) ; goto end; } st = fmt_ctx-> streams[ pkt. stream_index] ; codec_ctx = st-> codec; if ( codec_ctx-> codec_type != AVMEDIA_TYPE_VIDEO || st-> codec_info_nb_frames++ > 0 ) { av_packet_unref ( & pkt) ; continue ; } ret = try_decode_video_frame ( codec_ctx, & pkt, decode) ; if ( ret < 0 ) { av_log ( fmt_ctx, AV_LOG_ERROR, "Failed to decode video frame\n" ) ; goto end; } av_packet_unref ( & pkt) ; done = 1 ; for ( i = 0 ; i < fmt_ctx-> nb_streams; i++ ) { st = fmt_ctx-> streams[ i] ; codec_ctx = st-> codec; if ( codec_ctx-> codec_type != AVMEDIA_TYPE_VIDEO) continue ; done &= st-> codec_info_nb_frames > 0 ; } } end: av_packet_unref ( & pkt) ; for ( i = 0 ; i < fmt_ctx-> nb_streams; i++ ) { AVStream * st = fmt_ctx-> streams[ i] ; avcodec_close ( st-> codec) ; } return ret < 0 ;
}
static void dump_video_streams ( const AVFormatContext * fmt_ctx, int decode)
{ int i; for ( i = 0 ; i < fmt_ctx-> nb_streams; i++ ) { const AVOption * opt = NULL ; const AVStream * st = fmt_ctx-> streams[ i] ; AVCodecContext * codec_ctx = st-> codec; printf ( "stream=%d, decode=%d\n" , i, decode) ; while ( opt = av_opt_next ( codec_ctx, opt) ) { uint8_t * str; if ( opt-> type == AV_OPT_TYPE_CONST) continue ; if ( ! strcmp ( opt-> name, "frame_number" ) ) continue ; if ( av_opt_get ( codec_ctx, opt-> name, 0 , & str) >= 0 ) { printf ( " %s=%s\n" , opt-> name, str) ; av_free ( str) ; } } }
}
static int open_and_probe_video_streams ( AVFormatContext * * fmt_ctx, const char * filename, int decode)
{ int ret = 0 ; ret = avformat_open_input ( fmt_ctx, filename, NULL , NULL ) ; if ( ret < 0 ) { av_log ( NULL , AV_LOG_ERROR, "Failed to open input '%s'" , filename) ; goto end; } ret = find_video_stream_info ( * fmt_ctx, decode) ; if ( ret < 0 ) { goto end; } dump_video_streams ( * fmt_ctx, decode) ; end: return ret;
}
static int check_video_streams ( const AVFormatContext * fmt_ctx1, const AVFormatContext * fmt_ctx2)
{ int i; int ret = 0 ; av_assert0 ( fmt_ctx1-> nb_streams == fmt_ctx2-> nb_streams) ; for ( i = 0 ; i < fmt_ctx1-> nb_streams; i++ ) { const AVOption * opt = NULL ; const AVStream * st1 = fmt_ctx1-> streams[ i] ; const AVStream * st2 = fmt_ctx2-> streams[ i] ; AVCodecContext * codec_ctx1 = st1-> codec; AVCodecContext * codec_ctx2 = st2-> codec; if ( codec_ctx1-> codec_type != AVMEDIA_TYPE_VIDEO) continue ; while ( opt = av_opt_next ( codec_ctx1, opt) ) { uint8_t * str1 = NULL , * str2 = NULL ; if ( opt-> type == AV_OPT_TYPE_CONST) continue ; if ( ! strcmp ( opt-> name, "frame_number" ) ) continue ; av_assert0 ( av_opt_get ( codec_ctx1, opt-> name, 0 , & str1) >= 0 ) ; av_assert0 ( av_opt_get ( codec_ctx2, opt-> name, 0 , & str2) >= 0 ) ; if ( strcmp ( str1, str2) ) { av_log ( NULL , AV_LOG_ERROR, "Field %s differs: %s %s" , opt-> name, str1, str2) ; ret = AVERROR ( EINVAL) ; } av_free ( str1) ; av_free ( str2) ; } } return ret;
}