You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
10KB

  1. /*
  2. * libdcadec decoder wrapper
  3. * Copyright (C) 2015 Hendrik Leppkes
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg 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.
  11. *
  12. * FFmpeg 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.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <libdcadec/dca_context.h>
  22. #include "libavutil/channel_layout.h"
  23. #include "libavutil/common.h"
  24. #include "libavutil/opt.h"
  25. #include "avcodec.h"
  26. #include "dca.h"
  27. #include "dca_syncwords.h"
  28. #include "internal.h"
  29. #include "profiles.h"
  30. typedef struct DCADecContext {
  31. const AVClass *class;
  32. struct dcadec_context *ctx;
  33. uint8_t *buffer;
  34. int buffer_size;
  35. int lfe_filter;
  36. int core_only;
  37. } DCADecContext;
  38. static void my_log_cb(int level, const char *file, int line,
  39. const char *message, void *cbarg)
  40. {
  41. int av_level;
  42. switch (level) {
  43. case DCADEC_LOG_ERROR:
  44. av_level = AV_LOG_ERROR;
  45. break;
  46. case DCADEC_LOG_WARNING:
  47. av_level = AV_LOG_WARNING;
  48. break;
  49. case DCADEC_LOG_INFO:
  50. av_level = AV_LOG_INFO;
  51. break;
  52. case DCADEC_LOG_VERBOSE:
  53. av_level = AV_LOG_VERBOSE;
  54. break;
  55. case DCADEC_LOG_DEBUG:
  56. default:
  57. av_level = AV_LOG_DEBUG;
  58. break;
  59. }
  60. av_log(cbarg, av_level, "%s\n", message);
  61. }
  62. static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
  63. int *got_frame_ptr, AVPacket *avpkt)
  64. {
  65. DCADecContext *s = avctx->priv_data;
  66. AVFrame *frame = data;
  67. struct dcadec_exss_info *exss;
  68. int ret, i, k;
  69. int **samples, nsamples, channel_mask, sample_rate, bits_per_sample, profile;
  70. uint32_t mrk;
  71. uint8_t *input = avpkt->data;
  72. int input_size = avpkt->size;
  73. /* convert bytestream syntax to RAW BE format if required */
  74. if (input_size < 8) {
  75. av_log(avctx, AV_LOG_ERROR, "Input size too small\n");
  76. return AVERROR_INVALIDDATA;
  77. }
  78. mrk = AV_RB32(input);
  79. if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) {
  80. s->buffer = av_fast_realloc(s->buffer, &s->buffer_size, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE);
  81. if (!s->buffer)
  82. return AVERROR(ENOMEM);
  83. for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - 3 && ret < 0; i++)
  84. ret = avpriv_dca_convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size);
  85. if (ret < 0)
  86. return ret;
  87. input = s->buffer;
  88. input_size = ret;
  89. }
  90. if ((ret = dcadec_context_parse(s->ctx, input, input_size)) < 0) {
  91. av_log(avctx, AV_LOG_ERROR, "dcadec_context_parse() failed: %d (%s)\n", -ret, dcadec_strerror(ret));
  92. return AVERROR_EXTERNAL;
  93. }
  94. if ((ret = dcadec_context_filter(s->ctx, &samples, &nsamples, &channel_mask,
  95. &sample_rate, &bits_per_sample, &profile)) < 0) {
  96. av_log(avctx, AV_LOG_ERROR, "dcadec_context_filter() failed: %d (%s)\n", -ret, dcadec_strerror(ret));
  97. return AVERROR_EXTERNAL;
  98. }
  99. avctx->channels = av_get_channel_layout_nb_channels(channel_mask);
  100. avctx->channel_layout = channel_mask;
  101. avctx->sample_rate = sample_rate;
  102. if (bits_per_sample == 16)
  103. avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
  104. else if (bits_per_sample > 16 && bits_per_sample <= 24)
  105. avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
  106. else {
  107. av_log(avctx, AV_LOG_ERROR, "Unsupported number of bits per sample: %d\n",
  108. bits_per_sample);
  109. return AVERROR(ENOSYS);
  110. }
  111. avctx->bits_per_raw_sample = bits_per_sample;
  112. switch (profile) {
  113. case DCADEC_PROFILE_DS:
  114. avctx->profile = FF_PROFILE_DTS;
  115. break;
  116. case DCADEC_PROFILE_DS_96_24:
  117. avctx->profile = FF_PROFILE_DTS_96_24;
  118. break;
  119. case DCADEC_PROFILE_DS_ES:
  120. avctx->profile = FF_PROFILE_DTS_ES;
  121. break;
  122. case DCADEC_PROFILE_HD_HRA:
  123. avctx->profile = FF_PROFILE_DTS_HD_HRA;
  124. break;
  125. case DCADEC_PROFILE_HD_MA:
  126. avctx->profile = FF_PROFILE_DTS_HD_MA;
  127. break;
  128. case DCADEC_PROFILE_EXPRESS:
  129. avctx->profile = FF_PROFILE_DTS_EXPRESS;
  130. break;
  131. case DCADEC_PROFILE_UNKNOWN:
  132. default:
  133. avctx->profile = FF_PROFILE_UNKNOWN;
  134. break;
  135. }
  136. /* bitrate is only meaningful if there are no HD extensions, as they distort the bitrate */
  137. if (profile == DCADEC_PROFILE_DS || profile == DCADEC_PROFILE_DS_96_24 || profile == DCADEC_PROFILE_DS_ES) {
  138. struct dcadec_core_info *info = dcadec_context_get_core_info(s->ctx);
  139. avctx->bit_rate = info->bit_rate;
  140. dcadec_context_free_core_info(info);
  141. } else
  142. avctx->bit_rate = 0;
  143. if (exss = dcadec_context_get_exss_info(s->ctx)) {
  144. enum AVMatrixEncoding matrix_encoding = AV_MATRIX_ENCODING_NONE;
  145. switch(exss->matrix_encoding) {
  146. case DCADEC_MATRIX_ENCODING_SURROUND:
  147. matrix_encoding = AV_MATRIX_ENCODING_DOLBY;
  148. break;
  149. case DCADEC_MATRIX_ENCODING_HEADPHONE:
  150. matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE;
  151. break;
  152. }
  153. dcadec_context_free_exss_info(exss);
  154. if (matrix_encoding != AV_MATRIX_ENCODING_NONE &&
  155. (ret = ff_side_data_update_matrix_encoding(frame, matrix_encoding)) < 0)
  156. return ret;
  157. }
  158. frame->nb_samples = nsamples;
  159. if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  160. return ret;
  161. for (i = 0; i < avctx->channels; i++) {
  162. if (frame->format == AV_SAMPLE_FMT_S16P) {
  163. int16_t *plane = (int16_t *)frame->extended_data[i];
  164. for (k = 0; k < nsamples; k++)
  165. plane[k] = samples[i][k];
  166. } else {
  167. int32_t *plane = (int32_t *)frame->extended_data[i];
  168. int shift = 32 - bits_per_sample;
  169. for (k = 0; k < nsamples; k++)
  170. plane[k] = samples[i][k] << shift;
  171. }
  172. }
  173. *got_frame_ptr = 1;
  174. return avpkt->size;
  175. }
  176. static av_cold void dcadec_flush(AVCodecContext *avctx)
  177. {
  178. DCADecContext *s = avctx->priv_data;
  179. dcadec_context_clear(s->ctx);
  180. }
  181. static av_cold int dcadec_close(AVCodecContext *avctx)
  182. {
  183. DCADecContext *s = avctx->priv_data;
  184. dcadec_context_destroy(s->ctx);
  185. s->ctx = NULL;
  186. av_freep(&s->buffer);
  187. return 0;
  188. }
  189. static av_cold int dcadec_init(AVCodecContext *avctx)
  190. {
  191. DCADecContext *s = avctx->priv_data;
  192. int flags = 0;
  193. /* Affects only lossy DTS profiles. DTS-HD MA is always bitexact */
  194. if (avctx->flags & AV_CODEC_FLAG_BITEXACT)
  195. flags |= DCADEC_FLAG_CORE_BIT_EXACT;
  196. if (avctx->err_recognition & AV_EF_EXPLODE)
  197. flags |= DCADEC_FLAG_STRICT;
  198. if (avctx->request_channel_layout) {
  199. switch (avctx->request_channel_layout) {
  200. case AV_CH_LAYOUT_STEREO:
  201. case AV_CH_LAYOUT_STEREO_DOWNMIX:
  202. flags |= DCADEC_FLAG_KEEP_DMIX_2CH;
  203. break;
  204. case AV_CH_LAYOUT_5POINT1:
  205. flags |= DCADEC_FLAG_KEEP_DMIX_6CH;
  206. break;
  207. case AV_CH_LAYOUT_NATIVE:
  208. flags |= DCADEC_FLAG_NATIVE_LAYOUT;
  209. break;
  210. default:
  211. av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n");
  212. break;
  213. }
  214. }
  215. if (s->core_only)
  216. flags |= DCADEC_FLAG_CORE_ONLY;
  217. switch (s->lfe_filter) {
  218. #if DCADEC_API_VERSION >= DCADEC_VERSION_CODE(0, 1, 0)
  219. case 1:
  220. flags |= DCADEC_FLAG_CORE_LFE_IIR;
  221. break;
  222. #endif
  223. case 2:
  224. flags |= DCADEC_FLAG_CORE_LFE_FIR;
  225. break;
  226. }
  227. s->ctx = dcadec_context_create(flags);
  228. if (!s->ctx)
  229. return AVERROR(ENOMEM);
  230. dcadec_context_set_log_cb(s->ctx, my_log_cb, avctx);
  231. avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
  232. avctx->bits_per_raw_sample = 24;
  233. return 0;
  234. }
  235. #define OFFSET(x) offsetof(DCADecContext, x)
  236. #define PARAM AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  237. static const AVOption dcadec_options[] = {
  238. { "lfe_filter", "Lossy LFE channel interpolation filter", OFFSET(lfe_filter), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, PARAM, "lfe_filter" },
  239. { "default", "Library default", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
  240. { "iir", "IIR filter", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
  241. { "fir", "FIR filter", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
  242. { "core_only", "Decode core only without extensions", OFFSET(core_only), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, PARAM },
  243. { NULL }
  244. };
  245. static const AVClass dcadec_class = {
  246. .class_name = "libdcadec decoder",
  247. .item_name = av_default_item_name,
  248. .option = dcadec_options,
  249. .version = LIBAVUTIL_VERSION_INT,
  250. .category = AV_CLASS_CATEGORY_DECODER,
  251. };
  252. AVCodec ff_libdcadec_decoder = {
  253. .name = "libdcadec",
  254. .long_name = NULL_IF_CONFIG_SMALL("dcadec DCA decoder"),
  255. .type = AVMEDIA_TYPE_AUDIO,
  256. .id = AV_CODEC_ID_DTS,
  257. .priv_data_size = sizeof(DCADecContext),
  258. .init = dcadec_init,
  259. .decode = dcadec_decode_frame,
  260. .close = dcadec_close,
  261. .flush = dcadec_flush,
  262. .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
  263. .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P,
  264. AV_SAMPLE_FMT_NONE },
  265. .priv_class = &dcadec_class,
  266. .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles),
  267. };