Commit 9b7be888 authored by John Koleszar's avatar John Koleszar Committed by Gerrit Code Review
Browse files

Fix pulsing issue with scaling

Updates the YV12_BUFFER_CONFIG structure to be crop-aware. The
exiting width/height parameters are left unchanged, storing the
width and height algined to a 16 byte boundary. The cropped
dimensions are added as new fields.

This fixes a nasty visual pulse when switching between scaled and
unscaled frame dimensions due to a mismatch between the scaling
ratio and the 16-byte aligned sizes.

Change-Id: Id4a3f6aea6b9b9ae38bdfa1b87b7eb2cfcdd57b6
parent b3c350a1
......@@ -67,16 +67,13 @@ void vp9_de_alloc_frame_buffers(VP9_COMMON *oci) {
int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
int i;
int aligned_width, aligned_height;
vp9_de_alloc_frame_buffers(oci);
/* our internal buffers are always multiples of 16 */
if ((width & 0xf) != 0)
width += 16 - (width & 0xf);
if ((height & 0xf) != 0)
height += 16 - (height & 0xf);
aligned_width = (width + 15) & ~15;
aligned_height = (height + 15) & ~15;
for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0;
......@@ -110,8 +107,8 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
return 1;
}
oci->mb_rows = height >> 4;
oci->mb_cols = width >> 4;
oci->mb_rows = aligned_height >> 4;
oci->mb_cols = aligned_width >> 4;
oci->MBs = oci->mb_rows * oci->mb_cols;
oci->mode_info_stride = oci->mb_cols + 1;
oci->mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
......
......@@ -20,8 +20,8 @@
void vp9_setup_scale_factors_for_frame(struct scale_factors *scale,
YV12_BUFFER_CONFIG *other,
int this_w, int this_h) {
int other_h = other->y_height;
int other_w = other->y_width;
int other_h = other->y_crop_height;
int other_w = other->y_crop_width;
scale->x_num = other_w;
scale->x_den = this_w;
......@@ -95,7 +95,7 @@ void vp9_setup_interp_filters(MACROBLOCKD *xd,
vp9_setup_scale_factors_for_frame(&cm->active_ref_scale[i],
&cm->yv12_fb[cm->active_ref_idx[i]],
cm->mb_cols * 16, cm->mb_rows * 16);
cm->Width, cm->Height);
}
if (xd->mode_info_context) {
......
......@@ -1367,7 +1367,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
/* Reset the frame pointers to the current frame size */
vp8_yv12_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx],
pc->mb_cols * 16, pc->mb_rows * 16,
pc->Width, pc->Height,
VP9BORDERINPIXELS);
if (vp9_start_decode(&header_bc, data,
......
......@@ -62,10 +62,6 @@ struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
// Clamp the lookahead queue depth
depth = clamp(depth, 1, MAX_LAG_BUFFERS);
// Align the buffer dimensions
width = (width + 15) &~15;
height = (height + 15) &~15;
// Allocate the lookahead structures
ctx = calloc(1, sizeof(*ctx));
if (ctx) {
......
......@@ -873,9 +873,6 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
}
static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
int width = (cpi->oxcf.Width + 15) & ~15;
int height = (cpi->oxcf.Height + 15) & ~15;
cpi->lookahead = vp9_lookahead_init(cpi->oxcf.Width, cpi->oxcf.Height,
cpi->oxcf.lag_in_frames);
if (!cpi->lookahead)
......@@ -885,7 +882,8 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
#if VP9_TEMPORAL_ALT_REF
if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer,
width, height, VP9BORDERINPIXELS))
cpi->oxcf.Width, cpi->oxcf.Height,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate altref buffer");
......@@ -909,10 +907,7 @@ static int alloc_partition_data(VP9_COMP *cpi) {
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
int width = cm->Width;
int height = cm->Height;
if (vp9_alloc_frame_buffers(cm, width, height))
if (vp9_alloc_frame_buffers(cm, cm->Width, cm->Height))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffers");
......@@ -920,21 +915,13 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate partition data");
if ((width & 0xf) != 0)
width += 16 - (width & 0xf);
if ((height & 0xf) != 0)
height += 16 - (height & 0xf);
if (vp8_yv12_alloc_frame_buffer(&cpi->last_frame_uf,
width, height, VP9BORDERINPIXELS))
cm->Width, cm->Height, VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate last frame buffer");
if (vp8_yv12_alloc_frame_buffer(&cpi->scaled_source,
width, height, VP9BORDERINPIXELS))
cm->Width, cm->Height, VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer");
......@@ -996,11 +983,11 @@ static void update_frame_size(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
/* our internal buffers are always multiples of 16 */
int width = (cm->Width + 15) & ~15;
int height = (cm->Height + 15) & ~15;
int aligned_width = (cm->Width + 15) & ~15;
int aligned_height = (cm->Height + 15) & ~15;
cm->mb_rows = height >> 4;
cm->mb_cols = width >> 4;
cm->mb_rows = aligned_height >> 4;
cm->mb_cols = aligned_width >> 4;
cm->MBs = cm->mb_rows * cm->mb_cols;
cm->mode_info_stride = cm->mb_cols + 1;
memset(cm->mip, 0,
......@@ -1013,12 +1000,12 @@ static void update_frame_size(VP9_COMP *cpi) {
/* Update size of buffers local to this frame */
if (vp8_yv12_realloc_frame_buffer(&cpi->last_frame_uf,
width, height, VP9BORDERINPIXELS))
cm->Width, cm->Height, VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate last frame buffer");
if (vp8_yv12_realloc_frame_buffer(&cpi->scaled_source,
width, height, VP9BORDERINPIXELS))
cm->Width, cm->Height, VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer");
......@@ -1315,9 +1302,6 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->Width = cpi->oxcf.Width;
cm->Height = cpi->oxcf.Height;
cm->horiz_scale = cpi->horiz_scale;
cm->vert_scale = cpi->vert_scale;
// VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
if (cpi->oxcf.Sharpness > 7)
cpi->oxcf.Sharpness = 7;
......@@ -2223,10 +2207,10 @@ void vp9_write_yuv_rec_frame(VP9_COMMON *cm) {
static void scale_and_extend_frame(YV12_BUFFER_CONFIG *src_fb,
YV12_BUFFER_CONFIG *dst_fb) {
const int in_w = src_fb->y_width;
const int in_h = src_fb->y_height;
const int out_w = dst_fb->y_width;
const int out_h = dst_fb->y_height;
const int in_w = src_fb->y_crop_width;
const int in_h = src_fb->y_crop_height;
const int out_w = dst_fb->y_crop_width;
const int out_h = dst_fb->y_crop_height;
int x, y;
for (y = 0; y < out_h; y += 16) {
......@@ -2628,12 +2612,12 @@ static void scale_references(VP9_COMP *cpi) {
for (i = 0; i < 3; i++) {
YV12_BUFFER_CONFIG *ref = &cm->yv12_fb[cm->ref_frame_map[i]];
if (ref->y_width != cm->mb_cols * 16 || ref->y_height != cm->mb_rows * 16) {
if (ref->y_crop_width != cm->Width ||
ref->y_crop_height != cm->Height) {
int new_fb = get_free_fb(cm);
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[new_fb],
cm->mb_cols * 16,
cm->mb_rows * 16,
cm->Width, cm->Height,
VP9BORDERINPIXELS);
scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]);
cpi->scaled_ref_idx[i] = new_fb;
......@@ -3912,7 +3896,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
/* Reset the frame pointers to the current frame size */
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx],
cm->mb_cols * 16, cm->mb_rows * 16,
cm->Width, cm->Height,
VP9BORDERINPIXELS);
vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
......
......@@ -545,8 +545,6 @@ typedef struct VP9_COMP {
int goldfreq;
int auto_worst_q;
int cpu_used;
int horiz_scale;
int vert_scale;
int pass;
vp9_prob last_skip_false_probs[3][MBSKIP_CONTEXTS];
......
......@@ -247,7 +247,7 @@ void vp9_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi) {
int Bias = 0; // Bias against raising loop filter and in favour of lowering it
// Make a copy of the unfiltered / processed recon buffer
vp8_yv12_copy_frame(cm->frame_to_show, &cpi->last_frame_uf);
vp8_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
if (cm->frame_type == KEY_FRAME)
cm->sharpness_level = 0;
......
......@@ -3444,9 +3444,11 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
// Further refinement that is encode side only to test the top few candidates
// in full and choose the best as the centre point for subsequent searches.
mv_pred(cpi, x, yv12_mb[frame_type].y_buffer, yv12->y_stride,
frame_type, block_size);
// The current implementation doesn't support scaling.
if (scale[frame_type].x_num == scale[frame_type].x_den &&
scale[frame_type].y_num == scale[frame_type].y_den)
mv_pred(cpi, x, yv12_mb[frame_type].y_buffer, yv12->y_stride,
frame_type, block_size);
}
static void model_rd_from_var_lapndz(int var, int n, int qstep,
......
......@@ -459,8 +459,8 @@ void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
// Setup scaling factors. Scaling on each of the arnr frames is not supported
vp9_setup_scale_factors_for_frame(&cpi->mb.e_mbd.scale_factor[0],
&cpi->common.yv12_fb[cpi->common.new_fb_idx],
16 * cpi->common.mb_cols,
16 * cpi->common.mb_rows);
cpi->common.Width,
cpi->common.Height);
cpi->mb.e_mbd.scale_factor_uv[0] = cpi->mb.e_mbd.scale_factor[0];
// Setup frame pointers, NULL indicates frame not included in filter
......
......@@ -545,6 +545,8 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
yv12->u_buffer = img->planes[VPX_PLANE_U];
yv12->v_buffer = img->planes[VPX_PLANE_V];
yv12->y_crop_width = img->d_w;
yv12->y_crop_height = img->d_h;
yv12->y_width = img->d_w;
yv12->y_height = img->d_h;
yv12->uv_width = (1 + yv12->y_width) / 2;
......
......@@ -584,6 +584,8 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
yv12->u_buffer = img->planes[VPX_PLANE_U];
yv12->v_buffer = img->planes[VPX_PLANE_V];
yv12->y_crop_width = img->d_w;
yv12->y_crop_height = img->d_h;
yv12->y_width = img->d_w;
yv12->y_height = img->d_h;
yv12->uv_width = yv12->y_width / 2;
......
......@@ -38,10 +38,12 @@ vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
int width, int height, int border) {
if (ybf) {
int y_stride = ((width + 2 * border) + 31) & ~31;
int yplane_size = (height + 2 * border) * y_stride;
int uv_width = width >> 1;
int uv_height = height >> 1;
int aligned_width = (width + 15) & ~15;
int aligned_height = (height + 15) & ~15;
int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
int yplane_size = (aligned_height + 2 * border) * y_stride;
int uv_width = aligned_width >> 1;
int uv_height = aligned_height >> 1;
/** There is currently a bunch of code which assumes
* uv_stride == y_stride/2, so enforce this here. */
int uv_stride = y_stride >> 1;
......@@ -56,17 +58,18 @@ int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
return -1;
/** Only support allocating buffers that have a height and width that
* are multiples of 16, and a border that's a multiple of 32.
* The border restriction is required to get 16-byte alignment of the
* start of the chroma rows without intoducing an arbitrary gap
* between planes, which would break the semantics of things like
* vpx_img_set_rect(). */
if ((width & 0xf) | (height & 0xf) | (border & 0x1f))
/* Only support allocating buffers that have a border that's a multiple
* of 32. The border restriction is required to get 16-byte alignment of
* the start of the chroma rows without intoducing an arbitrary gap
* between planes, which would break the semantics of things like
* vpx_img_set_rect(). */
if (border & 0x1f)
return -3;
ybf->y_width = width;
ybf->y_height = height;
ybf->y_crop_width = width;
ybf->y_crop_height = height;
ybf->y_width = aligned_width;
ybf->y_height = aligned_height;
ybf->y_stride = y_stride;
ybf->uv_width = uv_width;
......
......@@ -20,180 +20,81 @@
/****************************************************************************
*
****************************************************************************/
void
vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
static void extend_plane(uint8_t *s, /* source */
int sp, /* source pitch */
int w, /* width */
int h, /* height */
int et, /* extend top border */
int el, /* extend left border */
int eb, /* extend bottom border */
int er) { /* extend right border */
int i;
unsigned char *src_ptr1, *src_ptr2;
unsigned char *dest_ptr1, *dest_ptr2;
unsigned int Border;
int plane_stride;
int plane_height;
int plane_width;
/***********/
/* Y Plane */
/***********/
Border = ybf->border;
plane_stride = ybf->y_stride;
plane_height = ybf->y_height;
plane_width = ybf->y_width;
uint8_t *src_ptr1, *src_ptr2;
uint8_t *dest_ptr1, *dest_ptr2;
int linesize;
/* copy the left and right most columns out */
src_ptr1 = ybf->y_buffer;
src_ptr2 = src_ptr1 + plane_width - 1;
dest_ptr1 = src_ptr1 - Border;
dest_ptr2 = src_ptr2 + 1;
for (i = 0; i < plane_height; i++) {
vpx_memset(dest_ptr1, src_ptr1[0], Border);
vpx_memset(dest_ptr2, src_ptr2[0], Border);
src_ptr1 += plane_stride;
src_ptr2 += plane_stride;
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
src_ptr1 = s;
src_ptr2 = s + w - 1;
dest_ptr1 = s - el;
dest_ptr2 = s + w;
for (i = 0; i < h; i++) {
vpx_memset(dest_ptr1, src_ptr1[0], el);
vpx_memset(dest_ptr2, src_ptr2[0], er);
src_ptr1 += sp;
src_ptr2 += sp;
dest_ptr1 += sp;
dest_ptr2 += sp;
}
/* Now copy the top and bottom source lines into each line of the respective borders */
src_ptr1 = ybf->y_buffer - Border;
src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
dest_ptr1 = src_ptr1 - (Border * plane_stride);
dest_ptr2 = src_ptr2 + plane_stride;
for (i = 0; i < (int)Border; i++) {
vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
/* Now copy the top and bottom lines into each line of the respective
* borders
*/
src_ptr1 = s - el;
src_ptr2 = s + sp * (h - 1) - el;
dest_ptr1 = s + sp * (-et) - el;
dest_ptr2 = s + sp * (h) - el;
linesize = el + er + w;
for (i = 0; i < et; i++) {
vpx_memcpy(dest_ptr1, src_ptr1, linesize);
dest_ptr1 += sp;
}
/***********/
/* U Plane */
/***********/
plane_stride = ybf->uv_stride;
plane_height = ybf->uv_height;
plane_width = ybf->uv_width;
Border /= 2;
/* copy the left and right most columns out */
src_ptr1 = ybf->u_buffer;
src_ptr2 = src_ptr1 + plane_width - 1;
dest_ptr1 = src_ptr1 - Border;
dest_ptr2 = src_ptr2 + 1;
for (i = 0; i < plane_height; i++) {
vpx_memset(dest_ptr1, src_ptr1[0], Border);
vpx_memset(dest_ptr2, src_ptr2[0], Border);
src_ptr1 += plane_stride;
src_ptr2 += plane_stride;
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
}
/* Now copy the top and bottom source lines into each line of the respective borders */
src_ptr1 = ybf->u_buffer - Border;
src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
dest_ptr1 = src_ptr1 - (Border * plane_stride);
dest_ptr2 = src_ptr2 + plane_stride;
for (i = 0; i < (int)(Border); i++) {
vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
}
/***********/
/* V Plane */
/***********/
/* copy the left and right most columns out */
src_ptr1 = ybf->v_buffer;
src_ptr2 = src_ptr1 + plane_width - 1;
dest_ptr1 = src_ptr1 - Border;
dest_ptr2 = src_ptr2 + 1;
for (i = 0; i < plane_height; i++) {
vpx_memset(dest_ptr1, src_ptr1[0], Border);
vpx_memset(dest_ptr2, src_ptr2[0], Border);
src_ptr1 += plane_stride;
src_ptr2 += plane_stride;
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
}
/* Now copy the top and bottom source lines into each line of the respective borders */
src_ptr1 = ybf->v_buffer - Border;
src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
dest_ptr1 = src_ptr1 - (Border * plane_stride);
dest_ptr2 = src_ptr2 + plane_stride;
for (i = 0; i < (int)(Border); i++) {
vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
for (i = 0; i < eb; i++) {
vpx_memcpy(dest_ptr2, src_ptr2, linesize);
dest_ptr2 += sp;
}
}
static void
extend_frame_borders_yonly_c(YV12_BUFFER_CONFIG *ybf) {
int i;
unsigned char *src_ptr1, *src_ptr2;
unsigned char *dest_ptr1, *dest_ptr2;
unsigned int Border;
int plane_stride;
int plane_height;
int plane_width;
/***********/
/* Y Plane */
/***********/
Border = ybf->border;
plane_stride = ybf->y_stride;
plane_height = ybf->y_height;
plane_width = ybf->y_width;
/* copy the left and right most columns out */
src_ptr1 = ybf->y_buffer;
src_ptr2 = src_ptr1 + plane_width - 1;
dest_ptr1 = src_ptr1 - Border;
dest_ptr2 = src_ptr2 + 1;
for (i = 0; i < plane_height; i++) {
vpx_memset(dest_ptr1, src_ptr1[0], Border);
vpx_memset(dest_ptr2, src_ptr2[0], Border);
src_ptr1 += plane_stride;
src_ptr2 += plane_stride;
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
}
/* Now copy the top and bottom source lines into each line of the respective borders */
src_ptr1 = ybf->y_buffer - Border;
src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
dest_ptr1 = src_ptr1 - (Border * plane_stride);
dest_ptr2 = src_ptr2 + plane_stride;
for (i = 0; i < (int)Border; i++) {
vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
dest_ptr1 += plane_stride;
dest_ptr2 += plane_stride;
}
plane_stride /= 2;
plane_height /= 2;
plane_width /= 2;
Border /= 2;
void
vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
assert(ybf->y_height - ybf->y_crop_height < 16);
assert(ybf->y_width - ybf->y_crop_width < 16);
assert(ybf->y_height - ybf->y_crop_height >= 0);
assert(ybf->y_width - ybf->y_crop_width >= 0);
extend_plane(ybf->y_buffer, ybf->y_stride,
ybf->y_crop_width, ybf->y_crop_height,
ybf->border, ybf->border,
ybf->border + ybf->y_height - ybf->y_crop_height,
ybf->border + ybf->y_width - ybf->y_crop_width);
extend_plane(ybf->u_buffer, ybf->uv_stride,
(ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
ybf->border / 2, ybf->border / 2,
(ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
(ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
extend_plane(ybf->v_buffer, ybf->uv_stride,
(ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
ybf->border / 2, ybf->border / 2,
(ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
(ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
}
/****************************************************************************
*
* ROUTINE : vp8_yv12_copy_frame
......
......@@ -42,6 +42,8 @@ extern "C" {
typedef struct yv12_buffer_config {
int y_width;
int y_height;
int y_crop_width;
int y_crop_height;
int y_stride;
/* int yinternal_width; */
......
......@@ -711,7 +711,7 @@ int main(int argc, const char **argv_) {
struct input_ctx input = {0};
int frames_corrupted = 0;
int dec_flags = 0;
int do_scale;
int do_scale = 0;
int stream_w = 0, stream_h = 0;
vpx_image_t *scaled_img = NULL;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment