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.
18 #include "vpx/vpx_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) {
57 for (p = _tags;; p = q) {
58 /*Skip any leading spaces.*/
59 while (*p == ' ') p++;
60 /*If that's all we have, stop.*/
61 if (p[0] == '\0') break;
62 /*Find the end of this tag.*/
63 for (q = p + 1; *q != '\0' && *q != ' '; q++) {
68 if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
72 if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
76 if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
82 _y4m->interlace = p[1];
86 if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
92 if (q - p > 16) return -1;
93 memcpy(_y4m->chroma_type, p + 1, q - p - 1);
94 _y4m->chroma_type[q - p - 1] = '\0';
97 /*Ignore unknown tags.*/
103 /* Returns 1 if tags were parsed successfully, 0 otherwise. */
104 static int parse_tags(y4m_input *y4m_ctx, char *buffer) {
105 /* Set Y4M tags to defaults, updating them as processing occurs. Mandatory
106 fields are marked with -1 and will be checked after the tags are parsed. */
110 y4m_ctx->fps_n = -1; /* Also serves as marker for fps_d */
113 y4m_ctx->interlace = '?';
114 snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");
116 ret = y4m_parse_tags(y4m_ctx, buffer);
121 /* Check the mandatory fields. */
122 if (y4m_ctx->pic_w == -1) {
123 fprintf(stderr, "Width field missing\n");
126 if (y4m_ctx->pic_h == -1) {
127 fprintf(stderr, "Height field missing\n");
130 if (y4m_ctx->fps_n == -1) {
131 fprintf(stderr, "FPS field missing\n");
137 /*All anti-aliasing filters in the following conversion functions are based on
138 one of two window functions:
139 The 6-tap Lanczos window (for down-sampling and shifts):
140 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
142 The 4-tap Mitchell window (for up-sampling):
143 7|t|^3-12|t|^2+16/3, |t|<1
144 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
146 The number of taps is intentionally kept small to reduce computational
147 overhead and limit ringing.
149 The taps from these filters are scaled so that their sum is 1, and the
150 result is scaled by 128 and rounded to integers to create a filter whose
151 intermediate values fit inside 16 bits.
152 Coefficients are rounded in such a way as to ensure their sum is still 128,
153 which is usually equivalent to normal rounding.
155 Conversions which require both horizontal and vertical filtering could
156 have these steps pipelined, for less memory consumption and better cache
157 performance, but we do them separately for simplicity.*/
158 #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
159 #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
160 #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
162 /*420jpeg chroma samples are sited like:
163 Y-------Y-------Y-------Y-------
167 Y-------Y-------Y-------Y-------
171 Y-------Y-------Y-------Y-------
175 Y-------Y-------Y-------Y-------
180 420mpeg2 chroma samples are sited like:
181 Y-------Y-------Y-------Y-------
185 Y-------Y-------Y-------Y-------
189 Y-------Y-------Y-------Y-------
193 Y-------Y-------Y-------Y-------
198 We use a resampling filter to shift the site locations one quarter pixel (at
199 the chroma plane's resolution) to the right.
200 The 4:2:2 modes look exactly the same, except there are twice as many chroma
201 lines, and they are vertically co-sited with the luma samples in both the
202 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
203 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
204 const unsigned char *_src, int _c_w,
208 for (y = 0; y < _c_h; y++) {
209 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
211 for (x = 0; x < OC_MINI(_c_w, 2); x++) {
212 _dst[x] = (unsigned char)OC_CLAMPI(
214 (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
215 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
216 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[OC_MINI(x + 3, _c_w - 1)] +
221 for (; x < _c_w - 3; x++) {
222 _dst[x] = (unsigned char)OC_CLAMPI(
224 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
225 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
229 for (; x < _c_w; x++) {
230 _dst[x] = (unsigned char)OC_CLAMPI(
232 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
233 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
234 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
243 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
244 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
245 unsigned char *_aux) {
250 /*Skip past the luma data.*/
251 _dst += _y4m->pic_w * _y4m->pic_h;
252 /*Compute the size of each chroma plane.*/
253 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
254 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
256 for (pli = 1; pli < 3; pli++) {
257 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
263 /*This format is only used for interlaced content, but is included for
266 420jpeg chroma samples are sited like:
267 Y-------Y-------Y-------Y-------
271 Y-------Y-------Y-------Y-------
275 Y-------Y-------Y-------Y-------
279 Y-------Y-------Y-------Y-------
284 420paldv chroma samples are sited like:
285 YR------Y-------YR------Y-------
289 YB------Y-------YB------Y-------
293 YR------Y-------YR------Y-------
297 YB------Y-------YB------Y-------
302 We use a resampling filter to shift the site locations one quarter pixel (at
303 the chroma plane's resolution) to the right.
304 Then we use another filter to move the C_r location down one quarter pixel,
305 and the C_b location up one quarter pixel.*/
306 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
307 unsigned char *_aux) {
315 /*Skip past the luma data.*/
316 _dst += _y4m->pic_w * _y4m->pic_h;
317 /*Compute the size of each chroma plane.*/
318 c_w = (_y4m->pic_w + 1) / 2;
319 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
321 tmp = _aux + 2 * c_sz;
322 for (pli = 1; pli < 3; pli++) {
323 /*First do the horizontal re-sampling.
324 This is the same as the mpeg2 case, except that after the horizontal
325 case, we need to apply a second vertical filter.*/
326 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
330 /*Slide C_b up a quarter-pel.
331 This is the same filter used above, but in the other order.*/
332 for (x = 0; x < c_w; x++) {
333 for (y = 0; y < OC_MINI(c_h, 3); y++) {
334 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
336 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
337 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
338 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
339 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
343 for (; y < c_h - 2; y++) {
344 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
346 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
347 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
348 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
352 for (; y < c_h; y++) {
353 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
355 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
356 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
357 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
358 4 * tmp[(c_h - 1) * c_w] + 64) >>
370 /*Slide C_r down a quarter-pel.
371 This is the same as the horizontal filter.*/
372 for (x = 0; x < c_w; x++) {
373 for (y = 0; y < OC_MINI(c_h, 2); y++) {
374 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
376 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
377 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
378 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
379 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
383 for (; y < c_h - 3; y++) {
384 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
386 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
387 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
388 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
392 for (; y < c_h; y++) {
393 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
395 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
396 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
397 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
408 /*For actual interlaced material, this would have to be done separately on
409 each field, and the shift amounts would be different.
410 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
411 C_b up 1/8 in the bottom field.
412 The corresponding filters would be:
413 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
414 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
418 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
419 This is used as a helper by several converation routines.*/
420 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
421 const unsigned char *_src, int _c_w,
425 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
426 for (x = 0; x < _c_w; x++) {
427 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
428 _dst[(y >> 1) * _c_w] =
430 (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
431 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
432 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
436 for (; y < _c_h - 3; y += 2) {
437 _dst[(y >> 1) * _c_w] =
439 (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
440 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
441 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
445 for (; y < _c_h; y += 2) {
446 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
448 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
449 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
450 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
460 /*420jpeg chroma samples are sited like:
461 Y-------Y-------Y-------Y-------
465 Y-------Y-------Y-------Y-------
469 Y-------Y-------Y-------Y-------
473 Y-------Y-------Y-------Y-------
478 422jpeg chroma samples are sited like:
479 Y---BR--Y-------Y---BR--Y-------
483 Y---BR--Y-------Y---BR--Y-------
487 Y---BR--Y-------Y---BR--Y-------
491 Y---BR--Y-------Y---BR--Y-------
496 We use a resampling filter to decimate the chroma planes by two in the
497 vertical direction.*/
498 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
499 unsigned char *_aux) {
507 /*Skip past the luma data.*/
508 _dst += _y4m->pic_w * _y4m->pic_h;
509 /*Compute the size of each chroma plane.*/
510 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
512 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
513 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
515 dst_c_sz = dst_c_w * dst_c_h;
516 for (pli = 1; pli < 3; pli++) {
517 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
523 /*420jpeg chroma samples are sited like:
524 Y-------Y-------Y-------Y-------
528 Y-------Y-------Y-------Y-------
532 Y-------Y-------Y-------Y-------
536 Y-------Y-------Y-------Y-------
541 422 chroma samples are sited like:
542 YBR-----Y-------YBR-----Y-------
546 YBR-----Y-------YBR-----Y-------
550 YBR-----Y-------YBR-----Y-------
554 YBR-----Y-------YBR-----Y-------
559 We use a resampling filter to shift the original site locations one quarter
560 pixel (at the original chroma resolution) to the right.
561 Then we use a second resampling filter to decimate the chroma planes by two
562 in the vertical direction.*/
563 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
564 unsigned char *_aux) {
572 /*Skip past the luma data.*/
573 _dst += _y4m->pic_w * _y4m->pic_h;
574 /*Compute the size of each chroma plane.*/
575 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
577 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
579 dst_c_sz = c_w * dst_c_h;
580 tmp = _aux + 2 * c_sz;
581 for (pli = 1; pli < 3; pli++) {
582 /*In reality, the horizontal and vertical steps could be pipelined, for
583 less memory consumption and better cache performance, but we do them
584 separately for simplicity.*/
585 /*First do horizontal filtering (convert to 422jpeg)*/
586 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
587 /*Now do the vertical filtering.*/
588 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
594 /*420jpeg chroma samples are sited like:
595 Y-------Y-------Y-------Y-------
599 Y-------Y-------Y-------Y-------
603 Y-------Y-------Y-------Y-------
607 Y-------Y-------Y-------Y-------
612 411 chroma samples are sited like:
613 YBR-----Y-------Y-------Y-------
617 YBR-----Y-------Y-------Y-------
621 YBR-----Y-------Y-------Y-------
625 YBR-----Y-------Y-------Y-------
630 We use a filter to resample at site locations one eighth pixel (at the source
631 chroma plane's horizontal resolution) and five eighths of a pixel to the
633 Then we use another filter to decimate the planes by 2 in the vertical
635 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
636 unsigned char *_aux) {
648 /*Skip past the luma data.*/
649 _dst += _y4m->pic_w * _y4m->pic_h;
650 /*Compute the size of each chroma plane.*/
651 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
653 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
654 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
656 dst_c_sz = dst_c_w * dst_c_h;
657 tmp_sz = dst_c_w * c_h;
658 tmp = _aux + 2 * c_sz;
659 for (pli = 1; pli < 3; pli++) {
660 /*In reality, the horizontal and vertical steps could be pipelined, for
661 less memory consumption and better cache performance, but we do them
662 separately for simplicity.*/
663 /*First do horizontal filtering (convert to 422jpeg)*/
664 for (y = 0; y < c_h; y++) {
665 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
666 4-tap Mitchell window.*/
667 for (x = 0; x < OC_MINI(c_w, 1); x++) {
668 tmp[x << 1] = (unsigned char)OC_CLAMPI(
670 (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
671 _aux[OC_MINI(2, c_w - 1)] + 64) >>
674 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
676 (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
677 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
681 for (; x < c_w - 2; x++) {
683 (unsigned char)OC_CLAMPI(0,
684 (_aux[x - 1] + 110 * _aux[x] +
685 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
688 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
690 (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
691 5 * _aux[x + 2] + 64) >>
695 for (; x < c_w; x++) {
696 tmp[x << 1] = (unsigned char)OC_CLAMPI(
698 (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
699 _aux[c_w - 1] + 64) >>
702 if ((x << 1 | 1) < dst_c_w) {
703 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
705 (-3 * _aux[x - 1] + 50 * _aux[x] +
706 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
715 /*Now do the vertical filtering.*/
716 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
721 /*Convert 444 to 420jpeg.*/
722 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
723 unsigned char *_aux) {
735 /*Skip past the luma data.*/
736 _dst += _y4m->pic_w * _y4m->pic_h;
737 /*Compute the size of each chroma plane.*/
738 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
740 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
741 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
743 dst_c_sz = dst_c_w * dst_c_h;
744 tmp_sz = dst_c_w * c_h;
745 tmp = _aux + 2 * c_sz;
746 for (pli = 1; pli < 3; pli++) {
747 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
748 for (y = 0; y < c_h; y++) {
749 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
750 tmp[x >> 1] = OC_CLAMPI(0,
751 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
752 17 * _aux[OC_MINI(2, c_w - 1)] +
753 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
757 for (; x < c_w - 3; x += 2) {
758 tmp[x >> 1] = OC_CLAMPI(0,
759 (3 * (_aux[x - 2] + _aux[x + 3]) -
760 17 * (_aux[x - 1] + _aux[x + 2]) +
761 78 * (_aux[x] + _aux[x + 1]) + 64) >>
765 for (; x < c_w; x += 2) {
768 (3 * (_aux[x - 2] + _aux[c_w - 1]) -
769 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
770 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
778 /*Now do the vertical filtering.*/
779 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
784 /*The image is padded with empty chroma components at 4:2:0.*/
785 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
786 unsigned char *_aux) {
789 _dst += _y4m->pic_w * _y4m->pic_h;
790 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
791 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
792 memset(_dst, 128, c_sz * 2);
795 /*No conversion function needed.*/
796 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
797 unsigned char *_aux) {
803 static const char TAG[] = "YUV4MPEG2";
804 /* Temporary until arbitrary header parsing submitted. */
805 #define Y4M_HEADER_BUF_SIZE 200
807 int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,
808 int num_skip, int only_420) {
809 // File must start with |TAG|.
810 char tag_buffer[9]; // 9 == strlen(TAG)
811 char buffer[Y4M_HEADER_BUF_SIZE] = { 0 }; // Rest of header.
813 // Read as much as possible from |skip_buffer|, which were characters
814 // that were previously read from the file to do input-type detection.
815 assert(num_skip >= 0 && num_skip <= 8);
817 memcpy(tag_buffer, skip_buffer, num_skip);
819 // Start reading from the file now that the |skip_buffer| is depleted.
820 if (!file_read(tag_buffer + num_skip, 9 - num_skip, file)) {
823 if (memcmp(TAG, tag_buffer, 9) != 0) {
824 fprintf(stderr, "Error parsing header: must start with %s\n", TAG);
827 // Next character must be a space.
828 if (!file_read(buffer, 1, file) || buffer[0] != ' ') {
829 fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);
832 /*Read until newline, or Y4M_HEADER_BUF_SIZE cols, whichever happens first.*/
833 for (i = 0; i < Y4M_HEADER_BUF_SIZE - 1; i++) {
834 if (!file_read(buffer + i, 1, file)) return -1;
835 if (buffer[i] == '\n') break;
837 if (i == Y4M_HEADER_BUF_SIZE - 1) {
838 fprintf(stderr, "Error parsing header; not a %s file?\n", TAG);
842 if (!parse_tags(y4m_ctx, buffer)) {
843 fprintf(stderr, "Error parsing %s header.\n", TAG);
846 if (y4m_ctx->interlace == '?') {
848 "Warning: Input video interlacing format unknown; "
849 "assuming progressive scan.\n");
850 } else if (y4m_ctx->interlace != 'p') {
852 "Input video is interlaced; "
853 "Only progressive scan handled.\n");
856 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I420;
858 y4m_ctx->bit_depth = 8;
859 y4m_ctx->aux_buf = NULL;
860 y4m_ctx->dst_buf = NULL;
861 if (strcmp(y4m_ctx->chroma_type, "420") == 0 ||
862 strcmp(y4m_ctx->chroma_type, "420jpeg") == 0) {
863 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
864 y4m_ctx->dst_c_dec_v = 2;
865 y4m_ctx->dst_buf_read_sz =
866 y4m_ctx->pic_w * y4m_ctx->pic_h +
867 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
868 /* Natively supported: no conversion required. */
869 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
870 y4m_ctx->convert = y4m_convert_null;
871 } else if (strcmp(y4m_ctx->chroma_type, "420p10") == 0) {
872 y4m_ctx->src_c_dec_h = 2;
873 y4m_ctx->dst_c_dec_h = 2;
874 y4m_ctx->src_c_dec_v = 2;
875 y4m_ctx->dst_c_dec_v = 2;
876 y4m_ctx->dst_buf_read_sz =
877 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
878 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
879 /* Natively supported: no conversion required. */
880 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
881 y4m_ctx->convert = y4m_convert_null;
882 y4m_ctx->bit_depth = 10;
884 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
886 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
889 } else if (strcmp(y4m_ctx->chroma_type, "420p12") == 0) {
890 y4m_ctx->src_c_dec_h = 2;
891 y4m_ctx->dst_c_dec_h = 2;
892 y4m_ctx->src_c_dec_v = 2;
893 y4m_ctx->dst_c_dec_v = 2;
894 y4m_ctx->dst_buf_read_sz =
895 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
896 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
897 /* Natively supported: no conversion required. */
898 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
899 y4m_ctx->convert = y4m_convert_null;
900 y4m_ctx->bit_depth = 12;
902 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
904 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
907 } else if (strcmp(y4m_ctx->chroma_type, "420mpeg2") == 0) {
908 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
909 y4m_ctx->dst_c_dec_v = 2;
910 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
911 /*Chroma filter required: read into the aux buf first.*/
912 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz =
913 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
914 y4m_ctx->convert = y4m_convert_42xmpeg2_42xjpeg;
915 } else if (strcmp(y4m_ctx->chroma_type, "420paldv") == 0) {
916 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
917 y4m_ctx->dst_c_dec_v = 2;
918 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
919 /*Chroma filter required: read into the aux buf first.
920 We need to make two filter passes, so we need some extra space in the
922 y4m_ctx->aux_buf_sz =
923 3 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
924 y4m_ctx->aux_buf_read_sz =
925 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
926 y4m_ctx->convert = y4m_convert_42xpaldv_42xjpeg;
927 } else if (strcmp(y4m_ctx->chroma_type, "422jpeg") == 0) {
928 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = 2;
929 y4m_ctx->src_c_dec_v = 1;
930 y4m_ctx->dst_c_dec_v = 2;
931 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
932 /*Chroma filter required: read into the aux buf first.*/
933 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz =
934 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
935 y4m_ctx->convert = y4m_convert_422jpeg_420jpeg;
936 } else if (strcmp(y4m_ctx->chroma_type, "422") == 0) {
937 y4m_ctx->src_c_dec_h = 2;
938 y4m_ctx->src_c_dec_v = 1;
940 y4m_ctx->dst_c_dec_h = 2;
941 y4m_ctx->dst_c_dec_v = 2;
942 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
943 /*Chroma filter required: read into the aux buf first.
944 We need to make two filter passes, so we need some extra space in the
946 y4m_ctx->aux_buf_read_sz =
947 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
948 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
949 ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
950 y4m_ctx->convert = y4m_convert_422_420jpeg;
952 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I422;
954 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
955 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
956 y4m_ctx->dst_buf_read_sz =
957 y4m_ctx->pic_w * y4m_ctx->pic_h +
958 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
959 /*Natively supported: no conversion required.*/
960 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
961 y4m_ctx->convert = y4m_convert_null;
963 } else if (strcmp(y4m_ctx->chroma_type, "422p10") == 0) {
964 y4m_ctx->src_c_dec_h = 2;
965 y4m_ctx->src_c_dec_v = 1;
966 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
968 y4m_ctx->bit_depth = 10;
969 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
970 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
971 y4m_ctx->dst_buf_read_sz =
972 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
973 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
974 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
975 y4m_ctx->convert = y4m_convert_null;
977 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
980 } else if (strcmp(y4m_ctx->chroma_type, "422p12") == 0) {
981 y4m_ctx->src_c_dec_h = 2;
982 y4m_ctx->src_c_dec_v = 1;
983 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
985 y4m_ctx->bit_depth = 12;
986 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
987 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
988 y4m_ctx->dst_buf_read_sz =
989 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
990 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
991 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
992 y4m_ctx->convert = y4m_convert_null;
994 fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
997 } else if (strcmp(y4m_ctx->chroma_type, "411") == 0) {
998 y4m_ctx->src_c_dec_h = 4;
999 y4m_ctx->dst_c_dec_h = 2;
1000 y4m_ctx->src_c_dec_v = 1;
1001 y4m_ctx->dst_c_dec_v = 2;
1002 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1003 /*Chroma filter required: read into the aux buf first.
1004 We need to make two filter passes, so we need some extra space in the
1006 y4m_ctx->aux_buf_read_sz = 2 * ((y4m_ctx->pic_w + 3) / 4) * y4m_ctx->pic_h;
1007 y4m_ctx->aux_buf_sz =
1008 y4m_ctx->aux_buf_read_sz + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1009 y4m_ctx->convert = y4m_convert_411_420jpeg;
1010 fprintf(stderr, "Unsupported conversion from yuv 411\n");
1012 } else if (strcmp(y4m_ctx->chroma_type, "444") == 0) {
1013 y4m_ctx->src_c_dec_h = 1;
1014 y4m_ctx->src_c_dec_v = 1;
1016 y4m_ctx->dst_c_dec_h = 2;
1017 y4m_ctx->dst_c_dec_v = 2;
1018 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1019 /*Chroma filter required: read into the aux buf first.
1020 We need to make two filter passes, so we need some extra space in the
1022 y4m_ctx->aux_buf_read_sz = 2 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1023 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
1024 ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1025 y4m_ctx->convert = y4m_convert_444_420jpeg;
1027 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I444;
1029 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1030 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1031 y4m_ctx->dst_buf_read_sz = 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1032 /*Natively supported: no conversion required.*/
1033 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1034 y4m_ctx->convert = y4m_convert_null;
1036 } else if (strcmp(y4m_ctx->chroma_type, "444p10") == 0) {
1037 y4m_ctx->src_c_dec_h = 1;
1038 y4m_ctx->src_c_dec_v = 1;
1039 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1041 y4m_ctx->bit_depth = 10;
1042 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1043 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1044 y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1045 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1046 y4m_ctx->convert = y4m_convert_null;
1048 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1051 } else if (strcmp(y4m_ctx->chroma_type, "444p12") == 0) {
1052 y4m_ctx->src_c_dec_h = 1;
1053 y4m_ctx->src_c_dec_v = 1;
1054 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1056 y4m_ctx->bit_depth = 12;
1057 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1058 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1059 y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1060 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1061 y4m_ctx->convert = y4m_convert_null;
1063 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1066 } else if (strcmp(y4m_ctx->chroma_type, "mono") == 0) {
1067 y4m_ctx->src_c_dec_h = y4m_ctx->src_c_dec_v = 0;
1068 y4m_ctx->dst_c_dec_h = y4m_ctx->dst_c_dec_v = 2;
1069 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1070 /*No extra space required, but we need to clear the chroma planes.*/
1071 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1072 y4m_ctx->convert = y4m_convert_mono_420jpeg;
1074 fprintf(stderr, "Unknown chroma sampling type: %s\n", y4m_ctx->chroma_type);
1077 /*The size of the final frame buffers is always computed from the
1078 destination chroma decimation type.*/
1079 y4m_ctx->dst_buf_sz =
1080 y4m_ctx->pic_w * y4m_ctx->pic_h +
1081 2 * ((y4m_ctx->pic_w + y4m_ctx->dst_c_dec_h - 1) / y4m_ctx->dst_c_dec_h) *
1082 ((y4m_ctx->pic_h + y4m_ctx->dst_c_dec_v - 1) / y4m_ctx->dst_c_dec_v);
1083 if (y4m_ctx->bit_depth == 8)
1084 y4m_ctx->dst_buf = (unsigned char *)malloc(y4m_ctx->dst_buf_sz);
1086 y4m_ctx->dst_buf = (unsigned char *)malloc(2 * y4m_ctx->dst_buf_sz);
1088 if (y4m_ctx->aux_buf_sz > 0)
1089 y4m_ctx->aux_buf = (unsigned char *)malloc(y4m_ctx->aux_buf_sz);
1093 void y4m_input_close(y4m_input *_y4m) {
1094 free(_y4m->dst_buf);
1095 free(_y4m->aux_buf);
1098 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1104 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1105 /*Read and skip the frame header.*/
1106 if (!file_read(frame, 6, _fin)) return 0;
1107 if (memcmp(frame, "FRAME", 5)) {
1108 fprintf(stderr, "Loss of framing in Y4M input data\n");
1111 if (frame[5] != '\n') {
1114 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1117 fprintf(stderr, "Error parsing Y4M frame header\n");
1121 /*Read the frame data that needs no conversion.*/
1122 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1123 fprintf(stderr, "Error reading Y4M frame data.\n");
1126 /*Read the frame data that does need conversion.*/
1127 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1128 fprintf(stderr, "Error reading Y4M frame data.\n");
1131 /*Now convert the just read frame.*/
1132 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1133 /*Fill in the frame buffer pointers.
1134 We don't use vpx_img_wrap() because it forces padding for odd picture
1135 sizes, which would require a separate fread call for every row.*/
1136 memset(_img, 0, sizeof(*_img));
1137 /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1138 _img->fmt = _y4m->vpx_fmt;
1139 _img->w = _img->d_w = _y4m->pic_w;
1140 _img->h = _img->d_h = _y4m->pic_h;
1141 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1142 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1143 _img->bps = _y4m->bps;
1145 /*Set up the buffer pointers.*/
1146 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1147 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1148 c_w *= bytes_per_sample;
1149 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1151 _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1152 _y4m->pic_w * bytes_per_sample;
1153 _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1154 _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1155 _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1156 _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1157 _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;