Commit da58436f authored by John Koleszar's avatar John Koleszar

Subsampling aware allocs and bitstream

Make framebuffer allocations according to the chroma subsamping
factors in use. A bit is placed in the raw part of the frame header for
each of the two subsampling factors. This will be moved in a future
commit to make them part of the TBD feature set bits, probably only set
on keyframes, etc.

Change-Id: I59ed38d3a3c0d4af3c7c277617de28d04a001853
parent 9e327dbb
......@@ -52,10 +52,10 @@ void vp9_free_frame_buffers(VP9_COMMON *oci) {
int i;
for (i = 0; i < NUM_YV12_BUFFERS; i++)
vp8_yv12_de_alloc_frame_buffer(&oci->yv12_fb[i]);
vp9_free_frame_buffer(&oci->yv12_fb[i]);
vp8_yv12_de_alloc_frame_buffer(&oci->temp_scale_frame);
vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer);
vp9_free_frame_buffer(&oci->temp_scale_frame);
vp9_free_frame_buffer(&oci->post_proc_buffer);
vpx_free(oci->mip);
vpx_free(oci->prev_mip);
......@@ -80,8 +80,9 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0;
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
VP9BORDERINPIXELS) < 0) {
if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
......@@ -98,14 +99,16 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
oci->fb_idx_ref_cnt[i] = 1;
}
if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
VP9BORDERINPIXELS) < 0) {
if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
VP9BORDERINPIXELS) < 0) {
if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
......
......@@ -692,7 +692,8 @@ static TX_TYPE get_tx_type_16x16(const MACROBLOCKD *xd, int ib) {
return tx_type;
}
void vp9_setup_block_dptrs(MACROBLOCKD *xd);
void vp9_setup_block_dptrs(MACROBLOCKD *xd,
int subsampling_x, int subsampling_y);
static TX_SIZE get_uv_tx_size(const MACROBLOCKD *xd) {
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
......
......@@ -11,12 +11,13 @@
#include "vp9/common/vp9_blockd.h"
void vp9_setup_block_dptrs(MACROBLOCKD *mb) {
void vp9_setup_block_dptrs(MACROBLOCKD *mb,
int subsampling_x, int subsampling_y) {
int i;
for (i = 0; i < MAX_MB_PLANE; i++) {
mb->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y_WITH_DC;
mb->plane[i].subsampling_x = !!i;
mb->plane[i].subsampling_y = !!i;
mb->plane[i].subsampling_x = i ? subsampling_x : 0;
mb->plane[i].subsampling_y = i ? subsampling_y : 0;
}
}
......@@ -132,6 +132,12 @@ typedef struct VP9Common {
int last_width;
int last_height;
// TODO(jkoleszar): this implies chroma ss right now, but could vary per
// plane. Revisit as part of the future change to YV12_BUFFER_CONFIG to
// support additional planes.
int subsampling_x;
int subsampling_y;
YUV_TYPE clr_type;
CLAMP_TYPE clamp_type;
......
......@@ -631,13 +631,7 @@ int vp9_post_proc_frame(VP9_COMMON *oci, YV12_BUFFER_CONFIG *dest,
if (!flags) {
*dest = *oci->frame_to_show;
/* handle problem with extending borders */
dest->y_width = oci->width;
dest->y_height = oci->height;
dest->uv_height = dest->y_height / 2;
return 0;
}
#if ARCH_X86||ARCH_X86_64
......
......@@ -929,6 +929,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
pc->version = (data[0] >> 1) & 7;
pc->show_frame = (data[0] >> 4) & 1;
scaling_active = (data[0] >> 5) & 1;
pc->subsampling_x = (data[0] >> 6) & 1;
pc->subsampling_y = (data[0] >> 7) & 1;
first_partition_size = read_le16(data + 1);
if (!read_is_valid(data, first_partition_size, data_end))
......@@ -961,8 +963,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
init_frame(pbi);
// Reset the frame pointers to the current frame size
vp8_yv12_realloc_frame_buffer(new_fb, pc->width, pc->height,
VP9BORDERINPIXELS);
vp9_realloc_frame_buffer(new_fb, pc->width, pc->height,
pc->subsampling_x, pc->subsampling_y,
VP9BORDERINPIXELS);
if (vp9_reader_init(&header_bc, data, first_partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
......@@ -1073,7 +1076,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
CHECK_MEM_ERROR(pc->last_frame_seg_map,
vpx_calloc((pc->mi_rows * pc->mi_cols), 1));
vp9_setup_block_dptrs(xd);
vp9_setup_block_dptrs(xd, pc->subsampling_x, pc->subsampling_y);
// clear out the coeff buffer
for (i = 0; i < MAX_MB_PLANE; ++i)
......
......@@ -1805,6 +1805,8 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
int scaling = (pc->width != pc->display_width ||
pc->height != pc->display_height);
int v = (oh.first_partition_length_in_bytes << 8) |
(pc->subsampling_y << 7) |
(pc->subsampling_x << 6) |
(scaling << 5) |
(oh.show_frame << 4) |
(oh.version << 1) |
......
......@@ -1423,7 +1423,7 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
vp9_build_block_offsets(x);
vp9_setup_block_dptrs(&x->e_mbd);
vp9_setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
xd->mode_info_context->mbmi.mode = DC_PRED;
xd->mode_info_context->mbmi.uv_mode = DC_PRED;
......
......@@ -489,7 +489,7 @@ void vp9_first_pass(VP9_COMP *cpi) {
vp9_build_block_offsets(x);
vp9_setup_block_dptrs(&x->e_mbd);
vp9_setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
vp9_frame_init_quantizer(cpi);
......
......@@ -46,7 +46,7 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
unsigned int i;
for (i = 0; i < ctx->max_sz; i++)
vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
vp9_free_frame_buffer(&ctx->buf[i].img);
free(ctx->buf);
}
free(ctx);
......@@ -56,6 +56,8 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
unsigned int depth) {
struct lookahead_ctx *ctx = NULL;
......@@ -71,8 +73,9 @@ struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
if (!ctx->buf)
goto bail;
for (i = 0; i < depth; i++)
if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
width, height, VP9BORDERINPIXELS))
if (vp9_alloc_frame_buffer(&ctx->buf[i].img,
width, height, subsampling_x, subsampling_y,
VP9BORDERINPIXELS))
goto bail;
}
return ctx;
......
......@@ -31,6 +31,8 @@ struct lookahead_ctx;
*/
struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
unsigned int depth);
......
......@@ -313,9 +313,9 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
vp9_free_frame_buffers(&cpi->common);
vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf);
vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source);
vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer);
vp9_free_frame_buffer(&cpi->last_frame_uf);
vp9_free_frame_buffer(&cpi->scaled_source);
vp9_free_frame_buffer(&cpi->alt_ref_buffer);
vp9_lookahead_destroy(cpi->lookahead);
vpx_free(cpi->tok);
......@@ -835,15 +835,19 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
}
static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
cpi->lookahead = vp9_lookahead_init(cpi->oxcf.width, cpi->oxcf.height,
cm->subsampling_x, cm->subsampling_y,
cpi->oxcf.lag_in_frames);
if (!cpi->lookahead)
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate lag buffers");
if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer,
cpi->oxcf.width, cpi->oxcf.height,
VP9BORDERINPIXELS))
if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
cpi->oxcf.width, cpi->oxcf.height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate altref buffer");
}
......@@ -873,13 +877,17 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate partition data");
if (vp8_yv12_alloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height, VP9BORDERINPIXELS))
if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
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,
cm->width, cm->height, VP9BORDERINPIXELS))
if (vp9_alloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer");
......@@ -914,13 +922,17 @@ static void update_frame_size(VP9_COMP *cpi) {
vp9_update_frame_size(cm);
// Update size of buffers local to this frame
if (vp8_yv12_realloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height, VP9BORDERINPIXELS))
if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
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,
cm->width, cm->height, VP9BORDERINPIXELS))
if (vp9_realloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer");
......@@ -1032,6 +1044,9 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->width = oxcf->width;
cm->height = oxcf->height;
cm->subsampling_x = 0;
cm->subsampling_y = 0;
vp9_alloc_compressor_data(cpi);
// change includes all joint functionality
vp9_change_config(ptr, oxcf);
......@@ -1196,17 +1211,13 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->sharpness_level = cpi->oxcf.Sharpness;
// Increasing the size of the frame beyond the first seen frame, or some
// otherwise signalled maximum size, is not supported.
// TODO(jkoleszar): exit gracefully.
if (!cpi->initial_width) {
alloc_raw_frame_buffers(cpi);
vp9_alloc_compressor_data(cpi);
cpi->initial_width = cm->width;
cpi->initial_height = cm->height;
if (cpi->initial_width) {
// Increasing the size of the frame beyond the first seen frame, or some
// otherwise signalled maximum size, is not supported.
// TODO(jkoleszar): exit gracefully.
assert(cm->width <= cpi->initial_width);
assert(cm->height <= cpi->initial_height);
}
assert(cm->width <= cpi->initial_width);
assert(cm->height <= cpi->initial_height);
update_frame_size(cpi);
if (cpi->oxcf.fixed_q >= 0) {
......@@ -2492,9 +2503,10 @@ static void scale_references(VP9_COMP *cpi) {
ref->y_crop_height != cm->height) {
int new_fb = get_free_fb(cm);
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[new_fb],
cm->width, cm->height,
VP9BORDERINPIXELS);
vp9_realloc_frame_buffer(&cm->yv12_fb[new_fb],
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS);
scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]);
cpi->scaled_ref_idx[i] = new_fb;
} else {
......@@ -3579,6 +3591,15 @@ int vp9_receive_raw_frame(VP9_PTR ptr, unsigned int frame_flags,
struct vpx_usec_timer timer;
int res = 0;
if (!cpi->initial_width) {
// TODO(jkoleszar): Support 1/4 subsampling?
cm->subsampling_x = sd->uv_width < sd->y_width;
cm->subsampling_y = sd->uv_height < sd->y_height;
alloc_raw_frame_buffers(cpi);
cpi->initial_width = cm->width;
cpi->initial_height = cm->height;
}
vpx_usec_timer_start(&timer);
if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, frame_flags,
cpi->active_map_enabled ? cpi->active_map : NULL))
......@@ -3843,9 +3864,10 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
cm->frame_flags = *frame_flags;
// Reset the frame pointers to the current frame size
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx],
cm->width, cm->height,
VP9BORDERINPIXELS);
vp9_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx],
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS);
// Calculate scaling factors for each of the 3 available references
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
......
......@@ -211,11 +211,12 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
switch (img->fmt) {
case VPX_IMG_FMT_YV12:
case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_VPXI420:
case VPX_IMG_FMT_VPXYV12:
case VPX_IMG_FMT_I422:
case VPX_IMG_FMT_I444:
break;
default:
ERROR("Invalid image format. Only YV12 and I420 images are supported");
ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
"supported.");
}
if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
......@@ -553,14 +554,17 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
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;
yv12->uv_height = (1 + yv12->y_height) / 2;
yv12->uv_width = img->x_chroma_shift == 1 ? (1 + yv12->y_width) / 2
: yv12->y_width;
yv12->uv_height = img->y_chroma_shift == 1 ? (1 + yv12->y_height) / 2
: yv12->y_height;
yv12->y_stride = img->stride[VPX_PLANE_Y];
yv12->uv_stride = img->stride[VPX_PLANE_U];
yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12); // REG_YUV = 0
yv12->clrtype = REG_YUV;
return res;
}
......@@ -940,39 +944,7 @@ static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx) {
}
if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
/*
vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
sd.y_width + 2*VP9BORDERINPIXELS,
sd.y_height + 2*VP9BORDERINPIXELS,
1,
sd.buffer_alloc);
vpx_img_set_rect(&ctx->preview_img,
VP9BORDERINPIXELS, VP9BORDERINPIXELS,
sd.y_width, sd.y_height);
*/
ctx->preview_img.bps = 12;
ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
if (sd.clrtype == REG_YUV)
ctx->preview_img.fmt = VPX_IMG_FMT_I420;
else
ctx->preview_img.fmt = VPX_IMG_FMT_VPXI420;
ctx->preview_img.x_chroma_shift = 1;
ctx->preview_img.y_chroma_shift = 1;
ctx->preview_img.d_w = sd.y_width;
ctx->preview_img.d_h = sd.y_height;
ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
ctx->preview_img.w = sd.y_width;
ctx->preview_img.h = sd.y_height;
yuvconfig2image(&ctx->preview_img, &sd, NULL);
return &ctx->preview_img;
} else
return NULL;
......
......@@ -16,13 +16,24 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
* the Y, U, and V planes, nor other alignment adjustments that
* might be representable by a YV12_BUFFER_CONFIG, so we just
* initialize all the fields.*/
img->fmt = yv12->clrtype == REG_YUV ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_VPXI420;
int bps = 12;
if (yv12->uv_height == yv12->y_height) {
if (yv12->uv_width == yv12->y_width) {
img->fmt = VPX_IMG_FMT_I444;
bps = 24;
} else {
img->fmt = VPX_IMG_FMT_I422;
bps = 16;
}
} else {
img->fmt = VPX_IMG_FMT_I420;
}
img->w = yv12->y_stride;
img->h = multiple16(yv12->y_height + 2 * VP9BORDERINPIXELS);
img->d_w = yv12->y_width;
img->d_h = yv12->y_height;
img->x_chroma_shift = 1;
img->y_chroma_shift = 1;
img->d_w = yv12->y_crop_width;
img->d_h = yv12->y_crop_height;
img->x_chroma_shift = yv12->uv_width < yv12->y_width;
img->y_chroma_shift = yv12->uv_height < yv12->y_height;
img->planes[VPX_PLANE_Y] = yv12->y_buffer;
img->planes[VPX_PLANE_U] = yv12->u_buffer;
img->planes[VPX_PLANE_V] = yv12->v_buffer;
......@@ -31,7 +42,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
img->stride[VPX_PLANE_U] = yv12->uv_stride;
img->stride[VPX_PLANE_V] = yv12->uv_stride;
img->stride[VPX_PLANE_ALPHA] = yv12->y_stride;
img->bps = 12;
img->bps = bps;
img->user_priv = user_priv;
img->img_data = yv12->buffer_alloc;
img->img_data_owner = 0;
......
......@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_config.h"
#include "vpx_scale/yv12config.h"
#include "vpx_mem/vpx_mem.h"
......@@ -97,3 +97,89 @@ int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
}
return -2;
}
#if CONFIG_VP9
// TODO(jkoleszar): Maybe replace this with struct vpx_image
int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
if (ybf) {
vpx_free(ybf->buffer_alloc);
/* buffer_alloc isn't accessed by most functions. Rather y_buffer,
u_buffer and v_buffer point to buffer_alloc and are used. Clear out
all of this so that a freed pointer isn't inadvertently used */
vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
} else {
return -1;
}
return 0;
}
int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
int width, int height,
int ss_x, int ss_y, int border) {
if (ybf) {
const int aligned_width = (width + 15) & ~15;
const int aligned_height = (height + 15) & ~15;
const int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
const int yplane_size = (aligned_height + 2 * border) * y_stride;
const int uv_width = aligned_width >> ss_x;
const int uv_height = aligned_height >> ss_y;
const int uv_stride = y_stride >> ss_x;
const int uv_border_w = border >> ss_x;
const int uv_border_h = border >> ss_y;
const int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
const int frame_size = yplane_size + 2 * uvplane_size;
if (!ybf->buffer_alloc) {
ybf->buffer_alloc = vpx_memalign(32, frame_size);
ybf->buffer_alloc_sz = frame_size;
}
if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
return -1;
/* 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_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;
ybf->uv_height = uv_height;
ybf->uv_stride = uv_stride;
ybf->border = border;
ybf->frame_size = frame_size;
ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
ybf->u_buffer = ybf->buffer_alloc + yplane_size +
(uv_border_h * uv_stride) + uv_border_w;
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
(uv_border_h * uv_stride) + uv_border_w;
ybf->corrupted = 0; /* assume not currupted by errors */
return 0;
}
return -2;
}
int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
int width, int height,
int ss_x, int ss_y, int border) {
if (ybf) {
vp9_free_frame_buffer(ybf);
return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border);
}
return -2;
}
#endif
......@@ -72,6 +72,14 @@ extern "C" {
int width, int height, int border);
int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf);
int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
int width, int height, int ss_x, int ss_y,
int border);
int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
int width, int height, int ss_x, int ss_y,
int border);
int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf);
#ifdef __cplusplus
}
#endif
......
......@@ -12,6 +12,7 @@
/* This is a simple program that reads ivf files and decodes them
* using the new interface. Decoded frames are output as YV12 raw.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
......@@ -890,6 +891,7 @@ int main(int argc, const char **argv_) {
if (use_y4m && !noblit) {
char buffer[128];
if (!single_file) {
fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
" try --i420 or --yv12.\n");
......@@ -907,8 +909,8 @@ int main(int argc, const char **argv_) {
/*Note: We can't output an aspect ratio here because IVF doesn't
store one, and neither does VP8.
That will have to wait until these tools support WebM natively.*/
sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
"420jpeg", width, height, fps_num, fps_den, 'p');
snprintf(buffer, sizeof(buffer), "YUV4MPEG2 W%u H%u F%u:%u I%c ",
width, height, fps_num, fps_den, 'p');
out_put(out, (unsigned char *)buffer,
(unsigned int)strlen(buffer), do_md5);
}
......@@ -1023,6 +1025,17 @@ int main(int argc, const char **argv_) {
show_progress(frame_in, frame_out, dx_time);
if (!noblit) {
if (frame_out == 1 && use_y4m) {
/* Write out the color format to terminate the header line */
const char *color =
img->fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
img->fmt == VPX_IMG_FMT_I444 ? "C444\n" :
img->fmt == VPX_IMG_FMT_I422 ? "C422\n" :
"C420jpeg\n";
out_put(out, (const unsigned char*)color, strlen(color), do_md5);
}
if (do_scale) {
if (img && frame_out == 1) {
stream_w = img->d_w;
......@@ -1031,6 +1044,7 @@ int main(int argc, const char **argv_) {
stream_w, stream_h, 16);
}
if (img && (img->d_w != stream_w || img->d_h != stream_h)) {
assert(img->fmt == VPX_IMG_FMT_I420);
I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
......@@ -1051,6 +1065,12 @@ int main(int argc, const char **argv_) {
unsigned int y;
char out_fn[PATH_MAX];
uint8_t *buf;
unsigned int c_w =
img->x_chroma_shift ? (1 + img->d_w) >> img->x_chroma_shift
: img->d_w;
unsigned int c_h =
img->y_chroma_shift ? (1 + img->d_h) >> img->y_chroma_shift
: img->d_h;
if (!single_file) {
size_t len = sizeof(out_fn) - 1;
......@@ -1071,15 +1091,15 @@ int main(int argc, const char **argv_) {
buf = img->planes[flipuv ? VPX_PLANE_V : VPX_PLANE_U];
for (y = 0; y < (1 + img->d_h) / 2; y++) {
out_put(out, buf, (1 + img->d_w) / 2, do_md5);
for (y = 0; y < c_h; y++) {
out_put(out, buf, c_w, do_md5);
buf += img->stride[VPX_PLANE_U];
}
buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V];
for (y = 0; y < (1 + img->d_h) / 2; y++) {
out_put(out, buf, (1 + img->d_w) / 2, do_md5);
for (y = 0; y < c_h; y++) {
out_put(out, buf, c_w, do_md5);
buf += img->stride[VPX_PLANE_V];
}
......
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