mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-10-24 02:09:03 +03:00
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 <jamrial@gmail.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user