]> granicus.if.org Git - libvpx/commitdiff
Changed how coefficient probability table is updated
authorYaowu Xu <yaowu@google.com>
Mon, 6 Feb 2012 23:10:13 +0000 (15:10 -0800)
committerPaul Wilkins <paulwilkins@google.com>
Mon, 13 Feb 2012 13:20:02 +0000 (13:20 +0000)
Added a frame level flag to indicate if coef probabilities are updated
at all for the frame.

During the experimental work with 8x8 transform, it is discovered that
even in the case of no probability is ever update, cost of transmitting
"no update" for each of probabilities can run up to become a significant
overhead cost. A single bit to indicate no-update for all coef probs
is therefore helpful, which is also demonstrated by the test results:

1. On Cif set:
http://www.corp.google.com/~yaowu/no_crawl/t8x8/cif_t8x8_updprob.html
(avg psnr: .14%, glb psnr: .14% SSIM: .13%)

2. On HD set:
http://www.corp.google.com/~yaowu/no_crawl/t8x8/HD_t8x8_updprob.html
(avg psnr: .02%  glb psnr: .01% SSIM: .02%)
It should be noted that the gain on HD is smaller because the average bit
rate is much higher in contrast to the overhead bit cost.

Change-Id: I46db270e693ee8799fef34a14d8260868ce4cd16

vp8/decoder/decodframe.c
vp8/encoder/bitstream.c

index 64b58b5bb7c94f943f7b8d1856a8d5b7844b4c4f..c5385a022c02d1b667eefeeff23102b6eca64dd7 100644 (file)
@@ -1399,13 +1399,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     {
         pbi->independent_partitions = 1;
 
+        if(vp8_read_bit(bc))
+        {
         /* read coef probability tree */
         for (i = 0; i < BLOCK_TYPES; i++)
             for (j = 0; j < COEF_BANDS; j++)
                 for (k = 0; k < PREV_COEF_CONTEXTS; k++)
                     for (l = 0; l < ENTROPY_NODES; l++)
                     {
-
                         vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
 
                         if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
@@ -1415,14 +1416,13 @@ int vp8_decode_frame(VP8D_COMP *pbi)
                         }
                         if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
                             pbi->independent_partitions = 0;
-
                     }
+        }
     }
 #if CONFIG_T8X8
-    if(pbi->common.txfm_mode == ALLOW_8X8)
+    if(pbi->common.txfm_mode == ALLOW_8X8 && vp8_read_bit(bc))
     {
         // read coef probability tree
-
         for (i = 0; i < BLOCK_TYPES; i++)
             for (j = 0; j < COEF_BANDS; j++)
                 for (k = 0; k < PREV_COEF_CONTEXTS; k++)
index f3f0c1ba2abc33235d08ee478f069479ee59ac83..2eb959d795bd8e694e3199154f0886a047bc6f3b 100644 (file)
@@ -2210,14 +2210,13 @@ static void update_coef_probs(VP8_COMP *cpi)
 {
     int i = 0;
     vp8_writer *const w = & cpi->bc;
-    int savings = 0;
+    int update = 0;
 
     vp8_clear_system_state(); //__asm emms;
-
+    /* dry run to see if there is any udpate at all needed */
     do
     {
         int j = 0;
-
         do
         {
             int k = 0;
@@ -2235,7 +2234,6 @@ static void update_coef_probs(VP8_COMP *cpi)
                         const vp8_prob oldp = cpi->common.fc.coef_probs[i][j]
                                                                        [k][t];
                         const vp8_prob upd = vp8_coef_update_probs[i][j][k][t];
-
                         prev_coef_savings[t] +=
                                 prob_update_savings(ct, oldp, newp, upd);
                     }
@@ -2246,29 +2244,22 @@ static void update_coef_probs(VP8_COMP *cpi)
             {
                 //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
                 /* at every context */
-
                 /* calc probs and branch cts for this frame only */
                 //vp8_prob new_p           [ENTROPY_NODES];
                 //unsigned int branch_ct   [ENTROPY_NODES] [2];
-
                 int t = 0;      /* token/prob index */
-
                 //vp8_tree_probs_from_distribution(
                 //    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
                 //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
                 //    256, 1
                 //    );
-
                 do
                 {
                     const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
-
                     vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
                     const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
-
                     int s = prev_coef_savings[t];
                     int u = 0;
-
                     if (!(cpi->oxcf.error_resilient_mode &
                             VPX_ERROR_RESILIENT_PARTITIONS))
                     {
@@ -2276,10 +2267,8 @@ static void update_coef_probs(VP8_COMP *cpi)
                                 cpi->frame_branch_ct [i][j][k][t],
                                 *Pold, newp, upd);
                     }
-
                     if (s > 0)
                         u = 1;
-
                     /* Force updates on key frames if the new is different,
                      * so that we can be sure we end up with equal probabilities
                      * over the prev coef contexts.
@@ -2288,113 +2277,162 @@ static void update_coef_probs(VP8_COMP *cpi)
                             VPX_ERROR_RESILIENT_PARTITIONS) &&
                         cpi->common.frame_type == KEY_FRAME && newp != *Pold)
                         u = 1;
-
-                    vp8_write(w, u, upd);
-
-
-#ifdef ENTROPY_STATS
-                    ++ tree_update_hist [i][j][k][t] [u];
-#endif
-
-                    if (u)
-                    {
-                        /* send/use new probability */
-
-                        *Pold = newp;
-                        vp8_write_literal(w, newp, 8);
-
-                        savings += s;
-
-                    }
-
+                    update += u;
                 }
                 while (++t < ENTROPY_NODES);
-
                 /* Accum token counts for generation of default statistics */
-#ifdef ENTROPY_STATS
-                t = 0;
-
-                do
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+    /* Is coef updated at all */
+    if(update==0)
+    {
+        vp8_write_bit(w, 0);
+    }
+    else
+    {
+        vp8_write_bit(w, 1);
+        i=0;
+        do
+        {
+            int j = 0;
+            do
+            {
+                int k = 0;
+                int prev_coef_savings[ENTROPY_NODES] = {0};
+                if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
                 {
-                    context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
+                    for (k = 0; k < PREV_COEF_CONTEXTS; ++k)
+                    {
+                        int t;      /* token/prob index */
+                        for (t = 0; t < ENTROPY_NODES; ++t)
+                        {
+                            const unsigned int *ct = cpi->frame_branch_ct [i][j]
+                            [k][t];
+                            const vp8_prob newp = cpi->frame_coef_probs[i][j][k][t];
+                            const vp8_prob oldp = cpi->common.fc.coef_probs[i][j]
+                            [k][t];
+                            const vp8_prob upd = vp8_coef_update_probs[i][j][k][t];
+                            prev_coef_savings[t] +=
+                                prob_update_savings(ct, oldp, newp, upd);
+                        }
+                    }
+                    k = 0;
                 }
-                while (++t < MAX_ENTROPY_TOKENS);
+                do
+                {
+                    //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+                    /* at every context */
 
+                    /* calc probs and branch cts for this frame only */
+                    //vp8_prob new_p           [ENTROPY_NODES];
+                    //unsigned int branch_ct   [ENTROPY_NODES] [2];
+                    int t = 0;      /* token/prob index */
+                    //vp8_tree_probs_from_distribution(
+                    //    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+                    //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+                    //    256, 1
+                    //    );
+                    do
+                    {
+                        const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+                        vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
+                        const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+                        int s = prev_coef_savings[t];
+                        int u = 0;
+                        if (!(cpi->oxcf.error_resilient_mode &
+                            VPX_ERROR_RESILIENT_PARTITIONS))
+                        {
+                            s = prob_update_savings(
+                                cpi->frame_branch_ct [i][j][k][t],
+                                *Pold, newp, upd);
+                        }
+                        if (s > 0)
+                            u = 1;
+                        /* Force updates on key frames if the new is different,
+                        * so that we can be sure we end up with equal probabilities
+                        * over the prev coef contexts.
+                        */
+                        if ((cpi->oxcf.error_resilient_mode &
+                            VPX_ERROR_RESILIENT_PARTITIONS) &&
+                            cpi->common.frame_type == KEY_FRAME && newp != *Pold)
+                            u = 1;
+                        vp8_write(w, u, upd);
+#ifdef ENTROPY_STATS
+                        ++ tree_update_hist [i][j][k][t] [u];
 #endif
-
+                        if (u)
+                        {
+                            /* send/use new probability */
+                            *Pold = newp;
+                            vp8_write_literal(w, newp, 8);
+                        }
+                    }
+                    while (++t < ENTROPY_NODES);
+                    /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+                    t = 0;
+                    do
+                    {
+                        context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
+                    }
+                    while (++t < MAX_ENTROPY_TOKENS);
+#endif
+                }
+                while (++k < PREV_COEF_CONTEXTS);
             }
-            while (++k < PREV_COEF_CONTEXTS);
+            while (++j < COEF_BANDS);
         }
-        while (++j < COEF_BANDS);
+        while (++i < BLOCK_TYPES);
     }
-    while (++i < BLOCK_TYPES);
+
 
 #if CONFIG_T8X8
     /* do not do this if not evena allowed */
     if(cpi->common.txfm_mode == ALLOW_8X8)
     {
+        update = 1;
+        /* dry run to see if update is necessary */
         i = 0;
         do
         {
             int j = 0;
-
             do
             {
                 int k = 0;
-
                 do
                 {
                     //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
                     /* at every context */
-
                     /* calc probs and branch cts for this frame only */
                     //vp8_prob new_p           [ENTROPY_NODES];
                     //unsigned int branch_ct   [ENTROPY_NODES] [2];
-
                     int t = 0;      /* token/prob index */
-
                     //vp8_tree_probs_from_distribution(
                     //    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
                     //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
                     //    256, 1
                     //    );
-
                     do
                     {
                         const unsigned int *ct  = cpi->frame_branch_ct_8x8 [i][j][k][t];
                         const vp8_prob newp = cpi->frame_coef_probs_8x8 [i][j][k][t];
-
                         vp8_prob *Pold = cpi->common.fc.coef_probs_8x8 [i][j][k] + t;
                         const vp8_prob old = *Pold;
                         const vp8_prob upd = vp8_coef_update_probs_8x8 [i][j][k][t];
-
                         const int old_b = vp8_cost_branch(ct, old);
                         const int new_b = vp8_cost_branch(ct, newp);
-
                         const int update_b = 8 +
                             ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
-
                         const int s = old_b - new_b - update_b;
                         const int u = s > 0 ? 1 : 0;
-
-                        vp8_write(w, u, upd);
-
-
 #ifdef ENTROPY_STATS
                         ++ tree_update_hist_8x8 [i][j][k][t] [u];
 #endif
-
-                        if (u)
-                        {
-                            /* send/use new probability */
-
-                            *Pold = newp;
-                            vp8_write_literal(w, newp, 8);
-
-                            savings += s;
-
-                        }
-
+                        update += u;
                     }
                     while (++t < MAX_ENTROPY_TOKENS - 1);
 
@@ -2415,6 +2453,76 @@ static void update_coef_probs(VP8_COMP *cpi)
             while (++j < COEF_BANDS);
         }
         while (++i < BLOCK_TYPES);
+
+        if(update == 0)
+        {
+            vp8_write_bit(w, 0);
+
+        }
+        else
+        {
+            vp8_write_bit(w, 1);
+            i = 0;
+            do
+            {
+                int j = 0;
+                do
+                {
+                    int k = 0;
+                    do
+                    {
+                        //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+                        /* at every context */
+                        /* calc probs and branch cts for this frame only */
+                        //vp8_prob new_p           [ENTROPY_NODES];
+                        //unsigned int branch_ct   [ENTROPY_NODES] [2];
+                        int t = 0;      /* token/prob index */
+                        //vp8_tree_probs_from_distribution(
+                        //    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+                        //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+                        //    256, 1
+                        //    );
+                        do
+                        {
+                            const unsigned int *ct  = cpi->frame_branch_ct_8x8 [i][j][k][t];
+                            const vp8_prob newp = cpi->frame_coef_probs_8x8 [i][j][k][t];
+                            vp8_prob *Pold = cpi->common.fc.coef_probs_8x8 [i][j][k] + t;
+                            const vp8_prob old = *Pold;
+                            const vp8_prob upd = vp8_coef_update_probs_8x8 [i][j][k][t];
+                            const int old_b = vp8_cost_branch(ct, old);
+                            const int new_b = vp8_cost_branch(ct, newp);
+                            const int update_b = 8 +
+                                ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+                            const int s = old_b - new_b - update_b;
+                            const int u = s > 0 ? 1 : 0;
+                            vp8_write(w, u, upd);
+#ifdef ENTROPY_STATS
+                            ++ tree_update_hist_8x8 [i][j][k][t] [u];
+#endif
+                            if (u)
+                            {
+                                /* send/use new probability */
+                                *Pold = newp;
+                                vp8_write_literal(w, newp, 8);
+                            }
+                        }
+                        while (++t < MAX_ENTROPY_TOKENS - 1);
+                        /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+                        t = 0;
+                        do
+                        {
+                            context_counters_8x8 [i][j][k][t] += cpi->coef_counts_8x8 [i][j][k][t];
+                        }
+                        while (++t < MAX_ENTROPY_TOKENS);
+#endif
+                    }
+                    while (++k < PREV_COEF_CONTEXTS);
+                }
+                while (++j < COEF_BANDS);
+            }
+            while (++i < BLOCK_TYPES);
+        }
     }
 
 #endif