2 * libdcadec decoder wrapper
3 * Copyright (C) 2015 Hendrik Leppkes
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <libdcadec/dca_context.h>
24 #include "libavutil/channel_layout.h"
25 #include "libavutil/common.h"
26 #include "libavutil/opt.h"
30 #include "dca_syncwords.h"
33 typedef struct DCADecContext
{
34 struct dcadec_context
*ctx
;
39 static int dcadec_decode_frame(AVCodecContext
*avctx
, void *data
,
40 int *got_frame_ptr
, AVPacket
*avpkt
)
42 DCADecContext
*s
= avctx
->priv_data
;
43 AVFrame
*frame
= data
;
45 int **samples
, nsamples
, channel_mask
, sample_rate
, bits_per_sample
, profile
;
47 uint8_t *input
= avpkt
->data
;
48 int input_size
= avpkt
->size
;
50 /* convert bytestream syntax to RAW BE format if required */
52 av_log(avctx
, AV_LOG_ERROR
, "Input size too small\n");
53 return AVERROR_INVALIDDATA
;
56 if (mrk
!= DCA_SYNCWORD_CORE_BE
&& mrk
!= DCA_SYNCWORD_SUBSTREAM
) {
57 s
->buffer
= av_fast_realloc(s
->buffer
, &s
->buffer_size
, avpkt
->size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
59 return AVERROR(ENOMEM
);
61 if ((ret
= ff_dca_convert_bitstream(avpkt
->data
, avpkt
->size
, s
->buffer
, s
->buffer_size
)) < 0)
68 if ((ret
= dcadec_context_parse(s
->ctx
, input
, input_size
)) < 0) {
69 av_log(avctx
, AV_LOG_ERROR
, "dcadec_context_parse() failed: %d (%s)\n", -ret
, dcadec_strerror(ret
));
70 return AVERROR_UNKNOWN
;
72 if ((ret
= dcadec_context_filter(s
->ctx
, &samples
, &nsamples
, &channel_mask
,
73 &sample_rate
, &bits_per_sample
, &profile
)) < 0) {
74 av_log(avctx
, AV_LOG_ERROR
, "dcadec_context_filter() failed: %d (%s)\n", -ret
, dcadec_strerror(ret
));
75 return AVERROR_UNKNOWN
;
78 avctx
->channels
= av_get_channel_layout_nb_channels(channel_mask
);
79 avctx
->channel_layout
= channel_mask
;
80 avctx
->sample_rate
= sample_rate
;
82 if (bits_per_sample
== 16)
83 avctx
->sample_fmt
= AV_SAMPLE_FMT_S16P
;
84 else if (bits_per_sample
<= 24)
85 avctx
->sample_fmt
= AV_SAMPLE_FMT_S32P
;
87 av_log(avctx
, AV_LOG_ERROR
, "Unsupported number of bits per sample: %d\n",
89 return AVERROR(ENOSYS
);
92 avctx
->bits_per_raw_sample
= bits_per_sample
;
95 case DCADEC_PROFILE_DS
:
96 avctx
->profile
= FF_PROFILE_DTS
;
98 case DCADEC_PROFILE_DS_96_24
:
99 avctx
->profile
= FF_PROFILE_DTS_96_24
;
101 case DCADEC_PROFILE_DS_ES
:
102 avctx
->profile
= FF_PROFILE_DTS_ES
;
104 case DCADEC_PROFILE_HD_HRA
:
105 avctx
->profile
= FF_PROFILE_DTS_HD_HRA
;
107 case DCADEC_PROFILE_HD_MA
:
108 avctx
->profile
= FF_PROFILE_DTS_HD_MA
;
110 case DCADEC_PROFILE_EXPRESS
:
111 avctx
->profile
= FF_PROFILE_DTS_EXPRESS
;
113 case DCADEC_PROFILE_UNKNOWN
:
115 avctx
->profile
= FF_PROFILE_UNKNOWN
;
119 /* bitrate is only meaningful if there are no HD extensions, as they distort the bitrate */
120 if (profile
== DCADEC_PROFILE_DS
|| profile
== DCADEC_PROFILE_DS_96_24
|| profile
== DCADEC_PROFILE_DS_ES
) {
121 struct dcadec_core_info
*info
= dcadec_context_get_core_info(s
->ctx
);
122 avctx
->bit_rate
= info
->bit_rate
;
123 dcadec_context_free_core_info(info
);
127 frame
->nb_samples
= nsamples
;
128 if ((ret
= ff_get_buffer(avctx
, frame
, 0)) < 0)
131 for (i
= 0; i
< avctx
->channels
; i
++) {
132 if (frame
->format
== AV_SAMPLE_FMT_S16P
) {
133 int16_t *plane
= (int16_t *)frame
->extended_data
[i
];
134 for (k
= 0; k
< nsamples
; k
++)
135 plane
[k
] = samples
[i
][k
];
137 int32_t *plane
= (int32_t *)frame
->extended_data
[i
];
138 int shift
= 32 - bits_per_sample
;
139 for (k
= 0; k
< nsamples
; k
++)
140 plane
[k
] = samples
[i
][k
] << shift
;
149 static av_cold
void dcadec_flush(AVCodecContext
*avctx
)
151 DCADecContext
*s
= avctx
->priv_data
;
152 dcadec_context_clear(s
->ctx
);
155 static av_cold
int dcadec_close(AVCodecContext
*avctx
)
157 DCADecContext
*s
= avctx
->priv_data
;
159 dcadec_context_destroy(s
->ctx
);
162 av_freep(&s
->buffer
);
167 static av_cold
int dcadec_init(AVCodecContext
*avctx
)
169 DCADecContext
*s
= avctx
->priv_data
;
171 s
->ctx
= dcadec_context_create(0);
173 return AVERROR(ENOMEM
);
175 avctx
->sample_fmt
= AV_SAMPLE_FMT_S32P
;
176 avctx
->bits_per_raw_sample
= 24;
181 static const AVProfile profiles
[] = {
182 { FF_PROFILE_DTS
, "DTS" },
183 { FF_PROFILE_DTS_ES
, "DTS-ES" },
184 { FF_PROFILE_DTS_96_24
, "DTS 96/24" },
185 { FF_PROFILE_DTS_HD_HRA
, "DTS-HD HRA" },
186 { FF_PROFILE_DTS_HD_MA
, "DTS-HD MA" },
187 { FF_PROFILE_DTS_EXPRESS
, "DTS Express" },
188 { FF_PROFILE_UNKNOWN
},
191 AVCodec ff_libdcadec_decoder
= {
193 .long_name
= NULL_IF_CONFIG_SMALL("dcadec DCA decoder"),
194 .type
= AVMEDIA_TYPE_AUDIO
,
195 .id
= AV_CODEC_ID_DTS
,
196 .priv_data_size
= sizeof(DCADecContext
),
198 .decode
= dcadec_decode_frame
,
199 .close
= dcadec_close
,
200 .flush
= dcadec_flush
,
201 .capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_CHANNEL_CONF
,
202 .sample_fmts
= (const enum AVSampleFormat
[]) { AV_SAMPLE_FMT_S32P
, AV_SAMPLE_FMT_S16P
,
203 AV_SAMPLE_FMT_NONE
},
204 .profiles
= NULL_IF_CONFIG_SMALL(profiles
),
205 .wrapper_name
= "libdcadec",