blob: e1c89a4cf651490e1d5b5f1c462e67944eb52a1b [file] [log] [blame]
John Koleszarc377bf02010-11-02 09:11:57 -04001/*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
Tom Finegan00a35aa2013-11-14 12:37:42 -080010
Dmitry Kovalev2dad0e12014-02-27 14:00:41 -080011#include <math.h>
Tom Finegan03848f52013-11-05 10:02:18 -080012#include <stdarg.h>
Tom Finegan00a35aa2013-11-14 12:37:42 -080013#include <stdio.h>
Tom Finegan03848f52013-11-05 10:02:18 -080014#include <stdlib.h>
Tom Finegan00a35aa2013-11-14 12:37:42 -080015#include <string.h>
Tom Finegan03848f52013-11-05 10:02:18 -080016
Dmitry Kovalev2dad0e12014-02-27 14:00:41 -080017#include "./tools_common.h"
18
Yaowu Xu3bd709f2016-07-25 15:39:46 -070019#if CONFIG_VP10_ENCODER
Dmitry Kovalev70d96642014-02-11 21:12:23 -080020#include "vpx/vp8cx.h"
21#endif
22
Yaowu Xu3bd709f2016-07-25 15:39:46 -070023#if CONFIG_VP10_DECODER
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080024#include "vpx/vp8dx.h"
25#endif
26
John Koleszar82b1a342012-11-06 12:08:05 -080027#if defined(_WIN32) || defined(__OS2__)
John Koleszarc377bf02010-11-02 09:11:57 -040028#include <io.h>
29#include <fcntl.h>
John Koleszar82b1a342012-11-06 12:08:05 -080030
31#ifdef __OS2__
clang-format6c4d83e2016-08-08 19:03:30 -070032#define _setmode setmode
33#define _fileno fileno
34#define _O_BINARY O_BINARY
John Koleszar82b1a342012-11-06 12:08:05 -080035#endif
John Koleszarc377bf02010-11-02 09:11:57 -040036#endif
37
clang-format6c4d83e2016-08-08 19:03:30 -070038#define LOG_ERROR(label) \
39 do { \
40 const char *l = label; \
41 va_list ap; \
42 va_start(ap, fmt); \
43 if (l) fprintf(stderr, "%s: ", l); \
44 vfprintf(stderr, fmt, ap); \
45 fprintf(stderr, "\n"); \
46 va_end(ap); \
47 } while (0)
Tom Finegan03848f52013-11-05 10:02:18 -080048
John Koleszarc6b90392012-07-13 15:21:29 -070049FILE *set_binary_mode(FILE *stream) {
50 (void)stream;
John Koleszar82b1a342012-11-06 12:08:05 -080051#if defined(_WIN32) || defined(__OS2__)
John Koleszarc6b90392012-07-13 15:21:29 -070052 _setmode(_fileno(stream), _O_BINARY);
John Koleszarc377bf02010-11-02 09:11:57 -040053#endif
John Koleszarc6b90392012-07-13 15:21:29 -070054 return stream;
John Koleszarc377bf02010-11-02 09:11:57 -040055}
Tom Finegan03848f52013-11-05 10:02:18 -080056
57void die(const char *fmt, ...) {
58 LOG_ERROR(NULL);
59 usage_exit();
60}
61
62void fatal(const char *fmt, ...) {
63 LOG_ERROR("Fatal");
64 exit(EXIT_FAILURE);
65}
66
clang-format6c4d83e2016-08-08 19:03:30 -070067void warn(const char *fmt, ...) { LOG_ERROR("Warning"); }
Tom Finegan00a35aa2013-11-14 12:37:42 -080068
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080069void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
70 const char *detail = vpx_codec_error_detail(ctx);
71
72 printf("%s: %s\n", s, vpx_codec_error(ctx));
clang-format6c4d83e2016-08-08 19:03:30 -070073 if (detail) printf(" %s\n", detail);
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080074 exit(EXIT_FAILURE);
75}
76
Tom Finegan00a35aa2013-11-14 12:37:42 -080077int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
78 FILE *f = input_ctx->file;
79 struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
80 int plane = 0;
81 int shortread = 0;
Deb Mukherjee5acfafb2014-08-26 12:35:15 -070082 const int bytespp = (yuv_frame->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
Tom Finegan00a35aa2013-11-14 12:37:42 -080083
84 for (plane = 0; plane < 3; ++plane) {
85 uint8_t *ptr;
Deb Mukherjee449e5f22014-07-11 11:43:31 -070086 const int w = vpx_img_plane_width(yuv_frame, plane);
87 const int h = vpx_img_plane_height(yuv_frame, plane);
Tom Finegan00a35aa2013-11-14 12:37:42 -080088 int r;
89
90 /* Determine the correct plane based on the image format. The for-loop
91 * always counts in Y,U,V order, but this may not match the order of
92 * the data on disk.
93 */
94 switch (plane) {
95 case 1:
clang-format6c4d83e2016-08-08 19:03:30 -070096 ptr =
97 yuv_frame->planes[yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V
98 : VPX_PLANE_U];
Tom Finegan00a35aa2013-11-14 12:37:42 -080099 break;
100 case 2:
clang-format6c4d83e2016-08-08 19:03:30 -0700101 ptr =
102 yuv_frame->planes[yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U
103 : VPX_PLANE_V];
Tom Finegan00a35aa2013-11-14 12:37:42 -0800104 break;
clang-format6c4d83e2016-08-08 19:03:30 -0700105 default: ptr = yuv_frame->planes[plane];
Tom Finegan00a35aa2013-11-14 12:37:42 -0800106 }
107
108 for (r = 0; r < h; ++r) {
Deb Mukherjee449e5f22014-07-11 11:43:31 -0700109 size_t needed = w * bytespp;
Tom Finegan00a35aa2013-11-14 12:37:42 -0800110 size_t buf_position = 0;
111 const size_t left = detect->buf_read - detect->position;
112 if (left > 0) {
113 const size_t more = (left < needed) ? left : needed;
114 memcpy(ptr, detect->buf + detect->position, more);
115 buf_position = more;
116 needed -= more;
117 detect->position += more;
118 }
119 if (needed > 0) {
120 shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
121 }
122
123 ptr += yuv_frame->stride[plane];
124 }
125 }
126
127 return shortread;
128}
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800129
James Zern8465c932015-08-10 16:45:49 -0700130#if CONFIG_ENCODERS
131
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800132static const VpxInterface vpx_encoders[] = {
Jingning Han5dccce52015-08-15 15:57:54 -0700133#if CONFIG_VP10_ENCODER
clang-format6c4d83e2016-08-08 19:03:30 -0700134 { "vp10", VP10_FOURCC, &vpx_codec_vp10_cx },
Jingning Han5dccce52015-08-15 15:57:54 -0700135#endif
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800136};
137
James Zern5a73bbd2015-05-09 10:40:51 -0700138int get_vpx_encoder_count(void) {
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800139 return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]);
140}
141
clang-format6c4d83e2016-08-08 19:03:30 -0700142const VpxInterface *get_vpx_encoder_by_index(int i) { return &vpx_encoders[i]; }
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800143
144const VpxInterface *get_vpx_encoder_by_name(const char *name) {
145 int i;
146
147 for (i = 0; i < get_vpx_encoder_count(); ++i) {
148 const VpxInterface *encoder = get_vpx_encoder_by_index(i);
clang-format6c4d83e2016-08-08 19:03:30 -0700149 if (strcmp(encoder->name, name) == 0) return encoder;
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800150 }
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800151
152 return NULL;
153}
154
James Zern8465c932015-08-10 16:45:49 -0700155#endif // CONFIG_ENCODERS
156
157#if CONFIG_DECODERS
158
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800159static const VpxInterface vpx_decoders[] = {
Jingning Han3ee6db62015-08-05 19:00:31 -0700160
161#if CONFIG_VP10_DECODER
clang-format6c4d83e2016-08-08 19:03:30 -0700162 { "vp10", VP10_FOURCC, &vpx_codec_vp10_dx },
Jingning Han3ee6db62015-08-05 19:00:31 -0700163#endif
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800164};
165
James Zernd1999cb2015-05-09 10:41:54 -0700166int get_vpx_decoder_count(void) {
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800167 return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
168}
169
clang-format6c4d83e2016-08-08 19:03:30 -0700170const VpxInterface *get_vpx_decoder_by_index(int i) { return &vpx_decoders[i]; }
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800171
172const VpxInterface *get_vpx_decoder_by_name(const char *name) {
173 int i;
174
175 for (i = 0; i < get_vpx_decoder_count(); ++i) {
clang-format6c4d83e2016-08-08 19:03:30 -0700176 const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
177 if (strcmp(decoder->name, name) == 0) return decoder;
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800178 }
179
180 return NULL;
181}
182
183const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc) {
184 int i;
185
186 for (i = 0; i < get_vpx_decoder_count(); ++i) {
187 const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
clang-format6c4d83e2016-08-08 19:03:30 -0700188 if (decoder->fourcc == fourcc) return decoder;
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800189 }
190
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800191 return NULL;
192}
193
James Zern8465c932015-08-10 16:45:49 -0700194#endif // CONFIG_DECODERS
195
Dmitry Kovalev2bdd43d2014-02-12 18:36:36 -0800196// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
197// of vpx_image_t support
198int vpx_img_plane_width(const vpx_image_t *img, int plane) {
199 if (plane > 0 && img->x_chroma_shift > 0)
200 return (img->d_w + 1) >> img->x_chroma_shift;
201 else
202 return img->d_w;
203}
204
205int vpx_img_plane_height(const vpx_image_t *img, int plane) {
clang-format6c4d83e2016-08-08 19:03:30 -0700206 if (plane > 0 && img->y_chroma_shift > 0)
Dmitry Kovalev2bdd43d2014-02-12 18:36:36 -0800207 return (img->d_h + 1) >> img->y_chroma_shift;
208 else
209 return img->d_h;
210}
211
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800212void vpx_img_write(const vpx_image_t *img, FILE *file) {
Dmitry Kovalev2bdd43d2014-02-12 18:36:36 -0800213 int plane;
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800214
215 for (plane = 0; plane < 3; ++plane) {
216 const unsigned char *buf = img->planes[plane];
217 const int stride = img->stride[plane];
Deb Mukherjee9ed23de2014-09-25 15:46:50 -0700218 const int w = vpx_img_plane_width(img, plane) *
clang-format6c4d83e2016-08-08 19:03:30 -0700219 ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
Dmitry Kovalev2bdd43d2014-02-12 18:36:36 -0800220 const int h = vpx_img_plane_height(img, plane);
221 int y;
Dmitry Kovalev592936b2014-02-07 11:37:39 -0800222
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800223 for (y = 0; y < h; ++y) {
224 fwrite(buf, 1, w, file);
225 buf += stride;
226 }
227 }
228}
Dmitry Kovalev592936b2014-02-07 11:37:39 -0800229
230int vpx_img_read(vpx_image_t *img, FILE *file) {
231 int plane;
232
233 for (plane = 0; plane < 3; ++plane) {
234 unsigned char *buf = img->planes[plane];
235 const int stride = img->stride[plane];
Deb Mukherjee5acfafb2014-08-26 12:35:15 -0700236 const int w = vpx_img_plane_width(img, plane) *
clang-format6c4d83e2016-08-08 19:03:30 -0700237 ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
Dmitry Kovalev2bdd43d2014-02-12 18:36:36 -0800238 const int h = vpx_img_plane_height(img, plane);
Dmitry Kovalev592936b2014-02-07 11:37:39 -0800239 int y;
240
241 for (y = 0; y < h; ++y) {
clang-format6c4d83e2016-08-08 19:03:30 -0700242 if (fread(buf, 1, w, file) != (size_t)w) return 0;
Dmitry Kovalev592936b2014-02-07 11:37:39 -0800243 buf += stride;
244 }
245 }
246
247 return 1;
248}
249
Dmitry Kovalev2dad0e12014-02-27 14:00:41 -0800250// TODO(dkovalev) change sse_to_psnr signature: double -> int64_t
251double sse_to_psnr(double samples, double peak, double sse) {
252 static const double kMaxPSNR = 100.0;
253
254 if (sse > 0.0) {
255 const double psnr = 10.0 * log10(samples * peak * peak / sse);
256 return psnr > kMaxPSNR ? kMaxPSNR : psnr;
257 } else {
258 return kMaxPSNR;
259 }
260}
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700261
262// TODO(debargha): Consolidate the functions below into a separate file.
Yaowu Xu72889a22015-08-14 12:16:07 -0700263#if CONFIG_VP9_HIGHBITDEPTH
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700264static void highbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
265 int input_shift) {
266 // Note the offset is 1 less than half.
267 const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
268 int plane;
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700269 if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700270 dst->x_chroma_shift != src->x_chroma_shift ||
clang-format6c4d83e2016-08-08 19:03:30 -0700271 dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
272 input_shift < 0) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700273 fatal("Unsupported image conversion");
274 }
275 switch (src->fmt) {
276 case VPX_IMG_FMT_I42016:
277 case VPX_IMG_FMT_I42216:
278 case VPX_IMG_FMT_I44416:
clang-format6c4d83e2016-08-08 19:03:30 -0700279 case VPX_IMG_FMT_I44016: break;
280 default: fatal("Unsupported image conversion"); break;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700281 }
282 for (plane = 0; plane < 3; plane++) {
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700283 int w = src->d_w;
284 int h = src->d_h;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700285 int x, y;
286 if (plane) {
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700287 w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
288 h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700289 }
290 for (y = 0; y < h; y++) {
291 uint16_t *p_src =
292 (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
293 uint16_t *p_dst =
294 (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
clang-format6c4d83e2016-08-08 19:03:30 -0700295 for (x = 0; x < w; x++) *p_dst++ = (*p_src++ << input_shift) + offset;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700296 }
297 }
298}
299
300static void lowbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
301 int input_shift) {
302 // Note the offset is 1 less than half.
303 const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
304 int plane;
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700305 if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700306 dst->x_chroma_shift != src->x_chroma_shift ||
307 dst->y_chroma_shift != src->y_chroma_shift ||
clang-format6c4d83e2016-08-08 19:03:30 -0700308 dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH || input_shift < 0) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700309 fatal("Unsupported image conversion");
310 }
311 switch (src->fmt) {
312 case VPX_IMG_FMT_I420:
313 case VPX_IMG_FMT_I422:
314 case VPX_IMG_FMT_I444:
clang-format6c4d83e2016-08-08 19:03:30 -0700315 case VPX_IMG_FMT_I440: break;
316 default: fatal("Unsupported image conversion"); break;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700317 }
318 for (plane = 0; plane < 3; plane++) {
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700319 int w = src->d_w;
320 int h = src->d_h;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700321 int x, y;
322 if (plane) {
323 w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
324 h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
325 }
326 for (y = 0; y < h; y++) {
327 uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
328 uint16_t *p_dst =
329 (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
330 for (x = 0; x < w; x++) {
331 *p_dst++ = (*p_src++ << input_shift) + offset;
332 }
333 }
334 }
335}
336
clang-format6c4d83e2016-08-08 19:03:30 -0700337void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src, int input_shift) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700338 if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
339 highbd_img_upshift(dst, src, input_shift);
340 } else {
341 lowbd_img_upshift(dst, src, input_shift);
342 }
343}
344
345void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src) {
346 int plane;
clang-format6c4d83e2016-08-08 19:03:30 -0700347 if (dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH != src->fmt || dst->d_w != src->d_w ||
348 dst->d_h != src->d_h || dst->x_chroma_shift != src->x_chroma_shift ||
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700349 dst->y_chroma_shift != src->y_chroma_shift) {
350 fatal("Unsupported image conversion");
351 }
352 switch (dst->fmt) {
353 case VPX_IMG_FMT_I420:
354 case VPX_IMG_FMT_I422:
355 case VPX_IMG_FMT_I444:
clang-format6c4d83e2016-08-08 19:03:30 -0700356 case VPX_IMG_FMT_I440: break;
357 default: fatal("Unsupported image conversion"); break;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700358 }
359 for (plane = 0; plane < 3; plane++) {
360 int w = src->d_w;
361 int h = src->d_h;
362 int x, y;
363 if (plane) {
Deb Mukherjee23fc1f72014-10-15 10:01:34 -0700364 w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
365 h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700366 }
367 for (y = 0; y < h; y++) {
368 uint16_t *p_src =
369 (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
370 uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
371 for (x = 0; x < w; x++) {
Yaowu Xuc369daf2015-07-07 14:22:07 -0700372 *p_dst++ = (uint8_t)(*p_src++);
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700373 }
374 }
375 }
376}
377
378static void highbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
379 int down_shift) {
380 int plane;
381 if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
382 dst->x_chroma_shift != src->x_chroma_shift ||
clang-format6c4d83e2016-08-08 19:03:30 -0700383 dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
384 down_shift < 0) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700385 fatal("Unsupported image conversion");
386 }
387 switch (src->fmt) {
388 case VPX_IMG_FMT_I42016:
389 case VPX_IMG_FMT_I42216:
390 case VPX_IMG_FMT_I44416:
clang-format6c4d83e2016-08-08 19:03:30 -0700391 case VPX_IMG_FMT_I44016: break;
392 default: fatal("Unsupported image conversion"); break;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700393 }
394 for (plane = 0; plane < 3; plane++) {
395 int w = src->d_w;
396 int h = src->d_h;
397 int x, y;
398 if (plane) {
399 w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
400 h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
401 }
402 for (y = 0; y < h; y++) {
403 uint16_t *p_src =
404 (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
405 uint16_t *p_dst =
406 (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
clang-format6c4d83e2016-08-08 19:03:30 -0700407 for (x = 0; x < w; x++) *p_dst++ = *p_src++ >> down_shift;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700408 }
409 }
410}
411
412static void lowbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
413 int down_shift) {
414 int plane;
415 if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
416 dst->x_chroma_shift != src->x_chroma_shift ||
417 dst->y_chroma_shift != src->y_chroma_shift ||
clang-format6c4d83e2016-08-08 19:03:30 -0700418 src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH || down_shift < 0) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700419 fatal("Unsupported image conversion");
420 }
421 switch (dst->fmt) {
422 case VPX_IMG_FMT_I420:
423 case VPX_IMG_FMT_I422:
424 case VPX_IMG_FMT_I444:
clang-format6c4d83e2016-08-08 19:03:30 -0700425 case VPX_IMG_FMT_I440: break;
426 default: fatal("Unsupported image conversion"); break;
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700427 }
428 for (plane = 0; plane < 3; plane++) {
429 int w = src->d_w;
430 int h = src->d_h;
431 int x, y;
432 if (plane) {
433 w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
434 h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
435 }
436 for (y = 0; y < h; y++) {
437 uint16_t *p_src =
438 (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
439 uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
440 for (x = 0; x < w; x++) {
441 *p_dst++ = *p_src++ >> down_shift;
442 }
443 }
444 }
445}
446
clang-format6c4d83e2016-08-08 19:03:30 -0700447void vpx_img_downshift(vpx_image_t *dst, vpx_image_t *src, int down_shift) {
Deb Mukherjee7a2a6112014-10-06 20:46:11 -0700448 if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
449 highbd_img_downshift(dst, src, down_shift);
450 } else {
451 lowbd_img_downshift(dst, src, down_shift);
452 }
453}
Yaowu Xu72889a22015-08-14 12:16:07 -0700454#endif // CONFIG_VP9_HIGHBITDEPTH