Index: libhb/decmpeg2.c =================================================================== --- libhb/decmpeg2.c (revision 1488) +++ libhb/decmpeg2.c (working copy) @@ -306,33 +306,6 @@ } /********************************************************************** - * 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 ********************************************************************** * @@ -455,11 +428,18 @@ 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->pwidth = m->info->sequence->pixel_width; + info->pheight = 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; Index: libhb/decavcodec.c =================================================================== --- libhb/decavcodec.c (revision 1488) +++ libhb/decavcodec.c (working copy) @@ -467,13 +467,11 @@ info->bitrate = context->bit_rate; info->width = context->width; info->height = context->height; + info->pwidth = context->sample_aspect_ratio.num ? + context->sample_aspect_ratio.num : 1; + info->pheight = context->sample_aspect_ratio.den ? + context->sample_aspect_ratio.den : 1; - /* ffmpeg gives the frame rate in frames per second while HB wants - * it in units of the 27MHz MPEG clock. */ - info->rate = 27000000; - info->rate_base = (int64_t)context->time_base.num * 27000000LL / - context->time_base.den; - /* ffmpeg returns the Pixel Aspect Ratio (PAR). Handbrake wants the * Display Aspect Ratio so we convert by scaling by the Storage * Aspect Ratio (w/h). We do the calc in floating point to get the @@ -484,10 +482,11 @@ (double)context->sample_aspect_ratio.den / (double)context->height + 0.05 ) * HB_ASPECT_BASE; - if( context->sample_aspect_ratio.num == 0 ) - { - info->aspect = (double)context->width / (double)context->height * HB_ASPECT_BASE; - } + /* ffmpeg gives the frame rate in frames per second while HB wants + * it in units of the 27MHz MPEG clock. */ + info->rate = 27000000; + info->rate_base = (int64_t)context->time_base.num * 27000000LL / + context->time_base.den; info->profile = context->profile; info->level = context->level; info->name = context->codec->name; @@ -680,17 +679,31 @@ { 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 four 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 uses something like the following logic: AVStream *st = hb_ffmpeg_avstream( w->codec_param ); AVRational tb; - if ( st->r_frame_rate.den && st->r_frame_rate.num ) + if ( st->time_base.num * 1000LL > st->time_base.den ) { + tb = st->time_base; + } + else if ( st->codec->time_base.num * 1000LL > st->codec->time_base.den ) + { + tb = st->codec->time_base; + } + else if ( st->r_frame_rate.den && st->r_frame_rate.num ) + { tb.num = st->r_frame_rate.den; tb.den = st->r_frame_rate.num; } else { - tb = st->time_base; + tb.num = 1; /*XXX*/ + tb.den = 30; /*XXX*/ } // ffmpeg gives the frame rate in frames per second while HB wants Index: libhb/scan.c =================================================================== --- libhb/scan.c (revision 1488) +++ libhb/scan.c (working copy) @@ -26,6 +26,20 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b ); static int AllAudioOK( hb_title_t * title ); +static const char *aspect_to_string( double aspect ) +{ + switch ( (int)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]; + sprintf( arstr, aspect >= 1.? "%.2f:1" : "1:%.2f", aspect / HB_ASPECT_BASE ); + return arstr; +} + hb_thread_t * hb_scan_init( hb_handle_t * handle, const char * path, int title_index, hb_list_t * list_title ) { @@ -227,6 +241,42 @@ _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 *********************************************************************** @@ -241,8 +291,7 @@ 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(); @@ -343,35 +392,12 @@ 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->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 ); - } - 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 ) { @@ -490,22 +516,22 @@ hb_buffer_close( &vid_buf ); } - /* 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; + hb_work_info_t vid_info; + most_common_info( info_list, &vid_info ); + title->aspect = vid_info.aspect; + 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", + 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], - title->aspect == HB_ASPECT_BASE * 16 / 9 ? "16:9" : - title->aspect == HB_ASPECT_BASE * 4 / 3 ? "4:3" : "none" ); + (float) title->rate_base, + title->crop[0], title->crop[1], title->crop[2], title->crop[3], + aspect_to_string( vid_info.aspect ), vid_info.pwidth, vid_info.pheight ); if( interlaced_preview_count >= ( npreviews / 2 ) ) { Index: libhb/common.h =================================================================== --- libhb/common.h (revision 1488) +++ libhb/common.h (working copy) @@ -519,8 +519,10 @@ int flags; union { struct { // info only valid for video decoders - int width; - int height; + uint16_t width; // SAR - width + uint16_t height; // SAR - height + uint16_t pwidth; // PAR - width + uint16_t pheight; // PAR - height double aspect; }; struct { // info only valid for audio decoders