2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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.
10 * Based on code from the OggTheora software codec source code,
11 * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
17 #include "vpx/vpx_integer.h"
20 // Reads 'size' bytes from 'file' into 'buf' with some fault tolerance.
21 // Returns true on success.
22 static int file_read(void *buf, size_t size, FILE *file) {
23 const int kMaxRetries = 5;
28 const size_t n = fread((uint8_t *)buf + len, 1, size - len, file);
30 file_error = ferror(file);
32 if (errno == EINTR || errno == EAGAIN) {
36 fprintf(stderr, "Error reading file: %u of %u bytes read, %d: %s\n",
37 (uint32_t)len, (uint32_t)size, errno, strerror(errno));
41 } while (!feof(file) && len < size && ++retry_count < kMaxRetries);
43 if (!feof(file) && len != size) {
45 "Error reading file: %u of %u bytes read,"
46 " error: %d, retries: %d, %d: %s\n",
47 (uint32_t)len, (uint32_t)size, file_error, retry_count, errno,
53 static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
62 got_w = got_h = got_fps = got_interlace = got_par = got_chroma = 0;
63 for (p = _tags;; p = q) {
64 /*Skip any leading spaces.*/
65 while (*p == ' ') p++;
66 /*If that's all we have, stop.*/
67 if (p[0] == '\0') break;
68 /*Find the end of this tag.*/
69 for (q = p + 1; *q != '\0' && *q != ' '; q++)
74 if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
78 if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
82 if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
88 _y4m->interlace = p[1];
92 if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
98 if (q - p > 16) return -1;
99 memcpy(_y4m->chroma_type, p + 1, q - p - 1);
100 _y4m->chroma_type[q - p - 1] = '\0';
103 /*Ignore unknown tags.*/
106 if (!got_w || !got_h || !got_fps) return -1;
107 if (!got_interlace) _y4m->interlace = '?';
108 if (!got_par) _y4m->par_n = _y4m->par_d = 0;
109 /*Chroma-type is not specified in older files, e.g., those generated by
111 if (!got_chroma) strcpy(_y4m->chroma_type, "420");
115 /*All anti-aliasing filters in the following conversion functions are based on
116 one of two window functions:
117 The 6-tap Lanczos window (for down-sampling and shifts):
118 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
120 The 4-tap Mitchell window (for up-sampling):
121 7|t|^3-12|t|^2+16/3, |t|<1
122 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
124 The number of taps is intentionally kept small to reduce computational
125 overhead and limit ringing.
127 The taps from these filters are scaled so that their sum is 1, and the result
128 is scaled by 128 and rounded to integers to create a filter whose
129 intermediate values fit inside 16 bits.
130 Coefficients are rounded in such a way as to ensure their sum is still 128,
131 which is usually equivalent to normal rounding.
133 Conversions which require both horizontal and vertical filtering could
134 have these steps pipelined, for less memory consumption and better cache
135 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(
192 0, (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
193 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
194 9 * _src[OC_MINI(x + 2, _c_w - 1)] +
195 _src[OC_MINI(x + 3, _c_w - 1)] + 64) >>
199 for (; x < _c_w - 3; x++) {
200 _dst[x] = (unsigned char)OC_CLAMPI(
201 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
202 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
206 for (; x < _c_w; x++) {
207 _dst[x] = (unsigned char)OC_CLAMPI(
208 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
209 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
210 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
219 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
220 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
221 unsigned char *_aux) {
226 /*Skip past the luma data.*/
227 _dst += _y4m->pic_w * _y4m->pic_h;
228 /*Compute the size of each chroma plane.*/
229 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
230 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
232 for (pli = 1; pli < 3; pli++) {
233 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
239 /*This format is only used for interlaced content, but is included for
242 420jpeg chroma samples are sited like:
243 Y-------Y-------Y-------Y-------
247 Y-------Y-------Y-------Y-------
251 Y-------Y-------Y-------Y-------
255 Y-------Y-------Y-------Y-------
260 420paldv chroma samples are sited like:
261 YR------Y-------YR------Y-------
265 YB------Y-------YB------Y-------
269 YR------Y-------YR------Y-------
273 YB------Y-------YB------Y-------
278 We use a resampling filter to shift the site locations one quarter pixel (at
279 the chroma plane's resolution) to the right.
280 Then we use another filter to move the C_r location down one quarter pixel,
281 and the C_b location up one quarter pixel.*/
282 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
283 unsigned char *_aux) {
291 /*Skip past the luma data.*/
292 _dst += _y4m->pic_w * _y4m->pic_h;
293 /*Compute the size of each chroma plane.*/
294 c_w = (_y4m->pic_w + 1) / 2;
295 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
297 tmp = _aux + 2 * c_sz;
298 for (pli = 1; pli < 3; pli++) {
299 /*First do the horizontal re-sampling.
300 This is the same as the mpeg2 case, except that after the horizontal
301 case, we need to apply a second vertical filter.*/
302 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
306 /*Slide C_b up a quarter-pel.
307 This is the same filter used above, but in the other order.*/
308 for (x = 0; x < c_w; x++) {
309 for (y = 0; y < OC_MINI(c_h, 3); y++) {
310 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
311 0, (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
312 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
313 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
314 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
318 for (; y < c_h - 2; y++) {
319 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
320 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
321 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
322 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
326 for (; y < c_h; y++) {
327 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
328 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
329 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
330 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
331 4 * tmp[(c_h - 1) * c_w] + 64) >>
342 /*Slide C_r down a quarter-pel.
343 This is the same as the horizontal filter.*/
344 for (x = 0; x < c_w; x++) {
345 for (y = 0; y < OC_MINI(c_h, 2); y++) {
346 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
348 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
349 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
350 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
351 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
355 for (; y < c_h - 3; y++) {
356 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
357 0, (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
358 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
359 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
363 for (; y < c_h; y++) {
364 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
366 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
367 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
368 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
378 /*For actual interlaced material, this would have to be done separately on
379 each field, and the shift amounts would be different.
380 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
381 C_b up 1/8 in the bottom field.
382 The corresponding filters would be:
383 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
384 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
388 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
389 This is used as a helper by several converation routines.*/
390 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
391 const unsigned char *_src, int _c_w,
395 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
396 for (x = 0; x < _c_w; x++) {
397 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
398 _dst[(y >> 1) * _c_w] =
399 OC_CLAMPI(0, (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
400 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
401 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
405 for (; y < _c_h - 3; y += 2) {
406 _dst[(y >> 1) * _c_w] =
407 OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
408 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
409 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
413 for (; y < _c_h; y += 2) {
414 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
416 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
417 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
418 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
428 /*420jpeg chroma samples are sited like:
429 Y-------Y-------Y-------Y-------
433 Y-------Y-------Y-------Y-------
437 Y-------Y-------Y-------Y-------
441 Y-------Y-------Y-------Y-------
446 422jpeg chroma samples are sited like:
447 Y---BR--Y-------Y---BR--Y-------
451 Y---BR--Y-------Y---BR--Y-------
455 Y---BR--Y-------Y---BR--Y-------
459 Y---BR--Y-------Y---BR--Y-------
464 We use a resampling filter to decimate the chroma planes by two in the
465 vertical direction.*/
466 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
467 unsigned char *_aux) {
475 /*Skip past the luma data.*/
476 _dst += _y4m->pic_w * _y4m->pic_h;
477 /*Compute the size of each chroma plane.*/
478 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
480 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
481 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
483 dst_c_sz = dst_c_w * dst_c_h;
484 for (pli = 1; pli < 3; pli++) {
485 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
491 /*420jpeg chroma samples are sited like:
492 Y-------Y-------Y-------Y-------
496 Y-------Y-------Y-------Y-------
500 Y-------Y-------Y-------Y-------
504 Y-------Y-------Y-------Y-------
509 422 chroma samples are sited like:
510 YBR-----Y-------YBR-----Y-------
514 YBR-----Y-------YBR-----Y-------
518 YBR-----Y-------YBR-----Y-------
522 YBR-----Y-------YBR-----Y-------
527 We use a resampling filter to shift the original site locations one quarter
528 pixel (at the original chroma resolution) to the right.
529 Then we use a second resampling filter to decimate the chroma planes by two
530 in the vertical direction.*/
531 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
532 unsigned char *_aux) {
540 /*Skip past the luma data.*/
541 _dst += _y4m->pic_w * _y4m->pic_h;
542 /*Compute the size of each chroma plane.*/
543 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
545 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
547 dst_c_sz = c_w * dst_c_h;
548 tmp = _aux + 2 * c_sz;
549 for (pli = 1; pli < 3; pli++) {
550 /*In reality, the horizontal and vertical steps could be pipelined, for
551 less memory consumption and better cache performance, but we do them
552 separately for simplicity.*/
553 /*First do horizontal filtering (convert to 422jpeg)*/
554 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
555 /*Now do the vertical filtering.*/
556 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
562 /*420jpeg chroma samples are sited like:
563 Y-------Y-------Y-------Y-------
567 Y-------Y-------Y-------Y-------
571 Y-------Y-------Y-------Y-------
575 Y-------Y-------Y-------Y-------
580 411 chroma samples are sited like:
581 YBR-----Y-------Y-------Y-------
585 YBR-----Y-------Y-------Y-------
589 YBR-----Y-------Y-------Y-------
593 YBR-----Y-------Y-------Y-------
598 We use a filter to resample at site locations one eighth pixel (at the source
599 chroma plane's horizontal resolution) and five eighths of a pixel to the
601 Then we use another filter to decimate the planes by 2 in the vertical
603 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
604 unsigned char *_aux) {
616 /*Skip past the luma data.*/
617 _dst += _y4m->pic_w * _y4m->pic_h;
618 /*Compute the size of each chroma plane.*/
619 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
621 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
622 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
624 dst_c_sz = dst_c_w * dst_c_h;
625 tmp_sz = dst_c_w * c_h;
626 tmp = _aux + 2 * c_sz;
627 for (pli = 1; pli < 3; pli++) {
628 /*In reality, the horizontal and vertical steps could be pipelined, for
629 less memory consumption and better cache performance, but we do them
630 separately for simplicity.*/
631 /*First do horizontal filtering (convert to 422jpeg)*/
632 for (y = 0; y < c_h; y++) {
633 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
634 4-tap Mitchell window.*/
635 for (x = 0; x < OC_MINI(c_w, 1); x++) {
636 tmp[x << 1] = (unsigned char)OC_CLAMPI(
637 0, (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
638 _aux[OC_MINI(2, c_w - 1)] + 64) >>
641 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
642 0, (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
643 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
647 for (; x < c_w - 2; x++) {
649 (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] +
650 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
653 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
654 0, (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
655 5 * _aux[x + 2] + 64) >>
659 for (; x < c_w; x++) {
660 tmp[x << 1] = (unsigned char)OC_CLAMPI(
661 0, (_aux[x - 1] + 110 * _aux[x] +
662 18 * _aux[OC_MINI(x + 1, c_w - 1)] - _aux[c_w - 1] + 64) >>
665 if ((x << 1 | 1) < dst_c_w) {
666 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
668 (-3 * _aux[x - 1] + 50 * _aux[x] +
669 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
678 /*Now do the vertical filtering.*/
679 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
684 /*Convert 444 to 420jpeg.*/
685 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
686 unsigned char *_aux) {
698 /*Skip past the luma data.*/
699 _dst += _y4m->pic_w * _y4m->pic_h;
700 /*Compute the size of each chroma plane.*/
701 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
703 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
704 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
706 dst_c_sz = dst_c_w * dst_c_h;
707 tmp_sz = dst_c_w * c_h;
708 tmp = _aux + 2 * c_sz;
709 for (pli = 1; pli < 3; pli++) {
710 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
711 for (y = 0; y < c_h; y++) {
712 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
714 OC_CLAMPI(0, (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
715 17 * _aux[OC_MINI(2, c_w - 1)] +
716 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
720 for (; x < c_w - 3; x += 2) {
721 tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[x + 3]) -
722 17 * (_aux[x - 1] + _aux[x + 2]) +
723 78 * (_aux[x] + _aux[x + 1]) + 64) >>
727 for (; x < c_w; x += 2) {
728 tmp[x >> 1] = OC_CLAMPI(
729 0, (3 * (_aux[x - 2] + _aux[c_w - 1]) -
730 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
731 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
739 /*Now do the vertical filtering.*/
740 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
745 /*The image is padded with empty chroma components at 4:2:0.*/
746 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
747 unsigned char *_aux) {
750 _dst += _y4m->pic_w * _y4m->pic_h;
751 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
752 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
753 memset(_dst, 128, c_sz * 2);
756 /*No conversion function needed.*/
757 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
758 unsigned char *_aux) {
764 int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
766 char buffer[80] = { 0 };
769 /*Read until newline, or 80 cols, whichever happens first.*/
770 for (i = 0; i < 79; i++) {
772 buffer[i] = *_skip++;
775 if (!file_read(buffer + i, 1, _fin)) return -1;
777 if (buffer[i] == '\n') break;
779 /*We skipped too much header data.*/
780 if (_nskip > 0) return -1;
782 fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
786 if (memcmp(buffer, "YUV4MPEG", 8)) {
787 fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
790 if (buffer[8] != '2') {
791 fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
793 ret = y4m_parse_tags(_y4m, buffer + 5);
795 fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
798 if (_y4m->interlace == '?') {
800 "Warning: Input video interlacing format unknown; "
801 "assuming progressive scan.\n");
802 } else if (_y4m->interlace != 'p') {
804 "Input video is interlaced; "
805 "Only progressive scan handled.\n");
808 _y4m->vpx_fmt = VPX_IMG_FMT_I420;
811 if (strcmp(_y4m->chroma_type, "420") == 0 ||
812 strcmp(_y4m->chroma_type, "420jpeg") == 0) {
813 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
814 _y4m->dst_c_dec_v = 2;
815 _y4m->dst_buf_read_sz =
816 _y4m->pic_w * _y4m->pic_h +
817 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
818 /* Natively supported: no conversion required. */
819 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
820 _y4m->convert = y4m_convert_null;
821 } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
822 _y4m->src_c_dec_h = 2;
823 _y4m->dst_c_dec_h = 2;
824 _y4m->src_c_dec_v = 2;
825 _y4m->dst_c_dec_v = 2;
826 _y4m->dst_buf_read_sz =
827 2 * (_y4m->pic_w * _y4m->pic_h +
828 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
829 /* Natively supported: no conversion required. */
830 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
831 _y4m->convert = y4m_convert_null;
832 _y4m->bit_depth = 10;
834 _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
836 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
839 } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
840 _y4m->src_c_dec_h = 2;
841 _y4m->dst_c_dec_h = 2;
842 _y4m->src_c_dec_v = 2;
843 _y4m->dst_c_dec_v = 2;
844 _y4m->dst_buf_read_sz =
845 2 * (_y4m->pic_w * _y4m->pic_h +
846 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
847 /* Natively supported: no conversion required. */
848 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
849 _y4m->convert = y4m_convert_null;
850 _y4m->bit_depth = 12;
852 _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
854 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
857 } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
858 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
859 _y4m->dst_c_dec_v = 2;
860 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
861 /*Chroma filter required: read into the aux buf first.*/
862 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
863 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
864 _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
865 } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
866 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
867 _y4m->dst_c_dec_v = 2;
868 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
869 /*Chroma filter required: read into the aux buf first.
870 We need to make two filter passes, so we need some extra space in the
872 _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
873 _y4m->aux_buf_read_sz =
874 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
875 _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
876 } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
877 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
878 _y4m->src_c_dec_v = 1;
879 _y4m->dst_c_dec_v = 2;
880 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
881 /*Chroma filter required: read into the aux buf first.*/
882 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
883 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
884 _y4m->convert = y4m_convert_422jpeg_420jpeg;
885 } else if (strcmp(_y4m->chroma_type, "422") == 0) {
886 _y4m->src_c_dec_h = 2;
887 _y4m->src_c_dec_v = 1;
889 _y4m->dst_c_dec_h = 2;
890 _y4m->dst_c_dec_v = 2;
891 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
892 /*Chroma filter required: read into the aux buf first.
893 We need to make two filter passes, so we need some extra space in the
895 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
897 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
898 _y4m->convert = y4m_convert_422_420jpeg;
900 _y4m->vpx_fmt = VPX_IMG_FMT_I422;
902 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
903 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
904 _y4m->dst_buf_read_sz =
905 _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
906 /*Natively supported: no conversion required.*/
907 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
908 _y4m->convert = y4m_convert_null;
910 } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
911 _y4m->src_c_dec_h = 2;
912 _y4m->src_c_dec_v = 1;
913 _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
915 _y4m->bit_depth = 10;
916 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
917 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
918 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
919 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
920 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
921 _y4m->convert = y4m_convert_null;
923 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
926 } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
927 _y4m->src_c_dec_h = 2;
928 _y4m->src_c_dec_v = 1;
929 _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
931 _y4m->bit_depth = 12;
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 422p12 to 420jpeg\n");
942 } else if (strcmp(_y4m->chroma_type, "411") == 0) {
943 _y4m->src_c_dec_h = 4;
944 _y4m->dst_c_dec_h = 2;
945 _y4m->src_c_dec_v = 1;
946 _y4m->dst_c_dec_v = 2;
947 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
948 /*Chroma filter required: read into the aux buf first.
949 We need to make two filter passes, so we need some extra space in the
951 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
953 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
954 _y4m->convert = y4m_convert_411_420jpeg;
955 } else if (strcmp(_y4m->chroma_type, "444") == 0) {
956 _y4m->src_c_dec_h = 1;
957 _y4m->src_c_dec_v = 1;
959 _y4m->dst_c_dec_h = 2;
960 _y4m->dst_c_dec_v = 2;
961 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
962 /*Chroma filter required: read into the aux buf first.
963 We need to make two filter passes, so we need some extra space in the
965 _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
967 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
968 _y4m->convert = y4m_convert_444_420jpeg;
970 _y4m->vpx_fmt = VPX_IMG_FMT_I444;
972 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
973 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
974 _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
975 /*Natively supported: no conversion required.*/
976 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
977 _y4m->convert = y4m_convert_null;
979 } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
980 _y4m->src_c_dec_h = 1;
981 _y4m->src_c_dec_v = 1;
982 _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
984 _y4m->bit_depth = 10;
985 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
986 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
987 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
988 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
989 _y4m->convert = y4m_convert_null;
991 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
994 } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
995 _y4m->src_c_dec_h = 1;
996 _y4m->src_c_dec_v = 1;
997 _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
999 _y4m->bit_depth = 12;
1000 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1001 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1002 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1003 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1004 _y4m->convert = y4m_convert_null;
1006 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1009 } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1010 _y4m->src_c_dec_h = 1;
1011 _y4m->src_c_dec_v = 1;
1013 _y4m->dst_c_dec_h = 2;
1014 _y4m->dst_c_dec_v = 2;
1015 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1016 /*Chroma filter required: read into the aux buf first.
1017 We need to make two filter passes, so we need some extra space in the
1019 The extra plane also gets read into the aux buf.
1020 It will be discarded.*/
1021 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1022 _y4m->convert = y4m_convert_444_420jpeg;
1024 _y4m->vpx_fmt = VPX_IMG_FMT_444A;
1026 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1027 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1028 _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1029 /*Natively supported: no conversion required.*/
1030 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1031 _y4m->convert = y4m_convert_null;
1033 } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1034 _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1035 _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1036 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1037 /*No extra space required, but we need to clear the chroma planes.*/
1038 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1039 _y4m->convert = y4m_convert_mono_420jpeg;
1041 fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
1044 /*The size of the final frame buffers is always computed from the
1045 destination chroma decimation type.*/
1047 _y4m->pic_w * _y4m->pic_h +
1048 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1049 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
1050 if (_y4m->bit_depth == 8)
1051 _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
1053 _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
1055 if (_y4m->aux_buf_sz > 0)
1056 _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
1060 void y4m_input_close(y4m_input *_y4m) {
1061 free(_y4m->dst_buf);
1062 free(_y4m->aux_buf);
1065 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1071 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1072 /*Read and skip the frame header.*/
1073 if (!file_read(frame, 6, _fin)) return 0;
1074 if (memcmp(frame, "FRAME", 5)) {
1075 fprintf(stderr, "Loss of framing in Y4M input data\n");
1078 if (frame[5] != '\n') {
1081 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1084 fprintf(stderr, "Error parsing Y4M frame header\n");
1088 /*Read the frame data that needs no conversion.*/
1089 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1090 fprintf(stderr, "Error reading Y4M frame data.\n");
1093 /*Read the frame data that does need conversion.*/
1094 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1095 fprintf(stderr, "Error reading Y4M frame data.\n");
1098 /*Now convert the just read frame.*/
1099 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1100 /*Fill in the frame buffer pointers.
1101 We don't use vpx_img_wrap() because it forces padding for odd picture
1102 sizes, which would require a separate fread call for every row.*/
1103 memset(_img, 0, sizeof(*_img));
1104 /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1105 _img->fmt = _y4m->vpx_fmt;
1106 _img->w = _img->d_w = _y4m->pic_w;
1107 _img->h = _img->d_h = _y4m->pic_h;
1108 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1109 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1110 _img->bps = _y4m->bps;
1112 /*Set up the buffer pointers.*/
1113 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1114 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1115 c_w *= bytes_per_sample;
1116 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1118 _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1119 _y4m->pic_w * bytes_per_sample;
1120 _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1121 _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1122 _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1123 _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1124 _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;