]> granicus.if.org Git - handbrake/commitdiff
Enable DTS passthru for matroska container
authorjstebbins <jstebbins.hb@gmail.com>
Sat, 18 Apr 2009 18:44:01 +0000 (18:44 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Sat, 18 Apr 2009 18:44:01 +0000 (18:44 +0000)
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

gtk/src/hb-backend.c
libhb/common.c
libhb/decdca.c
libhb/muxavi.c
libhb/muxmkv.c
libhb/sync.c
libhb/work.c

index ce4225a995e7d8489261912f4e2e660192c781f4..94e5c216bbff375d16a9bf34409ca0c8ffe6513a 100644 (file)
@@ -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 =
 {
index 0ddcccef576384690b08f411d42ac71ef8961591..88a8ea8ec07e4e0d98e26a1b33db9db208952a9a 100644 (file)
@@ -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:
index 9d1bde71c3041f9b1cafcc025ccf9e524399ab7b..ec625c5bd6726fe049a0d62a7d0902046fd9922e 100644 (file)
@@ -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;
index 913e84508fa6cce52c8056f5373e336dd0c608f4..4838ee1330e80b502546be0fa7e574ae48878b90 100644 (file)
@@ -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 );
     }
index 83a7daa45ca0c696e5a0fd58010abe654c4d8bc6..fa9241fe6ffbe3e7cc66fa19bad42e2b501d5bab 100644 (file)
@@ -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)
index 920a0e3889a7948acbeebe421d28755c8b8473df..f7b342b61676d0a79a74431c4fd70cdd4c986c72 100644 (file)
@@ -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;
         }
 
index b6e4aa6c29a2cb8355e15a92bd4f1d6d6cad5381..42613c3fb78c7c666e39ac5261a50b997fb907c4 100644 (file)
@@ -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