e0a338c428
Change-Id: I883b4f63559c1cf66a25016e946b1b1ae98a20da
280 lines
6.5 KiB
C
280 lines
6.5 KiB
C
/*
|
|
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "vp8/common/onyxc_int.h"
|
|
|
|
#define MAX_REGIONS 24000
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
|
|
#define min_mbs_in_region 3
|
|
|
|
// this linked list structure holds equivalences for connected
|
|
// component labeling
|
|
struct list_el {
|
|
int label;
|
|
int seg_value;
|
|
int count;
|
|
struct list_el * next;
|
|
};
|
|
typedef struct list_el item;
|
|
|
|
// connected colorsegments
|
|
typedef struct
|
|
{
|
|
int min_x;
|
|
int min_y;
|
|
int max_x;
|
|
int max_y;
|
|
long long sum_x;
|
|
long long sum_y;
|
|
int pixels;
|
|
int seg_value;
|
|
int label;
|
|
} segment_info;
|
|
|
|
|
|
typedef enum
|
|
{
|
|
SEGMENT_MODE,
|
|
SEGMENT_MV,
|
|
SEGMENT_REFFRAME,
|
|
SEGMENT_SKIPPED
|
|
} SEGMENT_TYPE;
|
|
|
|
|
|
// this merges the two equivalence lists and
|
|
// then makes sure that every label points to the same
|
|
// equivalence list
|
|
void merge ( item *labels, int u, int v )
|
|
{
|
|
item *a = labels[u].next;
|
|
item *b = labels[v].next;
|
|
item c;
|
|
item *it = &c;
|
|
int count;
|
|
|
|
// check if they are already merged
|
|
if(u==v || a==b)
|
|
return;
|
|
|
|
count = a->count + b->count;
|
|
|
|
// merge 2 sorted linked lists.
|
|
while ( a != NULL && b != NULL )
|
|
{
|
|
if ( a->label < b->label)
|
|
{
|
|
it->next = a;
|
|
a = a->next;
|
|
}
|
|
else
|
|
{
|
|
it->next = b;
|
|
b = b->next;
|
|
}
|
|
|
|
it = it->next;
|
|
}
|
|
|
|
if ( a == NULL )
|
|
it->next = b;
|
|
else
|
|
it->next = a;
|
|
|
|
it = c.next;
|
|
|
|
// make sure every equivalence in the linked list points to this new ll
|
|
while( it != NULL)
|
|
{
|
|
labels[it->label].next = c.next;
|
|
it=it->next;
|
|
}
|
|
c.next->count = count;
|
|
|
|
}
|
|
|
|
void segment_via_mode_info( VP8_COMMON *oci, int how)
|
|
{
|
|
MODE_INFO *mi = oci->mi;
|
|
int i,j;
|
|
int mb_index = 0;
|
|
|
|
int label=1;
|
|
int pitch = oci->mb_cols;
|
|
|
|
// holds linked list equivalences
|
|
// the max should probably be allocated at a higher level in oci
|
|
item equivalences[MAX_REGIONS];
|
|
int eq_ptr = 0;
|
|
item labels[MAX_REGIONS];
|
|
segment_info segments[MAX_REGIONS];
|
|
int label_count = 1;
|
|
int labeling[400*300];
|
|
int *lp = labeling;
|
|
|
|
label_count = 1;
|
|
memset(labels,0,sizeof(labels));
|
|
memset(segments,0,sizeof(segments));
|
|
|
|
/* Go through each macroblock first pass labelling */
|
|
for (i = 0; i < oci->mb_rows; i++,lp+=pitch)
|
|
{
|
|
for (j = 0; j < oci->mb_cols; j++)
|
|
{
|
|
// int above seg_value, left seg_value, this seg_value...
|
|
int a=-1,l=-1,n=-1;
|
|
|
|
// above label, left label
|
|
int al=-1,ll=-1;
|
|
if(i)
|
|
{
|
|
al=lp[j-pitch];
|
|
a = labels[al].next->seg_value;
|
|
}
|
|
if(j)
|
|
{
|
|
ll=lp[j-1];
|
|
l = labels[ll].next->seg_value;
|
|
}
|
|
|
|
// what setting are we going to do the implicit segmentation on
|
|
switch (how)
|
|
{
|
|
case SEGMENT_MODE:
|
|
n= mi[mb_index].mbmi.mode;
|
|
break;
|
|
case SEGMENT_MV:
|
|
n = mi[mb_index].mbmi.mv.as_int;
|
|
if(mi[mb_index].mbmi.ref_frame == INTRA_FRAME)
|
|
n=-9999999;
|
|
break;
|
|
case SEGMENT_REFFRAME:
|
|
n = mi[mb_index].mbmi.ref_frame;
|
|
break;
|
|
case SEGMENT_SKIPPED:
|
|
n = mi[mb_index].mbmi.mb_skip_coeff;
|
|
break;
|
|
}
|
|
|
|
// above and left both have the same seg_value
|
|
if(n==a&&n==l)
|
|
{
|
|
// pick the lowest label
|
|
lp[j] = (al<ll?al:ll);
|
|
labels[lp[j]].next->count++;
|
|
|
|
// merge the above and left equivalencies
|
|
merge( labels, al, ll );
|
|
}
|
|
// this matches above seg_value
|
|
else if(n==a)
|
|
{
|
|
// give it the same label as above
|
|
lp[j]=al;
|
|
labels[al].next->count++;
|
|
}
|
|
// this matches left seg_value
|
|
else if(n==l)
|
|
{
|
|
// give it the same label as above
|
|
lp[j]=ll;
|
|
labels[ll].next->count++;
|
|
}
|
|
else
|
|
{
|
|
// new label doesn't match either
|
|
item *e = &labels[label];
|
|
item *nl = &equivalences[eq_ptr++];
|
|
lp[j]=label;
|
|
nl->label = label;
|
|
nl->next = 0;
|
|
nl->seg_value = n;
|
|
nl->count = 1;
|
|
e->next = nl;
|
|
label++;
|
|
}
|
|
mb_index++;
|
|
}
|
|
mb_index++;
|
|
}
|
|
lp = labeling;
|
|
|
|
// give new labels to regions
|
|
for(i=1;i<label;i++)
|
|
if(labels[i].next->count >min_mbs_in_region && labels[labels[i].next->label].label == 0 )
|
|
{
|
|
segment_info *cs= &segments[label_count];
|
|
cs->label = label_count;
|
|
labels[labels[i].next->label].label = label_count++;
|
|
labels[labels[i].next->label].seg_value = labels[i].next->seg_value;
|
|
cs->seg_value = labels[labels[i].next->label].seg_value;
|
|
cs->min_x = oci->mb_cols;
|
|
cs->min_y = oci->mb_rows;
|
|
cs->max_x = 0;
|
|
cs->max_y = 0;
|
|
cs->sum_x = 0;
|
|
cs->sum_y = 0;
|
|
cs->pixels= 0;
|
|
|
|
}
|
|
lp = labeling;
|
|
|
|
// this is just to gather stats...
|
|
for(i=0;i<oci->mb_rows;i++,lp+=pitch)
|
|
{
|
|
for(j=0;j<oci->mb_cols;j++)
|
|
{
|
|
segment_info *cs;
|
|
int oldlab = labels[lp[j]].next->label;
|
|
int lab = labels[oldlab].label;
|
|
lp[j] = lab;
|
|
|
|
cs= &segments[lab];
|
|
|
|
cs->min_x = (j<cs->min_x?j:cs->min_x);
|
|
cs->max_x = (j>cs->max_x?j:cs->max_x);
|
|
cs->min_y = (i<cs->min_y?i:cs->min_y);
|
|
cs->max_y = (i>cs->max_y?i:cs->max_y);
|
|
cs->sum_x += j;
|
|
cs->sum_y += i;
|
|
cs->pixels ++;
|
|
|
|
lp[j] = lab;
|
|
mb_index++;
|
|
}
|
|
mb_index++;
|
|
}
|
|
|
|
{
|
|
lp = labeling;
|
|
printf("labelling \n");
|
|
mb_index = 0;
|
|
for(i=0;i<oci->mb_rows;i++,lp+=pitch)
|
|
{
|
|
for(j=0;j<oci->mb_cols;j++)
|
|
{
|
|
printf("%4d",lp[j]);
|
|
}
|
|
printf(" ");
|
|
for(j=0;j<oci->mb_cols;j++,mb_index++)
|
|
{
|
|
//printf("%3d",mi[mb_index].mbmi.mode );
|
|
printf("%4d:%4d",mi[mb_index].mbmi.mv.as_mv.row,mi[mb_index].mbmi.mv.as_mv.col );
|
|
}
|
|
printf("\n");
|
|
++mb_index;
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|