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;
79 if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
84 if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
91 _y4m->interlace = p[1];
96 if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
103 if (q - p > 16) return -1;
104 memcpy(_y4m->chroma_type, p + 1, q - p - 1);
105 _y4m->chroma_type[q - p - 1] = '\0';
109 /*Ignore unknown tags.*/
112 if (!got_w || !got_h || !got_fps) return -1;
113 if (!got_interlace) _y4m->interlace = '?';
114 if (!got_par) _y4m->par_n = _y4m->par_d = 0;
115 /*Chroma-type is not specified in older files, e.g., those generated by
117 if (!got_chroma) strcpy(_y4m->chroma_type, "420");
121 /*All anti-aliasing filters in the following conversion functions are based on
122 one of two window functions:
123 The 6-tap Lanczos window (for down-sampling and shifts):
124 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
126 The 4-tap Mitchell window (for up-sampling):
127 7|t|^3-12|t|^2+16/3, |t|<1
128 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
130 The number of taps is intentionally kept small to reduce computational
131 overhead and limit ringing.
133 The taps from these filters are scaled so that their sum is 1, and the
134 result is scaled by 128 and rounded to integers to create a filter whose
135 intermediate values fit inside 16 bits.
136 Coefficients are rounded in such a way as to ensure their sum is still 128,
137 which is usually equivalent to normal rounding.
139 Conversions which require both horizontal and vertical filtering could
140 have these steps pipelined, for less memory consumption and better cache
141 performance, but we do them separately for simplicity.*/
142 #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
143 #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
144 #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
146 /*420jpeg chroma samples are sited like:
147 Y-------Y-------Y-------Y-------
151 Y-------Y-------Y-------Y-------
155 Y-------Y-------Y-------Y-------
159 Y-------Y-------Y-------Y-------
164 420mpeg2 chroma samples are sited like:
165 Y-------Y-------Y-------Y-------
169 Y-------Y-------Y-------Y-------
173 Y-------Y-------Y-------Y-------
177 Y-------Y-------Y-------Y-------
182 We use a resampling filter to shift the site locations one quarter pixel (at
183 the chroma plane's resolution) to the right.
184 The 4:2:2 modes look exactly the same, except there are twice as many chroma
185 lines, and they are vertically co-sited with the luma samples in both the
186 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
187 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
188 const unsigned char *_src, int _c_w,
192 for (y = 0; y < _c_h; y++) {
193 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
195 for (x = 0; x < OC_MINI(_c_w, 2); x++) {
196 _dst[x] = (unsigned char)OC_CLAMPI(
198 (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
199 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
200 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[OC_MINI(x + 3, _c_w - 1)] +
205 for (; x < _c_w - 3; x++) {
206 _dst[x] = (unsigned char)OC_CLAMPI(
208 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
209 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
213 for (; x < _c_w; x++) {
214 _dst[x] = (unsigned char)OC_CLAMPI(
216 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
217 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
218 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
227 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
228 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
229 unsigned char *_aux) {
234 /*Skip past the luma data.*/
235 _dst += _y4m->pic_w * _y4m->pic_h;
236 /*Compute the size of each chroma plane.*/
237 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
238 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
240 for (pli = 1; pli < 3; pli++) {
241 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
247 /*This format is only used for interlaced content, but is included for
250 420jpeg chroma samples are sited like:
251 Y-------Y-------Y-------Y-------
255 Y-------Y-------Y-------Y-------
259 Y-------Y-------Y-------Y-------
263 Y-------Y-------Y-------Y-------
268 420paldv chroma samples are sited like:
269 YR------Y-------YR------Y-------
273 YB------Y-------YB------Y-------
277 YR------Y-------YR------Y-------
281 YB------Y-------YB------Y-------
286 We use a resampling filter to shift the site locations one quarter pixel (at
287 the chroma plane's resolution) to the right.
288 Then we use another filter to move the C_r location down one quarter pixel,
289 and the C_b location up one quarter pixel.*/
290 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
291 unsigned char *_aux) {
299 /*Skip past the luma data.*/
300 _dst += _y4m->pic_w * _y4m->pic_h;
301 /*Compute the size of each chroma plane.*/
302 c_w = (_y4m->pic_w + 1) / 2;
303 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
305 tmp = _aux + 2 * c_sz;
306 for (pli = 1; pli < 3; pli++) {
307 /*First do the horizontal re-sampling.
308 This is the same as the mpeg2 case, except that after the horizontal
309 case, we need to apply a second vertical filter.*/
310 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
314 /*Slide C_b up a quarter-pel.
315 This is the same filter used above, but in the other order.*/
316 for (x = 0; x < c_w; x++) {
317 for (y = 0; y < OC_MINI(c_h, 3); y++) {
318 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
320 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
321 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
322 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
323 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
327 for (; y < c_h - 2; y++) {
328 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
330 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
331 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
332 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
336 for (; y < c_h; y++) {
337 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
339 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
340 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
341 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
342 4 * tmp[(c_h - 1) * c_w] + 64) >>
354 /*Slide C_r down a quarter-pel.
355 This is the same as the horizontal filter.*/
356 for (x = 0; x < c_w; x++) {
357 for (y = 0; y < OC_MINI(c_h, 2); y++) {
358 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
360 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
361 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
362 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
363 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
367 for (; y < c_h - 3; y++) {
368 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
370 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
371 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
372 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
376 for (; y < c_h; y++) {
377 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
379 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
380 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
381 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
392 /*For actual interlaced material, this would have to be done separately on
393 each field, and the shift amounts would be different.
394 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
395 C_b up 1/8 in the bottom field.
396 The corresponding filters would be:
397 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
398 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
402 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
403 This is used as a helper by several converation routines.*/
404 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
405 const unsigned char *_src, int _c_w,
409 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
410 for (x = 0; x < _c_w; x++) {
411 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
412 _dst[(y >> 1) * _c_w] =
414 (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
415 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
416 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
420 for (; y < _c_h - 3; y += 2) {
421 _dst[(y >> 1) * _c_w] =
423 (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
424 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
425 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
429 for (; y < _c_h; y += 2) {
430 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
432 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
433 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
434 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
444 /*420jpeg chroma samples are sited like:
445 Y-------Y-------Y-------Y-------
449 Y-------Y-------Y-------Y-------
453 Y-------Y-------Y-------Y-------
457 Y-------Y-------Y-------Y-------
462 422jpeg chroma samples are sited like:
463 Y---BR--Y-------Y---BR--Y-------
467 Y---BR--Y-------Y---BR--Y-------
471 Y---BR--Y-------Y---BR--Y-------
475 Y---BR--Y-------Y---BR--Y-------
480 We use a resampling filter to decimate the chroma planes by two in the
481 vertical direction.*/
482 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
483 unsigned char *_aux) {
491 /*Skip past the luma data.*/
492 _dst += _y4m->pic_w * _y4m->pic_h;
493 /*Compute the size of each chroma plane.*/
494 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
496 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
497 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
499 dst_c_sz = dst_c_w * dst_c_h;
500 for (pli = 1; pli < 3; pli++) {
501 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
507 /*420jpeg chroma samples are sited like:
508 Y-------Y-------Y-------Y-------
512 Y-------Y-------Y-------Y-------
516 Y-------Y-------Y-------Y-------
520 Y-------Y-------Y-------Y-------
525 422 chroma samples are sited like:
526 YBR-----Y-------YBR-----Y-------
530 YBR-----Y-------YBR-----Y-------
534 YBR-----Y-------YBR-----Y-------
538 YBR-----Y-------YBR-----Y-------
543 We use a resampling filter to shift the original site locations one quarter
544 pixel (at the original chroma resolution) to the right.
545 Then we use a second resampling filter to decimate the chroma planes by two
546 in the vertical direction.*/
547 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
548 unsigned char *_aux) {
556 /*Skip past the luma data.*/
557 _dst += _y4m->pic_w * _y4m->pic_h;
558 /*Compute the size of each chroma plane.*/
559 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
561 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
563 dst_c_sz = c_w * dst_c_h;
564 tmp = _aux + 2 * c_sz;
565 for (pli = 1; pli < 3; pli++) {
566 /*In reality, the horizontal and vertical steps could be pipelined, for
567 less memory consumption and better cache performance, but we do them
568 separately for simplicity.*/
569 /*First do horizontal filtering (convert to 422jpeg)*/
570 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
571 /*Now do the vertical filtering.*/
572 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
578 /*420jpeg chroma samples are sited like:
579 Y-------Y-------Y-------Y-------
583 Y-------Y-------Y-------Y-------
587 Y-------Y-------Y-------Y-------
591 Y-------Y-------Y-------Y-------
596 411 chroma samples are sited like:
597 YBR-----Y-------Y-------Y-------
601 YBR-----Y-------Y-------Y-------
605 YBR-----Y-------Y-------Y-------
609 YBR-----Y-------Y-------Y-------
614 We use a filter to resample at site locations one eighth pixel (at the source
615 chroma plane's horizontal resolution) and five eighths of a pixel to the
617 Then we use another filter to decimate the planes by 2 in the vertical
619 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
620 unsigned char *_aux) {
632 /*Skip past the luma data.*/
633 _dst += _y4m->pic_w * _y4m->pic_h;
634 /*Compute the size of each chroma plane.*/
635 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
637 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
638 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
640 dst_c_sz = dst_c_w * dst_c_h;
641 tmp_sz = dst_c_w * c_h;
642 tmp = _aux + 2 * c_sz;
643 for (pli = 1; pli < 3; pli++) {
644 /*In reality, the horizontal and vertical steps could be pipelined, for
645 less memory consumption and better cache performance, but we do them
646 separately for simplicity.*/
647 /*First do horizontal filtering (convert to 422jpeg)*/
648 for (y = 0; y < c_h; y++) {
649 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
650 4-tap Mitchell window.*/
651 for (x = 0; x < OC_MINI(c_w, 1); x++) {
652 tmp[x << 1] = (unsigned char)OC_CLAMPI(
654 (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
655 _aux[OC_MINI(2, c_w - 1)] + 64) >>
658 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
660 (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
661 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
665 for (; x < c_w - 2; x++) {
667 (unsigned char)OC_CLAMPI(0,
668 (_aux[x - 1] + 110 * _aux[x] +
669 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
672 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
674 (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
675 5 * _aux[x + 2] + 64) >>
679 for (; x < c_w; x++) {
680 tmp[x << 1] = (unsigned char)OC_CLAMPI(
682 (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
683 _aux[c_w - 1] + 64) >>
686 if ((x << 1 | 1) < dst_c_w) {
687 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
689 (-3 * _aux[x - 1] + 50 * _aux[x] +
690 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
699 /*Now do the vertical filtering.*/
700 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
705 /*Convert 444 to 420jpeg.*/
706 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
707 unsigned char *_aux) {
719 /*Skip past the luma data.*/
720 _dst += _y4m->pic_w * _y4m->pic_h;
721 /*Compute the size of each chroma plane.*/
722 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
724 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
725 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
727 dst_c_sz = dst_c_w * dst_c_h;
728 tmp_sz = dst_c_w * c_h;
729 tmp = _aux + 2 * c_sz;
730 for (pli = 1; pli < 3; pli++) {
731 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
732 for (y = 0; y < c_h; y++) {
733 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
734 tmp[x >> 1] = OC_CLAMPI(0,
735 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
736 17 * _aux[OC_MINI(2, c_w - 1)] +
737 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
741 for (; x < c_w - 3; x += 2) {
742 tmp[x >> 1] = OC_CLAMPI(0,
743 (3 * (_aux[x - 2] + _aux[x + 3]) -
744 17 * (_aux[x - 1] + _aux[x + 2]) +
745 78 * (_aux[x] + _aux[x + 1]) + 64) >>
749 for (; x < c_w; x += 2) {
752 (3 * (_aux[x - 2] + _aux[c_w - 1]) -
753 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
754 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
762 /*Now do the vertical filtering.*/
763 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
768 /*The image is padded with empty chroma components at 4:2:0.*/
769 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
770 unsigned char *_aux) {
773 _dst += _y4m->pic_w * _y4m->pic_h;
774 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
775 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
776 memset(_dst, 128, c_sz * 2);
779 /*No conversion function needed.*/
780 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
781 unsigned char *_aux) {
787 int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
789 char buffer[80] = { 0 };
792 /*Read until newline, or 80 cols, whichever happens first.*/
793 for (i = 0; i < 79; i++) {
795 buffer[i] = *_skip++;
798 if (!file_read(buffer + i, 1, _fin)) return -1;
800 if (buffer[i] == '\n') break;
802 /*We skipped too much header data.*/
803 if (_nskip > 0) return -1;
805 fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
809 if (memcmp(buffer, "YUV4MPEG", 8)) {
810 fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
813 if (buffer[8] != '2') {
814 fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
816 ret = y4m_parse_tags(_y4m, buffer + 5);
818 fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
821 if (_y4m->interlace == '?') {
823 "Warning: Input video interlacing format unknown; "
824 "assuming progressive scan.\n");
825 } else if (_y4m->interlace != 'p') {
827 "Input video is interlaced; "
828 "Only progressive scan handled.\n");
831 _y4m->vpx_fmt = VPX_IMG_FMT_I420;
834 if (strcmp(_y4m->chroma_type, "420") == 0 ||
835 strcmp(_y4m->chroma_type, "420jpeg") == 0) {
836 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
837 _y4m->dst_c_dec_v = 2;
838 _y4m->dst_buf_read_sz =
839 _y4m->pic_w * _y4m->pic_h +
840 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
841 /* Natively supported: no conversion required. */
842 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
843 _y4m->convert = y4m_convert_null;
844 } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
845 _y4m->src_c_dec_h = 2;
846 _y4m->dst_c_dec_h = 2;
847 _y4m->src_c_dec_v = 2;
848 _y4m->dst_c_dec_v = 2;
849 _y4m->dst_buf_read_sz =
850 2 * (_y4m->pic_w * _y4m->pic_h +
851 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
852 /* Natively supported: no conversion required. */
853 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
854 _y4m->convert = y4m_convert_null;
855 _y4m->bit_depth = 10;
857 _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
859 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
862 } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
863 _y4m->src_c_dec_h = 2;
864 _y4m->dst_c_dec_h = 2;
865 _y4m->src_c_dec_v = 2;
866 _y4m->dst_c_dec_v = 2;
867 _y4m->dst_buf_read_sz =
868 2 * (_y4m->pic_w * _y4m->pic_h +
869 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
870 /* Natively supported: no conversion required. */
871 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
872 _y4m->convert = y4m_convert_null;
873 _y4m->bit_depth = 12;
875 _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
877 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
880 } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
881 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
882 _y4m->dst_c_dec_v = 2;
883 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
884 /*Chroma filter required: read into the aux buf first.*/
885 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
886 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
887 _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
888 } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
889 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
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_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
896 _y4m->aux_buf_read_sz =
897 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
898 _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
899 } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
900 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
901 _y4m->src_c_dec_v = 1;
902 _y4m->dst_c_dec_v = 2;
903 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
904 /*Chroma filter required: read into the aux buf first.*/
905 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
906 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
907 _y4m->convert = y4m_convert_422jpeg_420jpeg;
908 } else if (strcmp(_y4m->chroma_type, "422") == 0) {
909 _y4m->src_c_dec_h = 2;
910 _y4m->src_c_dec_v = 1;
912 _y4m->dst_c_dec_h = 2;
913 _y4m->dst_c_dec_v = 2;
914 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
915 /*Chroma filter required: read into the aux buf first.
916 We need to make two filter passes, so we need some extra space in the
918 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
920 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
921 _y4m->convert = y4m_convert_422_420jpeg;
923 _y4m->vpx_fmt = VPX_IMG_FMT_I422;
925 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
926 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
927 _y4m->dst_buf_read_sz =
928 _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
929 /*Natively supported: no conversion required.*/
930 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
931 _y4m->convert = y4m_convert_null;
933 } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
934 _y4m->src_c_dec_h = 2;
935 _y4m->src_c_dec_v = 1;
936 _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
938 _y4m->bit_depth = 10;
939 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
940 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
941 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
942 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
943 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
944 _y4m->convert = y4m_convert_null;
946 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
949 } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
950 _y4m->src_c_dec_h = 2;
951 _y4m->src_c_dec_v = 1;
952 _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
954 _y4m->bit_depth = 12;
955 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
956 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
957 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
958 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
959 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
960 _y4m->convert = y4m_convert_null;
962 fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
965 } else if (strcmp(_y4m->chroma_type, "411") == 0) {
966 _y4m->src_c_dec_h = 4;
967 _y4m->dst_c_dec_h = 2;
968 _y4m->src_c_dec_v = 1;
969 _y4m->dst_c_dec_v = 2;
970 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
971 /*Chroma filter required: read into the aux buf first.
972 We need to make two filter passes, so we need some extra space in the
974 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
976 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
977 _y4m->convert = y4m_convert_411_420jpeg;
978 fprintf(stderr, "Unsupported conversion from yuv 411\n");
980 } else if (strcmp(_y4m->chroma_type, "444") == 0) {
981 _y4m->src_c_dec_h = 1;
982 _y4m->src_c_dec_v = 1;
984 _y4m->dst_c_dec_h = 2;
985 _y4m->dst_c_dec_v = 2;
986 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
987 /*Chroma filter required: read into the aux buf first.
988 We need to make two filter passes, so we need some extra space in the
990 _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
992 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
993 _y4m->convert = y4m_convert_444_420jpeg;
995 _y4m->vpx_fmt = VPX_IMG_FMT_I444;
997 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
998 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
999 _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1000 /*Natively supported: no conversion required.*/
1001 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1002 _y4m->convert = y4m_convert_null;
1004 } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
1005 _y4m->src_c_dec_h = 1;
1006 _y4m->src_c_dec_v = 1;
1007 _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
1009 _y4m->bit_depth = 10;
1010 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1011 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1012 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1013 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1014 _y4m->convert = y4m_convert_null;
1016 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1019 } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
1020 _y4m->src_c_dec_h = 1;
1021 _y4m->src_c_dec_v = 1;
1022 _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
1024 _y4m->bit_depth = 12;
1025 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1026 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1027 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1028 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1029 _y4m->convert = y4m_convert_null;
1031 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1034 } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1035 _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1036 _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1037 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1038 /*No extra space required, but we need to clear the chroma planes.*/
1039 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1040 _y4m->convert = y4m_convert_mono_420jpeg;
1042 fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
1045 /*The size of the final frame buffers is always computed from the
1046 destination chroma decimation type.*/
1048 _y4m->pic_w * _y4m->pic_h +
1049 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1050 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
1051 if (_y4m->bit_depth == 8)
1052 _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
1054 _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
1056 if (_y4m->aux_buf_sz > 0)
1057 _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
1061 void y4m_input_close(y4m_input *_y4m) {
1062 free(_y4m->dst_buf);
1063 free(_y4m->aux_buf);
1066 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1072 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1073 /*Read and skip the frame header.*/
1074 if (!file_read(frame, 6, _fin)) return 0;
1075 if (memcmp(frame, "FRAME", 5)) {
1076 fprintf(stderr, "Loss of framing in Y4M input data\n");
1079 if (frame[5] != '\n') {
1082 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1085 fprintf(stderr, "Error parsing Y4M frame header\n");
1089 /*Read the frame data that needs no conversion.*/
1090 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1091 fprintf(stderr, "Error reading Y4M frame data.\n");
1094 /*Read the frame data that does need conversion.*/
1095 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1096 fprintf(stderr, "Error reading Y4M frame data.\n");
1099 /*Now convert the just read frame.*/
1100 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1101 /*Fill in the frame buffer pointers.
1102 We don't use vpx_img_wrap() because it forces padding for odd picture
1103 sizes, which would require a separate fread call for every row.*/
1104 memset(_img, 0, sizeof(*_img));
1105 /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1106 _img->fmt = _y4m->vpx_fmt;
1107 _img->w = _img->d_w = _y4m->pic_w;
1108 _img->h = _img->d_h = _y4m->pic_h;
1109 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1110 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1111 _img->bps = _y4m->bps;
1113 /*Set up the buffer pointers.*/
1114 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1115 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1116 c_w *= bytes_per_sample;
1117 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1119 _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1120 _y4m->pic_w * bytes_per_sample;
1121 _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1122 _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1123 _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1124 _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1125 _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;