ref: 9ed23de13f0ddfebea2a7ff6caa370126dd84979
parent: 8b4dd536a53623f27a5dde7a4e4bd4cae485ba1c
author: Deb Mukherjee <[email protected]>
date: Thu Sep 25 11:46:50 EDT 2014
Miscellaneous decoder changes for high bitdepth Also includes yv12 config changes. Change-Id: Iacf40d8bf486815b54c32a127ce3cd4516b7e44f
--- a/tools_common.c
+++ b/tools_common.c
@@ -224,7 +224,8 @@
for (plane = 0; plane < 3; ++plane) {
const unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane];
- const int w = vpx_img_plane_width(img, plane);
+ const int w = vpx_img_plane_width(img, plane) *
+ ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = vpx_img_plane_height(img, plane);
int y;
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -180,6 +180,7 @@
// VPX_BITS_8 in profile 0 or 1, VPX_BITS_10 or VPX_BITS_12 in profile 2 or 3.
vpx_bit_depth_t bit_depth;
+ vpx_bit_depth_t dequant_bit_depth; // bit_depth of current dequantizer
#if CONFIG_VP9_POSTPROC
struct postproc_state postproc_state;
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -467,13 +467,13 @@
int y1 = ((y0_16 + (h - 1) * ys) >> SUBPEL_BITS) + 1;
int x_pad = 0, y_pad = 0;
- if (subpel_x || (sf->x_step_q4 != 16)) {
+ if (subpel_x || (sf->x_step_q4 != SUBPEL_SHIFTS)) {
x0 -= VP9_INTERP_EXTEND - 1;
x1 += VP9_INTERP_EXTEND;
x_pad = 1;
}
- if (subpel_y || (sf->y_step_q4 != 16)) {
+ if (subpel_y || (sf->y_step_q4 != SUBPEL_SHIFTS)) {
y0 -= VP9_INTERP_EXTEND - 1;
y1 += VP9_INTERP_EXTEND;
y_pad = 1;
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -652,8 +652,10 @@
update |= read_delta_q(rb, &cm->y_dc_delta_q);
update |= read_delta_q(rb, &cm->uv_dc_delta_q);
update |= read_delta_q(rb, &cm->uv_ac_delta_q);
- if (update)
+ if (update || cm->bit_depth != cm->dequant_bit_depth) {
vp9_init_dequantizer(cm);
+ cm->dequant_bit_depth = cm->bit_depth;
+ }
xd->lossless = cm->base_qindex == 0 &&
cm->y_dc_delta_q == 0 &&
--- a/vp9/decoder/vp9_decoder.c
+++ b/vp9/decoder/vp9_decoder.c
@@ -69,6 +69,7 @@
cm->current_video_frame = 0;
pbi->ready_for_new_data = 1;
cm->bit_depth = VPX_BITS_8;
+ cm->dequant_bit_depth = VPX_BITS_8;
// vp9_init_dequantizer() is first called here. Add check in
// frame_init_dequantizer() to avoid unnecessary calling of
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -437,7 +437,6 @@
// call to get_frame.
if (!(*iter)) {
img = &ctx->img;
- img->bit_depth = (int)ctx->pbi->common.bit_depth;
*iter = img;
}
}
--- a/vp9/vp9_iface_common.h
+++ b/vp9/vp9_iface_common.h
@@ -46,6 +46,22 @@
img->stride[VPX_PLANE_U] = yv12->uv_stride;
img->stride[VPX_PLANE_V] = yv12->uv_stride;
img->stride[VPX_PLANE_ALPHA] = yv12->y_stride;
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (yv12->flags & YV12_FLAG_HIGHBITDEPTH) {
+ // vpx_image_t uses byte strides and a pointer to the first byte
+ // of the image.
+ img->fmt |= VPX_IMG_FMT_HIGHBITDEPTH;
+ img->bit_depth = yv12->bit_depth;
+ img->planes[VPX_PLANE_Y] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->y_buffer);
+ img->planes[VPX_PLANE_U] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->u_buffer);
+ img->planes[VPX_PLANE_V] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->v_buffer);
+ img->planes[VPX_PLANE_ALPHA] = NULL;
+ img->stride[VPX_PLANE_Y] = 2 * yv12->y_stride;
+ img->stride[VPX_PLANE_U] = 2 * yv12->uv_stride;
+ img->stride[VPX_PLANE_V] = 2 * yv12->uv_stride;
+ img->stride[VPX_PLANE_ALPHA] = 2 * yv12->y_stride;
+ }
+#endif // CONFIG_VP9_HIGHBITDEPTH
img->bps = bps;
img->user_priv = user_priv;
img->img_data = yv12->buffer_alloc;
@@ -71,6 +87,32 @@
yv12->y_stride = img->stride[VPX_PLANE_Y];
yv12->uv_stride = img->stride[VPX_PLANE_U];
+
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
+ // In vpx_image_t
+ // planes point to uint8 address of start of data
+ // stride counts uint8s to reach next row
+ // In YV12_BUFFER_CONFIG
+ // y_buffer, u_buffer, v_buffer point to uint16 address of data
+ // stride and border counts in uint16s
+ // This means that all the address calculations in the main body of code
+ // should work correctly.
+ // However, before we do any pixel operations we need to cast the address
+ // to a uint16 ponter and double its value.
+ yv12->y_buffer = CONVERT_TO_BYTEPTR(yv12->y_buffer);
+ yv12->u_buffer = CONVERT_TO_BYTEPTR(yv12->u_buffer);
+ yv12->v_buffer = CONVERT_TO_BYTEPTR(yv12->v_buffer);
+ yv12->y_stride >>= 1;
+ yv12->uv_stride >>= 1;
+ yv12->flags = YV12_FLAG_HIGHBITDEPTH;
+ } else {
+ yv12->flags = 0;
+ }
+ yv12->border = (yv12->y_stride - img->w) / 2;
+#else
+ yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
+#endif // CONFIG_VP9_HIGHBITDEPTH
yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
return VPX_CODEC_OK;
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -551,8 +551,8 @@
int h = src->d_h;
int x, y;
if (plane) {
- w >>= src->x_chroma_shift;
- h >>= src->y_chroma_shift;
+ w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
+ h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
}
for (y = 0; y < h; y++) {
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
@@ -590,8 +590,8 @@
int h = src->d_h;
int x, y;
if (plane) {
- w >>= src->x_chroma_shift;
- h >>= src->y_chroma_shift;
+ w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
+ h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
}
for (y = 0; y < h; y++) {
uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
@@ -636,8 +636,8 @@
int h = src->d_h;
int x, y;
if (plane) {
- w >>= src->x_chroma_shift;
- h >>= src->y_chroma_shift;
+ w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
+ h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
}
for (y = 0; y < h; y++) {
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
@@ -674,8 +674,8 @@
int h = src->d_h;
int x, y;
if (plane) {
- w >>= src->x_chroma_shift;
- h >>= src->y_chroma_shift;
+ w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
+ h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
}
for (y = 0; y < h; y++) {
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
@@ -696,6 +696,14 @@
low_img_downshift(dst, src, down_shift);
}
}
+
+static int img_shifted_realloc_required(const vpx_image_t *img,
+ const vpx_image_t *shifted,
+ vpx_img_fmt_t required_fmt) {
+ return img->d_w != shifted->d_w ||
+ img->d_h != shifted->d_h ||
+ required_fmt != shifted->fmt;
+}
#endif
int main_loop(int argc, const char **argv_) {
@@ -1130,16 +1138,17 @@
}
// Shift up or down if necessary
if (output_bit_depth != img->bit_depth) {
+ const vpx_img_fmt_t shifted_fmt = output_bit_depth == 8 ?
+ img->fmt ^ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) :
+ img->fmt | VPX_IMG_FMT_HIGHBITDEPTH;
+ if (img_shifted &&
+ img_shifted_realloc_required(img, img_shifted, shifted_fmt)) {
+ vpx_img_free(img_shifted);
+ img_shifted = NULL;
+ }
if (!img_shifted) {
- if (output_bit_depth == 8) {
- img_shifted = vpx_img_alloc(
- NULL, img->fmt - VPX_IMG_FMT_HIGHBITDEPTH,
- img->d_w, img->d_h, 16);
- } else {
- img_shifted = vpx_img_alloc(
- NULL, img->fmt | VPX_IMG_FMT_HIGHBITDEPTH,
- img->d_w, img->d_h, 16);
- }
+ img_shifted = vpx_img_alloc(NULL, shifted_fmt,
+ img->d_w, img->d_h, 16);
img_shifted->bit_depth = output_bit_depth;
}
if (output_bit_depth > img->bit_depth) {