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.
11 * Based on code from the OggTheora software codec source code,
12 * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
18 #include "aom/aom_integer.h"
21 // Reads 'size' bytes from 'file' into 'buf' with some fault tolerance.
22 // Returns true on success.
23 static int file_read(void *buf
, size_t size
, FILE *file
) {
24 const int kMaxRetries
= 5;
29 const size_t n
= fread((uint8_t *)buf
+ len
, 1, size
- len
, file
);
31 file_error
= ferror(file
);
33 if (errno
== EINTR
|| errno
== EAGAIN
) {
37 fprintf(stderr
, "Error reading file: %u of %u bytes read, %d: %s\n",
38 (uint32_t)len
, (uint32_t)size
, errno
, strerror(errno
));
42 } while (!feof(file
) && len
< size
&& ++retry_count
< kMaxRetries
);
44 if (!feof(file
) && len
!= size
) {
46 "Error reading file: %u of %u bytes read,"
47 " error: %d, retries: %d, %d: %s\n",
48 (uint32_t)len
, (uint32_t)size
, file_error
, retry_count
, errno
,
54 static int y4m_parse_tags(y4m_input
*_y4m
, char *_tags
) {
63 got_w
= got_h
= got_fps
= got_interlace
= got_par
= got_chroma
= 0;
64 for (p
= _tags
;; p
= q
) {
65 /*Skip any leading spaces.*/
66 while (*p
== ' ') p
++;
67 /*If that's all we have, stop.*/
68 if (p
[0] == '\0') break;
69 /*Find the end of this tag.*/
70 for (q
= p
+ 1; *q
!= '\0' && *q
!= ' '; q
++) {
75 if (sscanf(p
+ 1, "%d", &_y4m
->pic_w
) != 1) return -1;
79 if (sscanf(p
+ 1, "%d", &_y4m
->pic_h
) != 1) return -1;
83 if (sscanf(p
+ 1, "%d:%d", &_y4m
->fps_n
, &_y4m
->fps_d
) != 2) {
89 _y4m
->interlace
= p
[1];
93 if (sscanf(p
+ 1, "%d:%d", &_y4m
->par_n
, &_y4m
->par_d
) != 2) {
99 if (q
- p
> 16) return -1;
100 memcpy(_y4m
->chroma_type
, p
+ 1, q
- p
- 1);
101 _y4m
->chroma_type
[q
- p
- 1] = '\0';
104 /*Ignore unknown tags.*/
107 if (!got_w
|| !got_h
|| !got_fps
) return -1;
108 if (!got_interlace
) _y4m
->interlace
= '?';
109 if (!got_par
) _y4m
->par_n
= _y4m
->par_d
= 0;
110 /*Chroma-type is not specified in older files, e.g., those generated by
112 if (!got_chroma
) strcpy(_y4m
->chroma_type
, "420");
116 /*All anti-aliasing filters in the following conversion functions are based on
117 one of two window functions:
118 The 6-tap Lanczos window (for down-sampling and shifts):
119 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
121 The 4-tap Mitchell window (for up-sampling):
122 7|t|^3-12|t|^2+16/3, |t|<1
123 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
125 The number of taps is intentionally kept small to reduce computational
126 overhead and limit ringing.
128 The taps from these filters are scaled so that their sum is 1, and the
129 result is scaled by 128 and rounded to integers to create a filter whose
130 intermediate values fit inside 16 bits.
131 Coefficients are rounded in such a way as to ensure their sum is still 128,
132 which is usually equivalent to normal rounding.
134 Conversions which require both horizontal and vertical filtering could
135 have these steps pipelined, for less memory consumption and better cache
136 performance, but we do them separately for simplicity.*/
137 #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
138 #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
139 #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
141 /*420jpeg chroma samples are sited like:
142 Y-------Y-------Y-------Y-------
146 Y-------Y-------Y-------Y-------
150 Y-------Y-------Y-------Y-------
154 Y-------Y-------Y-------Y-------
159 420mpeg2 chroma samples are sited like:
160 Y-------Y-------Y-------Y-------
164 Y-------Y-------Y-------Y-------
168 Y-------Y-------Y-------Y-------
172 Y-------Y-------Y-------Y-------
177 We use a resampling filter to shift the site locations one quarter pixel (at
178 the chroma plane's resolution) to the right.
179 The 4:2:2 modes look exactly the same, except there are twice as many chroma
180 lines, and they are vertically co-sited with the luma samples in both the
181 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
182 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst
,
183 const unsigned char *_src
, int _c_w
,
187 for (y
= 0; y
< _c_h
; y
++) {
188 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
190 for (x
= 0; x
< OC_MINI(_c_w
, 2); x
++) {
191 _dst
[x
] = (unsigned char)OC_CLAMPI(
193 (4 * _src
[0] - 17 * _src
[OC_MAXI(x
- 1, 0)] + 114 * _src
[x
] +
194 35 * _src
[OC_MINI(x
+ 1, _c_w
- 1)] -
195 9 * _src
[OC_MINI(x
+ 2, _c_w
- 1)] + _src
[OC_MINI(x
+ 3, _c_w
- 1)] +
200 for (; x
< _c_w
- 3; x
++) {
201 _dst
[x
] = (unsigned char)OC_CLAMPI(
203 (4 * _src
[x
- 2] - 17 * _src
[x
- 1] + 114 * _src
[x
] +
204 35 * _src
[x
+ 1] - 9 * _src
[x
+ 2] + _src
[x
+ 3] + 64) >>
208 for (; x
< _c_w
; x
++) {
209 _dst
[x
] = (unsigned char)OC_CLAMPI(
211 (4 * _src
[x
- 2] - 17 * _src
[x
- 1] + 114 * _src
[x
] +
212 35 * _src
[OC_MINI(x
+ 1, _c_w
- 1)] -
213 9 * _src
[OC_MINI(x
+ 2, _c_w
- 1)] + _src
[_c_w
- 1] + 64) >>
222 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
223 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input
*_y4m
, unsigned char *_dst
,
224 unsigned char *_aux
) {
229 /*Skip past the luma data.*/
230 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
231 /*Compute the size of each chroma plane.*/
232 c_w
= (_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
233 c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
235 for (pli
= 1; pli
< 3; pli
++) {
236 y4m_42xmpeg2_42xjpeg_helper(_dst
, _aux
, c_w
, c_h
);
242 /*This format is only used for interlaced content, but is included for
245 420jpeg chroma samples are sited like:
246 Y-------Y-------Y-------Y-------
250 Y-------Y-------Y-------Y-------
254 Y-------Y-------Y-------Y-------
258 Y-------Y-------Y-------Y-------
263 420paldv chroma samples are sited like:
264 YR------Y-------YR------Y-------
268 YB------Y-------YB------Y-------
272 YR------Y-------YR------Y-------
276 YB------Y-------YB------Y-------
281 We use a resampling filter to shift the site locations one quarter pixel (at
282 the chroma plane's resolution) to the right.
283 Then we use another filter to move the C_r location down one quarter pixel,
284 and the C_b location up one quarter pixel.*/
285 static void y4m_convert_42xpaldv_42xjpeg(y4m_input
*_y4m
, unsigned char *_dst
,
286 unsigned char *_aux
) {
294 /*Skip past the luma data.*/
295 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
296 /*Compute the size of each chroma plane.*/
297 c_w
= (_y4m
->pic_w
+ 1) / 2;
298 c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
300 tmp
= _aux
+ 2 * c_sz
;
301 for (pli
= 1; pli
< 3; pli
++) {
302 /*First do the horizontal re-sampling.
303 This is the same as the mpeg2 case, except that after the horizontal
304 case, we need to apply a second vertical filter.*/
305 y4m_42xmpeg2_42xjpeg_helper(tmp
, _aux
, c_w
, c_h
);
309 /*Slide C_b up a quarter-pel.
310 This is the same filter used above, but in the other order.*/
311 for (x
= 0; x
< c_w
; x
++) {
312 for (y
= 0; y
< OC_MINI(c_h
, 3); y
++) {
313 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
315 (tmp
[0] - 9 * tmp
[OC_MAXI(y
- 2, 0) * c_w
] +
316 35 * tmp
[OC_MAXI(y
- 1, 0) * c_w
] + 114 * tmp
[y
* c_w
] -
317 17 * tmp
[OC_MINI(y
+ 1, c_h
- 1) * c_w
] +
318 4 * tmp
[OC_MINI(y
+ 2, c_h
- 1) * c_w
] + 64) >>
322 for (; y
< c_h
- 2; y
++) {
323 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
325 (tmp
[(y
- 3) * c_w
] - 9 * tmp
[(y
- 2) * c_w
] +
326 35 * tmp
[(y
- 1) * c_w
] + 114 * tmp
[y
* c_w
] -
327 17 * tmp
[(y
+ 1) * c_w
] + 4 * tmp
[(y
+ 2) * c_w
] + 64) >>
331 for (; y
< c_h
; y
++) {
332 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
334 (tmp
[(y
- 3) * c_w
] - 9 * tmp
[(y
- 2) * c_w
] +
335 35 * tmp
[(y
- 1) * c_w
] + 114 * tmp
[y
* c_w
] -
336 17 * tmp
[OC_MINI(y
+ 1, c_h
- 1) * c_w
] +
337 4 * tmp
[(c_h
- 1) * c_w
] + 64) >>
348 /*Slide C_r down a quarter-pel.
349 This is the same as the horizontal filter.*/
350 for (x
= 0; x
< c_w
; x
++) {
351 for (y
= 0; y
< OC_MINI(c_h
, 2); y
++) {
352 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
354 (4 * tmp
[0] - 17 * tmp
[OC_MAXI(y
- 1, 0) * c_w
] +
355 114 * tmp
[y
* c_w
] + 35 * tmp
[OC_MINI(y
+ 1, c_h
- 1) * c_w
] -
356 9 * tmp
[OC_MINI(y
+ 2, c_h
- 1) * c_w
] +
357 tmp
[OC_MINI(y
+ 3, c_h
- 1) * c_w
] + 64) >>
361 for (; y
< c_h
- 3; y
++) {
362 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
364 (4 * tmp
[(y
- 2) * c_w
] - 17 * tmp
[(y
- 1) * c_w
] +
365 114 * tmp
[y
* c_w
] + 35 * tmp
[(y
+ 1) * c_w
] -
366 9 * tmp
[(y
+ 2) * c_w
] + tmp
[(y
+ 3) * c_w
] + 64) >>
370 for (; y
< c_h
; y
++) {
371 _dst
[y
* c_w
] = (unsigned char)OC_CLAMPI(
373 (4 * tmp
[(y
- 2) * c_w
] - 17 * tmp
[(y
- 1) * c_w
] +
374 114 * tmp
[y
* c_w
] + 35 * tmp
[OC_MINI(y
+ 1, c_h
- 1) * c_w
] -
375 9 * tmp
[OC_MINI(y
+ 2, c_h
- 1) * c_w
] + tmp
[(c_h
- 1) * c_w
] +
385 /*For actual interlaced material, this would have to be done separately on
386 each field, and the shift amounts would be different.
387 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
388 C_b up 1/8 in the bottom field.
389 The corresponding filters would be:
390 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
391 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
395 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
396 This is used as a helper by several converation routines.*/
397 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst
,
398 const unsigned char *_src
, int _c_w
,
402 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
403 for (x
= 0; x
< _c_w
; x
++) {
404 for (y
= 0; y
< OC_MINI(_c_h
, 2); y
+= 2) {
405 _dst
[(y
>> 1) * _c_w
] =
407 (64 * _src
[0] + 78 * _src
[OC_MINI(1, _c_h
- 1) * _c_w
] -
408 17 * _src
[OC_MINI(2, _c_h
- 1) * _c_w
] +
409 3 * _src
[OC_MINI(3, _c_h
- 1) * _c_w
] + 64) >>
413 for (; y
< _c_h
- 3; y
+= 2) {
414 _dst
[(y
>> 1) * _c_w
] =
416 (3 * (_src
[(y
- 2) * _c_w
] + _src
[(y
+ 3) * _c_w
]) -
417 17 * (_src
[(y
- 1) * _c_w
] + _src
[(y
+ 2) * _c_w
]) +
418 78 * (_src
[y
* _c_w
] + _src
[(y
+ 1) * _c_w
]) + 64) >>
422 for (; y
< _c_h
; y
+= 2) {
423 _dst
[(y
>> 1) * _c_w
] = OC_CLAMPI(
425 (3 * (_src
[(y
- 2) * _c_w
] + _src
[(_c_h
- 1) * _c_w
]) -
426 17 * (_src
[(y
- 1) * _c_w
] + _src
[OC_MINI(y
+ 2, _c_h
- 1) * _c_w
]) +
427 78 * (_src
[y
* _c_w
] + _src
[OC_MINI(y
+ 1, _c_h
- 1) * _c_w
]) +
437 /*420jpeg chroma samples are sited like:
438 Y-------Y-------Y-------Y-------
442 Y-------Y-------Y-------Y-------
446 Y-------Y-------Y-------Y-------
450 Y-------Y-------Y-------Y-------
455 422jpeg chroma samples are sited like:
456 Y---BR--Y-------Y---BR--Y-------
460 Y---BR--Y-------Y---BR--Y-------
464 Y---BR--Y-------Y---BR--Y-------
468 Y---BR--Y-------Y---BR--Y-------
473 We use a resampling filter to decimate the chroma planes by two in the
474 vertical direction.*/
475 static void y4m_convert_422jpeg_420jpeg(y4m_input
*_y4m
, unsigned char *_dst
,
476 unsigned char *_aux
) {
484 /*Skip past the luma data.*/
485 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
486 /*Compute the size of each chroma plane.*/
487 c_w
= (_y4m
->pic_w
+ _y4m
->src_c_dec_h
- 1) / _y4m
->src_c_dec_h
;
489 dst_c_w
= (_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
490 dst_c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
492 dst_c_sz
= dst_c_w
* dst_c_h
;
493 for (pli
= 1; pli
< 3; pli
++) {
494 y4m_422jpeg_420jpeg_helper(_dst
, _aux
, c_w
, c_h
);
500 /*420jpeg chroma samples are sited like:
501 Y-------Y-------Y-------Y-------
505 Y-------Y-------Y-------Y-------
509 Y-------Y-------Y-------Y-------
513 Y-------Y-------Y-------Y-------
518 422 chroma samples are sited like:
519 YBR-----Y-------YBR-----Y-------
523 YBR-----Y-------YBR-----Y-------
527 YBR-----Y-------YBR-----Y-------
531 YBR-----Y-------YBR-----Y-------
536 We use a resampling filter to shift the original site locations one quarter
537 pixel (at the original chroma resolution) to the right.
538 Then we use a second resampling filter to decimate the chroma planes by two
539 in the vertical direction.*/
540 static void y4m_convert_422_420jpeg(y4m_input
*_y4m
, unsigned char *_dst
,
541 unsigned char *_aux
) {
549 /*Skip past the luma data.*/
550 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
551 /*Compute the size of each chroma plane.*/
552 c_w
= (_y4m
->pic_w
+ _y4m
->src_c_dec_h
- 1) / _y4m
->src_c_dec_h
;
554 dst_c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
556 dst_c_sz
= c_w
* dst_c_h
;
557 tmp
= _aux
+ 2 * c_sz
;
558 for (pli
= 1; pli
< 3; pli
++) {
559 /*In reality, the horizontal and vertical steps could be pipelined, for
560 less memory consumption and better cache performance, but we do them
561 separately for simplicity.*/
562 /*First do horizontal filtering (convert to 422jpeg)*/
563 y4m_42xmpeg2_42xjpeg_helper(tmp
, _aux
, c_w
, c_h
);
564 /*Now do the vertical filtering.*/
565 y4m_422jpeg_420jpeg_helper(_dst
, tmp
, c_w
, c_h
);
571 /*420jpeg chroma samples are sited like:
572 Y-------Y-------Y-------Y-------
576 Y-------Y-------Y-------Y-------
580 Y-------Y-------Y-------Y-------
584 Y-------Y-------Y-------Y-------
589 411 chroma samples are sited like:
590 YBR-----Y-------Y-------Y-------
594 YBR-----Y-------Y-------Y-------
598 YBR-----Y-------Y-------Y-------
602 YBR-----Y-------Y-------Y-------
607 We use a filter to resample at site locations one eighth pixel (at the source
608 chroma plane's horizontal resolution) and five eighths of a pixel to the
610 Then we use another filter to decimate the planes by 2 in the vertical
612 static void y4m_convert_411_420jpeg(y4m_input
*_y4m
, unsigned char *_dst
,
613 unsigned char *_aux
) {
625 /*Skip past the luma data.*/
626 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
627 /*Compute the size of each chroma plane.*/
628 c_w
= (_y4m
->pic_w
+ _y4m
->src_c_dec_h
- 1) / _y4m
->src_c_dec_h
;
630 dst_c_w
= (_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
631 dst_c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
633 dst_c_sz
= dst_c_w
* dst_c_h
;
634 tmp_sz
= dst_c_w
* c_h
;
635 tmp
= _aux
+ 2 * c_sz
;
636 for (pli
= 1; pli
< 3; pli
++) {
637 /*In reality, the horizontal and vertical steps could be pipelined, for
638 less memory consumption and better cache performance, but we do them
639 separately for simplicity.*/
640 /*First do horizontal filtering (convert to 422jpeg)*/
641 for (y
= 0; y
< c_h
; y
++) {
642 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
643 4-tap Mitchell window.*/
644 for (x
= 0; x
< OC_MINI(c_w
, 1); x
++) {
645 tmp
[x
<< 1] = (unsigned char)OC_CLAMPI(
647 (111 * _aux
[0] + 18 * _aux
[OC_MINI(1, c_w
- 1)] -
648 _aux
[OC_MINI(2, c_w
- 1)] + 64) >>
651 tmp
[x
<< 1 | 1] = (unsigned char)OC_CLAMPI(
653 (47 * _aux
[0] + 86 * _aux
[OC_MINI(1, c_w
- 1)] -
654 5 * _aux
[OC_MINI(2, c_w
- 1)] + 64) >>
658 for (; x
< c_w
- 2; x
++) {
660 (unsigned char)OC_CLAMPI(0,
661 (_aux
[x
- 1] + 110 * _aux
[x
] +
662 18 * _aux
[x
+ 1] - _aux
[x
+ 2] + 64) >>
665 tmp
[x
<< 1 | 1] = (unsigned char)OC_CLAMPI(
667 (-3 * _aux
[x
- 1] + 50 * _aux
[x
] + 86 * _aux
[x
+ 1] -
668 5 * _aux
[x
+ 2] + 64) >>
672 for (; x
< c_w
; x
++) {
673 tmp
[x
<< 1] = (unsigned char)OC_CLAMPI(
675 (_aux
[x
- 1] + 110 * _aux
[x
] + 18 * _aux
[OC_MINI(x
+ 1, c_w
- 1)] -
676 _aux
[c_w
- 1] + 64) >>
679 if ((x
<< 1 | 1) < dst_c_w
) {
680 tmp
[x
<< 1 | 1] = (unsigned char)OC_CLAMPI(
682 (-3 * _aux
[x
- 1] + 50 * _aux
[x
] +
683 86 * _aux
[OC_MINI(x
+ 1, c_w
- 1)] - 5 * _aux
[c_w
- 1] + 64) >>
692 /*Now do the vertical filtering.*/
693 y4m_422jpeg_420jpeg_helper(_dst
, tmp
, dst_c_w
, c_h
);
698 /*Convert 444 to 420jpeg.*/
699 static void y4m_convert_444_420jpeg(y4m_input
*_y4m
, unsigned char *_dst
,
700 unsigned char *_aux
) {
712 /*Skip past the luma data.*/
713 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
714 /*Compute the size of each chroma plane.*/
715 c_w
= (_y4m
->pic_w
+ _y4m
->src_c_dec_h
- 1) / _y4m
->src_c_dec_h
;
717 dst_c_w
= (_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
718 dst_c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
720 dst_c_sz
= dst_c_w
* dst_c_h
;
721 tmp_sz
= dst_c_w
* c_h
;
722 tmp
= _aux
+ 2 * c_sz
;
723 for (pli
= 1; pli
< 3; pli
++) {
724 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
725 for (y
= 0; y
< c_h
; y
++) {
726 for (x
= 0; x
< OC_MINI(c_w
, 2); x
+= 2) {
727 tmp
[x
>> 1] = OC_CLAMPI(0,
728 (64 * _aux
[0] + 78 * _aux
[OC_MINI(1, c_w
- 1)] -
729 17 * _aux
[OC_MINI(2, c_w
- 1)] +
730 3 * _aux
[OC_MINI(3, c_w
- 1)] + 64) >>
734 for (; x
< c_w
- 3; x
+= 2) {
735 tmp
[x
>> 1] = OC_CLAMPI(0,
736 (3 * (_aux
[x
- 2] + _aux
[x
+ 3]) -
737 17 * (_aux
[x
- 1] + _aux
[x
+ 2]) +
738 78 * (_aux
[x
] + _aux
[x
+ 1]) + 64) >>
742 for (; x
< c_w
; x
+= 2) {
745 (3 * (_aux
[x
- 2] + _aux
[c_w
- 1]) -
746 17 * (_aux
[x
- 1] + _aux
[OC_MINI(x
+ 2, c_w
- 1)]) +
747 78 * (_aux
[x
] + _aux
[OC_MINI(x
+ 1, c_w
- 1)]) + 64) >>
755 /*Now do the vertical filtering.*/
756 y4m_422jpeg_420jpeg_helper(_dst
, tmp
, dst_c_w
, c_h
);
761 /*The image is padded with empty chroma components at 4:2:0.*/
762 static void y4m_convert_mono_420jpeg(y4m_input
*_y4m
, unsigned char *_dst
,
763 unsigned char *_aux
) {
766 _dst
+= _y4m
->pic_w
* _y4m
->pic_h
;
767 c_sz
= ((_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
) *
768 ((_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
);
769 memset(_dst
, 128, c_sz
* 2);
772 /*No conversion function needed.*/
773 static void y4m_convert_null(y4m_input
*_y4m
, unsigned char *_dst
,
774 unsigned char *_aux
) {
780 int y4m_input_open(y4m_input
*_y4m
, FILE *_fin
, char *_skip
, int _nskip
,
782 char buffer
[80] = { 0 };
785 /*Read until newline, or 80 cols, whichever happens first.*/
786 for (i
= 0; i
< 79; i
++) {
788 buffer
[i
] = *_skip
++;
791 if (!file_read(buffer
+ i
, 1, _fin
)) return -1;
793 if (buffer
[i
] == '\n') break;
795 /*We skipped too much header data.*/
796 if (_nskip
> 0) return -1;
798 fprintf(stderr
, "Error parsing header; not a YUV2MPEG2 file?\n");
802 if (memcmp(buffer
, "YUV4MPEG", 8)) {
803 fprintf(stderr
, "Incomplete magic for YUV4MPEG file.\n");
806 if (buffer
[8] != '2') {
807 fprintf(stderr
, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
809 ret
= y4m_parse_tags(_y4m
, buffer
+ 5);
811 fprintf(stderr
, "Error parsing YUV4MPEG2 header.\n");
814 if (_y4m
->interlace
== '?') {
816 "Warning: Input video interlacing format unknown; "
817 "assuming progressive scan.\n");
818 } else if (_y4m
->interlace
!= 'p') {
820 "Input video is interlaced; "
821 "Only progressive scan handled.\n");
824 _y4m
->aom_fmt
= AOM_IMG_FMT_I420
;
827 if (strcmp(_y4m
->chroma_type
, "420") == 0 ||
828 strcmp(_y4m
->chroma_type
, "420jpeg") == 0) {
829 _y4m
->src_c_dec_h
= _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_v
=
830 _y4m
->dst_c_dec_v
= 2;
831 _y4m
->dst_buf_read_sz
=
832 _y4m
->pic_w
* _y4m
->pic_h
+
833 2 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2);
834 /* Natively supported: no conversion required. */
835 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
836 _y4m
->convert
= y4m_convert_null
;
837 } else if (strcmp(_y4m
->chroma_type
, "420p10") == 0) {
838 _y4m
->src_c_dec_h
= 2;
839 _y4m
->dst_c_dec_h
= 2;
840 _y4m
->src_c_dec_v
= 2;
841 _y4m
->dst_c_dec_v
= 2;
842 _y4m
->dst_buf_read_sz
=
843 2 * (_y4m
->pic_w
* _y4m
->pic_h
+
844 2 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2));
845 /* Natively supported: no conversion required. */
846 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
847 _y4m
->convert
= y4m_convert_null
;
848 _y4m
->bit_depth
= 10;
850 _y4m
->aom_fmt
= AOM_IMG_FMT_I42016
;
852 fprintf(stderr
, "Unsupported conversion from 420p10 to 420jpeg\n");
855 } else if (strcmp(_y4m
->chroma_type
, "420p12") == 0) {
856 _y4m
->src_c_dec_h
= 2;
857 _y4m
->dst_c_dec_h
= 2;
858 _y4m
->src_c_dec_v
= 2;
859 _y4m
->dst_c_dec_v
= 2;
860 _y4m
->dst_buf_read_sz
=
861 2 * (_y4m
->pic_w
* _y4m
->pic_h
+
862 2 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2));
863 /* Natively supported: no conversion required. */
864 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
865 _y4m
->convert
= y4m_convert_null
;
866 _y4m
->bit_depth
= 12;
868 _y4m
->aom_fmt
= AOM_IMG_FMT_I42016
;
870 fprintf(stderr
, "Unsupported conversion from 420p12 to 420jpeg\n");
873 } else if (strcmp(_y4m
->chroma_type
, "420mpeg2") == 0) {
874 _y4m
->src_c_dec_h
= _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_v
=
875 _y4m
->dst_c_dec_v
= 2;
876 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
877 /*Chroma filter required: read into the aux buf first.*/
878 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
=
879 2 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2);
880 _y4m
->convert
= y4m_convert_42xmpeg2_42xjpeg
;
881 } else if (strcmp(_y4m
->chroma_type
, "420paldv") == 0) {
882 _y4m
->src_c_dec_h
= _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_v
=
883 _y4m
->dst_c_dec_v
= 2;
884 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
885 /*Chroma filter required: read into the aux buf first.
886 We need to make two filter passes, so we need some extra space in the
888 _y4m
->aux_buf_sz
= 3 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2);
889 _y4m
->aux_buf_read_sz
=
890 2 * ((_y4m
->pic_w
+ 1) / 2) * ((_y4m
->pic_h
+ 1) / 2);
891 _y4m
->convert
= y4m_convert_42xpaldv_42xjpeg
;
892 } else if (strcmp(_y4m
->chroma_type
, "422jpeg") == 0) {
893 _y4m
->src_c_dec_h
= _y4m
->dst_c_dec_h
= 2;
894 _y4m
->src_c_dec_v
= 1;
895 _y4m
->dst_c_dec_v
= 2;
896 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
897 /*Chroma filter required: read into the aux buf first.*/
898 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
=
899 2 * ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
900 _y4m
->convert
= y4m_convert_422jpeg_420jpeg
;
901 } else if (strcmp(_y4m
->chroma_type
, "422") == 0) {
902 _y4m
->src_c_dec_h
= 2;
903 _y4m
->src_c_dec_v
= 1;
905 _y4m
->dst_c_dec_h
= 2;
906 _y4m
->dst_c_dec_v
= 2;
907 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
908 /*Chroma filter required: read into the aux buf first.
909 We need to make two filter passes, so we need some extra space in the
911 _y4m
->aux_buf_read_sz
= 2 * ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
913 _y4m
->aux_buf_read_sz
+ ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
914 _y4m
->convert
= y4m_convert_422_420jpeg
;
916 _y4m
->aom_fmt
= AOM_IMG_FMT_I422
;
918 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
919 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
920 _y4m
->dst_buf_read_sz
=
921 _y4m
->pic_w
* _y4m
->pic_h
+ 2 * ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
922 /*Natively supported: no conversion required.*/
923 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
924 _y4m
->convert
= y4m_convert_null
;
926 } else if (strcmp(_y4m
->chroma_type
, "422p10") == 0) {
927 _y4m
->src_c_dec_h
= 2;
928 _y4m
->src_c_dec_v
= 1;
929 _y4m
->aom_fmt
= AOM_IMG_FMT_I42216
;
931 _y4m
->bit_depth
= 10;
932 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
933 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
934 _y4m
->dst_buf_read_sz
= 2 * (_y4m
->pic_w
* _y4m
->pic_h
+
935 2 * ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
);
936 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
937 _y4m
->convert
= y4m_convert_null
;
939 fprintf(stderr
, "Unsupported conversion from 422p10 to 420jpeg\n");
942 } else if (strcmp(_y4m
->chroma_type
, "422p12") == 0) {
943 _y4m
->src_c_dec_h
= 2;
944 _y4m
->src_c_dec_v
= 1;
945 _y4m
->aom_fmt
= AOM_IMG_FMT_I42216
;
947 _y4m
->bit_depth
= 12;
948 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
949 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
950 _y4m
->dst_buf_read_sz
= 2 * (_y4m
->pic_w
* _y4m
->pic_h
+
951 2 * ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
);
952 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
953 _y4m
->convert
= y4m_convert_null
;
955 fprintf(stderr
, "Unsupported conversion from 422p12 to 420jpeg\n");
958 } else if (strcmp(_y4m
->chroma_type
, "411") == 0) {
959 _y4m
->src_c_dec_h
= 4;
960 _y4m
->dst_c_dec_h
= 2;
961 _y4m
->src_c_dec_v
= 1;
962 _y4m
->dst_c_dec_v
= 2;
963 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
964 /*Chroma filter required: read into the aux buf first.
965 We need to make two filter passes, so we need some extra space in the
967 _y4m
->aux_buf_read_sz
= 2 * ((_y4m
->pic_w
+ 3) / 4) * _y4m
->pic_h
;
969 _y4m
->aux_buf_read_sz
+ ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
970 _y4m
->convert
= y4m_convert_411_420jpeg
;
971 } else if (strcmp(_y4m
->chroma_type
, "444") == 0) {
972 _y4m
->src_c_dec_h
= 1;
973 _y4m
->src_c_dec_v
= 1;
975 _y4m
->dst_c_dec_h
= 2;
976 _y4m
->dst_c_dec_v
= 2;
977 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
978 /*Chroma filter required: read into the aux buf first.
979 We need to make two filter passes, so we need some extra space in the
981 _y4m
->aux_buf_read_sz
= 2 * _y4m
->pic_w
* _y4m
->pic_h
;
983 _y4m
->aux_buf_read_sz
+ ((_y4m
->pic_w
+ 1) / 2) * _y4m
->pic_h
;
984 _y4m
->convert
= y4m_convert_444_420jpeg
;
986 _y4m
->aom_fmt
= AOM_IMG_FMT_I444
;
988 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
989 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
990 _y4m
->dst_buf_read_sz
= 3 * _y4m
->pic_w
* _y4m
->pic_h
;
991 /*Natively supported: no conversion required.*/
992 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
993 _y4m
->convert
= y4m_convert_null
;
995 } else if (strcmp(_y4m
->chroma_type
, "444p10") == 0) {
996 _y4m
->src_c_dec_h
= 1;
997 _y4m
->src_c_dec_v
= 1;
998 _y4m
->aom_fmt
= AOM_IMG_FMT_I44416
;
1000 _y4m
->bit_depth
= 10;
1001 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
1002 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
1003 _y4m
->dst_buf_read_sz
= 2 * 3 * _y4m
->pic_w
* _y4m
->pic_h
;
1004 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
1005 _y4m
->convert
= y4m_convert_null
;
1007 fprintf(stderr
, "Unsupported conversion from 444p10 to 420jpeg\n");
1010 } else if (strcmp(_y4m
->chroma_type
, "444p12") == 0) {
1011 _y4m
->src_c_dec_h
= 1;
1012 _y4m
->src_c_dec_v
= 1;
1013 _y4m
->aom_fmt
= AOM_IMG_FMT_I44416
;
1015 _y4m
->bit_depth
= 12;
1016 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
1017 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
1018 _y4m
->dst_buf_read_sz
= 2 * 3 * _y4m
->pic_w
* _y4m
->pic_h
;
1019 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
1020 _y4m
->convert
= y4m_convert_null
;
1022 fprintf(stderr
, "Unsupported conversion from 444p12 to 420jpeg\n");
1025 } else if (strcmp(_y4m
->chroma_type
, "444alpha") == 0) {
1026 _y4m
->src_c_dec_h
= 1;
1027 _y4m
->src_c_dec_v
= 1;
1029 _y4m
->dst_c_dec_h
= 2;
1030 _y4m
->dst_c_dec_v
= 2;
1031 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
1032 /*Chroma filter required: read into the aux buf first.
1033 We need to make two filter passes, so we need some extra space in the
1035 The extra plane also gets read into the aux buf.
1036 It will be discarded.*/
1037 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 3 * _y4m
->pic_w
* _y4m
->pic_h
;
1038 _y4m
->convert
= y4m_convert_444_420jpeg
;
1040 _y4m
->aom_fmt
= AOM_IMG_FMT_444A
;
1042 _y4m
->dst_c_dec_h
= _y4m
->src_c_dec_h
;
1043 _y4m
->dst_c_dec_v
= _y4m
->src_c_dec_v
;
1044 _y4m
->dst_buf_read_sz
= 4 * _y4m
->pic_w
* _y4m
->pic_h
;
1045 /*Natively supported: no conversion required.*/
1046 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
1047 _y4m
->convert
= y4m_convert_null
;
1049 } else if (strcmp(_y4m
->chroma_type
, "mono") == 0) {
1050 _y4m
->src_c_dec_h
= _y4m
->src_c_dec_v
= 0;
1051 _y4m
->dst_c_dec_h
= _y4m
->dst_c_dec_v
= 2;
1052 _y4m
->dst_buf_read_sz
= _y4m
->pic_w
* _y4m
->pic_h
;
1053 /*No extra space required, but we need to clear the chroma planes.*/
1054 _y4m
->aux_buf_sz
= _y4m
->aux_buf_read_sz
= 0;
1055 _y4m
->convert
= y4m_convert_mono_420jpeg
;
1057 fprintf(stderr
, "Unknown chroma sampling type: %s\n", _y4m
->chroma_type
);
1060 /*The size of the final frame buffers is always computed from the
1061 destination chroma decimation type.*/
1063 _y4m
->pic_w
* _y4m
->pic_h
+
1064 2 * ((_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
) *
1065 ((_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
);
1066 if (_y4m
->bit_depth
== 8)
1067 _y4m
->dst_buf
= (unsigned char *)malloc(_y4m
->dst_buf_sz
);
1069 _y4m
->dst_buf
= (unsigned char *)malloc(2 * _y4m
->dst_buf_sz
);
1071 if (_y4m
->aux_buf_sz
> 0)
1072 _y4m
->aux_buf
= (unsigned char *)malloc(_y4m
->aux_buf_sz
);
1076 void y4m_input_close(y4m_input
*_y4m
) {
1077 free(_y4m
->dst_buf
);
1078 free(_y4m
->aux_buf
);
1081 int y4m_input_fetch_frame(y4m_input
*_y4m
, FILE *_fin
, aom_image_t
*_img
) {
1087 int bytes_per_sample
= _y4m
->bit_depth
> 8 ? 2 : 1;
1088 /*Read and skip the frame header.*/
1089 if (!file_read(frame
, 6, _fin
)) return 0;
1090 if (memcmp(frame
, "FRAME", 5)) {
1091 fprintf(stderr
, "Loss of framing in Y4M input data\n");
1094 if (frame
[5] != '\n') {
1097 for (j
= 0; j
< 79 && file_read(&c
, 1, _fin
) && c
!= '\n'; j
++) {
1100 fprintf(stderr
, "Error parsing Y4M frame header\n");
1104 /*Read the frame data that needs no conversion.*/
1105 if (!file_read(_y4m
->dst_buf
, _y4m
->dst_buf_read_sz
, _fin
)) {
1106 fprintf(stderr
, "Error reading Y4M frame data.\n");
1109 /*Read the frame data that does need conversion.*/
1110 if (!file_read(_y4m
->aux_buf
, _y4m
->aux_buf_read_sz
, _fin
)) {
1111 fprintf(stderr
, "Error reading Y4M frame data.\n");
1114 /*Now convert the just read frame.*/
1115 (*_y4m
->convert
)(_y4m
, _y4m
->dst_buf
, _y4m
->aux_buf
);
1116 /*Fill in the frame buffer pointers.
1117 We don't use aom_img_wrap() because it forces padding for odd picture
1118 sizes, which would require a separate fread call for every row.*/
1119 memset(_img
, 0, sizeof(*_img
));
1120 /*Y4M has the planes in Y'CbCr order, which libaom calls Y, U, and V.*/
1121 _img
->fmt
= _y4m
->aom_fmt
;
1122 _img
->w
= _img
->d_w
= _y4m
->pic_w
;
1123 _img
->h
= _img
->d_h
= _y4m
->pic_h
;
1124 _img
->x_chroma_shift
= _y4m
->dst_c_dec_h
>> 1;
1125 _img
->y_chroma_shift
= _y4m
->dst_c_dec_v
>> 1;
1126 _img
->bps
= _y4m
->bps
;
1128 /*Set up the buffer pointers.*/
1129 pic_sz
= _y4m
->pic_w
* _y4m
->pic_h
* bytes_per_sample
;
1130 c_w
= (_y4m
->pic_w
+ _y4m
->dst_c_dec_h
- 1) / _y4m
->dst_c_dec_h
;
1131 c_w
*= bytes_per_sample
;
1132 c_h
= (_y4m
->pic_h
+ _y4m
->dst_c_dec_v
- 1) / _y4m
->dst_c_dec_v
;
1134 _img
->stride
[AOM_PLANE_Y
] = _img
->stride
[AOM_PLANE_ALPHA
] =
1135 _y4m
->pic_w
* bytes_per_sample
;
1136 _img
->stride
[AOM_PLANE_U
] = _img
->stride
[AOM_PLANE_V
] = c_w
;
1137 _img
->planes
[AOM_PLANE_Y
] = _y4m
->dst_buf
;
1138 _img
->planes
[AOM_PLANE_U
] = _y4m
->dst_buf
+ pic_sz
;
1139 _img
->planes
[AOM_PLANE_V
] = _y4m
->dst_buf
+ pic_sz
+ c_sz
;
1140 _img
->planes
[AOM_PLANE_ALPHA
] = _y4m
->dst_buf
+ pic_sz
+ 2 * c_sz
;