Index: source/libvpx/tools_common.c |
=================================================================== |
--- source/libvpx/tools_common.c (revision 292608) |
+++ source/libvpx/tools_common.c (working copy) |
@@ -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; |
@@ -267,3 +268,219 @@ |
return kMaxPSNR; |
} |
} |
+ |
+// TODO(debargha): Consolidate the functions below into a separate file. |
+#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |
+static void highbd_img_upshift(vpx_image_t *dst, vpx_image_t *src, |
+ int input_shift) { |
+ // Note the offset is 1 less than half. |
+ const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0; |
+ int plane; |
+ if (dst->d_w != src->d_w || dst->d_h != src->d_h || |
+ dst->x_chroma_shift != src->x_chroma_shift || |
+ dst->y_chroma_shift != src->y_chroma_shift || |
+ dst->fmt != src->fmt || input_shift < 0) { |
+ fatal("Unsupported image conversion"); |
+ } |
+ switch (src->fmt) { |
+ case VPX_IMG_FMT_I42016: |
+ case VPX_IMG_FMT_I42216: |
+ case VPX_IMG_FMT_I44416: |
+ case VPX_IMG_FMT_I44016: |
+ break; |
+ default: |
+ fatal("Unsupported image conversion"); |
+ break; |
+ } |
+ for (plane = 0; plane < 3; plane++) { |
+ int w = src->d_w; |
+ int h = src->d_h; |
+ int x, y; |
+ if (plane) { |
+ 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] + y * src->stride[plane]); |
+ uint16_t *p_dst = |
+ (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]); |
+ for (x = 0; x < w; x++) |
+ *p_dst++ = (*p_src++ << input_shift) + offset; |
+ } |
+ } |
+} |
+ |
+static void lowbd_img_upshift(vpx_image_t *dst, vpx_image_t *src, |
+ int input_shift) { |
+ // Note the offset is 1 less than half. |
+ const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0; |
+ int plane; |
+ if (dst->d_w != src->d_w || dst->d_h != src->d_h || |
+ dst->x_chroma_shift != src->x_chroma_shift || |
+ dst->y_chroma_shift != src->y_chroma_shift || |
+ dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH || |
+ input_shift < 0) { |
+ fatal("Unsupported image conversion"); |
+ } |
+ switch (src->fmt) { |
+ case VPX_IMG_FMT_I420: |
+ case VPX_IMG_FMT_I422: |
+ case VPX_IMG_FMT_I444: |
+ case VPX_IMG_FMT_I440: |
+ break; |
+ default: |
+ fatal("Unsupported image conversion"); |
+ break; |
+ } |
+ for (plane = 0; plane < 3; plane++) { |
+ int w = src->d_w; |
+ int h = src->d_h; |
+ int x, y; |
+ if (plane) { |
+ 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]; |
+ uint16_t *p_dst = |
+ (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]); |
+ for (x = 0; x < w; x++) { |
+ *p_dst++ = (*p_src++ << input_shift) + offset; |
+ } |
+ } |
+ } |
+} |
+ |
+void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src, |
+ int input_shift) { |
+ if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { |
+ highbd_img_upshift(dst, src, input_shift); |
+ } else { |
+ lowbd_img_upshift(dst, src, input_shift); |
+ } |
+} |
+ |
+void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src) { |
+ int plane; |
+ if (dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH != src->fmt || |
+ dst->d_w != src->d_w || dst->d_h != src->d_h || |
+ dst->x_chroma_shift != src->x_chroma_shift || |
+ dst->y_chroma_shift != src->y_chroma_shift) { |
+ fatal("Unsupported image conversion"); |
+ } |
+ switch (dst->fmt) { |
+ case VPX_IMG_FMT_I420: |
+ case VPX_IMG_FMT_I422: |
+ case VPX_IMG_FMT_I444: |
+ case VPX_IMG_FMT_I440: |
+ break; |
+ default: |
+ fatal("Unsupported image conversion"); |
+ break; |
+ } |
+ for (plane = 0; plane < 3; plane++) { |
+ int w = src->d_w; |
+ int h = src->d_h; |
+ int x, y; |
+ if (plane) { |
+ 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] + y * src->stride[plane]); |
+ uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane]; |
+ for (x = 0; x < w; x++) { |
+ *p_dst++ = *p_src++; |
+ } |
+ } |
+ } |
+} |
+ |
+static void highbd_img_downshift(vpx_image_t *dst, vpx_image_t *src, |
+ int down_shift) { |
+ int plane; |
+ if (dst->d_w != src->d_w || dst->d_h != src->d_h || |
+ dst->x_chroma_shift != src->x_chroma_shift || |
+ dst->y_chroma_shift != src->y_chroma_shift || |
+ dst->fmt != src->fmt || down_shift < 0) { |
+ fatal("Unsupported image conversion"); |
+ } |
+ switch (src->fmt) { |
+ case VPX_IMG_FMT_I42016: |
+ case VPX_IMG_FMT_I42216: |
+ case VPX_IMG_FMT_I44416: |
+ case VPX_IMG_FMT_I44016: |
+ break; |
+ default: |
+ fatal("Unsupported image conversion"); |
+ break; |
+ } |
+ for (plane = 0; plane < 3; plane++) { |
+ int w = src->d_w; |
+ int h = src->d_h; |
+ int x, y; |
+ if (plane) { |
+ 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] + y * src->stride[plane]); |
+ uint16_t *p_dst = |
+ (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]); |
+ for (x = 0; x < w; x++) |
+ *p_dst++ = *p_src++ >> down_shift; |
+ } |
+ } |
+} |
+ |
+static void lowbd_img_downshift(vpx_image_t *dst, vpx_image_t *src, |
+ int down_shift) { |
+ int plane; |
+ if (dst->d_w != src->d_w || dst->d_h != src->d_h || |
+ dst->x_chroma_shift != src->x_chroma_shift || |
+ dst->y_chroma_shift != src->y_chroma_shift || |
+ src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH || |
+ down_shift < 0) { |
+ fatal("Unsupported image conversion"); |
+ } |
+ switch (dst->fmt) { |
+ case VPX_IMG_FMT_I420: |
+ case VPX_IMG_FMT_I422: |
+ case VPX_IMG_FMT_I444: |
+ case VPX_IMG_FMT_I440: |
+ break; |
+ default: |
+ fatal("Unsupported image conversion"); |
+ break; |
+ } |
+ for (plane = 0; plane < 3; plane++) { |
+ int w = src->d_w; |
+ int h = src->d_h; |
+ int x, y; |
+ if (plane) { |
+ 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] + y * src->stride[plane]); |
+ uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane]; |
+ for (x = 0; x < w; x++) { |
+ *p_dst++ = *p_src++ >> down_shift; |
+ } |
+ } |
+ } |
+} |
+ |
+void vpx_img_downshift(vpx_image_t *dst, vpx_image_t *src, |
+ int down_shift) { |
+ if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { |
+ highbd_img_downshift(dst, src, down_shift); |
+ } else { |
+ lowbd_img_downshift(dst, src, down_shift); |
+ } |
+} |
+#endif // CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH |