Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bryant <david@wavpack.com>2020-03-10 01:23:53 +0300
committerPaul B Mahol <onemda@gmail.com>2020-03-11 23:11:36 +0300
commit9a13ed522f361cdc3fa424922d59aca214d55a15 (patch)
treef5927db329e22a880cdb05575ebf3d1f8793e367 /libavformat/wvdec.c
parent34d7c8d942c370965d3823e017c79b58f18285ca (diff)
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: David Bryant <david@wavpack.com>
Diffstat (limited to 'libavformat/wvdec.c')
-rw-r--r--libavformat/wvdec.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c
index 0aa581534d..e56a6932ad 100644
--- a/libavformat/wvdec.c
+++ b/libavformat/wvdec.c
@@ -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;