]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
update ch_layout implementation
authorUkn Unknown <4031821+uknunknown@users.noreply.github.com>
Mon, 26 May 2025 20:14:30 +0000 (13:14 -0700)
committerFlole <Flole998@users.noreply.github.com>
Fri, 12 Sep 2025 12:57:53 +0000 (14:57 +0200)
- check the returned value from av_channel_layout_copy()
- unreference all layouts properly
- match input with output when channel numbers are equal

src/transcoding/transcode/audio.c

index 4db5e070f54fdacc5db404c26379c0142bb6b704..6c6119877a68de4a347f6e14ea8f3e5bc79ac253 100644 (file)
@@ -80,34 +80,76 @@ _audio_context_sample_rate(TVHContext *self, AVDictionary **opts)
 
 
 #if LIBAVCODEC_VERSION_MAJOR > 59
-static int
+static void
 _audio_context_channel_layout(TVHContext *self, AVDictionary **opts, AVChannelLayout *dst)
 {
-    const AVChannelLayout *channel_layouts =
-        tvh_codec_profile_audio_get_channel_layouts(self->profile);
+    const AVChannelLayout *channel_layouts = tvh_codec_profile_audio_get_channel_layouts(self->profile);
     AVChannelLayout ilayout = {0};
-    av_channel_layout_copy(&ilayout, &self->iavctx->ch_layout);
     AVChannelLayout olayout;
     av_channel_layout_default(&olayout, 0);
     AVChannelLayout altlayout;
     av_channel_layout_default(&altlayout, 0);
     int ch_layout_u_mask = 0, i = 0;
     char obuf[64], abuf[64], ibuf[64];
-
+    // setup ilayout
+    if (av_channel_layout_copy(&ilayout, &self->iavctx->ch_layout)){
+        tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from input stream");
+        goto _audio_context_channel_layout_exit;
+    }
+    // setup olayout
     if (!tvh_context_get_int_opt(opts, "ch_layout_u_mask", &ch_layout_u_mask) &&
-        !(av_channel_layout_from_mask(&olayout, ch_layout_u_mask)) && channel_layouts) {
-        if (olayout.nb_channels > ilayout.nb_channels) {
-            olayout = ilayout;
+        // only if value selected is not auto
+        ch_layout_u_mask &&
+        av_channel_layout_from_mask(&olayout, ch_layout_u_mask)){
+        tvh_context_log(self, LOG_ERR, "unable to initialize output layout from bitmask");
+        goto _audio_context_channel_layout_exit;
+    }
+
+    if (!channel_layouts) {
+        tvh_context_log(self, LOG_ERR, "channel_layouts is not available");
+        if (av_channel_layout_copy(&olayout, &ilayout)){
+            tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from input layout to output layout");
+            goto _audio_context_channel_layout_exit;
+        }
+    }
+    // match input with output based on number of channels
+    if (olayout.nb_channels >= ilayout.nb_channels) {
+        // input layout will fit in output layout
+        if (av_channel_layout_copy(&olayout, &ilayout)){
+            tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from input layout to output layout");
+            goto _audio_context_channel_layout_exit;
         }
-        while (channel_layouts[i].nb_channels != 0) {
+    }
+    // order of selection: 
+    // 1. try olayout
+    if (olayout.order == AV_CHANNEL_ORDER_UNSPEC){
+        // prepare the alternative layout
+        while (channel_layouts && channel_layouts[i].nb_channels != 0) {
             if (channel_layouts[i].nb_channels <= ilayout.nb_channels) {
-                altlayout = channel_layouts[i];
+                //altlayout = channel_layouts[i];
+                if (av_channel_layout_copy(&altlayout, &channel_layouts[i])){
+                    tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from channel_layouts to alternative layout");
+                    goto _audio_context_channel_layout_exit;
+                }
             }
             i++;
         }
+        // 2. try altlayout
+        if (altlayout.order == AV_CHANNEL_ORDER_UNSPEC){
+            // 3. default to stereo
+            if (av_channel_layout_copy(&olayout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)){
+                tvh_context_log(self, LOG_ERR, "unable to setup ch_layout stereo layout");
+            }
+        }
+        else
+            // use altlayout
+            if (av_channel_layout_copy(&olayout, &altlayout)){
+                tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from alternative layout to output layout");
+            }
     }
-    else
-        olayout = ilayout;
+
+_audio_context_channel_layout_exit:
+    // logging
     if (tvhtrace_enabled()) {
         strcpy(obuf, "none");
         av_channel_layout_describe(&olayout, obuf, sizeof(obuf));
@@ -118,11 +160,13 @@ _audio_context_channel_layout(TVHContext *self, AVDictionary **opts, AVChannelLa
         tvh_context_log(self, LOG_TRACE, "audio layout selection: in %s, alt %s, out %s",
                                                                      ibuf,   abuf,   obuf);
     }
-    if (olayout.order != AV_CHANNEL_ORDER_UNSPEC)
-        return av_channel_layout_copy(dst, &olayout);
-    if (altlayout.order != AV_CHANNEL_ORDER_UNSPEC)
-        return av_channel_layout_copy(dst, &altlayout);
-    return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
+    if (av_channel_layout_copy(dst, &olayout)){
+        tvh_context_log(self, LOG_ERR, "unable to copy ch_layout from output layout to destination layout");
+    }
+    // clean
+    av_channel_layout_uninit(&ilayout);
+    av_channel_layout_uninit(&altlayout);
+    av_channel_layout_uninit(&olayout);
 }
 #else
 static uint64_t