This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 57708daf619c1de0ea25366ef11e527f292acd55
Author:     James Almer <[email protected]>
AuthorDate: Thu Jun 4 14:51:57 2026 -0300
Commit:     James Almer <[email protected]>
CommitDate: Sat Jul 11 19:32:17 2026 -0300

    avcodec/dca_core: export downmix matrix coefficients
    
    $ ./ffmpeg -downmix stereo -i 
$fate-suite/dts/dcadec-suite/core_51_24_48_768_1.dtshd -y native.wav
    
    Before:
    $ ./ffmpeg -i $fate-suite/dts/dcadec-suite/core_51_24_48_768_1.dtshd -af 
aresample,aformat=channel_layouts=stereo -y swr.wav
    [...]
    [Parsed_aresample_0] [SWR] Using fltp internally between filters
    [Parsed_aresample_0] [SWR] Matrix coefficients:
    [Parsed_aresample_0] [SWR] FL: FL:0.414214 FR:0.000000 FC:0.292893 
LFE:0.000000 SL:0.292893 SR:0.000000
    [Parsed_aresample_0] [SWR] FR: FL:0.000000 FR:0.414214 FC:0.292893 
LFE:0.000000 SL:0.000000 SR:0.292893
    [Parsed_aresample_0] ch:6 chl:5.1(side) fmt:fltp r:48000Hz -> ch:2 
chl:stereo fmt:s16 r:48000Hz
    [...]
    
    $ tests/tiny_psnr.exe native.wav swr.wav s16
    stddev:18907.06 PSNR: 10.80 MAXDIFF:51590 bytes:     8192/     8192
    
    After:
    $ ./ffmpeg -i $fate-suite/dts/dcadec-suite/core_51_24_48_768_1.dtshd -af 
aresample,aformat=channel_layouts=stereo -y swr.wav
    [...]
    [Parsed_aresample_0] [SWR] Using fltp internally between filters
    [Parsed_aresample_0] [SWR] Custom matrix coefficients:
    [Parsed_aresample_0] [SWR] FL: FL:-0.100006 FR:0.000000 FC:0.000000 
LFE:0.000000 SL:-0.707092 SR:0.000000
    [Parsed_aresample_0] [SWR] FR: FL:0.000000 FR:-0.100006 FC:0.000000 
LFE:0.000000 SL:0.000000 SR:-0.707092
    [Parsed_aresample_0] ch:6 chl:5.1(side) fmt:fltp r:48000Hz -> ch:2 
chl:stereo fmt:s16 r:48000Hz
    [...]
    
    $ tests/tiny_psnr.exe native.wav swr.wav
    stddev:    0.02 PSNR:129.44 MAXDIFF:    1 bytes:     8192/     8192
    
    Signed-off-by: James Almer <[email protected]>
---
 libavcodec/dca_core.c | 11 +++++++
 libavcodec/dcadec.c   | 79 ++++++++++++++++++++++++++++++++++++++++++++-------
 libavcodec/dcadec.h   |  3 ++
 tests/fate/dca.mak    |  5 +++-
 4 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c
index cb1f7b7bbf..8383358b97 100644
--- a/libavcodec/dca_core.c
+++ b/libavcodec/dca_core.c
@@ -2384,6 +2384,17 @@ int ff_dca_core_filter_frame(DCACoreDecoder *s, AVFrame 
*frame)
     else
         avctx->bit_rate = 0;
 
+    if (s->request_mask == s->ch_mask && s->prim_dmix_embedded &&
+        !s->sumdiff_front && !s->sumdiff_surround &&
+        !(s->ext_audio_mask & (DCA_CSS_XXCH | DCA_CSS_XCH | DCA_EXSS_XXCH)) &&
+        s->audio_mode >= DCA_AMODE_2F2R && (s->prim_dmix_type == 
DCA_DMIX_TYPE_LoRo ||
+                                            s->prim_dmix_type == 
DCA_DMIX_TYPE_LtRt)) {
+        ret = ff_dca_export_downmix_matrix(avctx, frame, s->prim_dmix_type, 
s->ch_mask,
+                                           s->prim_dmix_coeff);
+        if (ret < 0)
+            return ret;
+    }
+
     if (s->audio_mode == DCA_AMODE_STEREO_TOTAL || (s->request_mask != 
s->ch_mask &&
                                                     s->prim_dmix_type == 
DCA_DMIX_TYPE_LtRt))
         matrix_encoding = AV_MATRIX_ENCODING_DOLBY;
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index 7fbd2c6e3f..55308abfd1 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -21,10 +21,12 @@
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/channel_layout.h"
+#include "libavutil/downmix_info.h"
 #include "libavutil/thread.h"
 
 #include "codec_internal.h"
 #include "dcadec.h"
+#include "dcadata.h"
 #include "dcahuff.h"
 #include "dca_syncwords.h"
 #include "profiles.h"
@@ -32,18 +34,19 @@
 #define MIN_PACKET_SIZE     16
 #define MAX_PACKET_SIZE     0x104000
 
-int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int 
dca_mask)
-{
-    static const uint8_t dca2wav_norm[28] = {
-         2,  0, 1, 9, 10,  3,  8,  4,  5,  9, 10, 6, 7, 12,
-        13, 14, 3, 6,  7, 11, 12, 14, 16, 15, 17, 8, 4,  5,
-    };
 
-    static const uint8_t dca2wav_wide[28] = {
-         2,  0, 1, 4,  5,  3,  8,  4,  5,  9, 10, 6, 7, 12,
-        13, 14, 3, 6,  7, 11, 12, 14, 16, 15, 17, 8, 4,  5,
-    };
+static const uint8_t dca2wav_norm[28] = {
+     2,  0, 1, 9, 10,  3,  8,  4,  5,  9, 10, 6, 7, 12,
+    13, 14, 3, 6,  7, 11, 12, 14, 16, 15, 17, 8, 4,  5,
+};
+
+static const uint8_t dca2wav_wide[28] = {
+     2,  0, 1, 4,  5,  3,  8,  4,  5,  9, 10, 6, 7, 12,
+    13, 14, 3, 6,  7, 11, 12, 14, 16, 15, 17, 8, 4,  5,
+};
 
+int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int 
dca_mask)
+{
     DCAContext *s = avctx->priv_data;
 
     int dca_ch, wav_ch, nchannels = 0;
@@ -156,6 +159,62 @@ void ff_dca_downmix_to_stereo_float(AVFloatDSPContext 
*fdsp, float **samples,
     }
 }
 
+int ff_dca_export_downmix_matrix(AVCodecContext *avctx, AVFrame *frame,
+                                 enum DCADownMixType downmix_type,
+                                 int output_mask, const int *coeff_l)
+{
+    enum AVDownmixType dmix_type = (downmix_type == DCA_DMIX_TYPE_LoRo) ?
+                                    AV_DOWNMIX_TYPE_LORO : 
AV_DOWNMIX_TYPE_LTRT;
+    size_t size;
+    AVDownmixMatrix *dm = av_downmix_matrix_alloc(dmix_type, 
av_popcount(output_mask), &size);
+    const int *coeff_r = coeff_l + av_popcount(output_mask);
+    const double scale = 1.0 / (1 << 15);
+    AVDownmixCoeff *matrix_l, *matrix_r;
+    const uint8_t *dca2wav;
+
+    if (!dm)
+        return AVERROR(ENOMEM);
+
+    if (output_mask == DCA_SPEAKER_LAYOUT_7POINT0_WIDE ||
+        output_mask == DCA_SPEAKER_LAYOUT_7POINT1_WIDE)
+        dca2wav = dca2wav_wide;
+    else
+        dca2wav = dca2wav_norm;
+
+    matrix_l = av_downmix_matrix_coeff(dm, 0, 0);
+    matrix_r = av_downmix_matrix_coeff(dm, 1, 0);
+
+    for (int i = 0; i <= av_log2(output_mask); i++) {
+        if (!(output_mask & (1U << i)))
+            continue;
+
+        int idx = av_channel_layout_index_from_channel(&avctx->ch_layout, 
dca2wav[i]);
+        av_assert0(idx >= 0);
+
+        if (*coeff_l)
+            matrix_l[idx] = *coeff_l * scale;
+
+        if (*coeff_r)
+            matrix_r[idx] = *coeff_r * scale;
+
+        coeff_l++;
+        coeff_r++;
+    }
+
+    AVBufferRef *buf = av_buffer_create((uint8_t *)dm, size, NULL, NULL, 0);
+    if (!buf) {
+        av_free(dm);
+        return AVERROR(ENOMEM);
+    }
+
+    if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOWNMIX_MATRIX, 
buf)) {
+        av_buffer_unref(&buf);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
 static int dcadec_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                                int *got_frame_ptr, AVPacket *avpkt)
 {
diff --git a/libavcodec/dcadec.h b/libavcodec/dcadec.h
index 0ff28dd4d1..b54eeb99d5 100644
--- a/libavcodec/dcadec.h
+++ b/libavcodec/dcadec.h
@@ -80,6 +80,9 @@ void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, 
int32_t **samples,
                                     int *coeff_l, int nsamples, int ch_mask);
 void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples,
                                     int *coeff_l, int nsamples, int ch_mask);
+int ff_dca_export_downmix_matrix(AVCodecContext *avctx, AVFrame *frame,
+                                 enum DCADownMixType downmix_type,
+                                 int output_mask, const int *coeff_l);
 
 static inline int ff_dca_check_crc(AVCodecContext *avctx, GetBitContext *s,
                                    int p1, int p2)
diff --git a/tests/fate/dca.mak b/tests/fate/dca.mak
index 609f924aa3..e083d6fd28 100644
--- a/tests/fate/dca.mak
+++ b/tests/fate/dca.mak
@@ -39,10 +39,13 @@ $(foreach N,$(DCADEC_SUITE_LOSSLESS_24),$(eval $(call 
FATE_DCADEC_LOSSLESS_SUITE
 $(foreach N,$(DCADEC_SUITE_LOSSY),$(eval $(call FATE_DCADEC_LOSSY_SUITE,$(N))))
 
 # lossy downmix tests
-FATE_DCADEC_LOSSY += fate-dca-core_51_24_48_768_1-dmix_2
+FATE_DCADEC_LOSSY += fate-dca-core_51_24_48_768_1-dmix_2 
fate-dca-core_51_24_48_768_1-dmix_2_matrix
 fate-dca-core_51_24_48_768_1-dmix_2: CMD = ffmpeg -downmix stereo -flags2 
skip_manual -i $(TARGET_SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1.dtshd -f 
f32le -af aresample -
 fate-dca-core_51_24_48_768_1-dmix_2: REF = 
$(SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1-dmix_2.f32
 
+fate-dca-core_51_24_48_768_1-dmix_2_matrix: CMD = ffmpeg -flags2 skip_manual 
-i $(TARGET_SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1.dtshd -f f32le -af 
aresample,aformat=channel_layouts=stereo -
+fate-dca-core_51_24_48_768_1-dmix_2_matrix: REF = 
$(SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1-dmix_2.f32
+
 FATE_DCADEC_LOSSY += fate-dca-x96_xxch_71_24_96_3840-dmix_2
 fate-dca-x96_xxch_71_24_96_3840-dmix_2: CMD = ffmpeg -downmix stereo -flags2 
skip_manual -i $(TARGET_SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840.dtshd 
-f f32le -af aresample -
 # intentionally uses the dmix_6 reference because the sample does not contain 
stereo downmix coefficients

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to