This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 078224ae98dfba868bccb0e8726a9ed4ef278573 Author: Kacper Michajłow <[email protected]> AuthorDate: Tue Aug 11 12:12:54 2026 +0200 Commit: Kacper Michajłow <[email protected]> CommitDate: Sun Sep 6 00:48:25 2026 +0200 avcodec/wavpack: support raw DSD output Output DSD frames as AV_SAMPLE_FMT_DSD. The default float output is unchanged. Raw frames carry no state between each other, so this mode does not allocate the shared DSD context. Signed-off-by: Kacper Michajłow <[email protected]> --- libavcodec/version.h | 2 +- libavcodec/wavpack.c | 93 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index c9b58eb269..6b350a0a6f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 10 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MICRO 103 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 87c2ded5e4..6435291cc7 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -107,6 +107,7 @@ typedef struct WavpackContext { int ch_offset; Modulation modulation; + int dsd_raw; ///< output the raw DSD bitstream instead of PCM DSDContext *dsdctx; ///< RefStruct reference ThreadProgress *curr_progress, *prev_progress; ///< RefStruct references @@ -432,7 +433,14 @@ typedef struct { unsigned int byte; } DSDfilters; -static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +static void wv_dsd_silence(uint8_t *dst, int samples, ptrdiff_t stride) +{ + for (int i = 0; i < samples; i++) + dst[i * stride] = 0x69; +} + +static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right, + ptrdiff_t stride) { uint32_t checksum = 0xFFFFFFFF; uint8_t *dst_l = dst_left, *dst_r = dst_right; @@ -553,12 +561,12 @@ static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t checksum += (checksum << 1) + (*dst_l = sp[0].byte & 0xff); sp[0].factor -= (sp[0].factor + 512) >> 10; - dst_l += 4; + dst_l += stride; if (stereo) { checksum += (checksum << 1) + (*dst_r = filters[1].byte & 0xff); filters[1].factor -= (filters[1].factor + 512) >> 10; - dst_r += 4; + dst_r += stride; } } @@ -566,16 +574,17 @@ static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t if (s->avctx->err_recognition & AV_EF_CRCCHECK) return AVERROR_INVALIDDATA; - memset(dst_left, 0x69, s->samples * 4); + wv_dsd_silence(dst_left, s->samples, stride); if (dst_r) - memset(dst_right, 0x69, s->samples * 4); + wv_dsd_silence(dst_right, s->samples, stride); } return 0; } -static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right, + ptrdiff_t stride) { uint8_t *dst_l = dst_left, *dst_r = dst_right; uint8_t history_bits, max_probability; @@ -689,18 +698,18 @@ static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t if ((*dst_l = code = s->value_lookup[p0][index])) low += s->summed_probabilities[p0][code-1] * mult; - dst_l += 4; + dst_l += stride; } else { if ((code = s->value_lookup[p0][index])) low += s->summed_probabilities[p0][code-1] * mult; if (chan) { *dst_r = code; - dst_r += 4; + dst_r += stride; } else { *dst_l = code; - dst_l += 4; + dst_l += stride; } chan ^= 1; @@ -727,16 +736,17 @@ static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t if (s->avctx->err_recognition & AV_EF_CRCCHECK) return AVERROR_INVALIDDATA; - memset(dst_left, 0x69, s->samples * 4); + wv_dsd_silence(dst_left, s->samples, stride); if (dst_r) - memset(dst_right, 0x69, s->samples * 4); + wv_dsd_silence(dst_right, s->samples, stride); } return 0; } -static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right, + ptrdiff_t stride) { uint8_t *dst_l = dst_left, *dst_r = dst_right; int total_samples = s->samples; @@ -747,11 +757,11 @@ static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t while (total_samples--) { checksum += (checksum << 1) + (*dst_l = bytestream2_get_byte(&s->gbyte)); - dst_l += 4; + dst_l += stride; if (dst_r) { checksum += (checksum << 1) + (*dst_r = bytestream2_get_byte(&s->gbyte)); - dst_r += 4; + dst_r += stride; } } @@ -759,10 +769,10 @@ static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t if (s->avctx->err_recognition & AV_EF_CRCCHECK) return AVERROR_INVALIDDATA; - memset(dst_left, 0x69, s->samples * 4); + wv_dsd_silence(dst_left, s->samples, stride); if (dst_r) - memset(dst_right, 0x69, s->samples * 4); + wv_dsd_silence(dst_right, s->samples, stride); } return 0; @@ -1056,6 +1066,8 @@ static av_cold int wavpack_decode_init(AVCodecContext *avctx) s->fdec_num = 0; + s->dsd_raw = avctx->request_sample_fmt == AV_SAMPLE_FMT_DSD; + #if HAVE_THREADS if (ff_thread_sync_ref(avctx, offsetof(WavpackContext, progress_pool)) == FF_THREAD_IS_FIRST_THREAD) { s->progress_pool = av_refstruct_pool_alloc_ext(sizeof(*s->curr_progress), @@ -1094,6 +1106,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block GetByteContext gb; enum AVSampleFormat sample_fmt; void *samples_l = NULL, *samples_r = NULL; + ptrdiff_t stride = 4; // the in-place DSD to PCM conversion reads at this stride int ret; int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_pcm = 0, got_float = 0, got_hybrid = 0; @@ -1126,7 +1139,9 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block } s->frame_flags = bytestream2_get_le32(&gb); - if (s->frame_flags & (WV_FLOAT_DATA | WV_DSD_DATA)) + if (s->frame_flags & WV_DSD_DATA) + sample_fmt = wc->dsd_raw ? AV_SAMPLE_FMT_DSD : AV_SAMPLE_FMT_FLTP; + else if (s->frame_flags & WV_FLOAT_DATA) sample_fmt = AV_SAMPLE_FMT_FLTP; else if ((s->frame_flags & 0x03) <= 1) sample_fmt = AV_SAMPLE_FMT_S16P; @@ -1145,9 +1160,10 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block s->joint = s->frame_flags & WV_JOINT_STEREO; s->hybrid = s->frame_flags & WV_HYBRID_MODE; s->hybrid_bitrate = s->frame_flags & WV_HYBRID_BITRATE; - s->post_shift = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f); - if (s->post_shift < 0 || s->post_shift > 31) { - return AVERROR_INVALIDDATA; + if (!(s->frame_flags & WV_DSD_DATA)) { + s->post_shift = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f); + if (s->post_shift < 0 || s->post_shift > 31) + return AVERROR_INVALIDDATA; } s->hybrid_maxclip = ((1LL << (orig_bpp - 1)) - 1); s->hybrid_minclip = ((-1UL << (orig_bpp - 1))); @@ -1529,6 +1545,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block /* clear DSD state if stream properties change */ if ((wc->dsdctx && !got_dsd) || + !wc->dsd_raw && got_dsd && (new_ch_layout.nb_channels != wc->dsd_channels || av_channel_layout_compare(&new_ch_layout, &avctx->ch_layout) || new_samplerate != avctx->sample_rate)) { @@ -1569,20 +1586,28 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block return ((avctx->err_recognition & AV_EF_EXPLODE) || !wc->ch_offset) ? AVERROR_INVALIDDATA : 0; } - samples_l = frame->extended_data[wc->ch_offset]; - if (s->stereo) - samples_r = frame->extended_data[wc->ch_offset + 1]; + if (got_dsd && wc->dsd_raw) { + // raw DSD output is interleaved + stride = avctx->ch_layout.nb_channels; + samples_l = frame->data[0] + wc->ch_offset; + if (s->stereo) + samples_r = (uint8_t *)samples_l + 1; + } else { + samples_l = frame->extended_data[wc->ch_offset]; + if (s->stereo) + samples_r = frame->extended_data[wc->ch_offset + 1]; + } wc->ch_offset += 1 + s->stereo; if (s->stereo_in) { if (got_dsd) { if (dsd_mode == 3) { - ret = wv_unpack_dsd_high(s, samples_l, samples_r); + ret = wv_unpack_dsd_high(s, samples_l, samples_r, stride); } else if (dsd_mode == 1) { - ret = wv_unpack_dsd_fast(s, samples_l, samples_r); + ret = wv_unpack_dsd_fast(s, samples_l, samples_r, stride); } else { - ret = wv_unpack_dsd_copy(s, samples_l, samples_r); + ret = wv_unpack_dsd_copy(s, samples_l, samples_r, stride); } } else { ret = wv_unpack_stereo(s, &s->gb, samples_l, samples_r, avctx->sample_fmt); @@ -1592,11 +1617,11 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block } else { if (got_dsd) { if (dsd_mode == 3) { - ret = wv_unpack_dsd_high(s, samples_l, NULL); + ret = wv_unpack_dsd_high(s, samples_l, NULL, stride); } else if (dsd_mode == 1) { - ret = wv_unpack_dsd_fast(s, samples_l, NULL); + ret = wv_unpack_dsd_fast(s, samples_l, NULL, stride); } else { - ret = wv_unpack_dsd_copy(s, samples_l, NULL); + ret = wv_unpack_dsd_copy(s, samples_l, NULL, stride); } } else { ret = wv_unpack_mono(s, &s->gb, samples_l, avctx->sample_fmt); @@ -1604,8 +1629,14 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block if (ret < 0) return ret; - if (s->stereo) - memcpy(samples_r, samples_l, bpp * s->samples); + if (s->stereo) { + if (got_dsd && wc->dsd_raw) { + for (int i = 0; i < s->samples; i++) + ((uint8_t *)samples_r)[i * stride] = + ((const uint8_t *)samples_l)[i * stride]; + } else + memcpy(samples_r, samples_l, bpp * s->samples); + } } return 0; -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
