OSDN Git Service

cli: make smarter mixdown decision when doing ac3 encode fallback
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 8 Oct 2010 20:30:53 +0000 (20:30 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 8 Oct 2010 20:30:53 +0000 (20:30 +0000)
also, clean up the mixdown sanitizing logic in work.c
added new functions
hb_get_default_mix(codec, layout)
hb_get_best_mix(codec, layout)

These take the output codec and the input layout as parameters.

git-svn-id: svn://localhost/HandBrake/trunk@3580 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/common.c
libhb/common.h
libhb/work.c
test/test.c

index 0c8c5cf..7b7e4d5 100644 (file)
@@ -201,6 +201,108 @@ int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown )
     return bitrate;
 }
 
+int hb_get_best_mixdown( uint32_t codec, int layout )
+{
+    switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
+    {
+        // stereo input or something not handled below
+        default:
+        case HB_INPUT_CH_LAYOUT_STEREO:
+            // mono gets mixed up to stereo & more than stereo gets mixed down
+            return HB_AMIXDOWN_STEREO;
+
+        // mono input
+        case HB_INPUT_CH_LAYOUT_MONO:
+            // everything else passes through
+            return HB_AMIXDOWN_MONO;
+
+        // dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input
+        // the A52 flags don't allow for a way to distinguish between DPL1 and
+        // DPL2 on a DVD so we always assume a DPL1 source for A52_DOLBY.
+        case HB_INPUT_CH_LAYOUT_DOLBY:
+            return HB_AMIXDOWN_DOLBY;
+
+        // 4 channel discrete
+        case HB_INPUT_CH_LAYOUT_2F2R:
+        case HB_INPUT_CH_LAYOUT_3F1R:
+            // a52dec and libdca can't upmix to 6ch, 
+            // so we must downmix these.
+            return HB_AMIXDOWN_DOLBYPLII;
+
+        // 5 or 6 channel discrete
+        case HB_INPUT_CH_LAYOUT_3F2R:
+            if ( ! ( layout & HB_INPUT_CH_LAYOUT_HAS_LFE ) )
+            {
+                // we don't do 5 channel discrete so mixdown to DPLII
+                // a52dec and libdca can't upmix to 6ch, 
+                // so we must downmix this.
+                return HB_AMIXDOWN_DOLBYPLII;
+            }
+            else
+            {
+                switch (codec)
+                {
+                    case HB_ACODEC_LAME:
+                        return HB_AMIXDOWN_DOLBYPLII;
+
+                    default:
+                        return HB_AMIXDOWN_6CH;
+                }
+            }
+    }
+}
+
+int hb_get_default_mixdown( uint32_t codec, int layout )
+{
+    switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
+    {
+        // stereo input or something not handled below
+        default:
+        case HB_INPUT_CH_LAYOUT_STEREO:
+            // mono gets mixed up to stereo & more than stereo gets mixed down
+            return HB_AMIXDOWN_STEREO;
+
+        // mono input
+        case HB_INPUT_CH_LAYOUT_MONO:
+            // everything else passes through
+            return HB_AMIXDOWN_MONO;
+
+        // dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input
+        // the A52 flags don't allow for a way to distinguish between DPL1 and
+        // DPL2 on a DVD so we always assume a DPL1 source for A52_DOLBY.
+        case HB_INPUT_CH_LAYOUT_DOLBY:
+            return HB_AMIXDOWN_DOLBY;
+
+        // 4 channel discrete
+        case HB_INPUT_CH_LAYOUT_2F2R:
+        case HB_INPUT_CH_LAYOUT_3F1R:
+            // a52dec and libdca can't upmix to 6ch, 
+            // so we must downmix these.
+            return HB_AMIXDOWN_DOLBYPLII;
+
+        // 5 or 6 channel discrete
+        case HB_INPUT_CH_LAYOUT_3F2R:
+            if ( ! ( layout & HB_INPUT_CH_LAYOUT_HAS_LFE ) )
+            {
+                // we don't do 5 channel discrete so mixdown to DPLII
+                // a52dec and libdca can't upmix to 6ch, 
+                // so we must downmix this.
+                return HB_AMIXDOWN_DOLBYPLII;
+            }
+            else
+            {
+                switch (codec)
+                {
+                    case HB_ACODEC_AC3:
+                        return HB_AMIXDOWN_6CH;
+
+                    default:
+                        return HB_AMIXDOWN_DOLBYPLII;
+                }
+            }
+    }
+}
+
 /**********************************************************************
  * hb_reduce
  **********************************************************************
index b21abb3..2a3d070 100644 (file)
@@ -150,6 +150,8 @@ extern hb_mixdown_t hb_audio_mixdowns[];
 extern int          hb_audio_mixdowns_count;
 int hb_mixdown_get_mixdown_from_short_name( const char * short_name );
 const char * hb_mixdown_get_short_name_from_mixdown( int amixdown );
+int hb_get_best_mixdown( uint32_t codec, int layout );
+int hb_get_default_mixdown( uint32_t codec, int layout );
 int hb_find_closest_audio_bitrate(int bitrate);
 void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high);
 int hb_get_best_audio_bitrate( uint32_t codec, int bitrate, int samplerate, int mixdown);
index b7dda27..7fdcab8 100644 (file)
@@ -559,100 +559,55 @@ static void do_job( hb_job_t * job, int cpu_count )
     }
 
     int requested_mixdown = 0;
+    int best_mixdown = 0;
     int requested_mixdown_index = 0;
 
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio = hb_list_item( title->list_audio, i );
 
-        if( audio->config.out.codec != audio->config.in.codec )
-        {
-            /* sense-check the current mixdown options */
+        best_mixdown = hb_get_best_mixdown( audio->config.out.codec,
+                                            audio->config.in.channel_layout );
 
-            /* log the requested mixdown */
-            for (j = 0; j < hb_audio_mixdowns_count; j++) {
-                if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {
-                    requested_mixdown = audio->config.out.mixdown;
-                    requested_mixdown_index = j;
-                }
-            }
+        /* sense-check the current mixdown options */
 
-            /* sense-check the requested mixdown */
-
-            if( audio->config.out.mixdown == 0 &&
-                audio->config.out.codec != HB_ACODEC_AC3_PASS && 
-                audio->config.out.codec != HB_ACODEC_DCA_PASS )
-            {
-                /*
-                 * Mixdown wasn't specified and this is not pass-through,
-                 * set a default mixdown of stereo.
-                 */
-                audio->config.out.mixdown = HB_AMIXDOWN_STEREO;
+        /* log the requested mixdown */
+        for (j = 0; j < hb_audio_mixdowns_count; j++) {
+            if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {
+                requested_mixdown = audio->config.out.mixdown;
+                requested_mixdown_index = j;
             }
+        }
 
-            // Here we try to sanitize the audio input to output mapping.
-            // Constraints are:
-            //   1. only the AC3 & DCA decoder libraries currently support mixdown
-            //   2. the lame encoder library only supports stereo.
-            // So if the encoder is lame we need the output to be stereo (or multichannel
-            // matrixed into stereo like dpl). If the decoder is not AC3 or DCA the
-            // encoder has to handle the input format since we can't do a mixdown.
-            switch (audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
-            {
-                // stereo input or something not handled below
-                default:
-                case HB_INPUT_CH_LAYOUT_STEREO:
-                    // mono gets mixed up to stereo & more than stereo gets mixed down
-                    if ( audio->config.out.mixdown > HB_AMIXDOWN_STEREO )
-                    {
-                        audio->config.out.mixdown = HB_AMIXDOWN_STEREO;
-                    }
-                    break;
-
-                // mono input
-                case HB_INPUT_CH_LAYOUT_MONO:
-                    // everything else passes through
-                    audio->config.out.mixdown = HB_AMIXDOWN_MONO;
-                    break;
-
-                // dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input
-                // the A52 flags don't allow for a way to distinguish between DPL1 and
-                // DPL2 on a DVD so we always assume a DPL1 source for A52_DOLBY.
-                case HB_INPUT_CH_LAYOUT_DOLBY:
-                    if ( audio->config.out.mixdown > HB_AMIXDOWN_DOLBY )
-                    {
-                        audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;
-                    }
-                    break;
-
-                // 4 channel discrete
-                case HB_INPUT_CH_LAYOUT_2F2R:
-                case HB_INPUT_CH_LAYOUT_3F1R:
-                    if ( audio->config.out.mixdown > HB_AMIXDOWN_DOLBY )
-                    {
-                        audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;
-                    }
-                    break;
+        /* sense-check the requested mixdown */
+        if( audio->config.out.mixdown == 0 &&
+            audio->config.out.codec != HB_ACODEC_AC3_PASS && 
+            audio->config.out.codec != HB_ACODEC_DCA_PASS )
+        {
+            /*
+             * Mixdown wasn't specified and this is not pass-through,
+             * set a default mixdown
+             */
+            audio->config.out.mixdown = best_mixdown;
+        }
 
-                // 5 or 6 channel discrete
-                case HB_INPUT_CH_LAYOUT_3F2R:
-                    if ( ! ( audio->config.in.channel_layout &
-                                    HB_INPUT_CH_LAYOUT_HAS_LFE ) )
-                    {
-                        // we don't do 5 channel discrete so mixdown to DPLII
-                        audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII;
-                    }
-                    break;
+        if ( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) )
+        {
+            if ( audio->config.out.mixdown > best_mixdown )
+            {
+                audio->config.out.mixdown = best_mixdown;
             }
+        }
 
+        if ( audio->config.out.mixdown != requested_mixdown )
+        {
             /* log the output mixdown */
-            for (j = 0; j < hb_audio_mixdowns_count; j++) {
-                if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {
-                    if ( audio->config.out.mixdown != requested_mixdown )
-                    {
-                        hb_log("work: sanitizing track %i mixdown %s to %s", i, hb_audio_mixdowns[requested_mixdown_index].human_readable_name, hb_audio_mixdowns[j].human_readable_name);
-                    }
-                    break;
+            for (j = 0; j < hb_audio_mixdowns_count; j++)
+            {
+                if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown)
+                {
+                    hb_log("work: sanitizing track %i mixdown %s to %s", i, hb_audio_mixdowns[requested_mixdown_index].human_readable_name, hb_audio_mixdowns[j].human_readable_name);
+                break;
                 }
             }
         }
index 5cacd82..019bdb0 100644 (file)
@@ -1796,26 +1796,11 @@ static int HandleEvents( hb_handle_t * h )
                      ( audio->out.codec & HB_ACODEC_PASS_FLAG ) &&
                     !( audio->out.codec & audio->in.codec ) )
                 {
-                    int channels;
                     audio->out.codec = HB_ACODEC_AC3;
-                    channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->in.channel_layout);
-                    // bitrate setting is a placeholder till we get 
-                    // defaults and limits implemented in libhb
-                    if (channels == 1)
-                    {
-                        audio->out.mixdown = HB_AMIXDOWN_MONO;
-                        audio->out.bitrate = 96;
-                    }
-                    if (channels == 2)
-                    {
-                        audio->out.mixdown = HB_AMIXDOWN_DOLBYPLII;
-                        audio->out.bitrate = 224;
-                    }
-                    else
-                    {
-                        audio->out.mixdown = HB_AMIXDOWN_6CH;
-                        audio->out.bitrate = 640;
-                    }
+                    audio->out.mixdown = hb_get_default_mixdown( audio->out.codec, audio->in.channel_layout );
+                    audio->out.bitrate = hb_get_default_audio_bitrate(
+                        audio->out.codec, audio->out.samplerate,
+                        audio->out.mixdown );
                 }
                 // fix 'copy' to select a specific codec
                 if ( audio->out.codec & HB_ACODEC_PASS_FLAG )