Merge "Subsampling aware allocs and bitstream" into experimental

This commit is contained in:
John Koleszar
2013-05-10 16:55:00 -07:00
committed by Gerrit Code Review
17 changed files with 243 additions and 109 deletions

View File

@@ -52,10 +52,10 @@ void vp9_free_frame_buffers(VP9_COMMON *oci) {
int i; int i;
for (i = 0; i < NUM_YV12_BUFFERS; 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); vp9_free_frame_buffer(&oci->temp_scale_frame);
vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer); vp9_free_frame_buffer(&oci->post_proc_buffer);
vpx_free(oci->mip); vpx_free(oci->mip);
vpx_free(oci->prev_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++) { for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0; oci->fb_idx_ref_cnt[i] = 0;
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height, if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
VP9BORDERINPIXELS) < 0) { oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci); vp9_free_frame_buffers(oci);
return 1; 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; oci->fb_idx_ref_cnt[i] = 1;
} }
if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16, if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
VP9BORDERINPIXELS) < 0) { oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci); vp9_free_frame_buffers(oci);
return 1; return 1;
} }
if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height, if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
VP9BORDERINPIXELS) < 0) { oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci); vp9_free_frame_buffers(oci);
return 1; return 1;
} }

View File

@@ -692,7 +692,8 @@ static TX_TYPE get_tx_type_16x16(const MACROBLOCKD *xd, int ib) {
return tx_type; 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) { static TX_SIZE get_uv_tx_size(const MACROBLOCKD *xd) {
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi; MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;

View File

@@ -11,12 +11,13 @@
#include "vp9/common/vp9_blockd.h" #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; int i;
for (i = 0; i < MAX_MB_PLANE; 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].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y_WITH_DC;
mb->plane[i].subsampling_x = !!i; mb->plane[i].subsampling_x = i ? subsampling_x : 0;
mb->plane[i].subsampling_y = !!i; mb->plane[i].subsampling_y = i ? subsampling_y : 0;
} }
} }

View File

@@ -132,6 +132,12 @@ typedef struct VP9Common {
int last_width; int last_width;
int last_height; 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; YUV_TYPE clr_type;
CLAMP_TYPE clamp_type; CLAMP_TYPE clamp_type;

View File

@@ -631,13 +631,7 @@ int vp9_post_proc_frame(VP9_COMMON *oci, YV12_BUFFER_CONFIG *dest,
if (!flags) { if (!flags) {
*dest = *oci->frame_to_show; *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; return 0;
} }
#if ARCH_X86||ARCH_X86_64 #if ARCH_X86||ARCH_X86_64

View File

@@ -929,6 +929,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
pc->version = (data[0] >> 1) & 7; pc->version = (data[0] >> 1) & 7;
pc->show_frame = (data[0] >> 4) & 1; pc->show_frame = (data[0] >> 4) & 1;
scaling_active = (data[0] >> 5) & 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); first_partition_size = read_le16(data + 1);
if (!read_is_valid(data, first_partition_size, data_end)) 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); init_frame(pbi);
// Reset the frame pointers to the current frame size // Reset the frame pointers to the current frame size
vp8_yv12_realloc_frame_buffer(new_fb, pc->width, pc->height, vp9_realloc_frame_buffer(new_fb, pc->width, pc->height,
VP9BORDERINPIXELS); pc->subsampling_x, pc->subsampling_y,
VP9BORDERINPIXELS);
if (vp9_reader_init(&header_bc, data, first_partition_size)) if (vp9_reader_init(&header_bc, data, first_partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 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, CHECK_MEM_ERROR(pc->last_frame_seg_map,
vpx_calloc((pc->mi_rows * pc->mi_cols), 1)); 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 // clear out the coeff buffer
for (i = 0; i < MAX_MB_PLANE; ++i) for (i = 0; i < MAX_MB_PLANE; ++i)

View File

@@ -1805,6 +1805,8 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
int scaling = (pc->width != pc->display_width || int scaling = (pc->width != pc->display_width ||
pc->height != pc->display_height); pc->height != pc->display_height);
int v = (oh.first_partition_length_in_bytes << 8) | int v = (oh.first_partition_length_in_bytes << 8) |
(pc->subsampling_y << 7) |
(pc->subsampling_x << 6) |
(scaling << 5) | (scaling << 5) |
(oh.show_frame << 4) | (oh.show_frame << 4) |
(oh.version << 1) | (oh.version << 1) |

View File

@@ -1139,7 +1139,7 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
vp9_build_block_offsets(x); 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.mode = DC_PRED;
xd->mode_info_context->mbmi.uv_mode = DC_PRED; xd->mode_info_context->mbmi.uv_mode = DC_PRED;

View File

@@ -489,7 +489,7 @@ void vp9_first_pass(VP9_COMP *cpi) {
vp9_build_block_offsets(x); 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); vp9_frame_init_quantizer(cpi);

View File

@@ -46,7 +46,7 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
unsigned int i; unsigned int i;
for (i = 0; i < ctx->max_sz; 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->buf);
} }
free(ctx); free(ctx);
@@ -56,6 +56,8 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
struct lookahead_ctx * vp9_lookahead_init(unsigned int width, struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
unsigned int height, unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
unsigned int depth) { unsigned int depth) {
struct lookahead_ctx *ctx = NULL; struct lookahead_ctx *ctx = NULL;
@@ -71,8 +73,9 @@ struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
if (!ctx->buf) if (!ctx->buf)
goto bail; goto bail;
for (i = 0; i < depth; i++) for (i = 0; i < depth; i++)
if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, if (vp9_alloc_frame_buffer(&ctx->buf[i].img,
width, height, VP9BORDERINPIXELS)) width, height, subsampling_x, subsampling_y,
VP9BORDERINPIXELS))
goto bail; goto bail;
} }
return ctx; return ctx;

View File

@@ -31,6 +31,8 @@ struct lookahead_ctx;
*/ */
struct lookahead_ctx *vp9_lookahead_init(unsigned int width, struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
unsigned int height, unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
unsigned int depth); unsigned int depth);

View File

@@ -313,9 +313,9 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
vp9_free_frame_buffers(&cpi->common); vp9_free_frame_buffers(&cpi->common);
vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf); vp9_free_frame_buffer(&cpi->last_frame_uf);
vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source); vp9_free_frame_buffer(&cpi->scaled_source);
vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer); vp9_free_frame_buffer(&cpi->alt_ref_buffer);
vp9_lookahead_destroy(cpi->lookahead); vp9_lookahead_destroy(cpi->lookahead);
vpx_free(cpi->tok); 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) { 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, cpi->lookahead = vp9_lookahead_init(cpi->oxcf.width, cpi->oxcf.height,
cm->subsampling_x, cm->subsampling_y,
cpi->oxcf.lag_in_frames); cpi->oxcf.lag_in_frames);
if (!cpi->lookahead) if (!cpi->lookahead)
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate lag buffers"); "Failed to allocate lag buffers");
if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer, if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
cpi->oxcf.width, cpi->oxcf.height, cpi->oxcf.width, cpi->oxcf.height,
VP9BORDERINPIXELS)) cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate altref buffer"); "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, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate partition data"); "Failed to allocate partition data");
if (vp8_yv12_alloc_frame_buffer(&cpi->last_frame_uf, if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height, VP9BORDERINPIXELS)) cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate last frame buffer"); "Failed to allocate last frame buffer");
if (vp8_yv12_alloc_frame_buffer(&cpi->scaled_source, if (vp9_alloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height, VP9BORDERINPIXELS)) cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer"); "Failed to allocate scaled source buffer");
@@ -914,13 +922,17 @@ static void update_frame_size(VP9_COMP *cpi) {
vp9_update_frame_size(cm); vp9_update_frame_size(cm);
// Update size of buffers local to this frame // Update size of buffers local to this frame
if (vp8_yv12_realloc_frame_buffer(&cpi->last_frame_uf, if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height, VP9BORDERINPIXELS)) cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate last frame buffer"); "Failed to reallocate last frame buffer");
if (vp8_yv12_realloc_frame_buffer(&cpi->scaled_source, if (vp9_realloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height, VP9BORDERINPIXELS)) cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS))
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer"); "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->width = oxcf->width;
cm->height = oxcf->height; cm->height = oxcf->height;
cm->subsampling_x = 0;
cm->subsampling_y = 0;
vp9_alloc_compressor_data(cpi);
// change includes all joint functionality // change includes all joint functionality
vp9_change_config(ptr, oxcf); 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; cm->sharpness_level = cpi->oxcf.Sharpness;
// Increasing the size of the frame beyond the first seen frame, or some if (cpi->initial_width) {
// otherwise signalled maximum size, is not supported. // Increasing the size of the frame beyond the first seen frame, or some
// TODO(jkoleszar): exit gracefully. // otherwise signalled maximum size, is not supported.
if (!cpi->initial_width) { // TODO(jkoleszar): exit gracefully.
alloc_raw_frame_buffers(cpi); assert(cm->width <= cpi->initial_width);
vp9_alloc_compressor_data(cpi); assert(cm->height <= cpi->initial_height);
cpi->initial_width = cm->width;
cpi->initial_height = cm->height;
} }
assert(cm->width <= cpi->initial_width);
assert(cm->height <= cpi->initial_height);
update_frame_size(cpi); update_frame_size(cpi);
if (cpi->oxcf.fixed_q >= 0) { if (cpi->oxcf.fixed_q >= 0) {
@@ -2500,9 +2511,10 @@ static void scale_references(VP9_COMP *cpi) {
ref->y_crop_height != cm->height) { ref->y_crop_height != cm->height) {
int new_fb = get_free_fb(cm); int new_fb = get_free_fb(cm);
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[new_fb], vp9_realloc_frame_buffer(&cm->yv12_fb[new_fb],
cm->width, cm->height, cm->width, cm->height,
VP9BORDERINPIXELS); cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS);
scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]); scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]);
cpi->scaled_ref_idx[i] = new_fb; cpi->scaled_ref_idx[i] = new_fb;
} else { } else {
@@ -3587,6 +3599,15 @@ int vp9_receive_raw_frame(VP9_PTR ptr, unsigned int frame_flags,
struct vpx_usec_timer timer; struct vpx_usec_timer timer;
int res = 0; 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); vpx_usec_timer_start(&timer);
if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, frame_flags, if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, frame_flags,
cpi->active_map_enabled ? cpi->active_map : NULL)) cpi->active_map_enabled ? cpi->active_map : NULL))
@@ -3851,9 +3872,10 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
cm->frame_flags = *frame_flags; cm->frame_flags = *frame_flags;
// Reset the frame pointers to the current frame size // Reset the frame pointers to the current frame size
vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx], vp9_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx],
cm->width, cm->height, cm->width, cm->height,
VP9BORDERINPIXELS); cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS);
// Calculate scaling factors for each of the 3 available references // Calculate scaling factors for each of the 3 available references
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) { for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {

View File

@@ -211,11 +211,12 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
switch (img->fmt) { switch (img->fmt) {
case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_YV12:
case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_VPXI420: case VPX_IMG_FMT_I422:
case VPX_IMG_FMT_VPXYV12: case VPX_IMG_FMT_I444:
break; break;
default: 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)) 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_crop_height = img->d_h;
yv12->y_width = img->d_w; yv12->y_width = img->d_w;
yv12->y_height = img->d_h; 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->y_stride = img->stride[VPX_PLANE_Y];
yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->uv_stride = img->stride[VPX_PLANE_U];
yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2; 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; 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)) { if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
yuvconfig2image(&ctx->preview_img, &sd, NULL);
/*
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;
return &ctx->preview_img; return &ctx->preview_img;
} else } else
return NULL; return NULL;

View File

@@ -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 * the Y, U, and V planes, nor other alignment adjustments that
* might be representable by a YV12_BUFFER_CONFIG, so we just * might be representable by a YV12_BUFFER_CONFIG, so we just
* initialize all the fields.*/ * 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->w = yv12->y_stride;
img->h = multiple16(yv12->y_height + 2 * VP9BORDERINPIXELS); img->h = multiple16(yv12->y_height + 2 * VP9BORDERINPIXELS);
img->d_w = yv12->y_width; img->d_w = yv12->y_crop_width;
img->d_h = yv12->y_height; img->d_h = yv12->y_crop_height;
img->x_chroma_shift = 1; img->x_chroma_shift = yv12->uv_width < yv12->y_width;
img->y_chroma_shift = 1; img->y_chroma_shift = yv12->uv_height < yv12->y_height;
img->planes[VPX_PLANE_Y] = yv12->y_buffer; img->planes[VPX_PLANE_Y] = yv12->y_buffer;
img->planes[VPX_PLANE_U] = yv12->u_buffer; img->planes[VPX_PLANE_U] = yv12->u_buffer;
img->planes[VPX_PLANE_V] = yv12->v_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_U] = yv12->uv_stride;
img->stride[VPX_PLANE_V] = yv12->uv_stride; img->stride[VPX_PLANE_V] = yv12->uv_stride;
img->stride[VPX_PLANE_ALPHA] = yv12->y_stride; img->stride[VPX_PLANE_ALPHA] = yv12->y_stride;
img->bps = 12; img->bps = bps;
img->user_priv = user_priv; img->user_priv = user_priv;
img->img_data = yv12->buffer_alloc; img->img_data = yv12->buffer_alloc;
img->img_data_owner = 0; img->img_data_owner = 0;

View File

@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "./vpx_config.h"
#include "vpx_scale/yv12config.h" #include "vpx_scale/yv12config.h"
#include "vpx_mem/vpx_mem.h" #include "vpx_mem/vpx_mem.h"
@@ -97,3 +97,89 @@ int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
} }
return -2; 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

View File

@@ -72,6 +72,14 @@ extern "C" {
int width, int height, int border); int width, int height, int border);
int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -12,6 +12,7 @@
/* This is a simple program that reads ivf files and decodes them /* This is a simple program that reads ivf files and decodes them
* using the new interface. Decoded frames are output as YV12 raw. * using the new interface. Decoded frames are output as YV12 raw.
*/ */
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
@@ -890,6 +891,7 @@ int main(int argc, const char **argv_) {
if (use_y4m && !noblit) { if (use_y4m && !noblit) {
char buffer[128]; char buffer[128];
if (!single_file) { if (!single_file) {
fprintf(stderr, "YUV4MPEG2 not supported with output patterns," fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
" try --i420 or --yv12.\n"); " 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 /*Note: We can't output an aspect ratio here because IVF doesn't
store one, and neither does VP8. store one, and neither does VP8.
That will have to wait until these tools support WebM natively.*/ 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", snprintf(buffer, sizeof(buffer), "YUV4MPEG2 W%u H%u F%u:%u I%c ",
"420jpeg", width, height, fps_num, fps_den, 'p'); width, height, fps_num, fps_den, 'p');
out_put(out, (unsigned char *)buffer, out_put(out, (unsigned char *)buffer,
(unsigned int)strlen(buffer), do_md5); (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); show_progress(frame_in, frame_out, dx_time);
if (!noblit) { 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 (do_scale) {
if (img && frame_out == 1) { if (img && frame_out == 1) {
stream_w = img->d_w; stream_w = img->d_w;
@@ -1031,6 +1044,7 @@ int main(int argc, const char **argv_) {
stream_w, stream_h, 16); stream_w, stream_h, 16);
} }
if (img && (img->d_w != stream_w || img->d_h != stream_h)) { 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], 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_U], img->stride[VPX_PLANE_U],
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
@@ -1051,6 +1065,12 @@ int main(int argc, const char **argv_) {
unsigned int y; unsigned int y;
char out_fn[PATH_MAX]; char out_fn[PATH_MAX];
uint8_t *buf; 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) { if (!single_file) {
size_t len = sizeof(out_fn) - 1; 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]; buf = img->planes[flipuv ? VPX_PLANE_V : VPX_PLANE_U];
for (y = 0; y < (1 + img->d_h) / 2; y++) { for (y = 0; y < c_h; y++) {
out_put(out, buf, (1 + img->d_w) / 2, do_md5); out_put(out, buf, c_w, do_md5);
buf += img->stride[VPX_PLANE_U]; buf += img->stride[VPX_PLANE_U];
} }
buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V]; buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V];
for (y = 0; y < (1 + img->d_h) / 2; y++) { for (y = 0; y < c_h; y++) {
out_put(out, buf, (1 + img->d_w) / 2, do_md5); out_put(out, buf, c_w, do_md5);
buf += img->stride[VPX_PLANE_V]; buf += img->stride[VPX_PLANE_V];
} }