Use of temporal context for encoding delta updates.
authorSuman Sunkara <sunkaras@google.com>
Thu, 23 Sep 2010 22:25:33 +0000 (18:25 -0400)
committerSuman Sunkara <sunkaras@google.com>
Thu, 11 Nov 2010 16:31:36 +0000 (11:31 -0500)
- Used three probability approach for temporal context as follows:
P0 - probability of no change if both above and left not changed
P1 - probability of no change if one of above and left has changed
P2 - probability of no change if both above and left have changed

In addition, a 1 bit/frame has been used to decide whether to use temporal context or to encode directly.  The cost of using both the schemes is calculated ahead and the temporal_update flag is set if the cost of using temporal context is lower than encoding the segment ids directly.

This approach has given around 20% reduction in cost of bits needed to encode segmentation ids.

Change-Id: I44a5509599eded215ae5be9554314280d3d35405

vp8/common/blockd.h
vp8/decoder/decodemv.c
vp8/decoder/decodframe.c
vp8/decoder/demode.c
vp8/decoder/onyxd_if.c
vp8/decoder/onyxd_int.h
vp8/encoder/bitstream.c
vp8/encoder/encodeframe.c
vp8/encoder/onyx_if.c

index da8c0e1..7a7b06b 100644 (file)
@@ -172,6 +172,7 @@ typedef struct
     int mb_skip_coeff;                                //does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens
     int dc_diff;
     unsigned char   segment_id;                  // Which set of segmentation parameters should be used for this MB
+    unsigned char segment_flag;
     int force_no_skip;
 
     B_MODE_INFO partition_bmi[16];
@@ -253,6 +254,7 @@ typedef struct
     // 0 (do not update) 1 (update) the macroblock segmentation feature data.
     unsigned char mb_segement_abs_delta;
 
+    unsigned char temporal_update;
     // Per frame flags that define which MB level features (such as quantizer or loop filter level)
     // are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO
 #if CONFIG_SEGMENTATION
index dfa4680..f151ef3 100644 (file)
@@ -113,7 +113,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
 
     VP8_COMMON *const pc = & pbi->common;
     vp8_reader *const bc = & pbi->bc;
-
+    MACROBLOCKD *xd = &pbi->mb;
     MODE_INFO *mi = pc->mi, *ms;
     const int mis = pc->mode_info_stride;
 
@@ -123,6 +123,8 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
 #if CONFIG_SEGMENTATION
     int left_id, above_id;
     int i;
+    int sum;
+    int index = 0;
 #endif
     vp8_prob prob_intra;
     vp8_prob prob_last;
@@ -161,7 +163,9 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
     }
 
     read_mvcontexts(bc, mvc);
-
+#if CONFIG_SEGMENTATION
+    xd->temporal_update = vp8_read_bit(bc);
+#endif
     while (++mb_row < pc->mb_rows)
     {
         int mb_col = -1;
@@ -171,7 +175,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
             MB_MODE_INFO *const mbmi = & mi->mbmi;
             MV *const mv = & mbmi->mv.as_mv;
             VP8_COMMON *const pc = &pbi->common;
-            MACROBLOCKD *xd = &pbi->mb;
+            // MACROBLOCKD *xd = &pbi->mb;
 
             vp8dx_bool_decoder_fill(bc);
             // Distance of Mb to the various image edges.
@@ -185,69 +189,40 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
             if (pbi->mb.update_mb_segmentation_map)
             {
 #if CONFIG_SEGMENTATION
-                xd->up_available = (mb_row != 0);
-                xd->left_available = (mb_col != 0);
-                int count = 0;
-                int j;
-                if(xd->left_available)
-                    left_id = (mi-1)->mbmi.segment_id;
-                else
-                    left_id = 0;
+                if (xd->temporal_update)
+                {
+                    sum = 0;
 
-                if(xd->up_available)
-                    above_id = (mi-pc->mb_cols)->mbmi.segment_id;
-                else
-                    above_id = 0;
+                    if (mb_col != 0)
+                        sum += (mi-1)->mbmi.segment_flag;
+                    if (mb_row != 0)
+                        sum += (mi-pc->mb_cols)->mbmi.segment_flag;
 
-                if (vp8_read(bc, xd->mb_segment_tree_probs[0]))
-                {
-                    for(i = 0; i < MAX_MB_SEGMENTS; i++)
+                    if (vp8_read(bc, xd->mb_segment_tree_probs[3+sum]) == 0)
                     {
-                        if((left_id != i) && (above_id != i))
-                        {
-                            if(left_id != above_id)
-                            {
-                                if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0)
-                                    mbmi->segment_id = i;
-                                else
-                                    mbmi->segment_id = 6-left_id-above_id-i;
-                                break;
-                            }
-                            else
-                            {
-                                if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0)
-                                {
-                                    mbmi->segment_id = i;
-                                    break;
-                                }
-                                else
-                                {
-                                    count++;
-                                    if(count == 1)
-                                        j = i;
-                                    if(count == 2)
-                                    {
-                                        mbmi->segment_id = 6-left_id-j-i;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
+                        mbmi->segment_id = pbi->segmentation_map[index];
+                        mbmi->segment_flag = 0;
+                    }
+                    else
+                    {
+                        vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
+                        mbmi->segment_flag = 1;
+                        pbi->segmentation_map[index] = mbmi->segment_id;
                     }
+
                 }
                 else
                 {
-                    if (vp8_read(bc, xd->mb_segment_tree_probs[1]))
-                        mbmi->segment_id = above_id;
-                    else
-                        mbmi->segment_id = left_id;
-
+                    vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
+                    pbi->segmentation_map[index] = mbmi->segment_id;
                 }
+                index++;
 #else
                 vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
 #endif
             }
 
+
             // Read the macroblock coeff skip flag if this feature is in use, else default to 0
             if (pc->mb_no_coeff_skip)
                 mbmi->mb_skip_coeff = vp8_read(bc, prob_skip_false);
index a26056e..01cd7ae 100644 (file)
@@ -632,7 +632,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
 
     // Is segmentation enabled
     xd->segmentation_enabled = (unsigned char)vp8_read_bit(bc);
-
     if (xd->segmentation_enabled)
     {
         // Signal whether or not the segmentation map is being explicitly updated this frame.
@@ -794,7 +793,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         fclose(z);
     }
 
-
     vp8dx_bool_decoder_fill(bc);
     {
         // read coef probability tree
@@ -818,6 +816,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     vpx_memcpy(&xd->pre, &pc->last_frame, sizeof(YV12_BUFFER_CONFIG));
     vpx_memcpy(&xd->dst, &pc->new_frame, sizeof(YV12_BUFFER_CONFIG));
 
+#if CONFIG_SEGMENTATION
+     // Create the encoder segmentation map and set all entries to 0
+     CHECK_MEM_ERROR(pbi->segmentation_map, vpx_calloc((pc->mb_rows * pc->mb_cols), 1));
+#endif
+
     // set up frame new frame for intra coded blocks
     vp8_setup_intra_recon(&pc->new_frame);
 
index 5b837ad..74fe918 100644 (file)
@@ -91,65 +91,8 @@ void vp8_kfread_modes(VP8D_COMP *pbi)
             {
 
 #if CONFIG_SEGMENTATION
-                MACROBLOCKD *xd = &pbi->mb;
-                xd->up_available = (mb_row != 0);
-                xd->left_available = (mb_col != 0);
-                int count = 0;
-                int j;
-                if(xd->left_available)
-                    left_id = (m-1)->mbmi.segment_id;
-                else
-                    left_id = 0;
-
-                if(xd->up_available)
-                    above_id = (m-cp->mb_cols)->mbmi.segment_id;
-                else
-                    above_id = 0;
-
-                if (vp8_read(bc, xd->mb_segment_tree_probs[0]))
-                {
-                    for(i = 0; i < MAX_MB_SEGMENTS; i++)
-                    {
-                        if((left_id != i) && (above_id != i))
-                        {
-                            if(left_id != above_id)
-                            {
-                                if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0)
-                                    m->mbmi.segment_id = i;
-                                else
-                                    m->mbmi.segment_id = 6-left_id-above_id-i;
-                                break;
-                            }
-                            else
-                            {
-                                if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0)
-                                {
-                                    m->mbmi.segment_id = i;
-                                    break;
-                                }
-                                else
-                                {
-                                    count++;
-                                    if(count == 1)
-                                        j = i;
-                                    if(count == 2)
-                                    {
-                                        m->mbmi.segment_id = 6-left_id-j-i;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                else
-                {
-                    if (vp8_read(bc, xd->mb_segment_tree_probs[1]))
-                        m->mbmi.segment_id = above_id;
-                    else
-                        m->mbmi.segment_id = left_id;
-
-                }
+                vp8_read_mb_features(bc, &m->mbmi, &pbi->mb);
+                pbi->segmentation_map[(mb_row * cp->mb_cols) + mb_col] = m->mbmi.segment_id;
 #else
                 vp8_read_mb_features(bc, &m->mbmi, &pbi->mb);
 #endif
index c87f3af..8d2b267 100644 (file)
@@ -137,7 +137,11 @@ void vp8dx_remove_decompressor(VP8D_PTR ptr)
 
     if (!pbi)
         return;
-
+#if CONFIG_SEGMENTATION
+     // Delete sementation map
+    if (pbi->segmentation_map != 0)
+        vpx_free(pbi->segmentation_map);
+#endif
     vp8_decoder_remove_threads(pbi);
     vp8_remove_common(&pbi->common);
     vpx_free(pbi);
index 218c239..e8b5d40 100644 (file)
@@ -81,7 +81,7 @@ typedef struct VP8Decompressor
     const unsigned char *Source;
     unsigned int   source_sz;
 
-
+    unsigned char *segmentation_map;
     unsigned int CPUFreq;
     unsigned int decode_microseconds;
     unsigned int time_decoding;
index f0b345b..8008920 100644 (file)
@@ -862,9 +862,12 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     VP8_COMMON *const pc = & cpi->common;
     vp8_writer *const w = & cpi->bc;
     const MV_CONTEXT *mvc = pc->fc.mvc;
+    MACROBLOCKD *xd = &cpi->mb.e_mbd;
 #if CONFIG_SEGMENTATION
     int left_id, above_id;
     int i;
+    int sum;
+    int index = 0;
 #endif
     const int *const rfct = cpi->count_mb_ref_frame_usage;
     const int rf_intra = rfct[INTRA_FRAME];
@@ -920,7 +923,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
     update_mbintra_mode_probs(cpi);
 
     vp8_write_mvprobs(cpi);
-
+#if CONFIG_SEGMENTATION
+    vp8_write_bit(w, (xd->temporal_update) ? 1:0);
+#endif
     while (++mb_row < pc->mb_rows)
     {
         int mb_col = -1;
@@ -931,7 +936,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
             const MV_REFERENCE_FRAME rf = mi->ref_frame;
             const MB_PREDICTION_MODE mode = mi->mode;
 
-            MACROBLOCKD *xd = &cpi->mb.e_mbd;
+            //MACROBLOCKD *xd = &cpi->mb.e_mbd;
 
             // Distance of Mb to the various image edges.
             // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
@@ -948,87 +953,37 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
             if (cpi->mb.e_mbd.update_mb_segmentation_map)
             {
 #if CONFIG_SEGMENTATION
-                if(xd->left_available)
-                    left_id = (m-1)->mbmi.segment_id;
-                else
-                    left_id = 0;
-
-                if(xd->up_available)
-                    above_id = (m-pc->mb_cols)->mbmi.segment_id;
-                else
-                    above_id = 0;
-
-                if ((m->mbmi.segment_id == left_id) || (m->mbmi.segment_id == above_id))
+                if (xd->temporal_update)
                 {
-                    vp8_write(w, 0, xd->mb_segment_tree_probs[0]);
-                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[0]);
+                    sum = 0;
+                    if (mb_col != 0)
+                        sum +=  (m-1)->mbmi.segment_flag;
+                    if (mb_row != 0)
+                        sum += (m-pc->mb_cols)->mbmi.segment_flag;
 
-                    if  (left_id != above_id)
+                    if (m->mbmi.segment_flag == 0)
                     {
-                        if(m->mbmi.segment_id == left_id)
-                        {
-                            vp8_write(w, 0, xd->mb_segment_tree_probs[1]);
-                            segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]);
-                        }
-                        else
-                        {
-                            vp8_write(w, 1, xd->mb_segment_tree_probs[1]);
-                            segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[1]);
-                        }
+                        vp8_write(w,0,xd->mb_segment_tree_probs[3+sum]);
+                        segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[3+sum]);
                     }
                     else
                     {
-                        vp8_write(w, 0, xd->mb_segment_tree_probs[1]);
-                        segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]);
+                        vp8_write(w,1,xd->mb_segment_tree_probs[3+sum]);
+                        segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[3+sum]);
+                        write_mb_features(w, mi, &cpi->mb.e_mbd);
+                        cpi->segmentation_map[index] = mi->segment_id;
                     }
                 }
                 else
                 {
-                    vp8_write(w, 1, xd->mb_segment_tree_probs[0]);
-                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[0]);
-                    int count = 0;
-                    for(i = 0; i < MAX_MB_SEGMENTS; i++)
-                    {
-                        if((left_id != i) && (above_id != i))
-                        {
-                            if(left_id != above_id)
-                            {
-                                if(m->mbmi.segment_id == i)
-                                {
-                                    vp8_write(w, 0, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]);
-                                }
-                                else
-                                {
-                                    vp8_write(w, 1, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]);
-                                }
-                                break;
-                            }
-                            else
-                            {
-                                if(m->mbmi.segment_id == i)
-                                {
-                                    vp8_write(w, 0, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]);
-                                    break;
-                                }
-                                else
-                                {
-                                    count++;
-                                    vp8_write(w, 1, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]);
-                                    if(count == 2)
-                                        break;
-                                }
-                            }
-                        }
-                    }
+                    write_mb_features(w, mi, &cpi->mb.e_mbd);
+                    cpi->segmentation_map[index] = mi->segment_id;
                 }
+                index++;
 #else
                 write_mb_features(w, mi, &cpi->mb.e_mbd);
 #endif
-                }
+            }
 
             if (pc->mb_no_coeff_skip)
                 vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);
@@ -1157,6 +1112,7 @@ static void write_kfmodes(VP8_COMP *cpi)
 #if CONFIG_SEGMENTATION
     int left_id, above_id;
     int i;
+    int index = 0;
 #endif
     int mb_row = -1;
     int prob_skip_false = 0;
@@ -1190,85 +1146,12 @@ static void write_kfmodes(VP8_COMP *cpi)
             if (cpi->mb.e_mbd.update_mb_segmentation_map)
             {
 #if CONFIG_SEGMENTATION
-                if(xd->left_available)
-                    left_id = (m-1)->mbmi.segment_id;
-                else
-                    left_id = 0;
-
-                if(xd->up_available)
-                    above_id = (m-c->mb_cols)->mbmi.segment_id;
-                else
-                    above_id = 0;
-
-                if ((m->mbmi.segment_id == left_id) || (m->mbmi.segment_id == above_id))
-                {
-                    vp8_write(bc, 0, xd->mb_segment_tree_probs[0]);
-                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[0]);
-                    if  (left_id != above_id)
-                    {
-                        if(m->mbmi.segment_id == left_id)
-                        {
-                            vp8_write(bc, 0, xd->mb_segment_tree_probs[1]);
-                            segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]);
-                        }
-                        else
-                        {
-                            vp8_write(bc, 1, xd->mb_segment_tree_probs[1]);
-                            segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[1]);
-                        }
-                    }
-                    else
-                    {
-                        vp8_write(bc, 0, xd->mb_segment_tree_probs[1]);
-                        segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]);
-                    }
-                }
-                else
-                {
-                    vp8_write(bc, 1, xd->mb_segment_tree_probs[0]);
-                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[0]);
-                    int count = 0;
-                    for(i = 0; i < MAX_MB_SEGMENTS; i++)
-                    {
-                        if((left_id != i) && (above_id != i))
-                        {
-                            if(left_id != above_id)
-                            {
-                                if(m->mbmi.segment_id == i)
-                                {
-                                    vp8_write(bc, 0, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]);
-                                }
-                                else
-                                {
-                                    vp8_write(bc, 1, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]);
-                                }
-                                break;
-                            }
-                            else
-                            {
-                                if(m->mbmi.segment_id == i)
-                                {
-                                    vp8_write(bc, 0, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]);
-                                    break;
-                                }
-                                else
-                                {
-                                    count++;
-                                    vp8_write(bc, 1, xd->mb_segment_tree_probs[2+i]);
-                                    segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]);
-                                    if(count == 2)
-                                        break;
-                                }
-                            }
 
-                        }
-                    }
-                }
+                write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
+                cpi->segmentation_map[index] = m->mbmi.segment_id;
+                index++;
 #else
-            write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
+                write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
 #endif
             }
 
@@ -1587,10 +1470,9 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     }
     else
         vp8_start_encode(bc, cx_data);
-#if CONFIG_SEGMENTATION
-     //xd->segmentation_enabled =1;
-     xd->update_mb_segmentation_map = 1;
-#endif
+
+    xd->update_mb_segmentation_map = 1;
+
     // Signal whether or not Segmentation is enabled
     vp8_write_bit(bc, (xd->segmentation_enabled) ? 1 : 0);
 
@@ -1810,7 +1692,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
 #endif
     }
 #if CONFIG_SEGMENTATION
-    //printf("\nseg_cost is %d\n",segment_cost);
+    //printf("%d\n",segment_cost);
 #endif
     vp8_stop_encode(bc);
 
index 4af2fdd..faf8e2b 100644 (file)
@@ -29,6 +29,7 @@
 #include "subpixel.h"
 #include "vpx_ports/vpx_timer.h"
 
+
 #if CONFIG_RUNTIME_CPU_DETECT
 #define RTCD(x)     &cpi->common.rtcd.x
 #define IF_RTCD(x)  (x)
 #define RTCD(x)     NULL
 #define IF_RTCD(x)  NULL
 #endif
+
+#if CONFIG_SEGMENTATION
+#define SEEK_SEGID 12
+#define SEEK_SAMEID 4
+#define SEEK_DIFFID 7
+#endif
+
 extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
 
 extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
@@ -260,6 +268,7 @@ void encode_mb_row(VP8_COMP *cpi,
     int seg_map_index = (mb_row * cpi->common.mb_cols);
 #if CONFIG_SEGMENTATION
     int left_id, above_id;
+    int sum;
 #endif
     // reset above block coeffs
     xd->above_context[Y1CONTEXT] = cm->above_context[Y1CONTEXT];
@@ -370,6 +379,11 @@ void encode_mb_row(VP8_COMP *cpi,
 
         xd->gf_active_ptr++;      // Increment pointer into gf useage flags structure for next mb
 
+        if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame == LAST_FRAME))
+            xd->mbmi.segment_id = 0;
+        else
+            xd->mbmi.segment_id = 1;
+
         // store macroblock mode info into context array
         vpx_memcpy(&xd->mode_info_context->mbmi, &xd->mbmi, sizeof(xd->mbmi));
 
@@ -385,66 +399,40 @@ void encode_mb_row(VP8_COMP *cpi,
         recon_uvoffset += 8;
 
 #if CONFIG_SEGMENTATION
-    if(xd->left_available)
-        left_id = cpi->segmentation_map[seg_map_index+mb_col-1];
-    else
-        left_id = 0;
-
-    if(xd->up_available)
-        above_id = cpi->segmentation_map[seg_map_index+mb_col-cpi->common.mb_cols];
-    else
-        above_id = 0;
-
-    if ((xd->mbmi.segment_id == left_id) || (xd->mbmi.segment_id == above_id))
-    {
-        segment_counts[8]++;
-        if  (left_id != above_id)
+       //cpi->segmentation_map[mb_row * cm->mb_cols + mb_col] =  xd->mbmi.segment_id;
+        if (cm->frame_type == KEY_FRAME)
         {
-            if(xd->mbmi.segment_id == left_id)
-                segment_counts[10]++;
-            else
-                segment_counts[11]++;
+            segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
         }
         else
-            segment_counts[10]++;
-    }
-    else
-    {
-        segment_counts[9]++;
-        int count =0;
-        for(i = 0; i < MAX_MB_SEGMENTS; i++)
         {
-            if((left_id != i) && (above_id != i))
+            sum = 0;
+            if (mb_col != 0)
+                sum += (xd->mode_info_context-1)->mbmi.segment_flag;
+            if (mb_row != 0)
+                sum += (xd->mode_info_context-cm->mb_cols)->mbmi.segment_flag;
+
+            if (xd->mbmi.segment_id == cpi->segmentation_map[(mb_row*cm->mb_cols) + mb_col])
+                xd->mode_info_context->mbmi.segment_flag = 0;
+            else
+                xd->mode_info_context->mbmi.segment_flag = 1;
+
+            if (xd->mode_info_context->mbmi.segment_flag == 0)
             {
-                if(above_id != left_id)
-                {
-                    if(xd->mbmi.segment_id == i)
-                        segment_counts[i]++;
-                    else
-                        segment_counts[MAX_MB_SEGMENTS + i]++;
-                    break;
-                }
-                else
-                {
-                    if(xd->mbmi.segment_id == i)
-                    {
-                        segment_counts[i]++;
-                        break;
-                    }
-                    else
-                    {
-                        count++;
-                        segment_counts[MAX_MB_SEGMENTS + i]++;
-                        if(count == 2)
-                            break;
-                    }
-                }
+                segment_counts[SEEK_SAMEID + sum]++;
+                segment_counts[10]++;
+            }
+            else
+            {
+                segment_counts[SEEK_DIFFID + sum]++;
+                segment_counts[11]++;
+                //calculate individual segment ids
+                segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
             }
         }
-    }
-
+        segment_counts[SEEK_SEGID + xd->mbmi.segment_id] ++;
 #else
-    segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
+        segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
 #endif
         // skip to next mb
         xd->mode_info_context++;
@@ -477,7 +465,9 @@ void vp8_encode_frame(VP8_COMP *cpi)
     int i;
     TOKENEXTRA *tp = cpi->tok;
 #if CONFIG_SEGMENTATION
-    int segment_counts[MAX_MB_SEGMENTS + 8];
+    int segment_counts[MAX_MB_SEGMENTS + SEEK_SEGID];
+    int prob[3];
+    int new_cost, original_cost;
 #else
     int segment_counts[MAX_MB_SEGMENTS];
 #endif
@@ -738,61 +728,114 @@ void vp8_encode_frame(VP8_COMP *cpi)
 
     }
 
-
     // Work out the segment probabilites if segmentation is enabled
     if (xd->segmentation_enabled)
     {
         int tot_count;
-        int i;
+        int i,j;
+        int count1,count2,count3,count4;
 
         // Set to defaults
         vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs));
 #if CONFIG_SEGMENTATION
-        tot_count = segment_counts[8] + segment_counts[9];
+
+        tot_count = segment_counts[12] + segment_counts[13] + segment_counts[14] + segment_counts[15];
+        count1 = segment_counts[12] + segment_counts[13];
+        count2 = segment_counts[14] + segment_counts[15];
 
         if (tot_count)
-            xd->mb_segment_tree_probs[0] = (segment_counts[8] * 255) / tot_count;
+            prob[0] = (count1 * 255) / tot_count;
 
-        tot_count = segment_counts[10] + segment_counts[11];
+        if (count1 > 0)
+            prob[1] = (segment_counts[12] * 255) /count1;
 
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[1] = (segment_counts[10] * 255) / tot_count;
+        if (count2 > 0)
+            prob[2] = (segment_counts[14] * 255) /count2;
 
-        tot_count = segment_counts[0] + segment_counts[4] ;
+        if (cm->frame_type != KEY_FRAME)
+        {
+            tot_count = segment_counts[4] + segment_counts[7];
+            if (tot_count)
+                xd->mb_segment_tree_probs[3] = (segment_counts[4] * 255)/tot_count;
 
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[2] = (segment_counts[0]  * 255) / tot_count;
+            tot_count = segment_counts[5] + segment_counts[8];
+            if (tot_count)
+                xd->mb_segment_tree_probs[4] = (segment_counts[5] * 255)/tot_count;
 
-        tot_count = segment_counts[1] + segment_counts[5];
+            tot_count = segment_counts[6] + segment_counts[9];
+            if (tot_count)
+                xd->mb_segment_tree_probs[5] = (segment_counts[6] * 255)/tot_count;
+        }
 
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[3] = (segment_counts[1] * 255) / tot_count;
+        tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3];
+        count3 = segment_counts[0] + segment_counts[1];
+        count4 = segment_counts[2] + segment_counts[3];
 
-        tot_count = segment_counts[2] + segment_counts[6];
+        if (tot_count)
+            xd->mb_segment_tree_probs[0] = (count3 * 255) / tot_count;
 
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[4] = (segment_counts[2] * 255) / tot_count;
+        if (count3 > 0)
+            xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count3;
+
+        if (count4 > 0)
+            xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count4;
+
+        for (i = 0; i < MB_FEATURE_TREE_PROBS+3; i++)
+        {
+            if (xd->mb_segment_tree_probs[i] == 0)
+                xd->mb_segment_tree_probs[i] = 1;
+        }
 
-        tot_count = segment_counts[3] + segment_counts[7];
+        original_cost = count1 * vp8_cost_zero(prob[0]) + count2 * vp8_cost_one(prob[0]);
+
+        if (count1 > 0)
+            original_cost += segment_counts[12] * vp8_cost_zero(prob[1]) + segment_counts[13] * vp8_cost_one(prob[1]);
+
+        if (count2 > 0)
+            original_cost += segment_counts[14] * vp8_cost_zero(prob[2]) + segment_counts[15] * vp8_cost_one(prob[2]) ;
+
+        new_cost = 0;
+
+        if (cm->frame_type != KEY_FRAME)
+        {
+            new_cost = segment_counts[4] * vp8_cost_zero(xd->mb_segment_tree_probs[3]) + segment_counts[7] *  vp8_cost_one(xd->mb_segment_tree_probs[3]);
+
+            new_cost += segment_counts[5] * vp8_cost_zero(xd->mb_segment_tree_probs[4]) + segment_counts[8] * vp8_cost_one(xd->mb_segment_tree_probs[4]);
+
+            new_cost += segment_counts[6] * vp8_cost_zero(xd->mb_segment_tree_probs[5]) + segment_counts[9] * vp8_cost_one (xd->mb_segment_tree_probs[5]);
+        }
 
         if (tot_count > 0)
-            xd->mb_segment_tree_probs[5] = (segment_counts[3] * 255) / tot_count;
+            new_cost += count3 * vp8_cost_zero(xd->mb_segment_tree_probs[0]) + count4 * vp8_cost_one(xd->mb_segment_tree_probs[0]);
+
+        if (count3 > 0)
+            new_cost += segment_counts[0] * vp8_cost_zero(xd->mb_segment_tree_probs[1]) + segment_counts[1] * vp8_cost_one(xd->mb_segment_tree_probs[1]);
 
+        if (count4 > 0)
+            new_cost += segment_counts[2] * vp8_cost_zero(xd->mb_segment_tree_probs[2]) + segment_counts[3] * vp8_cost_one(xd->mb_segment_tree_probs[2]) ;
+
+        if (new_cost < original_cost)
+            xd->temporal_update = 1;
+        else
+        {
+            xd->temporal_update = 0;
+            xd->mb_segment_tree_probs[0] = prob[0];
+            xd->mb_segment_tree_probs[1] = prob[1];
+            xd->mb_segment_tree_probs[2] = prob[2];
+        }
 #else
         tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3];
+        count1 = segment_counts[0] + segment_counts[1];
+        count2 = segment_counts[2] + segment_counts[3];
 
         if (tot_count)
-            xd->mb_segment_tree_probs[0] = ((segment_counts[0] + segment_counts[1]) * 255) / tot_count;
+            xd->mb_segment_tree_probs[0] = (count1 * 255) / tot_count;
 
-        tot_count = segment_counts[0] + segment_counts[1];
+        if (count1 > 0)
+            xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count1;
 
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) / tot_count;
-
-        tot_count = segment_counts[2] + segment_counts[3];
-
-        if (tot_count > 0)
-            xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) / tot_count;
+        if (count2 > 0)
+            xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count2;
 
 #endif
         // Zero probabilities not allowed
index bab5f36..9bc7f52 100644 (file)
@@ -277,27 +277,10 @@ static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned ch
 static void segmentation_test_function(VP8_PTR ptr)
 {
     VP8_COMP *cpi = (VP8_COMP *)(ptr);
-#if CONFIG_SEGMENTATION
-    int i,j;
-#endif
     unsigned char *seg_map;
     signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
     CHECK_MEM_ERROR(seg_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
     // Create a temporary map for segmentation data.
-#if CONFIG_SEGMENTATION
-    // MB loop to set local segmentation map
-    for (i = 0; i < cpi->common.mb_rows; i++ )
-    {
-        for (j = 0; j < cpi->common.mb_cols; j++ )
-        {
-            if (j >= cpi->common.mb_cols/4 && j < (cpi->common.mb_cols*3)/4 )
-                seg_map[(i*cpi->common.mb_cols) + j] = 2;
-            else
-                seg_map[(i*cpi->common.mb_cols) + j] = 0;
-        }
-    }
-
-#endif
 
     // MB loop to set local segmentation map
     /*for ( i = 0; i < cpi->common.mb_rows; i++ )
@@ -3542,17 +3525,16 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, unsigned long *size, unsign
     int drop_mark75 = drop_mark * 2 / 3;
     int drop_mark50 = drop_mark / 4;
     int drop_mark25 = drop_mark / 8;
-#if CONFIG_SEGMENTATION
-   int i;
-#endif
+
     // Clear down mmx registers to allow floating point in what follows
     vp8_clear_system_state();
 
     // Test code for segmentation of gf/arf (0,0)
+    //segmentation_test_function((VP8_PTR) cpi);
 #if CONFIG_SEGMENTATION
-    segmentation_test_function((VP8_PTR) cpi);
+    cpi->mb.e_mbd.segmentation_enabled = 1;
+    cpi->mb.e_mbd.update_mb_segmentation_map = 1;
 #endif
-    //segmentation_test_function((VP8_PTR) cpi);
 
     // For an alt ref frame in 2 pass we skip the call to the second pass function that sets the target bandwidth
 #if !(CONFIG_REALTIME_ONLY)
@@ -4057,28 +4039,6 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, unsigned long *size, unsign
             vp8_setup_key_frame(cpi);
 
         // transform / motion compensation build reconstruction frame
-#if CONFIG_SEGMENTATION
-   // MB loop to set local segmentation map
-    for (i = 0; i < cpi->common.mb_rows; i++ )
-    {
-        int j = (cpi->common.mb_cols/4);
-        int k = (cpi->common.mb_cols*3)/4;
-        if((cm->current_video_frame%2 == 0 && i<cpi->common.mb_rows/2)||(cm->current_video_frame%2 == 1 && i>cpi->common.mb_rows/2))
-        {
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + j] = 2;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + j-1] = 2;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + k] = 2;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + k+1] = 2;
-        }
-        else if((cm->current_video_frame%2 == 1 && i<cpi->common.mb_rows/2)||(cm->current_video_frame%2 == 0 && i>cpi->common.mb_rows/2))
-        {
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + j] = 0;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + j-1] = 0;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + k] = 0;
-            cpi->segmentation_map[(i*cpi->common.mb_cols) + k+1] = 0;
-        }
-    }
-#endif
         vp8_encode_frame(cpi);
         cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi);
         cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;