Commit 9a13ed52 authored by David Bryant's avatar David Bryant Committed by Paul B Mahol

avcodec/wavpack: add support for DSD files

Add support for WavPack DSD files to the existing WavPack decoder using
avcodec/dsd to perform the 8:1 decimation to 32-bit float samples. We must
serialize the dsd2pcm operation (cross-boundary filtering) but would like
to use frame-level multithreading for the CPU-intensive DSD decompression,
and this is accomplished with ff_thread_report/await_progress(). Because
the dsd2pcm operation is independent across channels we use slice-based
multithreading for that part.

Also a few things were removed from the existing WavPack decoder that
weren't being used (primarily the SavedContext stuff) and the WavPack
demuxer was enhanced to correctly determine the sampling rate of DSD
files (and of course to no longer reject them).
Signed-off-by: 's avatarDavid Bryant <david@wavpack.com>
parent 34d7c8d9
......@@ -693,7 +693,7 @@ OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o
OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o
OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o dsd.o
OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackenc.o
OBJS-$(CONFIG_WCMV_DECODER) += wcmv.o
OBJS-$(CONFIG_WEBP_DECODER) += webp.o
......
This diff is collapsed.
......@@ -35,6 +35,7 @@
#define WV_FLOAT_DATA 0x00000080
#define WV_INT32_DATA 0x00000100
#define WV_FALSE_STEREO 0x40000000
#define WV_DSD_DATA 0x80000000
#define WV_HYBRID_MODE 0x00000008
#define WV_HYBRID_SHAPE 0x00000008
......@@ -77,6 +78,7 @@ enum WP_ID {
WP_ID_CORR,
WP_ID_EXTRABITS,
WP_ID_CHANINFO,
WP_ID_DSD_DATA,
WP_ID_SAMPLE_RATE = 0x27,
};
......
......@@ -79,7 +79,7 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
{
WVContext *wc = ctx->priv_data;
int ret;
int rate, bpp, chan;
int rate, rate_x, bpp, chan;
uint32_t chmask, flags;
wc->pos = avio_tell(pb);
......@@ -98,11 +98,6 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
return ret;
}
if (wc->header.flags & WV_DSD) {
avpriv_report_missing_feature(ctx, "WV DSD");
return AVERROR_PATCHWELCOME;
}
if (wc->header.version < 0x402 || wc->header.version > 0x410) {
avpriv_report_missing_feature(ctx, "WV version 0x%03X",
wc->header.version);
......@@ -115,7 +110,8 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
return 0;
// parse flags
flags = wc->header.flags;
bpp = ((flags & 3) + 1) << 3;
rate_x = (flags & WV_DSD) ? 4 : 1;
bpp = (flags & WV_DSD) ? 0 : ((flags & 3) + 1) << 3;
chan = 1 + !(flags & WV_MONO);
chmask = flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
rate = wv_rates[(flags >> 23) & 0xF];
......@@ -124,7 +120,7 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
chan = wc->chan;
chmask = wc->chmask;
}
if ((rate == -1 || !chan) && !wc->block_parsed) {
if ((rate == -1 || !chan || flags & WV_DSD) && !wc->block_parsed) {
int64_t block_end = avio_tell(pb) + wc->header.blocksize;
if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
av_log(ctx, AV_LOG_ERROR,
......@@ -177,6 +173,16 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
return AVERROR_INVALIDDATA;
}
break;
case 0xE:
if (size <= 1) {
av_log(ctx, AV_LOG_ERROR,
"Invalid DSD block\n");
return AVERROR_INVALIDDATA;
}
rate_x = 1U << (avio_r8(pb) & 0x1f);
if (size)
avio_skip(pb, size-1);
break;
case 0x27:
rate = avio_rl24(pb);
break;
......@@ -200,7 +206,7 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
if (!wc->chmask)
wc->chmask = chmask;
if (!wc->rate)
wc->rate = rate;
wc->rate = rate * rate_x;
if (flags && bpp != wc->bpp) {
av_log(ctx, AV_LOG_ERROR,
......@@ -214,10 +220,10 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb)
chan, wc->chan);
return AVERROR_INVALIDDATA;
}
if (flags && rate != -1 && rate != wc->rate) {
if (flags && rate != -1 && !(flags & WV_DSD) && rate * rate_x != wc->rate) {
av_log(ctx, AV_LOG_ERROR,
"Sampling rate differ, this block: %i, header block: %i\n",
rate, wc->rate);
rate * rate_x, wc->rate);
return AVERROR_INVALIDDATA;
}
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment