y4m_input_open: check allocs
[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 /*This format is only used for interlaced content, but is included for
289    completeness.
290
291   420jpeg chroma samples are sited like:
292   Y-------Y-------Y-------Y-------
293   |       |       |       |
294   |   BR  |       |   BR  |
295   |       |       |       |
296   Y-------Y-------Y-------Y-------
297   |       |       |       |
298   |       |       |       |
299   |       |       |       |
300   Y-------Y-------Y-------Y-------
301   |       |       |       |
302   |   BR  |       |   BR  |
303   |       |       |       |
304   Y-------Y-------Y-------Y-------
305   |       |       |       |
306   |       |       |       |
307   |       |       |       |
308
309   420paldv chroma samples are sited like:
310   YR------Y-------YR------Y-------
311   |       |       |       |
312   |       |       |       |
313   |       |       |       |
314   YB------Y-------YB------Y-------
315   |       |       |       |
316   |       |       |       |
317   |       |       |       |
318   YR------Y-------YR------Y-------
319   |       |       |       |
320   |       |       |       |
321   |       |       |       |
322   YB------Y-------YB------Y-------
323   |       |       |       |
324   |       |       |       |
325   |       |       |       |
326
327   We use a resampling filter to shift the site locations one quarter pixel (at
328    the chroma plane's resolution) to the right.
329   Then we use another filter to move the C_r location down one quarter pixel,
330    and the C_b location up one quarter pixel.*/
331 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
332                                          unsigned char *_aux) {
333   unsigned char *tmp;
334   int c_w;
335   int c_h;
336   int c_sz;
337   int pli;
338   int y;
339   int x;
340   /*Skip past the luma data.*/
341   _dst += _y4m->pic_w * _y4m->pic_h;
342   /*Compute the size of each chroma plane.*/
343   c_w = (_y4m->pic_w + 1) / 2;
344   c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
345   c_sz = c_w * c_h;
346   tmp = _aux + 2 * c_sz;
347   for (pli = 1; pli < 3; pli++) {
348     /*First do the horizontal re-sampling.
349       This is the same as the mpeg2 case, except that after the horizontal
350        case, we need to apply a second vertical filter.*/
351     y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
352     _aux += c_sz;
353     switch (pli) {
354       case 1: {
355         /*Slide C_b up a quarter-pel.
356           This is the same filter used above, but in the other order.*/
357         for (x = 0; x < c_w; x++) {
358           for (y = 0; y < OC_MINI(c_h, 3); y++) {
359             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
360                 0,
361                 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
362                  35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
363                  17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
364                  4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
365                     7,
366                 255);
367           }
368           for (; y < c_h - 2; y++) {
369             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
370                 0,
371                 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
372                  35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
373                  17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
374                     7,
375                 255);
376           }
377           for (; y < c_h; y++) {
378             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
379                 0,
380                 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
381                  35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
382                  17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
383                  4 * tmp[(c_h - 1) * c_w] + 64) >>
384                     7,
385                 255);
386           }
387           _dst++;
388           tmp++;
389         }
390         _dst += c_sz - c_w;
391         tmp -= c_w;
392         break;
393       }
394       case 2: {
395         /*Slide C_r down a quarter-pel.
396           This is the same as the horizontal filter.*/
397         for (x = 0; x < c_w; x++) {
398           for (y = 0; y < OC_MINI(c_h, 2); y++) {
399             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
400                 0,
401                 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
402                  114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
403                  9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
404                  tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
405                     7,
406                 255);
407           }
408           for (; y < c_h - 3; y++) {
409             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
410                 0,
411                 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
412                  114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
413                  9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
414                     7,
415                 255);
416           }
417           for (; y < c_h; y++) {
418             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
419                 0,
420                 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
421                  114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
422                  9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
423                  64) >>
424                     7,
425                 255);
426           }
427           _dst++;
428           tmp++;
429         }
430         break;
431       }
432     }
433     /*For actual interlaced material, this would have to be done separately on
434        each field, and the shift amounts would be different.
435       C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
436        C_b up 1/8 in the bottom field.
437       The corresponding filters would be:
438        Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
439        Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
440   }
441 }
442
443 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
444   This is used as a helper by several converation routines.*/
445 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
446                                        const unsigned char *_src, int _c_w,
447                                        int _c_h) {
448   int y;
449   int x;
450   /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
451   for (x = 0; x < _c_w; x++) {
452     for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
453       _dst[(y >> 1) * _c_w] =
454           OC_CLAMPI(0,
455                     (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
456                      17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
457                      3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
458                         7,
459                     255);
460     }
461     for (; y < _c_h - 3; y += 2) {
462       _dst[(y >> 1) * _c_w] =
463           OC_CLAMPI(0,
464                     (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
465                      17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
466                      78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
467                         7,
468                     255);
469     }
470     for (; y < _c_h; y += 2) {
471       _dst[(y >> 1) * _c_w] = OC_CLAMPI(
472           0,
473           (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
474            17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
475            78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
476            64) >>
477               7,
478           255);
479     }
480     _src++;
481     _dst++;
482   }
483 }
484
485 /*420jpeg chroma samples are sited like:
486   Y-------Y-------Y-------Y-------
487   |       |       |       |
488   |   BR  |       |   BR  |
489   |       |       |       |
490   Y-------Y-------Y-------Y-------
491   |       |       |       |
492   |       |       |       |
493   |       |       |       |
494   Y-------Y-------Y-------Y-------
495   |       |       |       |
496   |   BR  |       |   BR  |
497   |       |       |       |
498   Y-------Y-------Y-------Y-------
499   |       |       |       |
500   |       |       |       |
501   |       |       |       |
502
503   422jpeg chroma samples are sited like:
504   Y---BR--Y-------Y---BR--Y-------
505   |       |       |       |
506   |       |       |       |
507   |       |       |       |
508   Y---BR--Y-------Y---BR--Y-------
509   |       |       |       |
510   |       |       |       |
511   |       |       |       |
512   Y---BR--Y-------Y---BR--Y-------
513   |       |       |       |
514   |       |       |       |
515   |       |       |       |
516   Y---BR--Y-------Y---BR--Y-------
517   |       |       |       |
518   |       |       |       |
519   |       |       |       |
520
521   We use a resampling filter to decimate the chroma planes by two in the
522    vertical direction.*/
523 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
524                                         unsigned char *_aux) {
525   int c_w;
526   int c_h;
527   int c_sz;
528   int dst_c_w;
529   int dst_c_h;
530   int dst_c_sz;
531   int pli;
532   /*Skip past the luma data.*/
533   _dst += _y4m->pic_w * _y4m->pic_h;
534   /*Compute the size of each chroma plane.*/
535   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
536   c_h = _y4m->pic_h;
537   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
538   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
539   c_sz = c_w * c_h;
540   dst_c_sz = dst_c_w * dst_c_h;
541   for (pli = 1; pli < 3; pli++) {
542     y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
543     _aux += c_sz;
544     _dst += dst_c_sz;
545   }
546 }
547
548 /*420jpeg chroma samples are sited like:
549   Y-------Y-------Y-------Y-------
550   |       |       |       |
551   |   BR  |       |   BR  |
552   |       |       |       |
553   Y-------Y-------Y-------Y-------
554   |       |       |       |
555   |       |       |       |
556   |       |       |       |
557   Y-------Y-------Y-------Y-------
558   |       |       |       |
559   |   BR  |       |   BR  |
560   |       |       |       |
561   Y-------Y-------Y-------Y-------
562   |       |       |       |
563   |       |       |       |
564   |       |       |       |
565
566   422 chroma samples are sited like:
567   YBR-----Y-------YBR-----Y-------
568   |       |       |       |
569   |       |       |       |
570   |       |       |       |
571   YBR-----Y-------YBR-----Y-------
572   |       |       |       |
573   |       |       |       |
574   |       |       |       |
575   YBR-----Y-------YBR-----Y-------
576   |       |       |       |
577   |       |       |       |
578   |       |       |       |
579   YBR-----Y-------YBR-----Y-------
580   |       |       |       |
581   |       |       |       |
582   |       |       |       |
583
584   We use a resampling filter to shift the original site locations one quarter
585    pixel (at the original chroma resolution) to the right.
586   Then we use a second resampling filter to decimate the chroma planes by two
587    in the vertical direction.*/
588 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
589                                     unsigned char *_aux) {
590   unsigned char *tmp;
591   int c_w;
592   int c_h;
593   int c_sz;
594   int dst_c_h;
595   int dst_c_sz;
596   int pli;
597   /*Skip past the luma data.*/
598   _dst += _y4m->pic_w * _y4m->pic_h;
599   /*Compute the size of each chroma plane.*/
600   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
601   c_h = _y4m->pic_h;
602   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
603   c_sz = c_w * c_h;
604   dst_c_sz = c_w * dst_c_h;
605   tmp = _aux + 2 * c_sz;
606   for (pli = 1; pli < 3; pli++) {
607     /*In reality, the horizontal and vertical steps could be pipelined, for
608        less memory consumption and better cache performance, but we do them
609        separately for simplicity.*/
610     /*First do horizontal filtering (convert to 422jpeg)*/
611     y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
612     /*Now do the vertical filtering.*/
613     y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
614     _aux += c_sz;
615     _dst += dst_c_sz;
616   }
617 }
618
619 /*420jpeg chroma samples are sited like:
620   Y-------Y-------Y-------Y-------
621   |       |       |       |
622   |   BR  |       |   BR  |
623   |       |       |       |
624   Y-------Y-------Y-------Y-------
625   |       |       |       |
626   |       |       |       |
627   |       |       |       |
628   Y-------Y-------Y-------Y-------
629   |       |       |       |
630   |   BR  |       |   BR  |
631   |       |       |       |
632   Y-------Y-------Y-------Y-------
633   |       |       |       |
634   |       |       |       |
635   |       |       |       |
636
637   411 chroma samples are sited like:
638   YBR-----Y-------Y-------Y-------
639   |       |       |       |
640   |       |       |       |
641   |       |       |       |
642   YBR-----Y-------Y-------Y-------
643   |       |       |       |
644   |       |       |       |
645   |       |       |       |
646   YBR-----Y-------Y-------Y-------
647   |       |       |       |
648   |       |       |       |
649   |       |       |       |
650   YBR-----Y-------Y-------Y-------
651   |       |       |       |
652   |       |       |       |
653   |       |       |       |
654
655   We use a filter to resample at site locations one eighth pixel (at the source
656    chroma plane's horizontal resolution) and five eighths of a pixel to the
657    right.
658   Then we use another filter to decimate the planes by 2 in the vertical
659    direction.*/
660 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
661                                     unsigned char *_aux) {
662   unsigned char *tmp;
663   int c_w;
664   int c_h;
665   int c_sz;
666   int dst_c_w;
667   int dst_c_h;
668   int dst_c_sz;
669   int tmp_sz;
670   int pli;
671   int y;
672   int x;
673   /*Skip past the luma data.*/
674   _dst += _y4m->pic_w * _y4m->pic_h;
675   /*Compute the size of each chroma plane.*/
676   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
677   c_h = _y4m->pic_h;
678   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
679   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
680   c_sz = c_w * c_h;
681   dst_c_sz = dst_c_w * dst_c_h;
682   tmp_sz = dst_c_w * c_h;
683   tmp = _aux + 2 * c_sz;
684   for (pli = 1; pli < 3; pli++) {
685     /*In reality, the horizontal and vertical steps could be pipelined, for
686        less memory consumption and better cache performance, but we do them
687        separately for simplicity.*/
688     /*First do horizontal filtering (convert to 422jpeg)*/
689     for (y = 0; y < c_h; y++) {
690       /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
691          4-tap Mitchell window.*/
692       for (x = 0; x < OC_MINI(c_w, 1); x++) {
693         tmp[x << 1] = (unsigned char)OC_CLAMPI(
694             0,
695             (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
696              _aux[OC_MINI(2, c_w - 1)] + 64) >>
697                 7,
698             255);
699         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
700             0,
701             (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
702              5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
703                 7,
704             255);
705       }
706       for (; x < c_w - 2; x++) {
707         tmp[x << 1] =
708             (unsigned char)OC_CLAMPI(0,
709                                      (_aux[x - 1] + 110 * _aux[x] +
710                                       18 * _aux[x + 1] - _aux[x + 2] + 64) >>
711                                          7,
712                                      255);
713         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
714             0,
715             (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
716              5 * _aux[x + 2] + 64) >>
717                 7,
718             255);
719       }
720       for (; x < c_w; x++) {
721         tmp[x << 1] = (unsigned char)OC_CLAMPI(
722             0,
723             (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
724              _aux[c_w - 1] + 64) >>
725                 7,
726             255);
727         if ((x << 1 | 1) < dst_c_w) {
728           tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
729               0,
730               (-3 * _aux[x - 1] + 50 * _aux[x] +
731                86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
732                   7,
733               255);
734         }
735       }
736       tmp += dst_c_w;
737       _aux += c_w;
738     }
739     tmp -= tmp_sz;
740     /*Now do the vertical filtering.*/
741     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
742     _dst += dst_c_sz;
743   }
744 }
745
746 /*Convert 444 to 420jpeg.*/
747 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
748                                     unsigned char *_aux) {
749   unsigned char *tmp;
750   int c_w;
751   int c_h;
752   int c_sz;
753   int dst_c_w;
754   int dst_c_h;
755   int dst_c_sz;
756   int tmp_sz;
757   int pli;
758   int y;
759   int x;
760   /*Skip past the luma data.*/
761   _dst += _y4m->pic_w * _y4m->pic_h;
762   /*Compute the size of each chroma plane.*/
763   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
764   c_h = _y4m->pic_h;
765   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
766   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
767   c_sz = c_w * c_h;
768   dst_c_sz = dst_c_w * dst_c_h;
769   tmp_sz = dst_c_w * c_h;
770   tmp = _aux + 2 * c_sz;
771   for (pli = 1; pli < 3; pli++) {
772     /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
773     for (y = 0; y < c_h; y++) {
774       for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
775         tmp[x >> 1] = OC_CLAMPI(0,
776                                 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
777                                  17 * _aux[OC_MINI(2, c_w - 1)] +
778                                  3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
779                                     7,
780                                 255);
781       }
782       for (; x < c_w - 3; x += 2) {
783         tmp[x >> 1] = OC_CLAMPI(0,
784                                 (3 * (_aux[x - 2] + _aux[x + 3]) -
785                                  17 * (_aux[x - 1] + _aux[x + 2]) +
786                                  78 * (_aux[x] + _aux[x + 1]) + 64) >>
787                                     7,
788                                 255);
789       }
790       for (; x < c_w; x += 2) {
791         tmp[x >> 1] =
792             OC_CLAMPI(0,
793                       (3 * (_aux[x - 2] + _aux[c_w - 1]) -
794                        17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
795                        78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
796                           7,
797                       255);
798       }
799       tmp += dst_c_w;
800       _aux += c_w;
801     }
802     tmp -= tmp_sz;
803     /*Now do the vertical filtering.*/
804     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
805     _dst += dst_c_sz;
806   }
807 }
808
809 /*The image is padded with empty chroma components at 4:2:0.*/
810 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
811                                      unsigned char *_aux) {
812   int c_sz;
813   (void)_aux;
814   _dst += _y4m->pic_w * _y4m->pic_h;
815   c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
816          ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
817   memset(_dst, 128, c_sz * 2);
818 }
819
820 /*No conversion function needed.*/
821 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
822                              unsigned char *_aux) {
823   (void)_y4m;
824   (void)_dst;
825   (void)_aux;
826 }
827
828 static const char TAG[] = "YUV4MPEG2";
829
830 int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,
831                    int num_skip, int only_420) {
832   // File must start with |TAG|.
833   char tag_buffer[9];  // 9 == strlen(TAG)
834   // Read as much as possible from |skip_buffer|, which were characters
835   // that were previously read from the file to do input-type detection.
836   assert(num_skip >= 0 && num_skip <= 8);
837   if (num_skip > 0) {
838     memcpy(tag_buffer, skip_buffer, num_skip);
839   }
840   // Start reading from the file now that the |skip_buffer| is depleted.
841   if (!file_read(tag_buffer + num_skip, 9 - num_skip, file)) {
842     return -1;
843   }
844   if (memcmp(TAG, tag_buffer, 9) != 0) {
845     fprintf(stderr, "Error parsing header: must start with %s\n", TAG);
846     return -1;
847   }
848   // Next character must be a space.
849   if (!file_read(tag_buffer, 1, file) || tag_buffer[0] != ' ') {
850     fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);
851     return -1;
852   }
853   if (!parse_tags(y4m_ctx, file)) {
854     fprintf(stderr, "Error parsing %s header.\n", TAG);
855   }
856   if (y4m_ctx->interlace == '?') {
857     fprintf(stderr,
858             "Warning: Input video interlacing format unknown; "
859             "assuming progressive scan.\n");
860   } else if (y4m_ctx->interlace != 'p') {
861     fprintf(stderr,
862             "Input video is interlaced; "
863             "Only progressive scan handled.\n");
864     return -1;
865   }
866   y4m_ctx->vpx_fmt = VPX_IMG_FMT_I420;
867   y4m_ctx->bps = 12;
868   y4m_ctx->bit_depth = 8;
869   y4m_ctx->aux_buf = NULL;
870   y4m_ctx->dst_buf = NULL;
871   if (strcmp(y4m_ctx->chroma_type, "420") == 0 ||
872       strcmp(y4m_ctx->chroma_type, "420jpeg") == 0 ||
873       strcmp(y4m_ctx->chroma_type, "420mpeg2") == 0) {
874     y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
875         y4m_ctx->dst_c_dec_v = 2;
876     y4m_ctx->dst_buf_read_sz =
877         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   } else if (strcmp(y4m_ctx->chroma_type, "420p10") == 0) {
883     y4m_ctx->src_c_dec_h = 2;
884     y4m_ctx->dst_c_dec_h = 2;
885     y4m_ctx->src_c_dec_v = 2;
886     y4m_ctx->dst_c_dec_v = 2;
887     y4m_ctx->dst_buf_read_sz =
888         2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
889              2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
890     /* Natively supported: no conversion required. */
891     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
892     y4m_ctx->convert = y4m_convert_null;
893     y4m_ctx->bit_depth = 10;
894     y4m_ctx->bps = 15;
895     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
896     if (only_420) {
897       fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
898       return -1;
899     }
900   } else if (strcmp(y4m_ctx->chroma_type, "420p12") == 0) {
901     y4m_ctx->src_c_dec_h = 2;
902     y4m_ctx->dst_c_dec_h = 2;
903     y4m_ctx->src_c_dec_v = 2;
904     y4m_ctx->dst_c_dec_v = 2;
905     y4m_ctx->dst_buf_read_sz =
906         2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
907              2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2));
908     /* Natively supported: no conversion required. */
909     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
910     y4m_ctx->convert = y4m_convert_null;
911     y4m_ctx->bit_depth = 12;
912     y4m_ctx->bps = 18;
913     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016;
914     if (only_420) {
915       fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
916       return -1;
917     }
918   } else if (strcmp(y4m_ctx->chroma_type, "420paldv") == 0) {
919     y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v =
920         y4m_ctx->dst_c_dec_v = 2;
921     y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
922     /*Chroma filter required: read into the aux buf first.
923       We need to make two filter passes, so we need some extra space in the
924        aux buffer.*/
925     y4m_ctx->aux_buf_sz =
926         3 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
927     y4m_ctx->aux_buf_read_sz =
928         2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2);
929     y4m_ctx->convert = y4m_convert_42xpaldv_42xjpeg;
930   } else if (strcmp(y4m_ctx->chroma_type, "422jpeg") == 0) {
931     y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = 2;
932     y4m_ctx->src_c_dec_v = 1;
933     y4m_ctx->dst_c_dec_v = 2;
934     y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
935     /*Chroma filter required: read into the aux buf first.*/
936     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz =
937         2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
938     y4m_ctx->convert = y4m_convert_422jpeg_420jpeg;
939   } else if (strcmp(y4m_ctx->chroma_type, "422") == 0) {
940     y4m_ctx->src_c_dec_h = 2;
941     y4m_ctx->src_c_dec_v = 1;
942     if (only_420) {
943       y4m_ctx->dst_c_dec_h = 2;
944       y4m_ctx->dst_c_dec_v = 2;
945       y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
946       /*Chroma filter required: read into the aux buf first.
947         We need to make two filter passes, so we need some extra space in the
948          aux buffer.*/
949       y4m_ctx->aux_buf_read_sz =
950           2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
951       y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
952                             ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
953       y4m_ctx->convert = y4m_convert_422_420jpeg;
954     } else {
955       y4m_ctx->vpx_fmt = VPX_IMG_FMT_I422;
956       y4m_ctx->bps = 16;
957       y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
958       y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
959       y4m_ctx->dst_buf_read_sz =
960           y4m_ctx->pic_w * y4m_ctx->pic_h +
961           2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
962       /*Natively supported: no conversion required.*/
963       y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
964       y4m_ctx->convert = y4m_convert_null;
965     }
966   } else if (strcmp(y4m_ctx->chroma_type, "422p10") == 0) {
967     y4m_ctx->src_c_dec_h = 2;
968     y4m_ctx->src_c_dec_v = 1;
969     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
970     y4m_ctx->bps = 20;
971     y4m_ctx->bit_depth = 10;
972     y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
973     y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
974     y4m_ctx->dst_buf_read_sz =
975         2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
976              2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
977     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
978     y4m_ctx->convert = y4m_convert_null;
979     if (only_420) {
980       fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
981       return -1;
982     }
983   } else if (strcmp(y4m_ctx->chroma_type, "422p12") == 0) {
984     y4m_ctx->src_c_dec_h = 2;
985     y4m_ctx->src_c_dec_v = 1;
986     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216;
987     y4m_ctx->bps = 24;
988     y4m_ctx->bit_depth = 12;
989     y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
990     y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
991     y4m_ctx->dst_buf_read_sz =
992         2 * (y4m_ctx->pic_w * y4m_ctx->pic_h +
993              2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h);
994     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
995     y4m_ctx->convert = y4m_convert_null;
996     if (only_420) {
997       fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
998       return -1;
999     }
1000   } else if (strcmp(y4m_ctx->chroma_type, "411") == 0) {
1001     y4m_ctx->src_c_dec_h = 4;
1002     y4m_ctx->dst_c_dec_h = 2;
1003     y4m_ctx->src_c_dec_v = 1;
1004     y4m_ctx->dst_c_dec_v = 2;
1005     y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1006     /*Chroma filter required: read into the aux buf first.
1007       We need to make two filter passes, so we need some extra space in the
1008        aux buffer.*/
1009     y4m_ctx->aux_buf_read_sz = 2 * ((y4m_ctx->pic_w + 3) / 4) * y4m_ctx->pic_h;
1010     y4m_ctx->aux_buf_sz =
1011         y4m_ctx->aux_buf_read_sz + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1012     y4m_ctx->convert = y4m_convert_411_420jpeg;
1013     fprintf(stderr, "Unsupported conversion from yuv 411\n");
1014     return -1;
1015   } else if (strcmp(y4m_ctx->chroma_type, "444") == 0) {
1016     y4m_ctx->src_c_dec_h = 1;
1017     y4m_ctx->src_c_dec_v = 1;
1018     if (only_420) {
1019       y4m_ctx->dst_c_dec_h = 2;
1020       y4m_ctx->dst_c_dec_v = 2;
1021       y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1022       /*Chroma filter required: read into the aux buf first.
1023         We need to make two filter passes, so we need some extra space in the
1024          aux buffer.*/
1025       y4m_ctx->aux_buf_read_sz = 2 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1026       y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz +
1027                             ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h;
1028       y4m_ctx->convert = y4m_convert_444_420jpeg;
1029     } else {
1030       y4m_ctx->vpx_fmt = VPX_IMG_FMT_I444;
1031       y4m_ctx->bps = 24;
1032       y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1033       y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1034       y4m_ctx->dst_buf_read_sz = 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1035       /*Natively supported: no conversion required.*/
1036       y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1037       y4m_ctx->convert = y4m_convert_null;
1038     }
1039   } else if (strcmp(y4m_ctx->chroma_type, "444p10") == 0) {
1040     y4m_ctx->src_c_dec_h = 1;
1041     y4m_ctx->src_c_dec_v = 1;
1042     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1043     y4m_ctx->bps = 30;
1044     y4m_ctx->bit_depth = 10;
1045     y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1046     y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1047     y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1048     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1049     y4m_ctx->convert = y4m_convert_null;
1050     if (only_420) {
1051       fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1052       return -1;
1053     }
1054   } else if (strcmp(y4m_ctx->chroma_type, "444p12") == 0) {
1055     y4m_ctx->src_c_dec_h = 1;
1056     y4m_ctx->src_c_dec_v = 1;
1057     y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416;
1058     y4m_ctx->bps = 36;
1059     y4m_ctx->bit_depth = 12;
1060     y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h;
1061     y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v;
1062     y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h;
1063     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1064     y4m_ctx->convert = y4m_convert_null;
1065     if (only_420) {
1066       fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1067       return -1;
1068     }
1069   } else if (strcmp(y4m_ctx->chroma_type, "mono") == 0) {
1070     y4m_ctx->src_c_dec_h = y4m_ctx->src_c_dec_v = 0;
1071     y4m_ctx->dst_c_dec_h = y4m_ctx->dst_c_dec_v = 2;
1072     y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h;
1073     /*No extra space required, but we need to clear the chroma planes.*/
1074     y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0;
1075     y4m_ctx->convert = y4m_convert_mono_420jpeg;
1076   } else {
1077     fprintf(stderr, "Unknown chroma sampling type: %s\n", y4m_ctx->chroma_type);
1078     return -1;
1079   }
1080   /*The size of the final frame buffers is always computed from the
1081      destination chroma decimation type.*/
1082   y4m_ctx->dst_buf_sz =
1083       y4m_ctx->pic_w * y4m_ctx->pic_h +
1084       2 * ((y4m_ctx->pic_w + y4m_ctx->dst_c_dec_h - 1) / y4m_ctx->dst_c_dec_h) *
1085           ((y4m_ctx->pic_h + y4m_ctx->dst_c_dec_v - 1) / y4m_ctx->dst_c_dec_v);
1086   if (y4m_ctx->bit_depth == 8)
1087     y4m_ctx->dst_buf = (unsigned char *)malloc(y4m_ctx->dst_buf_sz);
1088   else
1089     y4m_ctx->dst_buf = (unsigned char *)malloc(2 * y4m_ctx->dst_buf_sz);
1090   if (!y4m_ctx->dst_buf) return -1;
1091
1092   if (y4m_ctx->aux_buf_sz > 0) {
1093     y4m_ctx->aux_buf = (unsigned char *)malloc(y4m_ctx->aux_buf_sz);
1094     if (!y4m_ctx->aux_buf) {
1095       free(y4m_ctx->dst_buf);
1096       return -1;
1097     }
1098   }
1099   return 0;
1100 }
1101
1102 void y4m_input_close(y4m_input *_y4m) {
1103   free(_y4m->dst_buf);
1104   free(_y4m->aux_buf);
1105 }
1106
1107 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1108   char frame[6];
1109   int pic_sz;
1110   int c_w;
1111   int c_h;
1112   int c_sz;
1113   int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1114   /*Read and skip the frame header.*/
1115   if (!file_read(frame, 6, _fin)) return 0;
1116   if (memcmp(frame, "FRAME", 5)) {
1117     fprintf(stderr, "Loss of framing in Y4M input data\n");
1118     return -1;
1119   }
1120   if (frame[5] != '\n') {
1121     char c;
1122     int j;
1123     for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1124     }
1125     if (j == 79) {
1126       fprintf(stderr, "Error parsing Y4M frame header\n");
1127       return -1;
1128     }
1129   }
1130   /*Read the frame data that needs no conversion.*/
1131   if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1132     fprintf(stderr, "Error reading Y4M frame data.\n");
1133     return -1;
1134   }
1135   /*Read the frame data that does need conversion.*/
1136   if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1137     fprintf(stderr, "Error reading Y4M frame data.\n");
1138     return -1;
1139   }
1140   /*Now convert the just read frame.*/
1141   (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1142   /*Fill in the frame buffer pointers.
1143     We don't use vpx_img_wrap() because it forces padding for odd picture
1144      sizes, which would require a separate fread call for every row.*/
1145   memset(_img, 0, sizeof(*_img));
1146   /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1147   _img->fmt = _y4m->vpx_fmt;
1148   _img->w = _img->d_w = _y4m->pic_w;
1149   _img->h = _img->d_h = _y4m->pic_h;
1150   _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1151   _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1152   _img->bps = _y4m->bps;
1153
1154   /*Set up the buffer pointers.*/
1155   pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1156   c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1157   c_w *= bytes_per_sample;
1158   c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1159   c_sz = c_w * c_h;
1160   _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1161       _y4m->pic_w * bytes_per_sample;
1162   _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1163   _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1164   _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1165   _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1166   _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
1167   return 1;
1168 }