X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdsddec.c;h=21d1d9f5de513a77340d9bdd47a9b83cfbe4720b;hb=30f7021aa0be2c978aefb73894b643c9bafbf51c;hp=2c5c357acc51fa86740e37d142b95d77077d8e85;hpb=b668a1c8b35d7b45eb32cba465fb99b99355998c;p=ffmpeg diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c index 2c5c357acc5..21d1d9f5de5 100644 --- a/libavcodec/dsddec.c +++ b/libavcodec/dsddec.c @@ -27,11 +27,11 @@ */ #include "libavcodec/internal.h" -#include "libavcodec/mathops.h" #include "avcodec.h" #include "dsd.h" #define DSD_SILENCE 0x69 +#define DSD_SILENCE_REVERSED 0x96 /* 0x69 = 01101001 * This pattern "on repeat" makes a low energy 352.8 kHz tone * and a high energy 1.0584 MHz tone which should be filtered @@ -44,13 +44,16 @@ static av_cold int decode_init(AVCodecContext *avctx) int i; uint8_t silence; + if (!avctx->channels) + return AVERROR_INVALIDDATA; + ff_init_dsd_data(); s = av_malloc_array(sizeof(DSDContext), avctx->channels); if (!s) return AVERROR(ENOMEM); - silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR ? ff_reverse[DSD_SILENCE] : DSD_SILENCE; + silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR ? DSD_SILENCE_REVERSED : DSD_SILENCE; for (i = 0; i < avctx->channels; i++) { s[i].pos = 0; memset(s[i].buf, silence, sizeof(s[i].buf)); @@ -61,17 +64,20 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) +typedef struct ThreadData { + AVFrame *frame; + const AVPacket *avpkt; +} ThreadData; + +static int dsd_channel(AVCodecContext *avctx, void *tdata, int j, int threadnr) { - DSDContext * s = avctx->priv_data; - AVFrame *frame = data; - int ret, i; int lsbf = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR; - int src_next; - int src_stride; - - frame->nb_samples = avpkt->size / avctx->channels; + DSDContext *s = avctx->priv_data; + ThreadData *td = tdata; + AVFrame *frame = td->frame; + const AVPacket *avpkt = td->avpkt; + int src_next, src_stride; + float *dst = ((float **)frame->extended_data)[j]; if (avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR || avctx->codec_id == AV_CODEC_ID_DSD_MSBF_PLANAR) { src_next = frame->nb_samples; @@ -81,15 +87,28 @@ static int decode_frame(AVCodecContext *avctx, void *data, src_stride = avctx->channels; } + ff_dsd2pcm_translate(&s[j], frame->nb_samples, lsbf, + avpkt->data + j * src_next, src_stride, + dst, 1); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + ThreadData td; + AVFrame *frame = data; + int ret; + + frame->nb_samples = avpkt->size / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (i = 0; i < avctx->channels; i++) { - float * dst = ((float **)frame->extended_data)[i]; - ff_dsd2pcm_translate(&s[i], frame->nb_samples, lsbf, - avpkt->data + i * src_next, src_stride, - dst, 1); - } + td.frame = frame; + td.avpkt = avpkt; + avctx->execute2(avctx, dsd_channel, &td, NULL, avctx->channels); *got_frame_ptr = 1; return frame->nb_samples * avctx->channels; @@ -103,8 +122,10 @@ AVCodec ff_##name_##_decoder = { \ .id = AV_CODEC_ID_##id_, \ .init = decode_init, \ .decode = decode_frame, \ + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \ AV_SAMPLE_FMT_NONE }, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ }; DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first")