Merge "vp8_denoiser_sse2_test: use ASSERT instead of EXPECT"
[platform/upstream/libvpx.git] / y4minput.c
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
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.
9  *
10  *  Based on code from the OggTheora software codec source code,
11  *  Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
12  */
13 #include <assert.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "vpx/vpx_integer.h"
19 #include "y4minput.h"
20
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;
25   int retry_count = 0;
26   int file_error;
27   size_t len = 0;
28   do {
29     const size_t n = fread((uint8_t *)buf + len, 1, size - len, file);
30     len += n;
31     file_error = ferror(file);
32     if (file_error) {
33       if (errno == EINTR || errno == EAGAIN) {
34         clearerr(file);
35         continue;
36       } else {
37         fprintf(stderr, "Error reading file: %u of %u bytes read, %d: %s\n",
38                 (uint32_t)len, (uint32_t)size, errno, strerror(errno));
39         return 0;
40       }
41     }
42   } while (!feof(file) && len < size && ++retry_count < kMaxRetries);
43
44   if (!feof(file) && len != size) {
45     fprintf(stderr,
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,
49             strerror(errno));
50   }
51   return len == size;
52 }
53
54 static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
55   char *p;
56   char *q;
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++) {
64     }
65     /*Process the tag.*/
66     switch (p[0]) {
67       case 'W': {
68         if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
69         break;
70       }
71       case 'H': {
72         if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
73         break;
74       }
75       case 'F': {
76         if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
77           return -1;
78         }
79         break;
80       }
81       case 'I': {
82         _y4m->interlace = p[1];
83         break;
84       }
85       case 'A': {
86         if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
87           return -1;
88         }
89         break;
90       }
91       case 'C': {
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';
95         break;
96       }
97         /*Ignore unknown tags.*/
98     }
99   }
100   return 0;
101 }
102
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) {
106   size_t i;
107   assert(buf_len >= 1);
108   // Skip leading space characters.
109   do {
110     if (!file_read(buf, 1, file)) {
111       return 0;
112     }
113   } while (buf[0] == ' ');
114
115   // If we hit the newline, treat this as the "empty" tag.
116   if (buf[0] == '\n') {
117     buf[0] = '\0';
118     *end_tag = '\n';
119     return 1;
120   }
121
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)) {
125       return 0;
126     }
127     if (buf[i] == ' ' || buf[i] == '\n') {
128       break;
129     }
130   }
131   if (i == buf_len) {
132     fprintf(stderr, "Error: Y4M header tags must be less than %lu characters\n",
133             (unsigned long)i);
134     return 0;
135   }
136   *end_tag = buf[i];
137   buf[i] = '\0';
138   return 1;
139 }
140
141 /* Returns 1 if tags were parsed successfully, 0 otherwise. */
142 static int parse_tags(y4m_input *y4m_ctx, FILE *file) {
143   char tag[256];
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. */
147   y4m_ctx->pic_w = -1;
148   y4m_ctx->pic_h = -1;
149   y4m_ctx->fps_n = -1; /* Also serves as marker for fps_d */
150   y4m_ctx->par_n = 0;
151   y4m_ctx->par_d = 0;
152   y4m_ctx->interlace = '?';
153   snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");
154
155   /* Find one tag at a time. */
156   do {
157     if (!copy_tag(tag, sizeof(tag), &end, file)) {
158       return 0;
159     }
160     /* y4m_parse_tags returns 0 on success. */
161     if (y4m_parse_tags(y4m_ctx, tag)) {
162       return 0;
163     }
164   } while (end != '\n');
165
166   /* Check the mandatory fields. */
167   if (y4m_ctx->pic_w == -1) {
168     fprintf(stderr, "Width field missing\n");
169     return 0;
170   }
171   if (y4m_ctx->pic_h == -1) {
172     fprintf(stderr, "Height field missing\n");
173     return 0;
174   }
175   if (y4m_ctx->fps_n == -1) {
176     fprintf(stderr, "FPS field missing\n");
177     return 0;
178   }
179   return 1;
180 }
181
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)
186    0,                         |t|>=3
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
190    0,                               |t|>=2
191   The number of taps is intentionally kept small to reduce computational
192    overhead and limit ringing.
193
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.
199
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)))
206
207 /*420jpeg chroma samples are sited like:
208   Y-------Y-------Y-------Y-------
209   |       |       |       |
210   |   BR  |       |   BR  |
211   |       |       |       |
212   Y-------Y-------Y-------Y-------
213   |       |       |       |
214   |       |       |       |
215   |       |       |       |
216   Y-------Y-------Y-------Y-------
217   |       |       |       |
218   |   BR  |       |   BR  |
219   |       |       |       |
220   Y-------Y-------Y-------Y-------
221   |       |       |       |
222   |       |       |       |
223   |       |       |       |
224
225   420mpeg2 chroma samples are sited like:
226   Y-------Y-------Y-------Y-------
227   |       |       |       |
228   BR      |       BR      |
229   |       |       |       |
230   Y-------Y-------Y-------Y-------
231   |       |       |       |
232   |       |       |       |
233   |       |       |       |
234   Y-------Y-------Y-------Y-------
235   |       |       |       |
236   BR      |       BR      |
237   |       |       |       |
238   Y-------Y-------Y-------Y-------
239   |       |       |       |
240   |       |       |       |
241   |       |       |       |
242
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,
250                                         int _c_h) {
251   int y;
252   int x;
253   for (y = 0; y < _c_h; y++) {
254     /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
255        window.*/
256     for (x = 0; x < OC_MINI(_c_w, 2); x++) {
257       _dst[x] = (unsigned char)OC_CLAMPI(
258           0,
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)] +
262            64) >>
263               7,
264           255);
265     }
266     for (; x < _c_w - 3; x++) {
267       _dst[x] = (unsigned char)OC_CLAMPI(
268           0,
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) >>
271               7,
272           255);
273     }
274     for (; x < _c_w; x++) {
275       _dst[x] = (unsigned char)OC_CLAMPI(
276           0,
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) >>
280               7,
281           255);
282     }
283     _dst += _c_w;
284     _src += _c_w;
285   }
286 }
287
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) {
291   int c_w;
292   int c_h;
293   int c_sz;
294   int pli;
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;
300   c_sz = c_w * c_h;
301   for (pli = 1; pli < 3; pli++) {
302     y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
303     _dst += c_sz;
304     _aux += c_sz;
305   }
306 }
307
308 /*This format is only used for interlaced content, but is included for
309    completeness.
310
311   420jpeg chroma samples are sited like:
312   Y-------Y-------Y-------Y-------
313   |       |       |       |
314   |   BR  |       |   BR  |
315   |       |       |       |
316   Y-------Y-------Y-------Y-------
317   |       |       |       |
318   |       |       |       |
319   |       |       |       |
320   Y-------Y-------Y-------Y-------
321   |       |       |       |
322   |   BR  |       |   BR  |
323   |       |       |       |
324   Y-------Y-------Y-------Y-------
325   |       |       |       |
326   |       |       |       |
327   |       |       |       |
328
329   420paldv chroma samples are sited like:
330   YR------Y-------YR------Y-------
331   |       |       |       |
332   |       |       |       |
333   |       |       |       |
334   YB------Y-------YB------Y-------
335   |       |       |       |
336   |       |       |       |
337   |       |       |       |
338   YR------Y-------YR------Y-------
339   |       |       |       |
340   |       |       |       |
341   |       |       |       |
342   YB------Y-------YB------Y-------
343   |       |       |       |
344   |       |       |       |
345   |       |       |       |
346
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) {
353   unsigned char *tmp;
354   int c_w;
355   int c_h;
356   int c_sz;
357   int pli;
358   int y;
359   int x;
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;
365   c_sz = c_w * c_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);
372     _aux += c_sz;
373     switch (pli) {
374       case 1: {
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(
380                 0,
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) >>
385                     7,
386                 255);
387           }
388           for (; y < c_h - 2; y++) {
389             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
390                 0,
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) >>
394                     7,
395                 255);
396           }
397           for (; y < c_h; y++) {
398             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
399                 0,
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) >>
404                     7,
405                 255);
406           }
407           _dst++;
408           tmp++;
409         }
410         _dst += c_sz - c_w;
411         tmp -= c_w;
412         break;
413       }
414       case 2: {
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(
420                 0,
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) >>
425                     7,
426                 255);
427           }
428           for (; y < c_h - 3; y++) {
429             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
430                 0,
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) >>
434                     7,
435                 255);
436           }
437           for (; y < c_h; y++) {
438             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
439                 0,
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] +
443                  64) >>
444                     7,
445                 255);
446           }
447           _dst++;
448           tmp++;
449         }
450         break;
451       }
452     }
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*/
460   }
461 }
462
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,
467                                        int _c_h) {
468   int y;
469   int x;
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] =
474           OC_CLAMPI(0,
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) >>
478                         7,
479                     255);
480     }
481     for (; y < _c_h - 3; y += 2) {
482       _dst[(y >> 1) * _c_w] =
483           OC_CLAMPI(0,
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) >>
487                         7,
488                     255);
489     }
490     for (; y < _c_h; y += 2) {
491       _dst[(y >> 1) * _c_w] = OC_CLAMPI(
492           0,
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]) +
496            64) >>
497               7,
498           255);
499     }
500     _src++;
501     _dst++;
502   }
503 }
504
505 /*420jpeg chroma samples are sited like:
506   Y-------Y-------Y-------Y-------
507   |       |       |       |
508   |   BR  |       |   BR  |
509   |       |       |       |
510   Y-------Y-------Y-------Y-------
511   |       |       |       |
512   |       |       |       |
513   |       |       |       |
514   Y-------Y-------Y-------Y-------
515   |       |       |       |
516   |   BR  |       |   BR  |
517   |       |       |       |
518   Y-------Y-------Y-------Y-------
519   |       |       |       |
520   |       |       |       |
521   |       |       |       |
522
523   422jpeg chroma samples are sited like:
524   Y---BR--Y-------Y---BR--Y-------
525   |       |       |       |
526   |       |       |       |
527   |       |       |       |
528   Y---BR--Y-------Y---BR--Y-------
529   |       |       |       |
530   |       |       |       |
531   |       |       |       |
532   Y---BR--Y-------Y---BR--Y-------
533   |       |       |       |
534   |       |       |       |
535   |       |       |       |
536   Y---BR--Y-------Y---BR--Y-------
537   |       |       |       |
538   |       |       |       |
539   |       |       |       |
540
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) {
545   int c_w;
546   int c_h;
547   int c_sz;
548   int dst_c_w;
549   int dst_c_h;
550   int dst_c_sz;
551   int pli;
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;
556   c_h = _y4m->pic_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;
559   c_sz = c_w * c_h;
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);
563     _aux += c_sz;
564     _dst += dst_c_sz;
565   }
566 }
567
568 /*420jpeg chroma samples are sited like:
569   Y-------Y-------Y-------Y-------
570   |       |       |       |
571   |   BR  |       |   BR  |
572   |       |       |       |
573   Y-------Y-------Y-------Y-------
574   |       |       |       |
575   |       |       |       |
576   |       |       |       |
577   Y-------Y-------Y-------Y-------
578   |       |       |       |
579   |   BR  |       |   BR  |
580   |       |       |       |
581   Y-------Y-------Y-------Y-------
582   |       |       |       |
583   |       |       |       |
584   |       |       |       |
585
586   422 chroma samples are sited like:
587   YBR-----Y-------YBR-----Y-------
588   |       |       |       |
589   |       |       |       |
590   |       |       |       |
591   YBR-----Y-------YBR-----Y-------
592   |       |       |       |
593   |       |       |       |
594   |       |       |       |
595   YBR-----Y-------YBR-----Y-------
596   |       |       |       |
597   |       |       |       |
598   |       |       |       |
599   YBR-----Y-------YBR-----Y-------
600   |       |       |       |
601   |       |       |       |
602   |       |       |       |
603
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) {
610   unsigned char *tmp;
611   int c_w;
612   int c_h;
613   int c_sz;
614   int dst_c_h;
615   int dst_c_sz;
616   int pli;
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;
621   c_h = _y4m->pic_h;
622   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
623   c_sz = c_w * c_h;
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);
634     _aux += c_sz;
635     _dst += dst_c_sz;
636   }
637 }
638
639 /*420jpeg chroma samples are sited like:
640   Y-------Y-------Y-------Y-------
641   |       |       |       |
642   |   BR  |       |   BR  |
643   |       |       |       |
644   Y-------Y-------Y-------Y-------
645   |       |       |       |
646   |       |       |       |
647   |       |       |       |
648   Y-------Y-------Y-------Y-------
649   |       |       |       |
650   |   BR  |       |   BR  |
651   |       |       |       |
652   Y-------Y-------Y-------Y-------
653   |       |       |       |
654   |       |       |       |
655   |       |       |       |
656
657   411 chroma samples are sited like:
658   YBR-----Y-------Y-------Y-------
659   |       |       |       |
660   |       |       |       |
661   |       |       |       |
662   YBR-----Y-------Y-------Y-------
663   |       |       |       |
664   |       |       |       |
665   |       |       |       |
666   YBR-----Y-------Y-------Y-------
667   |       |       |       |
668   |       |       |       |
669   |       |       |       |
670   YBR-----Y-------Y-------Y-------
671   |       |       |       |
672   |       |       |       |
673   |       |       |       |
674
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
677    right.
678   Then we use another filter to decimate the planes by 2 in the vertical
679    direction.*/
680 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
681                                     unsigned char *_aux) {
682   unsigned char *tmp;
683   int c_w;
684   int c_h;
685   int c_sz;
686   int dst_c_w;
687   int dst_c_h;
688   int dst_c_sz;
689   int tmp_sz;
690   int pli;
691   int y;
692   int x;
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;
697   c_h = _y4m->pic_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;
700   c_sz = c_w * c_h;
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(
714             0,
715             (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
716              _aux[OC_MINI(2, c_w - 1)] + 64) >>
717                 7,
718             255);
719         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
720             0,
721             (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
722              5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
723                 7,
724             255);
725       }
726       for (; x < c_w - 2; x++) {
727         tmp[x << 1] =
728             (unsigned char)OC_CLAMPI(0,
729                                      (_aux[x - 1] + 110 * _aux[x] +
730                                       18 * _aux[x + 1] - _aux[x + 2] + 64) >>
731                                          7,
732                                      255);
733         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
734             0,
735             (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
736              5 * _aux[x + 2] + 64) >>
737                 7,
738             255);
739       }
740       for (; x < c_w; x++) {
741         tmp[x << 1] = (unsigned char)OC_CLAMPI(
742             0,
743             (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
744              _aux[c_w - 1] + 64) >>
745                 7,
746             255);
747         if ((x << 1 | 1) < dst_c_w) {
748           tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
749               0,
750               (-3 * _aux[x - 1] + 50 * _aux[x] +
751                86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
752                   7,
753               255);
754         }
755       }
756       tmp += dst_c_w;
757       _aux += c_w;
758     }
759     tmp -= tmp_sz;
760     /*Now do the vertical filtering.*/
761     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
762     _dst += dst_c_sz;
763   }
764 }
765
766 /*Convert 444 to 420jpeg.*/
767 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
768                                     unsigned char *_aux) {
769   unsigned char *tmp;
770   int c_w;
771   int c_h;
772   int c_sz;
773   int dst_c_w;
774   int dst_c_h;
775   int dst_c_sz;
776   int tmp_sz;
777   int pli;
778   int y;
779   int x;
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;
784   c_h = _y4m->pic_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;
787   c_sz = c_w * c_h;
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) >>
799                                     7,
800                                 255);
801       }
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) >>
807                                     7,
808                                 255);
809       }
810       for (; x < c_w; x += 2) {
811         tmp[x >> 1] =
812             OC_CLAMPI(0,
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) >>
816                           7,
817                       255);
818       }
819       tmp += dst_c_w;
820       _aux += c_w;
821     }
822     tmp -= tmp_sz;
823     /*Now do the vertical filtering.*/
824     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
825     _dst += dst_c_sz;
826   }
827 }
828
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) {
832   int c_sz;
833   (void)_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);
838 }
839
840 /*No conversion function needed.*/
841 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
842                              unsigned char *_aux) {
843   (void)_y4m;
844   (void)_dst;
845   (void)_aux;
846 }
847
848 static const char TAG[] = "YUV4MPEG2";
849
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);
857   if (num_skip > 0) {
858     memcpy(tag_buffer, skip_buffer, num_skip);
859   }
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)) {
862     return -1;
863   }
864   if (memcmp(TAG, tag_buffer, 9) != 0) {
865     fprintf(stderr, "Error parsing header: must start with %s\n", TAG);
866     return -1;
867   }
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);
871     return -1;
872   }
873   if (!parse_tags(y4m_ctx, file)) {
874     fprintf(stderr, "Error parsing %s header.\n", TAG);
875   }
876   if (y4m_ctx->interlace == '?') {
877     fprintf(stderr,
878             "Warning: Input video interlacing format unknown; "
879             "assuming progressive scan.\n");
880   } else if (y4m_ctx->interlace != 'p') {
881     fprintf(stderr,
882             "Input video is interlaced; "
883             "Only progressive scan handled.\n");
884     return -1;
885   }
886   y4m_ctx->vpx_fmt = VPX_IMG_FMT_I420;
887   y4m_ctx->bps = 12;
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;
913     y4m_ctx->bps = 15;
914     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
915     if (only_420) {
916       fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
917       return -1;
918     }
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;
931     y4m_ctx->bps = 18;
932     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
933     if (only_420) {
934       fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
935       return -1;
936     }
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
951        aux buffer.*/
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;
969     if (only_420) {
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
975          aux buffer.*/
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;
981     } else {
982       y4m_ctx->vpx_fmt = VPX_IMG_FMT_I422;
983       y4m_ctx->bps = 16;
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;
992     }
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;
997     y4m_ctx->bps = 20;
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;
1006     if (only_420) {
1007       fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
1008       return -1;
1009     }
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;
1014     y4m_ctx->bps = 24;
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;
1023     if (only_420) {
1024       fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
1025       return -1;
1026     }
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
1035        aux buffer.*/
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");
1041     return -1;
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;
1045     if (only_420) {
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
1051          aux buffer.*/
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;
1056     } else {
1057       y4m_ctx->vpx_fmt = VPX_IMG_FMT_I444;
1058       y4m_ctx->bps = 24;
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;
1065     }
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;
1070     y4m_ctx->bps = 30;
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;
1077     if (only_420) {
1078       fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1079       return -1;
1080     }
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;
1085     y4m_ctx->bps = 36;
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;
1092     if (only_420) {
1093       fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1094       return -1;
1095     }
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;
1103   } else {
1104     fprintf(stderr, "Unknown chroma sampling type: %s\n", y4m_ctx->chroma_type);
1105     return -1;
1106   }
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);
1115   else
1116     y4m_ctx->dst_buf = (unsigned char *)malloc(2 * y4m_ctx->dst_buf_sz);
1117
1118   if (y4m_ctx->aux_buf_sz > 0)
1119     y4m_ctx->aux_buf = (unsigned char *)malloc(y4m_ctx->aux_buf_sz);
1120   return 0;
1121 }
1122
1123 void y4m_input_close(y4m_input *_y4m) {
1124   free(_y4m->dst_buf);
1125   free(_y4m->aux_buf);
1126 }
1127
1128 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1129   char frame[6];
1130   int pic_sz;
1131   int c_w;
1132   int c_h;
1133   int c_sz;
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");
1139     return -1;
1140   }
1141   if (frame[5] != '\n') {
1142     char c;
1143     int j;
1144     for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1145     }
1146     if (j == 79) {
1147       fprintf(stderr, "Error parsing Y4M frame header\n");
1148       return -1;
1149     }
1150   }
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");
1154     return -1;
1155   }
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");
1159     return -1;
1160   }
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;
1174
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;
1180   c_sz = c_w * c_h;
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;
1188   return 1;
1189 }