mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-11-06 13:28:17 +00:00
A DTS:X stream in the standard presentation is DTS-HD Master Audio with a 7.1 bed and an extension at the end of every XLL frame, behind the syncword the decoder already recognises (DCA_SYNCWORD_XLL_X). The extension is a 22-byte header followed by a regular XLL channel set: four channels, every one coded in full (no residual against the core), no speaker mask, its own NAVI table with the frame's segment geometry, then a two-byte trailer. Its channels are the front and rear height pairs, and the encoder folds each of them into the bed speaker below it (L, R, Lsr, Rsr) at -3 dB, gain code 23170/32768, so the 7.1 bed plays them on players that ignore the extension. The decoder now parses that channel set with the existing channel set code, outputs 7.1.4 (TFL, TFR, TBL, TBR), and removes the fold from the bed at output resolution. A "downmix" request for 7.1 keeps the bed as coded, heights folded in, which is what the decoder output before; the requests for 5.1 and stereo skip the extension as well, so their output is unchanged. Streams without the extension are not affected. A frame whose extension does not decode keeps the 7.1.4 layout with silent heights and the bed as coded, and the frame still ends where it did before. The alternate presentations, which carry objects behind DCA_SYNCWORD_XLL_X_IMAX, are not touched. The format facts (header size, channel order, the fold) come from the public analysis in harletty-bridge's dca crate and kristofferR's SpatialAudioBridge; this is an implementation on FFmpeg's own XLL code, not a translation. Signed-off-by: Vincent Herbst <superuser404@tuta.com>
111 lines
3.6 KiB
C
111 lines
3.6 KiB
C
/*
|
|
* Copyright (C) 2016 foo86
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef AVCODEC_DCADEC_H
|
|
#define AVCODEC_DCADEC_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "libavutil/crc.h"
|
|
#include "libavutil/float_dsp.h"
|
|
#include "libavutil/log.h"
|
|
|
|
#include "avcodec.h"
|
|
#include "get_bits.h"
|
|
#include "dca.h"
|
|
#include "dcadsp.h"
|
|
#include "dca_core.h"
|
|
#include "dca_exss.h"
|
|
#include "dca_xll.h"
|
|
#include "dca_lbr.h"
|
|
|
|
#define DCA_PACKET_CORE 0x01
|
|
#define DCA_PACKET_EXSS 0x02
|
|
#define DCA_PACKET_XLL 0x04
|
|
#define DCA_PACKET_LBR 0x08
|
|
#define DCA_PACKET_MASK 0x0f
|
|
|
|
#define DCA_PACKET_RECOVERY 0x10 ///< Sync error recovery flag
|
|
#define DCA_PACKET_RESIDUAL 0x20 ///< Core valid for residual decoding
|
|
|
|
enum DCAOutputChannelOrder {
|
|
CHANNEL_ORDER_DEFAULT,
|
|
CHANNEL_ORDER_CODED,
|
|
};
|
|
|
|
typedef struct DCAContext {
|
|
const AVClass *class; ///< class for AVOptions
|
|
AVCodecContext *avctx;
|
|
|
|
DCACoreDecoder core; ///< Core decoder context
|
|
DCAExssParser exss; ///< EXSS parser context
|
|
DCAXllDecoder xll; ///< XLL decoder context
|
|
DCALbrDecoder lbr; ///< LBR decoder context
|
|
|
|
DCADSPContext dcadsp;
|
|
|
|
const AVCRC *crctab;
|
|
|
|
uint8_t *buffer; ///< Packet buffer
|
|
unsigned int buffer_size;
|
|
|
|
int packet; ///< Packet flags
|
|
|
|
int request_channel_layout; ///< Converted from avctx.request_channel_layout
|
|
int core_only; ///< Core only decoding flag
|
|
int output_channel_order;
|
|
AVChannelLayout downmix_layout;
|
|
int x_bed_only; ///< Keep a DTS:X 7.1 bed as coded, without its heights
|
|
} DCAContext;
|
|
|
|
int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask);
|
|
|
|
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)
|
|
{
|
|
DCAContext *dca = avctx->priv_data;
|
|
|
|
if (!(avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)))
|
|
return 0;
|
|
if (((p1 | p2) & 7) || p1 < 0 || p2 > s->size_in_bits || p2 - p1 < 16)
|
|
return -1;
|
|
if (av_crc(dca->crctab, 0xffff, s->buffer + p1 / 8, (p2 - p1) / 8))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
static inline int ff_dca_seek_bits(GetBitContext *s, int p)
|
|
{
|
|
if (p < get_bits_count(s) || p > s->size_in_bits)
|
|
return -1;
|
|
skip_bits_long(s, p - get_bits_count(s));
|
|
return 0;
|
|
}
|
|
|
|
#endif
|