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 // Copy a single tag into the buffer, along with a null character.
104 // Returns 0 if any file IO errors occur.
105 static int copy_tag(char *buf, size_t buf_len, char *end_tag, FILE *file) {
107 assert(buf_len >= 1);
108 // Skip leading space characters.
110 if (!file_read(buf, 1, file)) {
113 } while (buf[0] == ' ');
115 // If we hit the newline, treat this as the "empty" tag.
116 if (buf[0] == '\n') {
122 // Copy over characters until a space is hit, or the buffer is exhausted.
123 for (i = 1; i < buf_len; ++i) {
124 if (!file_read(buf + i, 1, file)) {
127 if (buf[i] == ' ' || buf[i] == '\n') {
132 fprintf(stderr, "Error: Y4M header tags must be less than %lu characters\n",
141 /* Returns 1 if tags were parsed successfully, 0 otherwise. */
142 static int parse_tags(y4m_input *y4m_ctx, FILE *file) {
144 char end; /* Character denoting the end of the tag, ' ' or '\n'. */
145 /* Set Y4M tags to defaults, updating them as processing occurs. Mandatory
146 fields are marked with -1 and will be checked after the tags are parsed. */
149 y4m_ctx->fps_n = -1; /* Also serves as marker for fps_d */
152 y4m_ctx->interlace = '?';
153 snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");
155 /* Find one tag at a time. */
157 if (!copy_tag(tag, sizeof(tag), &end, file)) {
160 /* y4m_parse_tags returns 0 on success. */
161 if (y4m_parse_tags(y4m_ctx, tag)) {
164 } while (end != '\n');
166 /* Check the mandatory fields. */
167 if (y4m_ctx->pic_w == -1) {
168 fprintf(stderr, "Width field missing\n");
171 if (y4m_ctx->pic_h == -1) {
172 fprintf(stderr, "Height field missing\n");
175 if (y4m_ctx->fps_n == -1) {
176 fprintf(stderr, "FPS field missing\n");
182 /*All anti-aliasing filters in the following conversion functions are based on
183 one of two window functions:
184 The 6-tap Lanczos window (for down-sampling and shifts):
185 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
187 The 4-tap Mitchell window (for up-sampling):
188 7|t|^3-12|t|^2+16/3, |t|<1
189 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
191 The number of taps is intentionally kept small to reduce computational
192 overhead and limit ringing.
194 The taps from these filters are scaled so that their sum is 1, and the
195 result is scaled by 128 and rounded to integers to create a filter whose
196 intermediate values fit inside 16 bits.
197 Coefficients are rounded in such a way as to ensure their sum is still 128,
198 which is usually equivalent to normal rounding.
200 Conversions which require both horizontal and vertical filtering could
201 have these steps pipelined, for less memory consumption and better cache
202 performance, but we do them separately for simplicity.*/
203 #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
204 #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
205 #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
207 /*420jpeg chroma samples are sited like:
208 Y-------Y-------Y-------Y-------
212 Y-------Y-------Y-------Y-------
216 Y-------Y-------Y-------Y-------
220 Y-------Y-------Y-------Y-------
225 420mpeg2 chroma samples are sited like:
226 Y-------Y-------Y-------Y-------
230 Y-------Y-------Y-------Y-------
234 Y-------Y-------Y-------Y-------
238 Y-------Y-------Y-------Y-------
243 We use a resampling filter to shift the site locations one quarter pixel (at
244 the chroma plane's resolution) to the right.
245 The 4:2:2 modes look exactly the same, except there are twice as many chroma
246 lines, and they are vertically co-sited with the luma samples in both the
247 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
248 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
249 const unsigned char *_src, int _c_w,
253 for (y = 0; y < _c_h; y++) {
254 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
256 for (x = 0; x < OC_MINI(_c_w, 2); x++) {
257 _dst[x] = (unsigned char)OC_CLAMPI(
259 (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
260 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
261 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[OC_MINI(x + 3, _c_w - 1)] +
266 for (; x < _c_w - 3; x++) {
267 _dst[x] = (unsigned char)OC_CLAMPI(
269 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
270 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
274 for (; x < _c_w; x++) {
275 _dst[x] = (unsigned char)OC_CLAMPI(
277 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
278 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
279 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
288 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
289 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
290 unsigned char *_aux) {
295 /*Skip past the luma data.*/
296 _dst += _y4m->pic_w * _y4m->pic_h;
297 /*Compute the size of each chroma plane.*/
298 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
299 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
301 for (pli = 1; pli < 3; pli++) {
302 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
308 /*This format is only used for interlaced content, but is included for
311 420jpeg chroma samples are sited like:
312 Y-------Y-------Y-------Y-------
316 Y-------Y-------Y-------Y-------
320 Y-------Y-------Y-------Y-------
324 Y-------Y-------Y-------Y-------
329 420paldv chroma samples are sited like:
330 YR------Y-------YR------Y-------
334 YB------Y-------YB------Y-------
338 YR------Y-------YR------Y-------
342 YB------Y-------YB------Y-------
347 We use a resampling filter to shift the site locations one quarter pixel (at
348 the chroma plane's resolution) to the right.
349 Then we use another filter to move the C_r location down one quarter pixel,
350 and the C_b location up one quarter pixel.*/
351 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
352 unsigned char *_aux) {
360 /*Skip past the luma data.*/
361 _dst += _y4m->pic_w * _y4m->pic_h;
362 /*Compute the size of each chroma plane.*/
363 c_w = (_y4m->pic_w + 1) / 2;
364 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
366 tmp = _aux + 2 * c_sz;
367 for (pli = 1; pli < 3; pli++) {
368 /*First do the horizontal re-sampling.
369 This is the same as the mpeg2 case, except that after the horizontal
370 case, we need to apply a second vertical filter.*/
371 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
375 /*Slide C_b up a quarter-pel.
376 This is the same filter used above, but in the other order.*/
377 for (x = 0; x < c_w; x++) {
378 for (y = 0; y < OC_MINI(c_h, 3); y++) {
379 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
381 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
382 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
383 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
384 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
388 for (; y < c_h - 2; y++) {
389 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
391 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
392 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
393 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
397 for (; y < c_h; y++) {
398 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
400 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
401 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
402 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
403 4 * tmp[(c_h - 1) * c_w] + 64) >>
415 /*Slide C_r down a quarter-pel.
416 This is the same as the horizontal filter.*/
417 for (x = 0; x < c_w; x++) {
418 for (y = 0; y < OC_MINI(c_h, 2); y++) {
419 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
421 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
422 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
423 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
424 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
428 for (; y < c_h - 3; y++) {
429 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
431 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
432 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
433 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
437 for (; y < c_h; y++) {
438 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
440 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
441 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
442 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
453 /*For actual interlaced material, this would have to be done separately on
454 each field, and the shift amounts would be different.
455 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
456 C_b up 1/8 in the bottom field.
457 The corresponding filters would be:
458 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
459 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
463 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
464 This is used as a helper by several converation routines.*/
465 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
466 const unsigned char *_src, int _c_w,
470 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
471 for (x = 0; x < _c_w; x++) {
472 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
473 _dst[(y >> 1) * _c_w] =
475 (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
476 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
477 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
481 for (; y < _c_h - 3; y += 2) {
482 _dst[(y >> 1) * _c_w] =
484 (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
485 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
486 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
490 for (; y < _c_h; y += 2) {
491 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
493 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
494 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
495 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
505 /*420jpeg chroma samples are sited like:
506 Y-------Y-------Y-------Y-------
510 Y-------Y-------Y-------Y-------
514 Y-------Y-------Y-------Y-------
518 Y-------Y-------Y-------Y-------
523 422jpeg chroma samples are sited like:
524 Y---BR--Y-------Y---BR--Y-------
528 Y---BR--Y-------Y---BR--Y-------
532 Y---BR--Y-------Y---BR--Y-------
536 Y---BR--Y-------Y---BR--Y-------
541 We use a resampling filter to decimate the chroma planes by two in the
542 vertical direction.*/
543 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
544 unsigned char *_aux) {
552 /*Skip past the luma data.*/
553 _dst += _y4m->pic_w * _y4m->pic_h;
554 /*Compute the size of each chroma plane.*/
555 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
557 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
558 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
560 dst_c_sz = dst_c_w * dst_c_h;
561 for (pli = 1; pli < 3; pli++) {
562 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
568 /*420jpeg chroma samples are sited like:
569 Y-------Y-------Y-------Y-------
573 Y-------Y-------Y-------Y-------
577 Y-------Y-------Y-------Y-------
581 Y-------Y-------Y-------Y-------
586 422 chroma samples are sited like:
587 YBR-----Y-------YBR-----Y-------
591 YBR-----Y-------YBR-----Y-------
595 YBR-----Y-------YBR-----Y-------
599 YBR-----Y-------YBR-----Y-------
604 We use a resampling filter to shift the original site locations one quarter
605 pixel (at the original chroma resolution) to the right.
606 Then we use a second resampling filter to decimate the chroma planes by two
607 in the vertical direction.*/
608 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
609 unsigned char *_aux) {
617 /*Skip past the luma data.*/
618 _dst += _y4m->pic_w * _y4m->pic_h;
619 /*Compute the size of each chroma plane.*/
620 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_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 = c_w * dst_c_h;
625 tmp = _aux + 2 * c_sz;
626 for (pli = 1; pli < 3; pli++) {
627 /*In reality, the horizontal and vertical steps could be pipelined, for
628 less memory consumption and better cache performance, but we do them
629 separately for simplicity.*/
630 /*First do horizontal filtering (convert to 422jpeg)*/
631 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
632 /*Now do the vertical filtering.*/
633 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
639 /*420jpeg chroma samples are sited like:
640 Y-------Y-------Y-------Y-------
644 Y-------Y-------Y-------Y-------
648 Y-------Y-------Y-------Y-------
652 Y-------Y-------Y-------Y-------
657 411 chroma samples are sited like:
658 YBR-----Y-------Y-------Y-------
662 YBR-----Y-------Y-------Y-------
666 YBR-----Y-------Y-------Y-------
670 YBR-----Y-------Y-------Y-------
675 We use a filter to resample at site locations one eighth pixel (at the source
676 chroma plane's horizontal resolution) and five eighths of a pixel to the
678 Then we use another filter to decimate the planes by 2 in the vertical
680 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
681 unsigned char *_aux) {
693 /*Skip past the luma data.*/
694 _dst += _y4m->pic_w * _y4m->pic_h;
695 /*Compute the size of each chroma plane.*/
696 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
698 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
699 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
701 dst_c_sz = dst_c_w * dst_c_h;
702 tmp_sz = dst_c_w * c_h;
703 tmp = _aux + 2 * c_sz;
704 for (pli = 1; pli < 3; pli++) {
705 /*In reality, the horizontal and vertical steps could be pipelined, for
706 less memory consumption and better cache performance, but we do them
707 separately for simplicity.*/
708 /*First do horizontal filtering (convert to 422jpeg)*/
709 for (y = 0; y < c_h; y++) {
710 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
711 4-tap Mitchell window.*/
712 for (x = 0; x < OC_MINI(c_w, 1); x++) {
713 tmp[x << 1] = (unsigned char)OC_CLAMPI(
715 (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
716 _aux[OC_MINI(2, c_w - 1)] + 64) >>
719 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
721 (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
722 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
726 for (; x < c_w - 2; x++) {
728 (unsigned char)OC_CLAMPI(0,
729 (_aux[x - 1] + 110 * _aux[x] +
730 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
733 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
735 (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
736 5 * _aux[x + 2] + 64) >>
740 for (; x < c_w; x++) {
741 tmp[x << 1] = (unsigned char)OC_CLAMPI(
743 (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
744 _aux[c_w - 1] + 64) >>
747 if ((x << 1 | 1) < dst_c_w) {
748 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
750 (-3 * _aux[x - 1] + 50 * _aux[x] +
751 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
760 /*Now do the vertical filtering.*/
761 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
766 /*Convert 444 to 420jpeg.*/
767 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
768 unsigned char *_aux) {
780 /*Skip past the luma data.*/
781 _dst += _y4m->pic_w * _y4m->pic_h;
782 /*Compute the size of each chroma plane.*/
783 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
785 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
786 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
788 dst_c_sz = dst_c_w * dst_c_h;
789 tmp_sz = dst_c_w * c_h;
790 tmp = _aux + 2 * c_sz;
791 for (pli = 1; pli < 3; pli++) {
792 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
793 for (y = 0; y < c_h; y++) {
794 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
795 tmp[x >> 1] = OC_CLAMPI(0,
796 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
797 17 * _aux[OC_MINI(2, c_w - 1)] +
798 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
802 for (; x < c_w - 3; x += 2) {
803 tmp[x >> 1] = OC_CLAMPI(0,
804 (3 * (_aux[x - 2] + _aux[x + 3]) -
805 17 * (_aux[x - 1] + _aux[x + 2]) +
806 78 * (_aux[x] + _aux[x + 1]) + 64) >>
810 for (; x < c_w; x += 2) {
813 (3 * (_aux[x - 2] + _aux[c_w - 1]) -
814 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
815 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
823 /*Now do the vertical filtering.*/
824 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
829 /*The image is padded with empty chroma components at 4:2:0.*/
830 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
831 unsigned char *_aux) {
834 _dst += _y4m->pic_w * _y4m->pic_h;
835 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
836 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
837 memset(_dst, 128, c_sz * 2);
840 /*No conversion function needed.*/
841 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
842 unsigned char *_aux) {
848 static const char TAG[] = "YUV4MPEG2";
850 int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,
851 int num_skip, int only_420) {
852 // File must start with |TAG|.
853 char tag_buffer[9]; // 9 == strlen(TAG)
854 // Read as much as possible from |skip_buffer|, which were characters
855 // that were previously read from the file to do input-type detection.
856 assert(num_skip >= 0 && num_skip <= 8);
858 memcpy(tag_buffer, skip_buffer, num_skip);
860 // Start reading from the file now that the |skip_buffer| is depleted.
861 if (!file_read(tag_buffer + num_skip, 9 - num_skip, file)) {
864 if (memcmp(TAG, tag_buffer, 9) != 0) {
865 fprintf(stderr, "Error parsing header: must start with %s\n", TAG);
868 // Next character must be a space.
869 if (!file_read(tag_buffer, 1, file) || tag_buffer[0] != ' ') {
870 fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);
873 if (!parse_tags(y4m_ctx, file)) {
874 fprintf(stderr, "Error parsing %s header.\n", TAG);
876 if (y4m_ctx->interlace == '?') {
878 "Warning: Input video interlacing format unknown; "
879 "assuming progressive scan.\n");
880 } else if (y4m_ctx->interlace != 'p') {
882 "Input video is interlaced; "
883 "Only progressive scan handled.\n");
886 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I420;
888 y4m_ctx->bit_depth = 8;
889 y4m_ctx->aux_buf = NULL;
890 y4m_ctx->dst_buf = NULL;
891 if (strcmp(y4m_ctx->chroma_type, "420") == 0 ||
892 strcmp(y4m_ctx->chroma_type, "420jpeg") == 0) {
893 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
894 y4m_ctx->dst_c_dec_v = 2;
895 y4m_ctx->dst_buf_read_sz =
896 y4m_ctx->pic_w * y4m_ctx->pic_h +
897 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
898 /* Natively supported: no conversion required. */
899 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
900 y4m_ctx->convert = y4m_convert_null;
901 } else if (strcmp(y4m_ctx->chroma_type, "420p10") == 0) {
902 y4m_ctx->src_c_dec_h = 2;
903 y4m_ctx->dst_c_dec_h = 2;
904 y4m_ctx->src_c_dec_v = 2;
905 y4m_ctx->dst_c_dec_v = 2;
906 y4m_ctx->dst_buf_read_sz =
907 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
908 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
909 /* Natively supported: no conversion required. */
910 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
911 y4m_ctx->convert = y4m_convert_null;
912 y4m_ctx->bit_depth = 10;
914 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
916 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
919 } else if (strcmp(y4m_ctx->chroma_type, "420p12") == 0) {
920 y4m_ctx->src_c_dec_h = 2;
921 y4m_ctx->dst_c_dec_h = 2;
922 y4m_ctx->src_c_dec_v = 2;
923 y4m_ctx->dst_c_dec_v = 2;
924 y4m_ctx->dst_buf_read_sz =
925 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
926 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
927 /* Natively supported: no conversion required. */
928 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
929 y4m_ctx->convert = y4m_convert_null;
930 y4m_ctx->bit_depth = 12;
932 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
934 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
937 } else if (strcmp(y4m_ctx->chroma_type, "420mpeg2") == 0) {
938 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
939 y4m_ctx->dst_c_dec_v = 2;
940 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
941 /*Chroma filter required: read into the aux buf first.*/
942 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz =
943 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
944 y4m_ctx->convert = y4m_convert_42xmpeg2_42xjpeg;
945 } else if (strcmp(y4m_ctx->chroma_type, "420paldv") == 0) {
946 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
947 y4m_ctx->dst_c_dec_v = 2;
948 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
949 /*Chroma filter required: read into the aux buf first.
950 We need to make two filter passes, so we need some extra space in the
952 y4m_ctx->aux_buf_sz =
953 3 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
954 y4m_ctx->aux_buf_read_sz =
955 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
956 y4m_ctx->convert = y4m_convert_42xpaldv_42xjpeg;
957 } else if (strcmp(y4m_ctx->chroma_type, "422jpeg") == 0) {
958 y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = 2;
959 y4m_ctx->src_c_dec_v = 1;
960 y4m_ctx->dst_c_dec_v = 2;
961 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
962 /*Chroma filter required: read into the aux buf first.*/
963 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz =
964 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
965 y4m_ctx->convert = y4m_convert_422jpeg_420jpeg;
966 } else if (strcmp(y4m_ctx->chroma_type, "422") == 0) {
967 y4m_ctx->src_c_dec_h = 2;
968 y4m_ctx->src_c_dec_v = 1;
970 y4m_ctx->dst_c_dec_h = 2;
971 y4m_ctx->dst_c_dec_v = 2;
972 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
973 /*Chroma filter required: read into the aux buf first.
974 We need to make two filter passes, so we need some extra space in the
976 y4m_ctx->aux_buf_read_sz =
977 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
978 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
979 ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
980 y4m_ctx->convert = y4m_convert_422_420jpeg;
982 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I422;
984 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
985 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
986 y4m_ctx->dst_buf_read_sz =
987 y4m_ctx->pic_w * y4m_ctx->pic_h +
988 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
989 /*Natively supported: no conversion required.*/
990 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
991 y4m_ctx->convert = y4m_convert_null;
993 } else if (strcmp(y4m_ctx->chroma_type, "422p10") == 0) {
994 y4m_ctx->src_c_dec_h = 2;
995 y4m_ctx->src_c_dec_v = 1;
996 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
998 y4m_ctx->bit_depth = 10;
999 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1000 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1001 y4m_ctx->dst_buf_read_sz =
1002 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
1003 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
1004 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1005 y4m_ctx->convert = y4m_convert_null;
1007 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
1010 } else if (strcmp(y4m_ctx->chroma_type, "422p12") == 0) {
1011 y4m_ctx->src_c_dec_h = 2;
1012 y4m_ctx->src_c_dec_v = 1;
1013 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
1015 y4m_ctx->bit_depth = 12;
1016 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1017 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1018 y4m_ctx->dst_buf_read_sz =
1019 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
1020 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
1021 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1022 y4m_ctx->convert = y4m_convert_null;
1024 fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
1027 } else if (strcmp(y4m_ctx->chroma_type, "411") == 0) {
1028 y4m_ctx->src_c_dec_h = 4;
1029 y4m_ctx->dst_c_dec_h = 2;
1030 y4m_ctx->src_c_dec_v = 1;
1031 y4m_ctx->dst_c_dec_v = 2;
1032 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1033 /*Chroma filter required: read into the aux buf first.
1034 We need to make two filter passes, so we need some extra space in the
1036 y4m_ctx->aux_buf_read_sz = 2 * ((y4m_ctx->pic_w + 3) / 4) * y4m_ctx->pic_h;
1037 y4m_ctx->aux_buf_sz =
1038 y4m_ctx->aux_buf_read_sz + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1039 y4m_ctx->convert = y4m_convert_411_420jpeg;
1040 fprintf(stderr, "Unsupported conversion from yuv 411\n");
1042 } else if (strcmp(y4m_ctx->chroma_type, "444") == 0) {
1043 y4m_ctx->src_c_dec_h = 1;
1044 y4m_ctx->src_c_dec_v = 1;
1046 y4m_ctx->dst_c_dec_h = 2;
1047 y4m_ctx->dst_c_dec_v = 2;
1048 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1049 /*Chroma filter required: read into the aux buf first.
1050 We need to make two filter passes, so we need some extra space in the
1052 y4m_ctx->aux_buf_read_sz = 2 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1053 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
1054 ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1055 y4m_ctx->convert = y4m_convert_444_420jpeg;
1057 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I444;
1059 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1060 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1061 y4m_ctx->dst_buf_read_sz = 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1062 /*Natively supported: no conversion required.*/
1063 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1064 y4m_ctx->convert = y4m_convert_null;
1066 } else if (strcmp(y4m_ctx->chroma_type, "444p10") == 0) {
1067 y4m_ctx->src_c_dec_h = 1;
1068 y4m_ctx->src_c_dec_v = 1;
1069 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1071 y4m_ctx->bit_depth = 10;
1072 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1073 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1074 y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1075 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1076 y4m_ctx->convert = y4m_convert_null;
1078 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1081 } else if (strcmp(y4m_ctx->chroma_type, "444p12") == 0) {
1082 y4m_ctx->src_c_dec_h = 1;
1083 y4m_ctx->src_c_dec_v = 1;
1084 y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1086 y4m_ctx->bit_depth = 12;
1087 y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1088 y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1089 y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1090 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1091 y4m_ctx->convert = y4m_convert_null;
1093 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1096 } else if (strcmp(y4m_ctx->chroma_type, "mono") == 0) {
1097 y4m_ctx->src_c_dec_h = y4m_ctx->src_c_dec_v = 0;
1098 y4m_ctx->dst_c_dec_h = y4m_ctx->dst_c_dec_v = 2;
1099 y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1100 /*No extra space required, but we need to clear the chroma planes.*/
1101 y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1102 y4m_ctx->convert = y4m_convert_mono_420jpeg;
1104 fprintf(stderr, "Unknown chroma sampling type: %s\n", y4m_ctx->chroma_type);
1107 /*The size of the final frame buffers is always computed from the
1108 destination chroma decimation type.*/
1109 y4m_ctx->dst_buf_sz =
1110 y4m_ctx->pic_w * y4m_ctx->pic_h +
1111 2 * ((y4m_ctx->pic_w + y4m_ctx->dst_c_dec_h - 1) / y4m_ctx->dst_c_dec_h) *
1112 ((y4m_ctx->pic_h + y4m_ctx->dst_c_dec_v - 1) / y4m_ctx->dst_c_dec_v);
1113 if (y4m_ctx->bit_depth == 8)
1114 y4m_ctx->dst_buf = (unsigned char *)malloc(y4m_ctx->dst_buf_sz);
1116 y4m_ctx->dst_buf = (unsigned char *)malloc(2 * y4m_ctx->dst_buf_sz);
1118 if (y4m_ctx->aux_buf_sz > 0)
1119 y4m_ctx->aux_buf = (unsigned char *)malloc(y4m_ctx->aux_buf_sz);
1123 void y4m_input_close(y4m_input *_y4m) {
1124 free(_y4m->dst_buf);
1125 free(_y4m->aux_buf);
1128 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1134 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1135 /*Read and skip the frame header.*/
1136 if (!file_read(frame, 6, _fin)) return 0;
1137 if (memcmp(frame, "FRAME", 5)) {
1138 fprintf(stderr, "Loss of framing in Y4M input data\n");
1141 if (frame[5] != '\n') {
1144 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1147 fprintf(stderr, "Error parsing Y4M frame header\n");
1151 /*Read the frame data that needs no conversion.*/
1152 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1153 fprintf(stderr, "Error reading Y4M frame data.\n");
1156 /*Read the frame data that does need conversion.*/
1157 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1158 fprintf(stderr, "Error reading Y4M frame data.\n");
1161 /*Now convert the just read frame.*/
1162 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1163 /*Fill in the frame buffer pointers.
1164 We don't use vpx_img_wrap() because it forces padding for odd picture
1165 sizes, which would require a separate fread call for every row.*/
1166 memset(_img, 0, sizeof(*_img));
1167 /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1168 _img->fmt = _y4m->vpx_fmt;
1169 _img->w = _img->d_w = _y4m->pic_w;
1170 _img->h = _img->d_h = _y4m->pic_h;
1171 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1172 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1173 _img->bps = _y4m->bps;
1175 /*Set up the buffer pointers.*/
1176 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1177 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1178 c_w *= bytes_per_sample;
1179 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1181 _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1182 _y4m->pic_w * bytes_per_sample;
1183 _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1184 _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1185 _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1186 _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1187 _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;