summaryrefslogtreecommitdiff
path: root/libavcodec/mlpenc.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2022-09-18 14:44:27 +0200
committerPaul B Mahol <onemda@gmail.com>2022-09-18 15:13:37 +0200
commitb0579cc298519653406be5ae3d4d9358c0cb46fb (patch)
tree914dc7c9c414777ff3ac16ba1fef4c43c179be73 /libavcodec/mlpenc.c
parentc12a6fd227735e9d56c653dfa12bfd9f73ef222a (diff)
avcodec/mlpenc: improve encoding of stereo TrueHD and add mono support
Diffstat (limited to 'libavcodec/mlpenc.c')
-rw-r--r--libavcodec/mlpenc.c72
1 files changed, 53 insertions, 19 deletions
diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c
index 99b05476ad..b66f3a3067 100644
--- a/libavcodec/mlpenc.c
+++ b/libavcodec/mlpenc.c
@@ -122,6 +122,7 @@ typedef struct MLPEncodeContext {
/* channel_meaning */
int substream_info;
+ int thd_substream_info;
int fs;
int wordlength;
int channel_occupancy;
@@ -536,9 +537,8 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
}
ctx->substream_info |= SUBSTREAM_INFO_ALWAYS_SET;
- if (avctx->ch_layout.nb_channels <= 2) {
+ if (avctx->ch_layout.nb_channels <= 2)
ctx->substream_info |= SUBSTREAM_INFO_MAX_2_CHAN;
- }
switch (avctx->sample_fmt) {
case AV_SAMPLE_FMT_S16:
@@ -614,23 +614,33 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
} else {
/* TrueHD */
if (!av_channel_layout_compare(&avctx->ch_layout,
+ &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) {
+ ctx->ch_modifier_thd0 = 3;
+ ctx->ch_modifier_thd1 = 3;
+ ctx->ch_modifier_thd2 = 3;
+ ctx->channel_arrangement = 2;
+ ctx->thd_substream_info = 0x14;
+ } else if (!av_channel_layout_compare(&avctx->ch_layout,
&(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) {
- ctx->ch_modifier_thd0 = 0;
- ctx->ch_modifier_thd1 = 0;
- ctx->ch_modifier_thd2 = 0;
+ ctx->ch_modifier_thd0 = 1;
+ ctx->ch_modifier_thd1 = 1;
+ ctx->ch_modifier_thd2 = 1;
ctx->channel_arrangement = 1;
+ ctx->thd_substream_info = 0x14;
} else if (!av_channel_layout_compare(&avctx->ch_layout,
&(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) {
ctx->ch_modifier_thd0 = 1;
ctx->ch_modifier_thd1 = 1;
ctx->ch_modifier_thd2 = 1;
ctx->channel_arrangement = 11;
+ ctx->thd_substream_info = 0x104;
} else if (!av_channel_layout_compare(&avctx->ch_layout,
&(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) {
ctx->ch_modifier_thd0 = 2;
ctx->ch_modifier_thd1 = 1;
ctx->ch_modifier_thd2 = 2;
ctx->channel_arrangement = 15;
+ ctx->thd_substream_info = 0x104;
} else {
av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n");
return AVERROR(EINVAL);
@@ -718,7 +728,9 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
} else if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
put_bits(&pb, 8, SYNC_TRUEHD );
put_bits(&pb, 4, ctx->coded_sample_rate[0]);
- put_bits(&pb, 4, 0 ); /* ignored */
+ put_bits(&pb, 1, 0 ); /* 6ch multichannel type */
+ put_bits(&pb, 1, 0 ); /* 8ch multichannel type */
+ put_bits(&pb, 2, 0 ); /* ignored */
put_bits(&pb, 2, ctx->ch_modifier_thd0 );
put_bits(&pb, 2, ctx->ch_modifier_thd1 );
put_bits(&pb, 5, ctx->channel_arrangement );
@@ -732,20 +744,41 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
put_bits(&pb, 1, 1 ); /* is_vbr */
put_bits(&pb, 15, ctx->coded_peak_bitrate );
put_bits(&pb, 4, 1 ); /* num_substreams */
- put_bits(&pb, 4, 0x1 ); /* ignored */
+ put_bits(&pb, 2, 0 ); /* ignored */
+ put_bits(&pb, 2, 0 ); /* extended substream info */
/* channel_meaning */
- put_bits(&pb, 8, ctx->substream_info );
- put_bits(&pb, 5, ctx->fs );
- put_bits(&pb, 5, ctx->wordlength );
- put_bits(&pb, 6, ctx->channel_occupancy );
- put_bits(&pb, 3, 0 ); /* ignored */
- put_bits(&pb, 10, 0 ); /* speaker_layout */
- put_bits(&pb, 3, 0 ); /* copy_protection */
- put_bits(&pb, 16, 0x8080 ); /* ignored */
- put_bits(&pb, 7, 0 ); /* ignored */
- put_bits(&pb, 4, 0 ); /* source_format */
- put_bits(&pb, 5, ctx->summary_info );
+ if (ctx->avctx->codec_id == AV_CODEC_ID_MLP) {
+ put_bits(&pb, 8, ctx->substream_info );
+ put_bits(&pb, 5, ctx->fs );
+ put_bits(&pb, 5, ctx->wordlength );
+ put_bits(&pb, 6, ctx->channel_occupancy );
+ put_bits(&pb, 3, 0 ); /* ignored */
+ put_bits(&pb, 10, 0 ); /* speaker_layout */
+ put_bits(&pb, 3, 0 ); /* copy_protection */
+ put_bits(&pb, 16, 0x8080 ); /* ignored */
+ put_bits(&pb, 7, 0 ); /* ignored */
+ put_bits(&pb, 4, 0 ); /* source_format */
+ put_bits(&pb, 5, ctx->summary_info );
+ } else if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
+ put_bits(&pb, 8, ctx->thd_substream_info );
+ put_bits(&pb, 6, 0 ); /* reserved */
+ put_bits(&pb, 1, 0 ); /* 2ch control enabled */
+ put_bits(&pb, 1, 0 ); /* 6ch control enabled */
+ put_bits(&pb, 1, 0 ); /* 8ch control enabled */
+ put_bits(&pb, 1, 0 ); /* reserved */
+ put_bits(&pb, 7, 0 ); /* drc start up gain */
+ put_bits(&pb, 6, 0 ); /* 2ch dialogue norm */
+ put_bits(&pb, 6, 0 ); /* 2ch mix level */
+ put_bits(&pb, 5, 0 ); /* 6ch dialogue norm */
+ put_bits(&pb, 6, 0 ); /* 6ch mix level */
+ put_bits(&pb, 5, 0 ); /* 6ch source format */
+ put_bits(&pb, 5, 0 ); /* 8ch dialogue norm */
+ put_bits(&pb, 6, 0 ); /* 8ch mix level */
+ put_bits(&pb, 6, 0 ); /* 8ch source format */
+ put_bits(&pb, 1, 0 ); /* reserved */
+ put_bits(&pb, 1, 0 ); /* extra channel meaning present */
+ }
flush_put_bits(&pb);
@@ -2244,9 +2277,10 @@ const FFCodec ff_truehd_encoder = {
.p.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
.p.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
#if FF_API_OLD_CHANNEL_LAYOUT
- .p.channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
+ .p.channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
#endif
.p.ch_layouts = (const AVChannelLayout[]) {
+ AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_5POINT0_BACK,
AV_CHANNEL_LAYOUT_5POINT1_BACK,