diff options
author | van <[email protected]> | 2008-06-04 07:00:01 +0000 |
---|---|---|
committer | van <[email protected]> | 2008-06-04 07:00:01 +0000 |
commit | 2eaa5e617f47be280c9fd546f1d10451865d216c (patch) | |
tree | 3f21d31dc191a76d92f104bf8229ed0e8dfa90df /libhb | |
parent | 9f5c03a4bb522f1df63b52190461fc46366ba2c9 (diff) |
- add pixel_aspect_ratio reporting to the mpeg decoder
- try lots harder to extract a useful video frame rate from libavcodec (successful for more files but still get junk from wmv's).
- save all video parameters while we're getting previews then use the set we've seen most frequently as the parameters of the title.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1490 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/decavcodec.c | 28 | ||||
-rw-r--r-- | libhb/decmpeg2.c | 41 | ||||
-rw-r--r-- | libhb/scan.c | 165 |
3 files changed, 133 insertions, 101 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index d050e39f9..10a750142 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -683,17 +683,39 @@ static int decavcodecviInfo( hb_work_object_t *w, hb_work_info_t *info ) { if ( decavcodecvInfo( w, info ) ) { - // the frame rate in the codec seems to be bogus but it's ok in the stream. + // There are at least three different video frame rates in ffmpeg: + // - time_base in the AVStream + // - time_base in the AVCodecContext + // - r_frame_rate in the AVStream + // There's no guidence on which if any of these to believe but the + // routine compute_frame_duration tries the stream first then the codec. + // In general the codec time base seems bogus & the stream time base is + // ok except for wmv's where the stream time base is also bogus but + // r_frame_rate is sometimes ok & sometimes a random number. AVStream *st = hb_ffmpeg_avstream( w->codec_param ); AVRational tb; - if ( st->r_frame_rate.den && st->r_frame_rate.num ) + // XXX because the time bases are so screwed up, we only take values + // in the range 8fps - 64fps. + if ( st->time_base.num * 64 > st->time_base.den && + st->time_base.den > st->time_base.num * 8 ) + { + tb = st->time_base; + } + else if ( st->codec->time_base.num * 64 > st->codec->time_base.den && + st->codec->time_base.den > st->codec->time_base.num * 8 ) + { + tb = st->codec->time_base; + } + else if ( st->r_frame_rate.den * 64 > st->r_frame_rate.num && + st->r_frame_rate.num > st->r_frame_rate.den * 8 ) { tb.num = st->r_frame_rate.den; tb.den = st->r_frame_rate.num; } else { - tb = st->time_base; + tb.num = 1001; /*XXX*/ + tb.den = 30000; /*XXX*/ } // ffmpeg gives the frame rate in frames per second while HB wants diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c index 52abfb729..bccbd065b 100644 --- a/libhb/decmpeg2.c +++ b/libhb/decmpeg2.c @@ -306,33 +306,6 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, } /********************************************************************** - * hb_libmpeg2_info - ********************************************************************** - * - *********************************************************************/ -static void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height, - int * rate, int *aspect_ratio ) -{ - *width = m->width; - *height = m->height; - if (m->info->display_fbuf) - { - if( (m->info->display_picture->flags & PROGRESSIVE) && (m->height == 480) ) - { - /* The frame is progressive and it's NTSC DVD height, so change its FPS to 23.976. - This might not be correct for the title. It's really just for scan.c's benefit. - Scan.c will reset the fps to 29.97, until a simple majority of the preview - frames report at 23.976. - */ - //hb_log("Detecting NTSC Progressive Frame"); - m->rate = 1126125; - } - } - *rate = m->rate; - *aspect_ratio = m->aspect_ratio; -} - -/********************************************************************** * hb_libmpeg2_close ********************************************************************** * @@ -452,14 +425,20 @@ static int decmpeg2Info( hb_work_object_t *w, hb_work_info_t *info ) if ( pv && pv->libmpeg2 && pv->libmpeg2->info && pv->libmpeg2->info->sequence ) { - int aspect; hb_libmpeg2_t *m = pv->libmpeg2; - hb_libmpeg2_info( m, &info->width, &info->height, &info->rate_base, - &aspect ); + info->width = m->width; + info->height = m->height; + info->pixel_aspect_width = m->info->sequence->pixel_width; + info->pixel_aspect_height = m->info->sequence->pixel_height; + info->aspect = (double)m->aspect_ratio; - info->aspect = (double)aspect; + // if the frame is progressive & NTSC DVD height report it as 23.976 FPS + // so that scan can autodetect NTSC film info->rate = 27000000; + info->rate_base = ( m->info->display_fbuf && m->info->display_picture && + (m->info->display_picture->flags & PROGRESSIVE) && + (m->height == 480 ) ) ? 1126125 : m->rate; info->bitrate = m->info->sequence->byte_rate * 8; info->profile = m->info->sequence->profile_level_id >> 4; diff --git a/libhb/scan.c b/libhb/scan.c index d66ccca42..265cfb245 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -26,6 +26,21 @@ static int DecodePreviews( hb_scan_t *, hb_title_t * title ); static void LookForAudio( hb_title_t * title, hb_buffer_t * b ); static int AllAudioOK( hb_title_t * title ); +static const char *aspect_to_string( int aspect ) +{ + switch ( aspect ) + { + case HB_ASPECT_BASE * 1 / 1: return "1:1"; + case HB_ASPECT_BASE * 4 / 3: return "4:3"; + case HB_ASPECT_BASE * 16 / 9: return "16:9"; + case HB_ASPECT_BASE * 221 / 100: return "2.21:1"; + } + static char arstr[32]; + double a = (double)aspect / HB_ASPECT_BASE; + sprintf( arstr, aspect >= 1.? "%.2f:1" : "1:%.2f", a ); + return arstr; +} + hb_thread_t * hb_scan_init( hb_handle_t * handle, const char * path, int title_index, hb_list_t * list_title ) { @@ -234,6 +249,42 @@ static void ScanFunc( void * _data ) _data = NULL; } +typedef struct { + int count; /* number of times we've seen this info entry */ + hb_work_info_t info; /* copy of info entry */ +} info_list_t; + +static void remember_info( info_list_t *info_list, hb_work_info_t *info ) +{ + for ( ; info_list->count; ++info_list ) + { + if ( memcmp( &info_list->info, info, sizeof(*info) ) == 0 ) + { + // we found a match - bump its count + ++info_list->count; + return; + } + } + // no match found - add new entry to list (info_list points to + // the first free slot). NB - we assume that info_list was allocated + // so that it's big enough even if there are no dups. I.e., 10 slots + // allocated if there are 10 previews. + info_list->count = 1; + info_list->info = *info; +} + +static void most_common_info( info_list_t *info_list, hb_work_info_t *info ) +{ + int i, biggest = 0; + for ( i = 1; info_list[i].count; ++i ) + { + if ( info_list[i].count > info_list[biggest].count ) + biggest = i; + } + *info = info_list[biggest].info; + free( info_list ); +} + /*********************************************************************** * DecodePreviews *********************************************************************** @@ -248,8 +299,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) hb_list_t * list_es; int progressive_count = 0; int interlaced_preview_count = 0; - double last_ar = 0; - int ar16_count = 0, ar4_count = 0; + info_list_t * info_list = calloc( 10+1, sizeof(*info_list) ); buf_ps = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE ); list_es = hb_list_init(); @@ -350,44 +400,12 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) vid_decoder->close( vid_decoder ); free( vid_decoder ); + remember_info( info_list, &vid_info ); + title->width = vid_info.width; title->height = vid_info.height; - title->pixel_aspect_width = vid_info.pixel_aspect_width; - title->pixel_aspect_height = vid_info.pixel_aspect_height; - title->rate = vid_info.rate; title->rate_base = vid_info.rate_base; - if ( vid_info.aspect != 0 ) - { - if ( vid_info.aspect != last_ar && last_ar != 0 ) - { - hb_log( "aspect ratio changed from %g to %g", - last_ar, vid_info.aspect ); - } - - if( !title->pixel_aspect_width && !title->pixel_aspect_height ) - { - /* We don't have pixel aspect info from the source, so we're - going to have to make a guess on the display aspect ratio. */ - switch ( (int)vid_info.aspect ) - { - case HB_ASPECT_BASE * 4 / 3: - ++ar4_count; - break; - case HB_ASPECT_BASE * 16 / 9: - ++ar16_count; - break; - default: - hb_log( "unknown aspect ratio %g", vid_info.aspect ); - /* if the aspect is closer to 4:3 use that - * otherwise use 16:9 */ - vid_info.aspect < HB_ASPECT_BASE * 14 / 9 ? ++ar4_count : - ++ar16_count; - break; - } - } - last_ar = vid_info.aspect; - } if( title->rate_base == 1126125 ) { @@ -505,41 +523,54 @@ skip_preview: if ( vid_buf ) hb_buffer_close( &vid_buf ); } - - if( title->pixel_aspect_width && title->pixel_aspect_width ) - { - title->aspect = ( (double)title->pixel_aspect_width * - (double)title->width / - (double)title->pixel_aspect_height / - (double)title->height + 0.05 ) * HB_ASPECT_BASE; - } - else + + if ( npreviews ) { - /* if we found mostly 4:3 previews use that as the aspect ratio otherwise - use 16:9 */ - title->aspect = ar4_count > ar16_count ? - HB_ASPECT_BASE * 4 / 3 : HB_ASPECT_BASE * 16 / 9; - } + // use the most common frame info for our final title dimensions + hb_work_info_t vid_info; + most_common_info( info_list, &vid_info ); - title->crop[0] = EVEN( title->crop[0] ); - title->crop[1] = EVEN( title->crop[1] ); - title->crop[2] = EVEN( title->crop[2] ); - title->crop[3] = EVEN( title->crop[3] ); + title->width = vid_info.width; + title->height = vid_info.height; + title->pixel_aspect_width = vid_info.pixel_aspect_width; + title->pixel_aspect_height = vid_info.pixel_aspect_height; - hb_log( "scan: %d previews, %dx%d, %.3f fps, autocrop = %d/%d/%d/%d, aspect %.2f", - npreviews, title->width, title->height, (float) title->rate / - (float) title->rate_base, title->crop[0], title->crop[1], - title->crop[2], title->crop[3], (float)title->aspect/(float)HB_ASPECT_BASE); + // compute the aspect ratio based on the storage dimensions and the + // pixel aspect ratio (if supplied) or just storage dimensions if no PAR. + title->aspect = ( (double)title->width / (double)title->height + 0.05 ) * + HB_ASPECT_BASE; - if( interlaced_preview_count >= ( npreviews / 2 ) ) - { - hb_log("Title is likely interlaced or telecined (%i out of %i previews). You should do something about that.", - interlaced_preview_count, npreviews); - title->detected_interlacing = 1; - } - else - { - title->detected_interlacing = 0; + double aspect = (double)title->width / (double)title->height; + if( title->pixel_aspect_width && title->pixel_aspect_height ) + { + aspect *= (double)title->pixel_aspect_width / + (double)title->pixel_aspect_height; + } + title->aspect = ( aspect + 0.05 ) * HB_ASPECT_BASE; + + title->crop[0] = EVEN( title->crop[0] ); + title->crop[1] = EVEN( title->crop[1] ); + title->crop[2] = EVEN( title->crop[2] ); + title->crop[3] = EVEN( title->crop[3] ); + + hb_log( "scan: %d previews, %dx%d, %.3f fps, autocrop = %d/%d/%d/%d, " + "aspect %s, PAR %d:%d", + npreviews, title->width, title->height, (float) title->rate / + (float) title->rate_base, + title->crop[0], title->crop[1], title->crop[2], title->crop[3], + aspect_to_string( title->aspect ), title->pixel_aspect_width, + title->pixel_aspect_height ); + + if( interlaced_preview_count >= ( npreviews / 2 ) ) + { + hb_log("Title is likely interlaced or telecined (%i out of %i previews). You should do something about that.", + interlaced_preview_count, npreviews); + title->detected_interlacing = 1; + } + else + { + title->detected_interlacing = 0; + } } hb_buffer_close( &buf_ps ); |