X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fscan.c;h=272f03ffbd72923ed342e1fb1fccb6fd1d56bd20;hb=5dc7807a9d52d7e907bb39c3c45a9eeb150c3ae6;hp=4f28bac6d526a43d59e19cb43a0b1477701b6ff9;hpb=f0cd20016371a6fe6aaf3588da57ee439201150a;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/scan.c b/libhb/scan.c index 4f28bac6..272f03ff 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -6,6 +6,7 @@ #include "hb.h" #include "a52dec/a52.h" +#include "dca.h" typedef struct { @@ -16,13 +17,14 @@ typedef struct hb_list_t * list_title; hb_dvd_t * dvd; - + hb_stream_t * stream; + } hb_scan_t; static void ScanFunc( void * ); static int DecodePreviews( hb_scan_t *, hb_title_t * title ); -static void LookForAC3( hb_title_t * title, hb_buffer_t * b ); -static int AllAC3OK( hb_title_t * title ); +static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ); +static int AllAC3AndDCAOK( hb_title_t * title ); hb_thread_t * hb_scan_init( hb_handle_t * handle, const char * path, int title_index, hb_list_t * list_title ) @@ -43,6 +45,9 @@ static void ScanFunc( void * _data ) hb_title_t * title; int i; + data->dvd = NULL; + data->stream = NULL; + /* Try to open the path as a DVD. If it fails, try as a file */ hb_log( "scan: trying to open with libdvdread" ); if( ( data->dvd = hb_dvd_init( data->path ) ) ) @@ -67,18 +72,15 @@ static void ScanFunc( void * _data ) } else { - /* Open as a VOB file */ - FILE * file; - hb_log( "scan: trying to open as VOB file" ); - file = fopen( data->path, "rb" ); - if( file ) + if ( hb_stream_is_stream_type(data->path) ) { - /* XXX */ - fclose( file ); + hb_log( "scan: trying to open as MPEG-2 Stream"); + data->stream = hb_stream_open (data->path); + hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) ); } else { - hb_log( "scan: fopen failed" ); + hb_log( "scan: unrecognized file type" ); return; } } @@ -122,25 +124,54 @@ static void ScanFunc( void * _data ) /* Update the UI */ state.state = HB_STATE_SCANNING; p.title_cur = title->index; - p.title_count = hb_dvd_title_count( data->dvd ); + p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : hb_list_count(data->list_title); hb_set_state( data->h, &state ); #undef p /* Decode previews */ + /* this will also detect more AC3 / DTS information */ if( !DecodePreviews( data, title ) ) { /* TODO: free things */ hb_list_rem( data->list_title, title ); continue; } - - /* Make sure we found AC3 rates and bitrates */ + + if (data->stream) + { + // Stream based processing uses PID's to handle the different audio options for a given title + for( j = 0; j < hb_list_count( title->list_audio ); j++ ) + { + audio = hb_list_item( title->list_audio, j ); + hb_stream_update_audio(data->stream, audio); + } + } + else if (data->dvd) + { + /* Make sure we found AC3 rates and bitrates */ + for( j = 0; j < hb_list_count( title->list_audio ); ) + { + audio = hb_list_item( title->list_audio, j ); + if( audio->codec == HB_ACODEC_AC3 && + !audio->bitrate ) + { + hb_list_rem( title->list_audio, audio ); + free( audio ); + continue; + } + j++; + } + } + + /* Make sure we found AC3 / DCA rates and bitrates */ for( j = 0; j < hb_list_count( title->list_audio ); ) { audio = hb_list_item( title->list_audio, j ); - if( audio->codec == HB_ACODEC_AC3 && + if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && !audio->bitrate ) { + hb_log( "scan: removing audio with codec of 0x%x because of no bitrate", + audio->codec ); hb_list_rem( title->list_audio, audio ); free( audio ); continue; @@ -155,6 +186,18 @@ static void ScanFunc( void * _data ) free( title ); continue; } + + /* set a default input channel layout of stereo for LPCM or MPEG2 audio */ + /* AC3 and DCA will already have had their layout set via DecodePreviews above, */ + /* which calls LookForAC3AndDCA */ + for( j = 0; j < hb_list_count( title->list_audio ); j++ ) + { + audio = hb_list_item( title->list_audio, j ); + if( audio->codec == HB_ACODEC_LPCM || audio->codec == HB_ACODEC_MPGA ) + { + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + } + } i++; } @@ -225,6 +268,10 @@ static void ScanFunc( void * _data ) { hb_dvd_close( &data->dvd ); } + if (data->stream) + { + hb_stream_close(&data->stream); + } free( data->path ); free( data ); _data = NULL; @@ -243,35 +290,61 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) hb_buffer_t * buf_ps, * buf_es, * buf_raw; hb_list_t * list_es, * list_raw; hb_libmpeg2_t * mpeg2; - - buf_ps = hb_buffer_init( 2048 ); + int progressive_count = 0; + + buf_ps = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE ); list_es = hb_list_init(); list_raw = hb_list_init(); hb_log( "scan: decoding previews for title %d", title->index ); - hb_dvd_start( data->dvd, title->index, 1 ); - + if (data->dvd) + hb_dvd_start( data->dvd, title->index, 1 ); + for( i = 0; i < 10; i++ ) { int j, k; FILE * file_preview; char filename[1024]; - if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) ) + //hb_log("Seeking to: %f", (float) ( i + 1 ) / 11.0 ); + + if (data->dvd) + { + if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) ) + { + goto error; + } + } + else if (data->stream) { + if (!hb_stream_seek(data->stream, (float) ( i + 1 ) / 11.0 ) ) + { goto error; + } } - + hb_log( "scan: preview %d", i + 1 ); mpeg2 = hb_libmpeg2_init(); for( j = 0; j < 10240 ; j++ ) { - if( !hb_dvd_read( data->dvd, buf_ps ) ) + if (data->dvd) { - goto error; + if( !hb_dvd_read( data->dvd, buf_ps ) ) + { + hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 ); + goto skip_preview; + } + } + else if (data->stream) + { + if ( !hb_stream_read(data->stream,buf_ps) ) + { + hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 ); + goto skip_preview; + } } hb_demux_ps( buf_ps, list_es ); @@ -284,12 +357,12 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) } else if( !i ) { - LookForAC3( title, buf_es ); + LookForAC3AndDCA( title, buf_es ); } hb_buffer_close( &buf_es ); if( hb_list_count( list_raw ) && - ( i || AllAC3OK( title ) ) ) + ( i || AllAC3AndDCAOK( title ) ) ) { /* We got a picture */ break; @@ -297,7 +370,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) } if( hb_list_count( list_raw ) && - ( i || AllAC3OK( title ) ) ) + ( i || AllAC3AndDCAOK( title ) ) ) { break; } @@ -309,12 +382,56 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) goto error; } - if( !i ) + /* Get size and rate infos */ + title->rate = 27000000; + int ar; + hb_libmpeg2_info( mpeg2, &title->width, &title->height, + &title->rate_base, &ar ); + + if( title->rate_base == 1126125 ) { - /* Get size and rate infos */ - title->rate = 27000000; - hb_libmpeg2_info( mpeg2, &title->width, &title->height, - &title->rate_base ); + /* Frame FPS is 23.976 (meaning it's progressive), so + start keeping track of how many are reporting at + that speed. When enough show up that way, we want + to make that the overall title FPS. + */ + progressive_count++; + + if( progressive_count < 6 ) + { + /* Not enough frames are reporting as progressive, + which means we should be conservative and use + 29.97 as the title's FPS for now. + */ + title->rate_base = 900900; + } + else + { + /* A majority of the scan frames are progressive. Make that + the title's FPS, and announce it once to the log. + */ + if( progressive_count == 6 ) + { + hb_log("Title's mostly progressive NTSC, setting fps to 23.976"); + } + title->rate_base = 1126125; + } + } + else if( title->rate_base == 900900 && progressive_count >= 6 ) + { + /* + * We've already deduced that the frame rate is 23.976, so set it + * back again. + */ + title->rate_base = 1126125; + } + + if( i == 2) // Use the third frame's info, so as to skip opening logos + { + // The aspect ratio may have already been set by parsing the VOB/IFO details on a DVD, however + // if we're working with program/transport streams that data needs to come from within the stream. + if (title->aspect <= 0) + title->aspect = ar; title->crop[0] = title->crop[1] = title->height / 2; title->crop[2] = title->crop[3] = title->width / 2; } @@ -330,7 +447,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) buf_raw = hb_list_item( list_raw, 0 ); hb_get_tempory_filename( data->h, filename, "%x%d", - (int) title, i ); + (intptr_t)title, i ); file_preview = fopen( filename, "w" ); if( file_preview ) @@ -382,6 +499,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) } } +skip_preview: while( ( buf_raw = hb_list_item( list_raw, 0 ) ) ) { hb_list_rem( list_raw, buf_raw ); @@ -419,23 +537,28 @@ cleanup: hb_buffer_close( &buf_raw ); } hb_list_close( &list_raw ); - hb_dvd_stop( data->dvd ); + if (data->dvd) + hb_dvd_stop( data->dvd ); + return ret; } -static void LookForAC3( hb_title_t * title, hb_buffer_t * b ) +static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) { int i; int flags; int rate; int bitrate; + int frame_length; + dca_state_t * state; - /* Figure out if this is a AC3 buffer for a known track */ + /* Figure out if this is a AC3 or DCA buffer for a known track */ hb_audio_t * audio = NULL; for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - if( audio->codec == HB_ACODEC_AC3 && + /* check if we have an AC3 or DCA which we recognise */ + if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && audio->id == b->id ) { break; @@ -458,95 +581,170 @@ static void LookForAC3( hb_title_t * title, hb_buffer_t * b ) for( i = 0; i < b->size - 7; i++ ) { - if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) ) + + if ( audio->codec == HB_ACODEC_AC3 ) { - hb_log( "scan: rate=%dHz, bitrate=%d", rate, bitrate ); - audio->rate = rate; - audio->bitrate = bitrate; - switch( flags & A52_CHANNEL_MASK ) + + /* check for a52 */ + if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) ) { - case A52_MONO: - case A52_CHANNEL1: - case A52_CHANNEL2: - audio->src_discrete_front_channels = 1; - audio->src_discrete_rear_channels = 0; - audio->src_encoded_front_channels = 1; - audio->src_encoded_rear_channels = 0; - break; - case A52_STEREO: - case A52_CHANNEL: - audio->src_discrete_front_channels = 2; - audio->src_discrete_rear_channels = 0; - audio->src_encoded_front_channels = 2; - audio->src_encoded_rear_channels = 0; - break; - case A52_DOLBY: - audio->src_discrete_front_channels = 2; - audio->src_discrete_rear_channels = 0; - audio->src_encoded_front_channels = 3; - audio->src_encoded_rear_channels = 1; - break; - case A52_3F: - audio->src_discrete_front_channels = 3; - audio->src_discrete_rear_channels = 0; - audio->src_encoded_front_channels = 3; - audio->src_encoded_rear_channels = 0; - break; - case A52_2F1R: - audio->src_discrete_front_channels = 2; - audio->src_discrete_rear_channels = 1; - audio->src_encoded_front_channels = 2; - audio->src_encoded_rear_channels = 1; - break; - case A52_3F1R: - audio->src_discrete_front_channels = 3; - audio->src_discrete_rear_channels = 1; - audio->src_encoded_front_channels = 3; - audio->src_encoded_rear_channels = 1; - break; - case A52_2F2R: - audio->src_discrete_front_channels = 2; - audio->src_discrete_rear_channels = 2; - audio->src_encoded_front_channels = 2; - audio->src_encoded_rear_channels = 2; - break; - case A52_3F2R: - audio->src_discrete_front_channels = 3; - audio->src_discrete_rear_channels = 2; - audio->src_encoded_front_channels = 3; - audio->src_encoded_rear_channels = 2; - break; + hb_log( "scan: AC3, rate=%dHz, bitrate=%d", rate, bitrate ); + audio->rate = rate; + audio->bitrate = bitrate; + switch( flags & A52_CHANNEL_MASK ) + { + /* mono sources */ + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO; + break; + /* stereo input */ + case A52_CHANNEL: + case A52_STEREO: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + break; + /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */ + case A52_DOLBY: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; + break; + /* 3F/2R input */ + case A52_3F2R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R; + break; + /* 3F/1R input */ + case A52_3F1R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R; + break; + /* other inputs */ + case A52_3F: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F; + break; + case A52_2F1R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R; + break; + case A52_2F2R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R; + break; + /* unknown */ + default: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + } + + /* add in our own LFE flag if the source has LFE */ + if (flags & A52_LFE) + { + audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; + } + + /* store the AC3 flags for future reference + This enables us to find out if we had a stereo or Dolby source later on */ + audio->config.a52.ac3flags = flags; + + /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */ + audio->ac3flags = audio->config.a52.ac3flags; + + /* XXX */ + if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) { + sprintf( audio->lang + strlen( audio->lang ), + " (Dolby Surround)" ); + } else { + sprintf( audio->lang + strlen( audio->lang ), + " (%d.%d ch)", + HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) + + HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout), + HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout)); + } + + break; + } - if (flags & A52_LFE) { - audio->src_discrete_lfe_channels = 1; - } else { - audio->src_discrete_lfe_channels = 0; - } - - /* store the AC3 flags for future reference - This enables us to find out if we had a stereo or Dolby source later on */ - audio->config.a52.ac3flags = flags; - - /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */ - audio->ac3flags = audio->config.a52.ac3flags; - - /* XXX */ - if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) { - sprintf( audio->lang + strlen( audio->lang ), - " (Dolby Surround)" ); - } else { - sprintf( audio->lang + strlen( audio->lang ), - " (%d.%d ch)", - audio->src_discrete_front_channels + audio->src_discrete_rear_channels, audio->src_discrete_lfe_channels ); - } + } + else if ( audio->codec == HB_ACODEC_DCA ) + { - break; + hb_log( "scan: checking for DCA syncinfo" ); + + /* check for dca */ + state = dca_init( 0 ); + if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate, &frame_length ) ) + { + hb_log( "scan: DCA, rate=%dHz, bitrate=%d", rate, bitrate ); + audio->rate = rate; + audio->bitrate = bitrate; + switch( flags & DCA_CHANNEL_MASK ) + { + /* mono sources */ + case DCA_MONO: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO; + break; + /* stereo input */ + case DCA_CHANNEL: + case DCA_STEREO: + case DCA_STEREO_SUMDIFF: + case DCA_STEREO_TOTAL: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + break; + /* 3F/2R input */ + case DCA_3F2R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R; + break; + /* 3F/1R input */ + case DCA_3F1R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R; + break; + /* other inputs */ + case DCA_3F: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F; + break; + case DCA_2F1R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R; + break; + case DCA_2F2R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R; + break; + case DCA_4F2R: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_4F2R; + break; + /* unknown */ + default: + audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + } + + /* add in our own LFE flag if the source has LFE */ + if (flags & DCA_LFE) + { + audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; + } + + /* store the DCA flags for future reference + This enables us to find out if we had a stereo or Dolby source later on */ + audio->config.dca.dcaflags = flags; + + /* store the dca flags in the public dcaflags property too, so we can access it from the GUI */ + audio->dcaflags = audio->config.dca.dcaflags; + + /* XXX */ + if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) { + sprintf( audio->lang + strlen( audio->lang ), + " (Dolby Surround)" ); + } else { + sprintf( audio->lang + strlen( audio->lang ), + " (%d.%d ch)", + HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) + + HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout), + HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout)); + } + + break; + } } } + } -static int AllAC3OK( hb_title_t * title ) +static int AllAC3AndDCAOK( hb_title_t * title ) { int i; hb_audio_t * audio; @@ -554,7 +752,7 @@ static int AllAC3OK( hb_title_t * title ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - if( audio->codec == HB_ACODEC_AC3 && + if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && !audio->bitrate ) { return 0;