ref: da58436f43095743d77f7ee84500fd22851317d8
parent: 9e327dbb76540f128cde7367b85bca05aa5863e6
author: John Koleszar <[email protected]>
date: Mon May 6 11:52:06 EDT 2013
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
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -52,10 +52,10 @@
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 @@
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 @@
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;
}
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -692,7 +692,8 @@
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;
--- a/vp9/common/vp9_mbpitch.c
+++ b/vp9/common/vp9_mbpitch.c
@@ -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;
}
}
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -132,6 +132,12 @@
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;
--- a/vp9/common/vp9_postproc.c
+++ b/vp9/common/vp9_postproc.c
@@ -631,13 +631,7 @@
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
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -929,6 +929,8 @@
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 @@
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 @@
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)
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1805,6 +1805,8 @@
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) |
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1423,7 +1423,7 @@
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;
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -489,7 +489,7 @@
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);
--- a/vp9/encoder/vp9_lookahead.c
+++ b/vp9/encoder/vp9_lookahead.c
@@ -46,7 +46,7 @@
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 @@
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 @@
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;
--- a/vp9/encoder/vp9_lookahead.h
+++ b/vp9/encoder/vp9_lookahead.h
@@ -31,6 +31,8 @@
*/
struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
unsigned int height,
+ unsigned int subsampling_x,
+ unsigned int subsampling_y,
unsigned int depth);
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -313,9 +313,9 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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) {
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -211,11 +211,12 @@
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 @@
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 @@
}
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;
--- a/vp9/vp9_iface_common.h
+++ b/vp9/vp9_iface_common.h
@@ -16,13 +16,24 @@
* 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 @@
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;
--- a/vpx_scale/generic/yv12config.c
+++ b/vpx_scale/generic/yv12config.c
@@ -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 @@
}
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
--- a/vpx_scale/yv12config.h
+++ b/vpx_scale/yv12config.h
@@ -72,6 +72,14 @@
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
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -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 @@
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 @@
/*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 @@
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 @@
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 @@
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 @@
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];
}