Hi, patch attached.
From 654a9d565d963eeb7c2e1c72559d0df17a9814ab Mon Sep 17 00:00:00 2001 From: Paul B Mahol <one...@gmail.com> Date: Mon, 25 Jan 2016 21:54:17 +0100 Subject: [PATCH] avcodec: add Ulead DV audio decoder
Signed-off-by: Paul B Mahol <one...@gmail.com> --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/dvaudiodec.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/riff.c | 2 + 4 files changed, 148 insertions(+) create mode 100644 libavcodec/dvaudiodec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 472c662..696f699 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -244,6 +244,7 @@ OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o +OBJS-$(CONFIG_DVAUDIO_DECODER) += dvaudiodec.o OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o OBJS-$(CONFIG_DXA_DECODER) += dxa.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 2128546..66a57b0 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -160,6 +160,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (DNXHD, dnxhd); REGISTER_ENCDEC (DPX, dpx); REGISTER_DECODER(DSICINVIDEO, dsicinvideo); + REGISTER_DECODER(DVAUDIO, dvaudio); REGISTER_ENCDEC (DVVIDEO, dvvideo); REGISTER_DECODER(DXA, dxa); REGISTER_DECODER(DXTORY, dxtory); diff --git a/libavcodec/dvaudiodec.c b/libavcodec/dvaudiodec.c new file mode 100644 index 0000000..84db509 --- /dev/null +++ b/libavcodec/dvaudiodec.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2012 Laurent Aimar + * + * 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 + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct DVAudioContext { + int block_size; + int is_12bit; + int is_pal; + int16_t shuffle[2000]; +} DVAudioContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + DVAudioContext *s = avctx->priv_data; + int i; + + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + + if (avctx->codec_tag == 0x0215) { + s->block_size = 7200; + s->is_pal = 0; + } else if (avctx->codec_tag == 0x0216) { + s->block_size = 8640; + s->is_pal = 1; + } else { + return AVERROR(EINVAL); + } + + s->is_12bit = avctx->bits_per_raw_sample == 12; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + for (i = 0; i < FF_ARRAY_ELEMS(s->shuffle); i++) { + const unsigned a = s->is_pal ? 18 : 15; + const unsigned b = 3 * a; + + s->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) + + (2 + s->is_12bit) * (i / b) + 8; + } + + return 0; +} + +static inline int dv_get_audio_sample_count(const uint8_t *buffer, int dsf) +{ + int samples = buffer[0] & 0x3f; /* samples in this frame - min samples */ + + switch ((buffer[3] >> 3) & 0x07) { + case 0: + return samples + (dsf ? 1896 : 1580); + case 1: + return samples + (dsf ? 1742 : 1452); + case 2: + default: + return samples + (dsf ? 1264 : 1053); + } +} + +static inline uint16_t dv_audio_12to16(uint16_t sample) +{ + uint16_t shift, result; + + sample = (sample < 0x800) ? sample : sample | 0xf000; + shift = (sample & 0xf00) >> 8; + + if (shift < 0x2 || shift > 0xd) { + result = sample; + } else if (shift < 0x8) { + shift--; + result = (sample - (256 * shift)) << shift; + } else { + shift = 0xe - shift; + result = ((sample + ((256 * shift) + 1)) << shift) - 1; + } + + return result; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + DVAudioContext *s = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *src = pkt->data; + int16_t *dst; + int ret, i; + + if (pkt->size != s->block_size) + return AVERROR_INVALIDDATA; + + frame->nb_samples = dv_get_audio_sample_count(pkt->data + 244, s->is_pal); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + dst = (int16_t *)frame->data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + const uint8_t *v = &src[s->shuffle[i]]; + + if (s->is_12bit) { + *dst++ = dv_audio_12to16((v[0] << 4) | ((v[2] >> 4) & 0x0f)); + *dst++ = dv_audio_12to16((v[1] << 4) | ((v[2] >> 0) & 0x0f)); + } else { + *dst++ = AV_RB16(&v[0]); + *dst++ = AV_RB16(&v[s->is_pal ? 4320 : 3600]); + } + } + + *got_frame_ptr = 1; + + return pkt->size; +} + +AVCodec ff_dvaudio_decoder = { + .name = "dvaudio", + .long_name = NULL_IF_CONFIG_SMALL("Ulead DV Audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DVAUDIO, + .init = decode_init, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(DVAudioContext), +}; diff --git a/libavformat/riff.c b/libavformat/riff.c index afded54..9a92615 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -463,6 +463,8 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_XMA1, 0x0165 }, { AV_CODEC_ID_XMA2, 0x0166 }, { AV_CODEC_ID_ADPCM_CT, 0x0200 }, + { AV_CODEC_ID_DVAUDIO, 0x0215 }, + { AV_CODEC_ID_DVAUDIO, 0x0216 }, { AV_CODEC_ID_ATRAC3, 0x0270 }, { AV_CODEC_ID_ADPCM_G722, 0x028F }, { AV_CODEC_ID_IMC, 0x0401 }, -- 1.9.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel