]> granicus.if.org Git - handbrake/commitdiff
audio_resample: fix mapping of mono to single channel (#593)
authorJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 24 Feb 2017 17:28:33 +0000 (10:28 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 24 Feb 2017 17:32:40 +0000 (10:32 -0700)
* audio_resample: fix mapping of mono to single channel

libav's mixer code can't map single channel layouts to other single
channel layouts. And we were asking it to map e.g. front left to front
center because out MONO mixdown == libav front center.  So when we
request MONO and the source is any single channel, change our output
layout to match the input.

fixes
https://forum.handbrake.fr/viewtopic.php?f=12&t=36016&sid=c5993fa7375792a940152c8adda19a54

* Incorporate Rodeo's suggestions

* fix grammar

(cherry picked from commit b7882e031c91817da3d69df9968656904c4f9640)

libhb/audio_resample.c

index edd84a5890d19ae6edce5d6c84909bf4383e7f15..35585dd663bc0e416a53bf4971130b966470fdb1 100644 (file)
@@ -75,6 +75,26 @@ fail:
     return NULL;
 }
 
+static int is_mono(uint64_t layout)
+{
+    int ii, channel_count;
+    int64_t mask;
+
+    if (layout == AV_CH_LAYOUT_NATIVE)
+    {
+        return 0;
+    }
+    for (ii = 0, channel_count = 0, mask = 1;
+         ii < 64 && channel_count < 2; ii++, mask <<= 1)
+    {
+        if (layout & mask)
+        {
+            channel_count++;
+        }
+    }
+    return channel_count == 1;
+}
+
 void hb_audio_resample_set_channel_layout(hb_audio_resample_t *resample,
                                           uint64_t channel_layout)
 {
@@ -85,6 +105,13 @@ void hb_audio_resample_set_channel_layout(hb_audio_resample_t *resample,
             // Dolby Surround is Stereo when it comes to remixing
             channel_layout = AV_CH_LAYOUT_STEREO;
         }
+        // avresample can't remap a single-channel layout to
+        // another single-channel layout
+        if (resample->out.channel_layout == AV_CH_LAYOUT_MONO &&
+            is_mono(channel_layout))
+        {
+            channel_layout = AV_CH_LAYOUT_MONO;
+        }
         resample->in.channel_layout = channel_layout;
     }
 }