X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Fproducer_avformat.c;h=e1822298cb2f05e2ee7948b8edb7ff1eee714353;hb=70933f360aa7d16e5140267ce2f716de924464c7;hp=a8d54804d208f9dfd476627a7b75240d6137be42;hpb=e23647b24149d5cce3d0b22f06a9739e24791336;p=melted diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index a8d5480..e182229 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -160,6 +160,88 @@ static void producer_codec_close( void *codec ) } } +static inline int dv_is_pal( AVPacket *pkt ) +{ + return pkt->data[3] & 0x80; +} + +static int dv_is_wide( AVPacket *pkt ) +{ + int i = 80 /* block size */ *3 /* VAUX starts at block 3 */ +3 /* skip block header */; + + for ( ; i < pkt->size; i += 5 /* packet size */ ) + { + if ( pkt->data[ i ] == 0x61 ) + { + uint8_t x = pkt->data[ i + 2 ] & 0x7; + return ( x == 2 ) || ( x == 7 ); + } + } + return 0; +} + +static double get_aspect_ratio( AVStream *stream, AVCodecContext *codec_context, AVPacket *pkt ) +{ + double aspect_ratio = 1.0; + + if ( codec_context->codec_id == CODEC_ID_DVVIDEO ) + { + if ( pkt ) + { + if ( dv_is_pal( pkt ) ) + { + aspect_ratio = dv_is_wide( pkt ) + ? 64.0/45.0 // 16:9 PAL + : 16.0/15.0; // 4:3 PAL + } + else + { + aspect_ratio = dv_is_wide( pkt ) + ? 32.0/27.0 // 16:9 NTSC + : 8.0/9.0; // 4:3 NTSC + } + } + else + { + AVRational ar = +#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0) + stream->sample_aspect_ratio; +#else + codec_context->sample_aspect_ratio; +#endif + // Override FFmpeg's notion of DV aspect ratios, which are + // based upon a width of 704. Since we do not have a normaliser + // that crops (nor is cropping 720 wide ITU-R 601 video always desirable) + // we just coerce the values to facilitate a passive behaviour through + // the rescale normaliser when using equivalent producers and consumers. + // = display_aspect / (width * height) + if ( ar.num == 10 && ar.den == 11 ) + aspect_ratio = 8.0/9.0; // 4:3 NTSC + else if ( ar.num == 59 && ar.den == 54 ) + aspect_ratio = 16.0/15.0; // 4:3 PAL + else if ( ar.num == 40 && ar.den == 33 ) + aspect_ratio = 32.0/27.0; // 16:9 NTSC + else if ( ar.num == 118 && ar.den == 81 ) + aspect_ratio = 64.0/45.0; // 16:9 PAL + } + } + else + { + AVRational codec_sar = codec_context->sample_aspect_ratio; + AVRational stream_sar = +#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0) + stream->sample_aspect_ratio; +#else + { 0, 1 }; +#endif + if ( codec_sar.num > 0 ) + aspect_ratio = av_q2d( codec_sar ); + else if ( stream_sar.num > 0 ) + aspect_ratio = av_q2d( stream_sar ); + } + return aspect_ratio; +} + /** Open the file. */ @@ -317,7 +399,28 @@ static int producer_open( mlt_producer this, mlt_profile profile, char *file ) AVCodecContext *codec_context = context->streams[ video_index ]->codec; mlt_properties_set_int( properties, "width", codec_context->width ); mlt_properties_set_int( properties, "height", codec_context->height ); - mlt_properties_set_double( properties, "aspect_ratio", av_q2d( codec_context->sample_aspect_ratio ) ); + + if ( codec_context->codec_id == CODEC_ID_DVVIDEO ) + { + // Fetch the first frame of DV so we can read it directly + AVPacket pkt; + int ret = 0; + while ( ret >= 0 ) + { + ret = av_read_frame( context, &pkt ); + if ( ret >= 0 && pkt.stream_index == video_index && pkt.size > 0 ) + { + mlt_properties_set_double( properties, "aspect_ratio", + get_aspect_ratio( context->streams[ video_index ], codec_context, &pkt ) ); + break; + } + } + } + else + { + mlt_properties_set_double( properties, "aspect_ratio", + get_aspect_ratio( context->streams[ video_index ], codec_context, NULL ) ); + } } // Read Metadata @@ -704,16 +807,21 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) // Exception handling for video_index if ( context && index >= (int) context->nb_streams ) { + // Get the last video stream for ( index = context->nb_streams - 1; index >= 0 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_VIDEO; --index ); + mlt_properties_set_int( properties, "video_index", index ); } if ( context && index > -1 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_VIDEO ) + { + // Invalidate the video stream index = -1; - mlt_properties_set_int( properties, "video_index", index ); + mlt_properties_set_int( properties, "video_index", index ); + } // Get the frame properties mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); - if ( context != NULL && index > -1 ) + if ( context && index > -1 ) { // Get the video stream AVStream *stream = context->streams[ index ]; @@ -724,6 +832,20 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) // Get the codec AVCodec *codec = mlt_properties_get_data( properties, "video_codec", NULL ); + // Update the video properties if the index changed + if ( index != mlt_properties_get_int( properties, "_video_index" ) ) + { + // Reset the video properties if the index changed + mlt_properties_set_int( properties, "_video_index", index ); + mlt_properties_set_data( properties, "video_codec", NULL, 0, NULL, NULL ); + mlt_properties_set_int( properties, "width", codec_context->width ); + mlt_properties_set_int( properties, "height", codec_context->height ); + // TODO: get the first usable AVPacket and reset the stream position + mlt_properties_set_double( properties, "aspect_ratio", + get_aspect_ratio( context->streams[ index ], codec_context, NULL ) ); + codec = NULL; + } + // Initialise the codec if necessary if ( codec == NULL ) { @@ -759,47 +881,9 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) if ( codec != NULL ) { double source_fps = 0; - int norm_aspect_ratio = mlt_properties_get_int( properties, "norm_aspect_ratio" ); double force_aspect_ratio = mlt_properties_get_double( properties, "force_aspect_ratio" ); - double aspect_ratio; - - if ( strcmp( codec_context->codec->name, "dvvideo" ) == 0 ) - { - // Override FFmpeg's notion of DV aspect ratios, which are - // based upon a width of 704. Since we do not have a normaliser - // that crops (nor is cropping 720 wide ITU-R 601 video always desirable) - // we just coerce the values to facilitate a passive behaviour through - // the rescale normaliser when using equivalent producers and consumers. - // = display_aspect / (width * height) - if ( codec_context->sample_aspect_ratio.num == 10 && - codec_context->sample_aspect_ratio.den == 11 ) - force_aspect_ratio = 8.0/9.0; // 4:3 NTSC - else if ( codec_context->sample_aspect_ratio.num == 59 && - codec_context->sample_aspect_ratio.den == 54 ) - force_aspect_ratio = 16.0/15.0; // 4:3 PAL - else if ( codec_context->sample_aspect_ratio.num == 40 && - codec_context->sample_aspect_ratio.den == 33 ) - force_aspect_ratio = 32.0/27.0; // 16:9 NTSC - else if ( codec_context->sample_aspect_ratio.num == 118 && - codec_context->sample_aspect_ratio.den == 81 ) - force_aspect_ratio = 64.0/45.0; // 16:9 PAL - } - - // XXX: We won't know the real aspect ratio until an image is decoded - // but we do need it now (to satisfy filter_resize) - take a guess based - // on pal/ntsc - if ( force_aspect_ratio > 0.0 ) - { - aspect_ratio = force_aspect_ratio; - } - else if ( !norm_aspect_ratio && codec_context->sample_aspect_ratio.num > 0 ) - { - aspect_ratio = av_q2d( codec_context->sample_aspect_ratio ); - } - else - { - aspect_ratio = 1.0; - } + double aspect_ratio = ( force_aspect_ratio > 0.0 ) ? + force_aspect_ratio : mlt_properties_get_double( properties, "aspect_ratio" ); // Determine the fps source_fps = ( double )codec_context->time_base.den / ( codec_context->time_base.num == 0 ? 1 : codec_context->time_base.num ); @@ -1076,10 +1160,19 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame ) if ( context && index >= (int) context->nb_streams ) { for ( index = context->nb_streams - 1; index >= 0 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_AUDIO; --index ); + mlt_properties_set_int( properties, "audio_index", index ); } if ( context && index > -1 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_AUDIO ) + { index = -1; - mlt_properties_set_int( properties, "audio_index", index ); + mlt_properties_set_int( properties, "audio_index", index ); + } + + // Update the audio properties if the index changed + if ( index > -1 && index != mlt_properties_get_int( properties, "_audio_index" ) ) { + mlt_properties_set_int( properties, "_audio_index", index ); + mlt_properties_set_data( properties, "audio_codec", NULL, 0, NULL, NULL ); + } // Deal with audio context if ( context != NULL && index > -1 )