OSDN Git Service

add test to ensure that ffmpeg's reported audio layout agrees with channel count
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 24 Apr 2010 17:36:07 +0000 (17:36 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 24 Apr 2010 17:36:07 +0000 (17:36 +0000)
a crash report from a user leads me to believe ffmpeg is giving us
a channel layout that has a different number of channels than the
channel count it tells us.

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

libhb/hb.c
libhb/stream.c

index 30fce03..1a72565 100644 (file)
@@ -86,47 +86,95 @@ int hb_avcodec_close(AVCodecContext *avctx)
 
 int hb_ff_layout_xlat(int64_t ff_channel_layout, int channels)
 {
+    int hb_layout;
+
     switch (ff_channel_layout)
     {
         case CH_LAYOUT_MONO:
-            return HB_INPUT_CH_LAYOUT_MONO;
+            hb_layout = HB_INPUT_CH_LAYOUT_MONO;
+            break;
         case CH_LAYOUT_STEREO:
-            return HB_INPUT_CH_LAYOUT_STEREO;
+            hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
+            break;
         case CH_LAYOUT_SURROUND:
-            return HB_INPUT_CH_LAYOUT_3F;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F;
+            break;
         case CH_LAYOUT_4POINT0:
-            return HB_INPUT_CH_LAYOUT_3F1R;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
+            break;
         case CH_LAYOUT_2_2:
-            return HB_INPUT_CH_LAYOUT_2F2R;
+            hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
+            break;
         case CH_LAYOUT_QUAD:
-            return HB_INPUT_CH_LAYOUT_2F2R;
+            hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
+            break;
         case CH_LAYOUT_5POINT0:
-            // ffmpeg like to neglect to signal LFE
-            if (channels == 6)
-                return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
-            return HB_INPUT_CH_LAYOUT_3F2R;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
+            break;
         case CH_LAYOUT_5POINT1:
-            return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            break;
         case CH_LAYOUT_5POINT0_BACK:
-            // ffmpeg like to neglect to signal LFE
-            if (channels == 6)
-                return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
-            return HB_INPUT_CH_LAYOUT_3F2R;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
+            break;
         case CH_LAYOUT_5POINT1_BACK:
-            return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            break;
         case CH_LAYOUT_7POINT0:
-            // ffmpeg like to neglect to signal LFE
-            if (channels == 8)
-                return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
-            return HB_INPUT_CH_LAYOUT_3F4R;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
+            break;
         case CH_LAYOUT_7POINT1:
-            return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            break;
         case CH_LAYOUT_STEREO_DOWNMIX:
-            return HB_INPUT_CH_LAYOUT_STEREO;
+            hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
+            break;
+        default:
+            hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
+            break;
+    }
+    // Now make sure the chosen layout agrees with the number of channels
+    // ffmpeg tells us there are.  It seems ffmpeg is sometimes confused
+    // about this. So we will make a best guess based on the number
+    // of channels.
+    int chans = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( hb_layout );
+    if ( chans == channels )
+    {
+        return hb_layout;
+    }
+    hb_log( "Channels reported by ffmpeg (%d) != computed layout channels (%d).\n", channels, chans );
+    switch (channels)
+    {
+        case 1:
+            hb_layout = HB_INPUT_CH_LAYOUT_MONO;
+            break;
+        case 2:
+            hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
+            break;
+        case 3:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F;
+            break;
+        case 4:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
+            break;
+        case 5:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
+            break;
+        case 6:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            break;
+        case 7:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
+            break;
+        case 8:
+            hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
+            break;
         default:
-            return HB_INPUT_CH_LAYOUT_STEREO;
+            hb_log("Unsupported number of audio channels (%d).\n", channels);
+            hb_layout = 0;
+            break;
     }
-    return HB_INPUT_CH_LAYOUT_STEREO;
+    return hb_layout;
 }
 
 /**
index f75400f..d2d2a4a 100644 (file)
@@ -2783,10 +2783,17 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id )
 {
     AVStream *st = stream->ffmpeg_ic->streams[id];
     AVCodecContext *codec = st->codec;
+    int layout;
 
     // scan will ignore any audio without a bitrate. Since we've already
     // typed the audio in order to determine its codec we set up the audio
     // paramters here.
+    layout = hb_ff_layout_xlat( codec->channel_layout, codec->channels );
+    if ( !layout )
+    {
+        // Unsupported layout
+        return;
+    }
     if ( codec->bit_rate || codec->sample_rate )
     {
         hb_audio_t *audio = calloc( 1, sizeof(*audio) );;
@@ -2807,8 +2814,7 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id )
 
             audio->config.in.bitrate = codec->bit_rate? codec->bit_rate : 1;
             audio->config.in.samplerate = codec->sample_rate;
-            audio->config.in.channel_layout = 
-                hb_ff_layout_xlat(codec->channel_layout, codec->channels);
+            audio->config.in.channel_layout = layout;
         }
 
         set_audio_description( audio, lang_for_code2( st->language ) );