Merge "Subsampling aware allocs and bitstream" into experimental
This commit is contained in:
commit
64667d5af7
@ -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) |
|
||||
|
@ -1139,7 +1139,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) {
|
||||
@ -2500,9 +2511,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 {
|
||||
@ -3587,6 +3599,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))
|
||||
@ -3851,9 +3872,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
|
||||
|
32
vpxdec.c
32
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 @@ 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];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user