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]

Reply via email to