2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
18 #include "./tools_common.h"
20 #if CONFIG_AV1_ENCODER
21 #include "aom/aomcx.h"
24 #if CONFIG_AV1_DECODER
25 #include "aom/aomdx.h"
28 #if defined(_WIN32) || defined(__OS2__)
33 #define _setmode setmode
34 #define _fileno fileno
35 #define _O_BINARY O_BINARY
39 #define LOG_ERROR(label) \
41 const char *l = label; \
44 if (l) fprintf(stderr, "%s: ", l); \
45 vfprintf(stderr, fmt, ap); \
46 fprintf(stderr, "\n"); \
50 FILE *set_binary_mode(FILE *stream
) {
52 #if defined(_WIN32) || defined(__OS2__)
53 _setmode(_fileno(stream
), _O_BINARY
);
58 void die(const char *fmt
, ...) {
63 void fatal(const char *fmt
, ...) {
68 void warn(const char *fmt
, ...) { LOG_ERROR("Warning"); }
70 void die_codec(aom_codec_ctx_t
*ctx
, const char *s
) {
71 const char *detail
= aom_codec_error_detail(ctx
);
73 printf("%s: %s\n", s
, aom_codec_error(ctx
));
74 if (detail
) printf(" %s\n", detail
);
78 int read_yuv_frame(struct AvxInputContext
*input_ctx
, aom_image_t
*yuv_frame
) {
79 FILE *f
= input_ctx
->file
;
80 struct FileTypeDetectionBuffer
*detect
= &input_ctx
->detect
;
83 const int bytespp
= (yuv_frame
->fmt
& AOM_IMG_FMT_HIGHBITDEPTH
) ? 2 : 1;
85 for (plane
= 0; plane
< 3; ++plane
) {
87 const int w
= aom_img_plane_width(yuv_frame
, plane
);
88 const int h
= aom_img_plane_height(yuv_frame
, plane
);
91 /* Determine the correct plane based on the image format. The for-loop
92 * always counts in Y,U,V order, but this may not match the order of
98 yuv_frame
->planes
[yuv_frame
->fmt
== AOM_IMG_FMT_YV12
? AOM_PLANE_V
103 yuv_frame
->planes
[yuv_frame
->fmt
== AOM_IMG_FMT_YV12
? AOM_PLANE_U
106 default: ptr
= yuv_frame
->planes
[plane
];
109 for (r
= 0; r
< h
; ++r
) {
110 size_t needed
= w
* bytespp
;
111 size_t buf_position
= 0;
112 const size_t left
= detect
->buf_read
- detect
->position
;
114 const size_t more
= (left
< needed
) ? left
: needed
;
115 memcpy(ptr
, detect
->buf
+ detect
->position
, more
);
118 detect
->position
+= more
;
121 shortread
|= (fread(ptr
+ buf_position
, 1, needed
, f
) < needed
);
124 ptr
+= yuv_frame
->stride
[plane
];
131 #if CONFIG_AV1_ENCODER
132 static const AvxInterface aom_encoders
[] = {
133 { "av1", AV1_FOURCC
, &aom_codec_av1_cx
},
136 int get_aom_encoder_count(void) {
137 return sizeof(aom_encoders
) / sizeof(aom_encoders
[0]);
140 const AvxInterface
*get_aom_encoder_by_index(int i
) { return &aom_encoders
[i
]; }
142 const AvxInterface
*get_aom_encoder_by_name(const char *name
) {
145 for (i
= 0; i
< get_aom_encoder_count(); ++i
) {
146 const AvxInterface
*encoder
= get_aom_encoder_by_index(i
);
147 if (strcmp(encoder
->name
, name
) == 0) return encoder
;
152 #endif // CONFIG_AV1_ENCODER
154 #if CONFIG_AV1_DECODER
155 static const AvxInterface aom_decoders
[] = {
156 { "av1", AV1_FOURCC
, &aom_codec_av1_dx
},
159 int get_aom_decoder_count(void) {
160 return sizeof(aom_decoders
) / sizeof(aom_decoders
[0]);
163 const AvxInterface
*get_aom_decoder_by_index(int i
) { return &aom_decoders
[i
]; }
165 const AvxInterface
*get_aom_decoder_by_name(const char *name
) {
168 for (i
= 0; i
< get_aom_decoder_count(); ++i
) {
169 const AvxInterface
*const decoder
= get_aom_decoder_by_index(i
);
170 if (strcmp(decoder
->name
, name
) == 0) return decoder
;
176 const AvxInterface
*get_aom_decoder_by_fourcc(uint32_t fourcc
) {
179 for (i
= 0; i
< get_aom_decoder_count(); ++i
) {
180 const AvxInterface
*const decoder
= get_aom_decoder_by_index(i
);
181 if (decoder
->fourcc
== fourcc
) return decoder
;
186 #endif // CONFIG_AV1_DECODER
188 void aom_img_write(const aom_image_t
*img
, FILE *file
) {
191 for (plane
= 0; plane
< 3; ++plane
) {
192 const unsigned char *buf
= img
->planes
[plane
];
193 const int stride
= img
->stride
[plane
];
194 const int w
= aom_img_plane_width(img
, plane
) *
195 ((img
->fmt
& AOM_IMG_FMT_HIGHBITDEPTH
) ? 2 : 1);
196 const int h
= aom_img_plane_height(img
, plane
);
199 for (y
= 0; y
< h
; ++y
) {
200 fwrite(buf
, 1, w
, file
);
206 int aom_img_read(aom_image_t
*img
, FILE *file
) {
209 for (plane
= 0; plane
< 3; ++plane
) {
210 unsigned char *buf
= img
->planes
[plane
];
211 const int stride
= img
->stride
[plane
];
212 const int w
= aom_img_plane_width(img
, plane
) *
213 ((img
->fmt
& AOM_IMG_FMT_HIGHBITDEPTH
) ? 2 : 1);
214 const int h
= aom_img_plane_height(img
, plane
);
217 for (y
= 0; y
< h
; ++y
) {
218 if (fread(buf
, 1, w
, file
) != (size_t)w
) return 0;
226 // TODO(dkovalev) change sse_to_psnr signature: double -> int64_t
227 double sse_to_psnr(double samples
, double peak
, double sse
) {
228 static const double kMaxPSNR
= 100.0;
231 const double psnr
= 10.0 * log10(samples
* peak
* peak
/ sse
);
232 return psnr
> kMaxPSNR
? kMaxPSNR
: psnr
;
238 // TODO(debargha): Consolidate the functions below into a separate file.
239 static void highbd_img_upshift(aom_image_t
*dst
, aom_image_t
*src
,
241 // Note the offset is 1 less than half.
242 const int offset
= input_shift
> 0 ? (1 << (input_shift
- 1)) - 1 : 0;
244 if (dst
->d_w
!= src
->d_w
|| dst
->d_h
!= src
->d_h
||
245 dst
->x_chroma_shift
!= src
->x_chroma_shift
||
246 dst
->y_chroma_shift
!= src
->y_chroma_shift
|| dst
->fmt
!= src
->fmt
||
248 fatal("Unsupported image conversion");
251 case AOM_IMG_FMT_I42016
:
252 case AOM_IMG_FMT_I42216
:
253 case AOM_IMG_FMT_I44416
:
254 case AOM_IMG_FMT_I44016
: break;
255 default: fatal("Unsupported image conversion"); break;
257 for (plane
= 0; plane
< 3; plane
++) {
262 w
= (w
+ src
->x_chroma_shift
) >> src
->x_chroma_shift
;
263 h
= (h
+ src
->y_chroma_shift
) >> src
->y_chroma_shift
;
265 for (y
= 0; y
< h
; y
++) {
267 (uint16_t *)(src
->planes
[plane
] + y
* src
->stride
[plane
]);
269 (uint16_t *)(dst
->planes
[plane
] + y
* dst
->stride
[plane
]);
270 for (x
= 0; x
< w
; x
++) *p_dst
++ = (*p_src
++ << input_shift
) + offset
;
275 static void lowbd_img_upshift(aom_image_t
*dst
, aom_image_t
*src
,
277 // Note the offset is 1 less than half.
278 const int offset
= input_shift
> 0 ? (1 << (input_shift
- 1)) - 1 : 0;
280 if (dst
->d_w
!= src
->d_w
|| dst
->d_h
!= src
->d_h
||
281 dst
->x_chroma_shift
!= src
->x_chroma_shift
||
282 dst
->y_chroma_shift
!= src
->y_chroma_shift
||
283 dst
->fmt
!= src
->fmt
+ AOM_IMG_FMT_HIGHBITDEPTH
|| input_shift
< 0) {
284 fatal("Unsupported image conversion");
287 case AOM_IMG_FMT_I420
:
288 case AOM_IMG_FMT_I422
:
289 case AOM_IMG_FMT_I444
:
290 case AOM_IMG_FMT_I440
: break;
291 default: fatal("Unsupported image conversion"); break;
293 for (plane
= 0; plane
< 3; plane
++) {
298 w
= (w
+ src
->x_chroma_shift
) >> src
->x_chroma_shift
;
299 h
= (h
+ src
->y_chroma_shift
) >> src
->y_chroma_shift
;
301 for (y
= 0; y
< h
; y
++) {
302 uint8_t *p_src
= src
->planes
[plane
] + y
* src
->stride
[plane
];
304 (uint16_t *)(dst
->planes
[plane
] + y
* dst
->stride
[plane
]);
305 for (x
= 0; x
< w
; x
++) {
306 *p_dst
++ = (*p_src
++ << input_shift
) + offset
;
312 void aom_img_upshift(aom_image_t
*dst
, aom_image_t
*src
, int input_shift
) {
313 if (src
->fmt
& AOM_IMG_FMT_HIGHBITDEPTH
) {
314 highbd_img_upshift(dst
, src
, input_shift
);
316 lowbd_img_upshift(dst
, src
, input_shift
);
320 void aom_img_truncate_16_to_8(aom_image_t
*dst
, aom_image_t
*src
) {
322 if (dst
->fmt
+ AOM_IMG_FMT_HIGHBITDEPTH
!= src
->fmt
|| dst
->d_w
!= src
->d_w
||
323 dst
->d_h
!= src
->d_h
|| dst
->x_chroma_shift
!= src
->x_chroma_shift
||
324 dst
->y_chroma_shift
!= src
->y_chroma_shift
) {
325 fatal("Unsupported image conversion");
328 case AOM_IMG_FMT_I420
:
329 case AOM_IMG_FMT_I422
:
330 case AOM_IMG_FMT_I444
:
331 case AOM_IMG_FMT_I440
: break;
332 default: fatal("Unsupported image conversion"); break;
334 for (plane
= 0; plane
< 3; plane
++) {
339 w
= (w
+ src
->x_chroma_shift
) >> src
->x_chroma_shift
;
340 h
= (h
+ src
->y_chroma_shift
) >> src
->y_chroma_shift
;
342 for (y
= 0; y
< h
; y
++) {
344 (uint16_t *)(src
->planes
[plane
] + y
* src
->stride
[plane
]);
345 uint8_t *p_dst
= dst
->planes
[plane
] + y
* dst
->stride
[plane
];
346 for (x
= 0; x
< w
; x
++) {
347 *p_dst
++ = (uint8_t)(*p_src
++);
353 static void highbd_img_downshift(aom_image_t
*dst
, aom_image_t
*src
,
356 if (dst
->d_w
!= src
->d_w
|| dst
->d_h
!= src
->d_h
||
357 dst
->x_chroma_shift
!= src
->x_chroma_shift
||
358 dst
->y_chroma_shift
!= src
->y_chroma_shift
|| dst
->fmt
!= src
->fmt
||
360 fatal("Unsupported image conversion");
363 case AOM_IMG_FMT_I42016
:
364 case AOM_IMG_FMT_I42216
:
365 case AOM_IMG_FMT_I44416
:
366 case AOM_IMG_FMT_I44016
: break;
367 default: fatal("Unsupported image conversion"); break;
369 for (plane
= 0; plane
< 3; plane
++) {
374 w
= (w
+ src
->x_chroma_shift
) >> src
->x_chroma_shift
;
375 h
= (h
+ src
->y_chroma_shift
) >> src
->y_chroma_shift
;
377 for (y
= 0; y
< h
; y
++) {
379 (uint16_t *)(src
->planes
[plane
] + y
* src
->stride
[plane
]);
381 (uint16_t *)(dst
->planes
[plane
] + y
* dst
->stride
[plane
]);
382 for (x
= 0; x
< w
; x
++) *p_dst
++ = *p_src
++ >> down_shift
;
387 static void lowbd_img_downshift(aom_image_t
*dst
, aom_image_t
*src
,
390 if (dst
->d_w
!= src
->d_w
|| dst
->d_h
!= src
->d_h
||
391 dst
->x_chroma_shift
!= src
->x_chroma_shift
||
392 dst
->y_chroma_shift
!= src
->y_chroma_shift
||
393 src
->fmt
!= dst
->fmt
+ AOM_IMG_FMT_HIGHBITDEPTH
|| down_shift
< 0) {
394 fatal("Unsupported image conversion");
397 case AOM_IMG_FMT_I420
:
398 case AOM_IMG_FMT_I422
:
399 case AOM_IMG_FMT_I444
:
400 case AOM_IMG_FMT_I440
: break;
401 default: fatal("Unsupported image conversion"); break;
403 for (plane
= 0; plane
< 3; plane
++) {
408 w
= (w
+ src
->x_chroma_shift
) >> src
->x_chroma_shift
;
409 h
= (h
+ src
->y_chroma_shift
) >> src
->y_chroma_shift
;
411 for (y
= 0; y
< h
; y
++) {
413 (uint16_t *)(src
->planes
[plane
] + y
* src
->stride
[plane
]);
414 uint8_t *p_dst
= dst
->planes
[plane
] + y
* dst
->stride
[plane
];
415 for (x
= 0; x
< w
; x
++) {
416 *p_dst
++ = *p_src
++ >> down_shift
;
422 void aom_img_downshift(aom_image_t
*dst
, aom_image_t
*src
, int down_shift
) {
423 if (dst
->fmt
& AOM_IMG_FMT_HIGHBITDEPTH
) {
424 highbd_img_downshift(dst
, src
, down_shift
);
426 lowbd_img_downshift(dst
, src
, down_shift
);