OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include "vp9/common/vp9_onyxc_int.h" |
| 12 |
| 13 #define MAX_REGIONS 24000 |
| 14 #ifndef NULL |
| 15 #define NULL 0 |
| 16 #endif |
| 17 |
| 18 #define min_mbs_in_region 3 |
| 19 |
| 20 // this linked list structure holds equivalences for connected |
| 21 // component labeling |
| 22 struct list_el { |
| 23 int label; |
| 24 int seg_value; |
| 25 int count; |
| 26 struct list_el *next; |
| 27 }; |
| 28 typedef struct list_el item; |
| 29 |
| 30 // connected colorsegments |
| 31 typedef struct { |
| 32 int min_x; |
| 33 int min_y; |
| 34 int max_x; |
| 35 int max_y; |
| 36 long long sum_x; |
| 37 long long sum_y; |
| 38 int pixels; |
| 39 int seg_value; |
| 40 int label; |
| 41 } segment_info; |
| 42 |
| 43 |
| 44 typedef enum { |
| 45 SEGMENT_MODE, |
| 46 SEGMENT_MV, |
| 47 SEGMENT_REFFRAME, |
| 48 SEGMENT_SKIPPED |
| 49 } SEGMENT_TYPE; |
| 50 |
| 51 |
| 52 // this merges the two equivalence lists and |
| 53 // then makes sure that every label points to the same |
| 54 // equivalence list |
| 55 void merge(item *labels, int u, int v) { |
| 56 item *a = labels[u].next; |
| 57 item *b = labels[v].next; |
| 58 item c; |
| 59 item *it = &c; |
| 60 int count; |
| 61 |
| 62 // check if they are already merged |
| 63 if (u == v || a == b) |
| 64 return; |
| 65 |
| 66 count = a->count + b->count; |
| 67 |
| 68 // merge 2 sorted linked lists. |
| 69 while (a != NULL && b != NULL) { |
| 70 if (a->label < b->label) { |
| 71 it->next = a; |
| 72 a = a->next; |
| 73 } else { |
| 74 it->next = b; |
| 75 b = b->next; |
| 76 } |
| 77 |
| 78 it = it->next; |
| 79 } |
| 80 |
| 81 if (a == NULL) |
| 82 it->next = b; |
| 83 else |
| 84 it->next = a; |
| 85 |
| 86 it = c.next; |
| 87 |
| 88 // make sure every equivalence in the linked list points to this new ll |
| 89 while (it != NULL) { |
| 90 labels[it->label].next = c.next; |
| 91 it = it->next; |
| 92 } |
| 93 c.next->count = count; |
| 94 |
| 95 } |
| 96 |
| 97 void segment_via_mode_info(VP9_COMMON *oci, int how) { |
| 98 MODE_INFO *mi = oci->mi; |
| 99 int i, j; |
| 100 int mb_index = 0; |
| 101 |
| 102 int label = 1; |
| 103 int pitch = oci->mb_cols; |
| 104 |
| 105 // holds linked list equivalences |
| 106 // the max should probably be allocated at a higher level in oci |
| 107 item equivalences[MAX_REGIONS]; |
| 108 int eq_ptr = 0; |
| 109 item labels[MAX_REGIONS]; |
| 110 segment_info segments[MAX_REGIONS]; |
| 111 int label_count = 1; |
| 112 int labeling[400 * 300]; |
| 113 int *lp = labeling; |
| 114 |
| 115 label_count = 1; |
| 116 memset(labels, 0, sizeof(labels)); |
| 117 memset(segments, 0, sizeof(segments)); |
| 118 |
| 119 /* Go through each macroblock first pass labelling */ |
| 120 for (i = 0; i < oci->mb_rows; i++, lp += pitch) { |
| 121 for (j = 0; j < oci->mb_cols; j++) { |
| 122 // int above seg_value, left seg_value, this seg_value... |
| 123 int a = -1, l = -1, n = -1; |
| 124 |
| 125 // above label, left label |
| 126 int al = -1, ll = -1; |
| 127 if (i) { |
| 128 al = lp[j - pitch]; |
| 129 a = labels[al].next->seg_value; |
| 130 } |
| 131 if (j) { |
| 132 ll = lp[j - 1]; |
| 133 l = labels[ll].next->seg_value; |
| 134 } |
| 135 |
| 136 // what setting are we going to do the implicit segmentation on |
| 137 switch (how) { |
| 138 case SEGMENT_MODE: |
| 139 n = mi[mb_index].mbmi.mode; |
| 140 break; |
| 141 case SEGMENT_MV: |
| 142 n = mi[mb_index].mbmi.mv[0].as_int; |
| 143 if (mi[mb_index].mbmi.ref_frame == INTRA_FRAME) |
| 144 n = -9999999; |
| 145 break; |
| 146 case SEGMENT_REFFRAME: |
| 147 n = mi[mb_index].mbmi.ref_frame; |
| 148 break; |
| 149 case SEGMENT_SKIPPED: |
| 150 n = mi[mb_index].mbmi.mb_skip_coeff; |
| 151 break; |
| 152 } |
| 153 |
| 154 // above and left both have the same seg_value |
| 155 if (n == a && n == l) { |
| 156 // pick the lowest label |
| 157 lp[j] = (al < ll ? al : ll); |
| 158 labels[lp[j]].next->count++; |
| 159 |
| 160 // merge the above and left equivalencies |
| 161 merge(labels, al, ll); |
| 162 } |
| 163 // this matches above seg_value |
| 164 else if (n == a) { |
| 165 // give it the same label as above |
| 166 lp[j] = al; |
| 167 labels[al].next->count++; |
| 168 } |
| 169 // this matches left seg_value |
| 170 else if (n == l) { |
| 171 // give it the same label as above |
| 172 lp[j] = ll; |
| 173 labels[ll].next->count++; |
| 174 } else { |
| 175 // new label doesn't match either |
| 176 item *e = &labels[label]; |
| 177 item *nl = &equivalences[eq_ptr++]; |
| 178 lp[j] = label; |
| 179 nl->label = label; |
| 180 nl->next = 0; |
| 181 nl->seg_value = n; |
| 182 nl->count = 1; |
| 183 e->next = nl; |
| 184 label++; |
| 185 } |
| 186 mb_index++; |
| 187 } |
| 188 mb_index++; |
| 189 } |
| 190 lp = labeling; |
| 191 |
| 192 // give new labels to regions |
| 193 for (i = 1; i < label; i++) |
| 194 if (labels[i].next->count > min_mbs_in_region && labels[labels[i].next->la
bel].label == 0) { |
| 195 segment_info *cs = &segments[label_count]; |
| 196 cs->label = label_count; |
| 197 labels[labels[i].next->label].label = label_count++; |
| 198 labels[labels[i].next->label].seg_value = labels[i].next->seg_value; |
| 199 cs->seg_value = labels[labels[i].next->label].seg_value; |
| 200 cs->min_x = oci->mb_cols; |
| 201 cs->min_y = oci->mb_rows; |
| 202 cs->max_x = 0; |
| 203 cs->max_y = 0; |
| 204 cs->sum_x = 0; |
| 205 cs->sum_y = 0; |
| 206 cs->pixels = 0; |
| 207 |
| 208 } |
| 209 lp = labeling; |
| 210 |
| 211 // this is just to gather stats... |
| 212 for (i = 0; i < oci->mb_rows; i++, lp += pitch) { |
| 213 for (j = 0; j < oci->mb_cols; j++) { |
| 214 segment_info *cs; |
| 215 int oldlab = labels[lp[j]].next->label; |
| 216 int lab = labels[oldlab].label; |
| 217 lp[j] = lab; |
| 218 |
| 219 cs = &segments[lab]; |
| 220 |
| 221 cs->min_x = (j < cs->min_x ? j : cs->min_x); |
| 222 cs->max_x = (j > cs->max_x ? j : cs->max_x); |
| 223 cs->min_y = (i < cs->min_y ? i : cs->min_y); |
| 224 cs->max_y = (i > cs->max_y ? i : cs->max_y); |
| 225 cs->sum_x += j; |
| 226 cs->sum_y += i; |
| 227 cs->pixels++; |
| 228 |
| 229 lp[j] = lab; |
| 230 mb_index++; |
| 231 } |
| 232 mb_index++; |
| 233 } |
| 234 |
| 235 { |
| 236 lp = labeling; |
| 237 printf("labelling \n"); |
| 238 mb_index = 0; |
| 239 for (i = 0; i < oci->mb_rows; i++, lp += pitch) { |
| 240 for (j = 0; j < oci->mb_cols; j++) { |
| 241 printf("%4d", lp[j]); |
| 242 } |
| 243 printf(" "); |
| 244 for (j = 0; j < oci->mb_cols; j++, mb_index++) { |
| 245 // printf("%3d",mi[mb_index].mbmi.mode ); |
| 246 printf("%4d:%4d", mi[mb_index].mbmi.mv[0].as_mv.row, |
| 247 mi[mb_index].mbmi.mv[0].as_mv.col); |
| 248 } |
| 249 printf("\n"); |
| 250 ++mb_index; |
| 251 } |
| 252 printf("\n"); |
| 253 } |
| 254 } |
| 255 |
OLD | NEW |