diff options
author | jstebbins <[email protected]> | 2009-04-18 18:44:01 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2009-04-18 18:44:01 +0000 |
commit | f090626988119eef202bfa9eddae7f92d99f3967 (patch) | |
tree | 06fd13bf5a2b98ef966db3ce9a778aac494e2b98 | |
parent | 2776908045cff478bc3d3269978c9c193be8bc1d (diff) |
Enable DTS passthru for matroska container
since we have no way to create silent dts frames for insertion to
maintain sync, frames from other streams may be dropped when there is
a sync problem on the DTS stream
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2339 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | gtk/src/hb-backend.c | 2 | ||||
-rw-r--r-- | libhb/common.c | 1 | ||||
-rw-r--r-- | libhb/decdca.c | 36 | ||||
-rw-r--r-- | libhb/muxavi.c | 22 | ||||
-rw-r--r-- | libhb/muxmkv.c | 15 | ||||
-rw-r--r-- | libhb/sync.c | 42 | ||||
-rw-r--r-- | libhb/work.c | 6 |
7 files changed, 89 insertions, 35 deletions
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index ce4225a99..94e5c216b 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -196,7 +196,7 @@ static options_map_t d_acodec_opts[] = {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"}, {"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"}, {"AC3 (pass-thru)", "ac3", HB_ACODEC_AC3, "ac3"}, -// {"DTS (pass-thru)", "dts", HB_ACODEC_DCA, "dts"}, + {"DTS (pass-thru)", "dts", HB_ACODEC_DCA, "dts"}, }; combo_opts_t acodec_opts = { diff --git a/libhb/common.c b/libhb/common.c index 0ddcccef5..88a8ea8ec 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -234,6 +234,7 @@ int hb_calc_bitrate( hb_job_t * job, int size ) samples_per_frame = 1152; break; case HB_ACODEC_AC3: + case HB_ACODEC_DCA: samples_per_frame = 1536; break; default: diff --git a/libhb/decdca.c b/libhb/decdca.c index 9d1bde71c..ec625c5bd 100644 --- a/libhb/decdca.c +++ b/libhb/decdca.c @@ -153,6 +153,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * buf; + hb_audio_t * audio = w->audio; int i, j, k; int64_t pts, pos; int num_blocks; @@ -210,16 +211,6 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) pts = -1; } - /* Feed libdca */ - dca_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 ); - - /* find out how many blocks are in this frame */ - num_blocks = dca_blocks_num( pv->state ); - - /* num_blocks blocks per frame, 256 samples per block, channelsused channels */ - int nsamp = num_blocks * 256; - buf = hb_buffer_init( nsamp * pv->out_discrete_channels * sizeof( float ) ); - // mkv files typically use a 1ms timebase which results in a lot of // truncation error in their timestamps. Also, TSMuxer or something // in the m2ts-to-mkv toolchain seems to take a very casual attitude @@ -230,6 +221,31 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) { pts = pv->next_pts; } + + double frame_dur = (double)(pv->frame_length & ~0xFF) / (double)pv->rate * 90000.; + + /* DCA passthrough: don't decode the DCA frame */ + if( audio->config.out.codec == HB_ACODEC_DCA ) + { + buf = hb_buffer_init( pv->size ); + memcpy( buf->data, pv->frame, pv->size ); + buf->start = pts; + pv->next_pts = pts + frame_dur; + buf->stop = pv->next_pts; + pv->sync = 0; + return buf; + } + + /* Feed libdca */ + dca_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 ); + + /* find out how many blocks are in this frame */ + num_blocks = dca_blocks_num( pv->state ); + + /* num_blocks blocks per frame, 256 samples per block, channelsused channels */ + int nsamp = num_blocks * 256; + buf = hb_buffer_init( nsamp * pv->out_discrete_channels * sizeof( float ) ); + buf->start = pts; pv->next_pts = pts + (double)nsamp / (double)pv->rate * 90000.; buf->stop = pv->next_pts; diff --git a/libhb/muxavi.c b/libhb/muxavi.c index 913e84508..4838ee133 100644 --- a/libhb/muxavi.c +++ b/libhb/muxavi.c @@ -332,6 +332,7 @@ static int AVIInit( hb_mux_object_t * m ) hb_mux_data_t * mux_data; int audio_count = hb_list_count( title->list_audio ); + int is_passthru = 0; int is_ac3 = 0; int hdrl_bytes; int i; @@ -427,6 +428,8 @@ static int AVIInit( hb_mux_object_t * m ) audio = hb_list_item( title->list_audio, i ); is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3); + is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) || + (audio->config.out.codec == HB_ACODEC_DCA); mux_data = calloc( sizeof( hb_mux_data_t ), 1 ); audio->priv.mux_data = mux_data; @@ -440,17 +443,17 @@ static int AVIInit( hb_mux_object_t * m ) h.Type = FOURCC( "auds" ); h.InitialFrames = 1; h.Scale = 1; - h.Rate = is_ac3 ? ( audio->config.in.bitrate / 8 ) : + h.Rate = is_passthru ? ( audio->config.in.bitrate / 8 ) : ( audio->config.out.bitrate * 1000 / 8 ); h.Quality = 0xFFFFFFFF; h.SampleSize = 1; /* Audio stream format */ f.FourCC = FOURCC( "strf" ); - if( is_ac3 ) + if( is_passthru ) { f.BytesCount = sizeof( hb_wave_formatex_t ) - 8; - f.FormatTag = 0x2000; + f.FormatTag = is_ac3 ? 0x2000 : 0x2001; f.Channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout); f.SamplesPerSec = audio->config.in.samplerate; } @@ -464,7 +467,7 @@ static int AVIInit( hb_mux_object_t * m ) } f.AvgBytesPerSec = h.Rate; f.BlockAlign = 1; - if( is_ac3 ) + if( is_passthru ) { f.Size = 0; } @@ -493,7 +496,7 @@ static int AVIInit( hb_mux_object_t * m ) ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) + /* audios strf */ audio_count * ( sizeof( hb_wave_formatex_t ) + - ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) ); + ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) ); /* Here we really start to write into the file */ @@ -537,11 +540,11 @@ static int AVIInit( hb_mux_object_t * m ) WriteInt32( m->file, FOURCC( "LIST" ) ); WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) + sizeof( hb_wave_formatex_t ) + - ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) ); + ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) ); WriteInt32( m->file, FOURCC( "strl" ) ); WriteStreamHeader( m->file, &mux_data->header ); WriteWaveFormatEx( m->file, &mux_data->format.a.f ); - if( !is_ac3 ) + if( !is_passthru ) { WriteWaveMp3( m->file, &mux_data->format.a.m ); } @@ -600,9 +603,12 @@ static int AVIMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, WriteInt32( m->file, job->mux_data->header.Length ); for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { + int is_passthru; audio = hb_list_item( title->list_audio, i ); + is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) || + (audio->config.out.codec == HB_ACODEC_DCA); fseek( m->file, 264 + i * - ( 102 + ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? 0 : + ( 102 + ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) ), SEEK_SET ); WriteInt32( m->file, audio->priv.mux_data->header.Length ); } diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 83a7daa45..fa9241fe6 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -165,6 +165,11 @@ static int MKVInit( hb_mux_object_t * m ) switch (audio->config.out.codec) { + case HB_ACODEC_DCA: + track->codecPrivate = NULL; + track->codecPrivateSize = 0; + track->codecID = MK_ACODEC_DTS; + break; case HB_ACODEC_AC3: track->codecPrivate = NULL; track->codecPrivateSize = 0; @@ -221,7 +226,15 @@ static int MKVInit( hb_mux_object_t * m ) track->trackType = MK_TRACK_AUDIO; track->language = audio->config.lang.iso639_2; track->extra.audio.samplingFreq = (float)audio->config.out.samplerate; - track->extra.audio.channels = (audio->config.out.codec == HB_ACODEC_AC3 ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); + if (audio->config.out.codec == HB_ACODEC_AC3 || + audio->config.out.codec == HB_ACODEC_DCA) + { + track->extra.audio.channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout); + } + else + { + track->extra.audio.channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); + } // track->defaultDuration = job->arate * 1000; mux_data->track = mk_createTrack(m->file, track); if (audio->config.out.codec == HB_ACODEC_VORBIS && track->codecPrivate != NULL) diff --git a/libhb/sync.c b/libhb/sync.c index 920a0e388..f7b342b61 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -60,6 +60,7 @@ struct hb_work_private_s /* Audio */ hb_sync_audio_t sync_audio[8]; + int64_t audio_passthru_slip; /* Statistics */ uint64_t st_counts[4]; @@ -351,7 +352,8 @@ static void SyncVideo( hb_work_object_t * w ) * can deal with overlaps of up to a frame time but anything larger * we handle by dropping frames here. */ - if ( (int64_t)( next->start - cur->start ) <= 0 ) + if ( (int64_t)( next->start - cur->start ) <= 0 || + (int64_t)( (cur->start - pv->audio_passthru_slip ) - pv->next_pts ) < 0 ) { if ( pv->first_drop == 0 ) { @@ -730,8 +732,10 @@ static void SyncAudio( hb_work_object_t * w, int i ) hb_audio_t * audio = sync->audio; hb_buffer_t * buf; hb_fifo_t * fifo; + int64_t start; - if( audio->config.out.codec == HB_ACODEC_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3 || + audio->config.out.codec == HB_ACODEC_DCA ) { fifo = audio->priv.fifo_out; } @@ -742,6 +746,7 @@ static void SyncAudio( hb_work_object_t * w, int i ) while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->priv.fifo_raw ) ) ) { + start = buf->start - pv->audio_passthru_slip; /* if the next buffer is an eof send it downstream */ if ( buf->size <= 0 ) { @@ -756,13 +761,13 @@ static void SyncAudio( hb_work_object_t * w, int i ) pv->busy &=~ (1 << (i + 1) ); return; } - if ( (int64_t)( buf->start - sync->next_pts ) < 0 ) + if ( (int64_t)( start - sync->next_pts ) < 0 ) { // audio time went backwards. // If our output clock is more than a half frame ahead of the // input clock drop this frame to move closer to sync. // Otherwise drop frames until the input clock matches the output clock. - if ( sync->first_drop || sync->next_start - buf->start > 90*15 ) + if ( sync->first_drop || sync->next_start - start > 90*15 ) { // Discard data that's in the past. if ( sync->first_drop == 0 ) @@ -774,7 +779,7 @@ static void SyncAudio( hb_work_object_t * w, int i ) hb_buffer_close( &buf ); continue; } - sync->next_pts = buf->start; + sync->next_pts = start; } if ( sync->first_drop ) { @@ -785,19 +790,19 @@ static void SyncAudio( hb_work_object_t * w, int i ) sync->drop_count, sync->first_drop, sync->next_pts ); sync->first_drop = 0; sync->drop_count = 0; - sync->next_pts = buf->start; + sync->next_pts = start; } - if ( buf->start - sync->next_pts >= (90 * 70) ) + if ( start - sync->next_pts >= (90 * 70) ) { - if ( buf->start - sync->next_pts > (90000LL * 60) ) + if ( start - sync->next_pts > (90000LL * 60) ) { // there's a gap of more than a minute between the last // frame and this. assume we got a corrupted timestamp // and just drop the next buf. hb_log( "sync: %d minute time gap in audio %d - dropping buf" " start %lld, next %lld", - (int)((buf->start - sync->next_pts) / (90000*60)), - i, buf->start, sync->next_pts ); + (int)((start - sync->next_pts) / (90000*60)), + i, start, sync->next_pts ); buf = hb_fifo_get( audio->priv.fifo_raw ); hb_buffer_close( &buf ); continue; @@ -805,12 +810,23 @@ static void SyncAudio( hb_work_object_t * w, int i ) /* * there's a gap of at least 70ms between the last * frame we processed & the next. Fill it with silence. + * Or in the case of DCA, skip some frames from the + * other streams. */ + if( sync->audio->config.out.codec == HB_ACODEC_DCA ) + { + hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d" + " start %lld, next %lld", + (int)((start - sync->next_pts) / 90), + i, start, sync->next_pts ); + pv->audio_passthru_slip += (start - sync->next_pts); + return; + } hb_log( "sync: adding %d ms of silence to audio %d" " start %lld, next %lld", - (int)((buf->start - sync->next_pts) / 90), - i, buf->start, sync->next_pts ); - InsertSilence( w, i, buf->start - sync->next_pts ); + (int)((start - sync->next_pts) / 90), + i, start, sync->next_pts ); + InsertSilence( w, i, start - sync->next_pts ); return; } diff --git a/libhb/work.c b/libhb/work.c index b6e4aa6c2..42613c3fb 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -576,7 +576,8 @@ static void do_job( hb_job_t * job, int cpu_count ) /* sense-check the requested mixdown */ if( audio->config.out.mixdown == 0 && - audio->config.out.codec != HB_ACODEC_AC3 ) + audio->config.out.codec != HB_ACODEC_AC3 && + audio->config.out.codec != HB_ACODEC_DCA ) { /* * Mixdown wasn't specified and this is not pass-through, @@ -742,7 +743,8 @@ static void do_job( hb_job_t * job, int cpu_count ) /* * Audio Encoder Thread */ - if( audio->config.out.codec != HB_ACODEC_AC3 ) + if( audio->config.out.codec != HB_ACODEC_AC3 && + audio->config.out.codec != HB_ACODEC_DCA ) { /* * Add the encoder thread if not doing AC-3 pass through |