[FFmpeg-devel] [RFC PATCH v5 2/3] libavcodec/j2kenc: Fix tag tree coding

gautamramk at gmail.com gautamramk at gmail.com
Tue Aug 25 16:55:44 EEST 2020


From: Gautam Ramakrishnan <gautamramk at gmail.com>

The implementation of tag tree encoding was incorrect.
However, this error was not visible as the current j2k
encoder encodes only 1 layer.
This patch fixes tag tree coding for JPEG2000 such tag
tree coding would work for multi layer encoding.
---
 libavcodec/j2kenc.c   | 41 +++++++++++++++++++++++++----------------
 libavcodec/jpeg2000.c |  9 +++++----
 libavcodec/jpeg2000.h |  3 ++-
 3 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index 16863f8e8c..87acd2d5c9 100644
--- a/libavcodec/j2kenc.c
+++ b/libavcodec/j2kenc.c
@@ -242,27 +242,36 @@ static void j2k_flush(Jpeg2000EncoderContext *s)
 static void tag_tree_code(Jpeg2000EncoderContext *s, Jpeg2000TgtNode *node, int threshold)
 {
     Jpeg2000TgtNode *stack[30];
-    int sp = 1, curval = 0;
-    stack[0] = node;
+    int sp = -1, curval = 0;
 
-    node = node->parent;
-    while(node){
-        if (node->vis){
-            curval = node->val;
-            break;
-        }
-        node->vis++;
-        stack[sp++] = node;
+    while(node->parent){
+        stack[++sp] = node;
         node = node->parent;
     }
-    while(--sp >= 0){
-        if (stack[sp]->val >= threshold){
+
+    while (1) {
+        if (curval > node->temp_val)
+            node->temp_val = curval;
+        else {
+            curval = node->temp_val;
+        }
+
+        if (node->val >= threshold) {
             put_bits(s, 0, threshold - curval);
-            break;
+            curval = threshold;
+        } else {
+            put_bits(s, 0, node->val - curval);
+            curval = node->val;
+            if (!node->vis) {
+                put_bits(s, 1, 1);
+                node->vis = 1;
+            }
         }
-        put_bits(s, 0, stack[sp]->val - curval);
-        put_bits(s, 1, 1);
-        curval = stack[sp]->val;
+
+        node->temp_val = curval;
+        if (sp < 0)
+            break;
+        node = stack[sp--];
     }
 }
 
diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 26e09fbe38..2e26bc5b00 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -82,12 +82,13 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h)
     return res;
 }
 
-void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h)
+void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val)
 {
     int i, siz = ff_tag_tree_size(w, h);
 
     for (i = 0; i < siz; i++) {
-        t[i].val = 0;
+        t[i].val = val;
+        t[i].temp_val = 0;
         t[i].vis = 0;
     }
 }
@@ -567,8 +568,8 @@ void ff_jpeg2000_reinit(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)
             Jpeg2000Band *band = rlevel->band + bandno;
             for(precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
                 Jpeg2000Prec *prec = band->prec + precno;
-                ff_tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height);
-                ff_tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height);
+                ff_tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 0);
+                ff_tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 0);
                 for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) {
                     Jpeg2000Cblk *cblk = prec->cblk + cblkno;
                     cblk->length = 0;
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index c3437b02fe..a9f2e01632 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -127,6 +127,7 @@ typedef struct Jpeg2000T1Context {
 
 typedef struct Jpeg2000TgtNode {
     uint8_t val;
+    uint8_t temp_val;
     uint8_t vis;
     struct Jpeg2000TgtNode *parent;
 } Jpeg2000TgtNode;
@@ -291,6 +292,6 @@ static inline int needs_termination(int style, int passno) {
 }
 
 int32_t ff_tag_tree_size(int w, int h);
-void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h);
+void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val);
 
 #endif /* AVCODEC_JPEG2000_H */
-- 
2.17.1



More information about the ffmpeg-devel mailing list