This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit faa7c882cb86334aa962340451e087c30e063d31
Author:     Lynne <[email protected]>
AuthorDate: Sun Sep 20 23:39:32 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Thu Sep 24 08:02:22 2026 +0900

    prores_raw: use the 16-bit iDCT
    
    The decoder converted the 32-bit output of its transform to 16 bits
    through an empirically found offset, and added one to every DC
    coefficient to compensate for the bias of the result. Neither
    reproduces the transform well: against a bit-exact model of the
    reference decoder, most samples are off, with a quantizer-dependent
    bias and errors of up to 357 out of 65535 at the extremes of the range,
    and the DC offset only helps on HQ material.
    
    Use the 16-bit output variant of simple_idct instead, with the
    dequantized coefficients saturated to 16 bits as the reference does,
    and the centered transform output biased in the output stage.
    
    Against an exact transform, the error drops from 5.6 LSB RMS with a
    maximum of 21 to 0.49 LSB RMS with a maximum of 2.3 and no bias, on par
    with the reference decoder's 0.29 and 2.4. The decoded output agrees
    with the reference decoder on 95% of the samples of a 5.7K RAW HQ frame
    with a log curve, within 3.5 LSB of a 14-bit sensor in its top stop and
    within 1 LSB elsewhere. Speed is unchanged.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    Claude-Session: https://claude.ai/code/session_016LFnYMstwe4woBzpxfzDzg
---
 libavcodec/prores_raw.c |  4 ++--
 libavcodec/proresdsp.c  | 28 ++++++++++++----------------
 2 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index dc11b14331..36c3879f73 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -185,7 +185,7 @@ static int decode_comp(AVCodecContext *avctx, TileContext 
*tile,
     if (dc < 0)
         goto end;
     int prev_dc = (dc >> 1) ^ -(dc & 1);
-    block[0] = prev_dc + 1;
+    block[0] = prev_dc;
 
     for (int n = 1; n < nb_blocks; n++) {
         if ((n & 15) == 1)
@@ -202,7 +202,7 @@ static int decode_comp(AVCodecContext *avctx, TileContext 
*tile,
         sign = dc_add < 0;
         prev_dc += dc_add;
 
-        block[n*64] = prev_dc + 1;
+        block[n*64] = prev_dc;
     }
 
     for (int n = nb_blocks; n < nb_codes;) {
diff --git a/libavcodec/proresdsp.c b/libavcodec/proresdsp.c
index cf4aa9d0cf..919a5d6797 100644
--- a/libavcodec/proresdsp.c
+++ b/libavcodec/proresdsp.c
@@ -42,9 +42,9 @@
 #undef BIT_DEPTH
 #undef IN_IDCT_DEPTH
 
-/* 32bit iDCT for the ProRes RAW */
+/* 16-bit iDCT for ProRes RAW */
 #define IN_IDCT_DEPTH 32
-#define BIT_DEPTH 12
+#define BIT_DEPTH 16
 #include "simple_idct_template.c"
 #undef BIT_DEPTH
 #undef IN_IDCT_DEPTH
@@ -83,21 +83,18 @@ static void prores_idct_12(int16_t *restrict block, const 
int16_t *restrict qmat
 }
 
 /*
- * 32-bit iDCT for the ProRes RAW
- * qmat must be s->qmat[i] * scale
+ * ProRes RAW iDCT: 16-bit coefficients to a 16-bit output centered on zero
  */
-static void prores_idct_bayer_32(int32_t *restrict block, const int16_t 
*restrict qmat)
+static void prores_idct_bayer_16(int32_t *restrict block, const int16_t 
*restrict qmat)
 {
     for (int i = 0; i < 64; i++)
-        block[i] = (block[i] * qmat[i]) >> 1;
+        block[i] = av_clip_int16(block[i] * qmat[i]);
 
     for (int i = 0; i < 8; i++)
-        idctRowCondDC_int32_12bit(block + i*8, 0);
+        idctRowCondDC_int32_16bit(block + i*8, 0);
 
-    for (int i = 0; i < 8; i++) {
-        block[i] += 8192;
-        idctSparseCol_int32_12bit(block + i);
-    }
+    for (int i = 0; i < 8; i++)
+        idctSparseCol_int32_16bit(block + i);
 }
 
 #define CLIP_MIN (1 << 2)                     ///< minimum value for clipping 
resulting pixels
@@ -131,10 +128,9 @@ static inline void put_pixel_bayer_lin_curve_12(uint16_t 
*dst, ptrdiff_t linesiz
 {
     for (int y = 0; y < 8; y++, dst += linesize) {
         for (int x = 0; x < 8; x++) {
-            /* Convert the 32-bit input into 16-bits (lrintf(x*16 - 15.5f) = 
16) */
-            int u = av_clip_uint16(in[(y << 3) + x]*16 - 16);
-            uint32_t seg  = (uint32_t)u >> 13;
-            uint32_t frac = (uint32_t)u & 0x1FFF;
+            uint32_t u    = av_clip_uint16(in[(y << 3) + x] + 32768);
+            uint32_t seg  = u >> 13;
+            uint32_t frac = u & 0x1FFF;
             uint32_t cp0  = lin_curve[seg];
             uint32_t cp1  = seg < 7 ? lin_curve[seg + 1] : 0;
             uint32_t o    = (cp0 * 8192 + ((cp1 - cp0) & 0xFFFF) * frac + 
4096) >> 13;
@@ -169,7 +165,7 @@ static void prores_idct_put_bayer_12_c(uint16_t *out, 
ptrdiff_t linesize,
                                        int32_t *block, const int16_t *qmat,
                                        const uint16_t *lin_curve)
 {
-    prores_idct_bayer_32(block, qmat);
+    prores_idct_bayer_16(block, qmat);
     put_pixel_bayer_lin_curve_12(out, linesize << 1, block, lin_curve);
 }
 

-- 
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