top-level: apply clang-format
[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 <errno.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "vpx/vpx_integer.h"
18 #include "y4minput.h"
19
20 // Reads 'size' bytes from 'file' into 'buf' with some fault tolerance.
21 // Returns true on success.
22 static int file_read(void *buf, size_t size, FILE *file) {
23   const int kMaxRetries = 5;
24   int retry_count = 0;
25   int file_error;
26   size_t len = 0;
27   do {
28     const size_t n = fread((uint8_t *)buf + len, 1, size - len, file);
29     len += n;
30     file_error = ferror(file);
31     if (file_error) {
32       if (errno == EINTR || errno == EAGAIN) {
33         clearerr(file);
34         continue;
35       } else {
36         fprintf(stderr, "Error reading file: %u of %u bytes read, %d: %s\n",
37                 (uint32_t)len, (uint32_t)size, errno, strerror(errno));
38         return 0;
39       }
40     }
41   } while (!feof(file) && len < size && ++retry_count < kMaxRetries);
42
43   if (!feof(file) && len != size) {
44     fprintf(stderr,
45             "Error reading file: %u of %u bytes read,"
46             " error: %d, retries: %d, %d: %s\n",
47             (uint32_t)len, (uint32_t)size, file_error, retry_count, errno,
48             strerror(errno));
49   }
50   return len == size;
51 }
52
53 static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
54   int got_w;
55   int got_h;
56   int got_fps;
57   int got_interlace;
58   int got_par;
59   int got_chroma;
60   char *p;
61   char *q;
62   got_w = got_h = got_fps = got_interlace = got_par = got_chroma = 0;
63   for (p = _tags;; p = q) {
64     /*Skip any leading spaces.*/
65     while (*p == ' ') p++;
66     /*If that's all we have, stop.*/
67     if (p[0] == '\0') break;
68     /*Find the end of this tag.*/
69     for (q = p + 1; *q != '\0' && *q != ' '; q++)
70       ;
71     /*Process the tag.*/
72     switch (p[0]) {
73       case 'W': {
74         if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
75         got_w = 1;
76       } break;
77       case 'H': {
78         if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
79         got_h = 1;
80       } break;
81       case 'F': {
82         if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
83           return -1;
84         }
85         got_fps = 1;
86       } break;
87       case 'I': {
88         _y4m->interlace = p[1];
89         got_interlace = 1;
90       } break;
91       case 'A': {
92         if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
93           return -1;
94         }
95         got_par = 1;
96       } break;
97       case 'C': {
98         if (q - p > 16) return -1;
99         memcpy(_y4m->chroma_type, p + 1, q - p - 1);
100         _y4m->chroma_type[q - p - 1] = '\0';
101         got_chroma = 1;
102       } break;
103         /*Ignore unknown tags.*/
104     }
105   }
106   if (!got_w || !got_h || !got_fps) return -1;
107   if (!got_interlace) _y4m->interlace = '?';
108   if (!got_par) _y4m->par_n = _y4m->par_d = 0;
109   /*Chroma-type is not specified in older files, e.g., those generated by
110      mplayer.*/
111   if (!got_chroma) strcpy(_y4m->chroma_type, "420");
112   return 0;
113 }
114
115 /*All anti-aliasing filters in the following conversion functions are based on
116    one of two window functions:
117   The 6-tap Lanczos window (for down-sampling and shifts):
118    sinc(\pi*t)*sinc(\pi*t/3), |t|<3  (sinc(t)==sin(t)/t)
119    0,                         |t|>=3
120   The 4-tap Mitchell window (for up-sampling):
121    7|t|^3-12|t|^2+16/3,             |t|<1
122    -(7/3)|x|^3+12|x|^2-20|x|+32/3,  |t|<2
123    0,                               |t|>=2
124   The number of taps is intentionally kept small to reduce computational
125    overhead and limit ringing.
126
127   The taps from these filters are scaled so that their sum is 1, and the result
128    is scaled by 128 and rounded to integers to create a filter whose
129    intermediate values fit inside 16 bits.
130   Coefficients are rounded in such a way as to ensure their sum is still 128,
131    which is usually equivalent to normal rounding.
132
133   Conversions which require both horizontal and vertical filtering could
134    have these steps pipelined, for less memory consumption and better cache
135    performance, but we do them separately for simplicity.*/
136
137 #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
138 #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
139 #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
140
141 /*420jpeg chroma samples are sited like:
142   Y-------Y-------Y-------Y-------
143   |       |       |       |
144   |   BR  |       |   BR  |
145   |       |       |       |
146   Y-------Y-------Y-------Y-------
147   |       |       |       |
148   |       |       |       |
149   |       |       |       |
150   Y-------Y-------Y-------Y-------
151   |       |       |       |
152   |   BR  |       |   BR  |
153   |       |       |       |
154   Y-------Y-------Y-------Y-------
155   |       |       |       |
156   |       |       |       |
157   |       |       |       |
158
159   420mpeg2 chroma samples are sited like:
160   Y-------Y-------Y-------Y-------
161   |       |       |       |
162   BR      |       BR      |
163   |       |       |       |
164   Y-------Y-------Y-------Y-------
165   |       |       |       |
166   |       |       |       |
167   |       |       |       |
168   Y-------Y-------Y-------Y-------
169   |       |       |       |
170   BR      |       BR      |
171   |       |       |       |
172   Y-------Y-------Y-------Y-------
173   |       |       |       |
174   |       |       |       |
175   |       |       |       |
176
177   We use a resampling filter to shift the site locations one quarter pixel (at
178    the chroma plane's resolution) to the right.
179   The 4:2:2 modes look exactly the same, except there are twice as many chroma
180    lines, and they are vertically co-sited with the luma samples in both the
181    mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
182 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
183                                         const unsigned char *_src, int _c_w,
184                                         int _c_h) {
185   int y;
186   int x;
187   for (y = 0; y < _c_h; y++) {
188     /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
189        window.*/
190     for (x = 0; x < OC_MINI(_c_w, 2); x++) {
191       _dst[x] = (unsigned char)OC_CLAMPI(
192           0, (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
193               35 * _src[OC_MINI(x + 1, _c_w - 1)] -
194               9 * _src[OC_MINI(x + 2, _c_w - 1)] +
195               _src[OC_MINI(x + 3, _c_w - 1)] + 64) >>
196                  7,
197           255);
198     }
199     for (; x < _c_w - 3; x++) {
200       _dst[x] = (unsigned char)OC_CLAMPI(
201           0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
202               35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
203                  7,
204           255);
205     }
206     for (; x < _c_w; x++) {
207       _dst[x] = (unsigned char)OC_CLAMPI(
208           0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
209               35 * _src[OC_MINI(x + 1, _c_w - 1)] -
210               9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
211                  7,
212           255);
213     }
214     _dst += _c_w;
215     _src += _c_w;
216   }
217 }
218
219 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
220 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
221                                          unsigned char *_aux) {
222   int c_w;
223   int c_h;
224   int c_sz;
225   int pli;
226   /*Skip past the luma data.*/
227   _dst += _y4m->pic_w * _y4m->pic_h;
228   /*Compute the size of each chroma plane.*/
229   c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
230   c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
231   c_sz = c_w * c_h;
232   for (pli = 1; pli < 3; pli++) {
233     y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
234     _dst += c_sz;
235     _aux += c_sz;
236   }
237 }
238
239 /*This format is only used for interlaced content, but is included for
240    completeness.
241
242   420jpeg chroma samples are sited like:
243   Y-------Y-------Y-------Y-------
244   |       |       |       |
245   |   BR  |       |   BR  |
246   |       |       |       |
247   Y-------Y-------Y-------Y-------
248   |       |       |       |
249   |       |       |       |
250   |       |       |       |
251   Y-------Y-------Y-------Y-------
252   |       |       |       |
253   |   BR  |       |   BR  |
254   |       |       |       |
255   Y-------Y-------Y-------Y-------
256   |       |       |       |
257   |       |       |       |
258   |       |       |       |
259
260   420paldv chroma samples are sited like:
261   YR------Y-------YR------Y-------
262   |       |       |       |
263   |       |       |       |
264   |       |       |       |
265   YB------Y-------YB------Y-------
266   |       |       |       |
267   |       |       |       |
268   |       |       |       |
269   YR------Y-------YR------Y-------
270   |       |       |       |
271   |       |       |       |
272   |       |       |       |
273   YB------Y-------YB------Y-------
274   |       |       |       |
275   |       |       |       |
276   |       |       |       |
277
278   We use a resampling filter to shift the site locations one quarter pixel (at
279    the chroma plane's resolution) to the right.
280   Then we use another filter to move the C_r location down one quarter pixel,
281    and the C_b location up one quarter pixel.*/
282 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
283                                          unsigned char *_aux) {
284   unsigned char *tmp;
285   int c_w;
286   int c_h;
287   int c_sz;
288   int pli;
289   int y;
290   int x;
291   /*Skip past the luma data.*/
292   _dst += _y4m->pic_w * _y4m->pic_h;
293   /*Compute the size of each chroma plane.*/
294   c_w = (_y4m->pic_w + 1) / 2;
295   c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
296   c_sz = c_w * c_h;
297   tmp = _aux + 2 * c_sz;
298   for (pli = 1; pli < 3; pli++) {
299     /*First do the horizontal re-sampling.
300       This is the same as the mpeg2 case, except that after the horizontal
301        case, we need to apply a second vertical filter.*/
302     y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
303     _aux += c_sz;
304     switch (pli) {
305       case 1: {
306         /*Slide C_b up a quarter-pel.
307           This is the same filter used above, but in the other order.*/
308         for (x = 0; x < c_w; x++) {
309           for (y = 0; y < OC_MINI(c_h, 3); y++) {
310             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
311                 0, (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
312                     35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
313                     17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
314                     4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
315                        7,
316                 255);
317           }
318           for (; y < c_h - 2; y++) {
319             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
320                 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
321                     35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
322                     17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
323                        7,
324                 255);
325           }
326           for (; y < c_h; y++) {
327             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
328                 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
329                     35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
330                     17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
331                     4 * tmp[(c_h - 1) * c_w] + 64) >>
332                        7,
333                 255);
334           }
335           _dst++;
336           tmp++;
337         }
338         _dst += c_sz - c_w;
339         tmp -= c_w;
340       } break;
341       case 2: {
342         /*Slide C_r down a quarter-pel.
343           This is the same as the horizontal filter.*/
344         for (x = 0; x < c_w; x++) {
345           for (y = 0; y < OC_MINI(c_h, 2); y++) {
346             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
347                 0,
348                 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
349                  114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
350                  9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
351                  tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
352                     7,
353                 255);
354           }
355           for (; y < c_h - 3; y++) {
356             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
357                 0, (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
358                     114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
359                     9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
360                        7,
361                 255);
362           }
363           for (; y < c_h; y++) {
364             _dst[y * c_w] = (unsigned char)OC_CLAMPI(
365                 0,
366                 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
367                  114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
368                  9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
369                  64) >>
370                     7,
371                 255);
372           }
373           _dst++;
374           tmp++;
375         }
376       } break;
377     }
378     /*For actual interlaced material, this would have to be done separately on
379        each field, and the shift amounts would be different.
380       C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
381        C_b up 1/8 in the bottom field.
382       The corresponding filters would be:
383        Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
384        Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
385   }
386 }
387
388 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
389   This is used as a helper by several converation routines.*/
390 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
391                                        const unsigned char *_src, int _c_w,
392                                        int _c_h) {
393   int y;
394   int x;
395   /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
396   for (x = 0; x < _c_w; x++) {
397     for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
398       _dst[(y >> 1) * _c_w] =
399           OC_CLAMPI(0, (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
400                         17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
401                         3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
402                            7,
403                     255);
404     }
405     for (; y < _c_h - 3; y += 2) {
406       _dst[(y >> 1) * _c_w] =
407           OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
408                         17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
409                         78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
410                            7,
411                     255);
412     }
413     for (; y < _c_h; y += 2) {
414       _dst[(y >> 1) * _c_w] = OC_CLAMPI(
415           0,
416           (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
417            17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
418            78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
419            64) >>
420               7,
421           255);
422     }
423     _src++;
424     _dst++;
425   }
426 }
427
428 /*420jpeg chroma samples are sited like:
429   Y-------Y-------Y-------Y-------
430   |       |       |       |
431   |   BR  |       |   BR  |
432   |       |       |       |
433   Y-------Y-------Y-------Y-------
434   |       |       |       |
435   |       |       |       |
436   |       |       |       |
437   Y-------Y-------Y-------Y-------
438   |       |       |       |
439   |   BR  |       |   BR  |
440   |       |       |       |
441   Y-------Y-------Y-------Y-------
442   |       |       |       |
443   |       |       |       |
444   |       |       |       |
445
446   422jpeg chroma samples are sited like:
447   Y---BR--Y-------Y---BR--Y-------
448   |       |       |       |
449   |       |       |       |
450   |       |       |       |
451   Y---BR--Y-------Y---BR--Y-------
452   |       |       |       |
453   |       |       |       |
454   |       |       |       |
455   Y---BR--Y-------Y---BR--Y-------
456   |       |       |       |
457   |       |       |       |
458   |       |       |       |
459   Y---BR--Y-------Y---BR--Y-------
460   |       |       |       |
461   |       |       |       |
462   |       |       |       |
463
464   We use a resampling filter to decimate the chroma planes by two in the
465    vertical direction.*/
466 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
467                                         unsigned char *_aux) {
468   int c_w;
469   int c_h;
470   int c_sz;
471   int dst_c_w;
472   int dst_c_h;
473   int dst_c_sz;
474   int pli;
475   /*Skip past the luma data.*/
476   _dst += _y4m->pic_w * _y4m->pic_h;
477   /*Compute the size of each chroma plane.*/
478   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
479   c_h = _y4m->pic_h;
480   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
481   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
482   c_sz = c_w * c_h;
483   dst_c_sz = dst_c_w * dst_c_h;
484   for (pli = 1; pli < 3; pli++) {
485     y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
486     _aux += c_sz;
487     _dst += dst_c_sz;
488   }
489 }
490
491 /*420jpeg chroma samples are sited like:
492   Y-------Y-------Y-------Y-------
493   |       |       |       |
494   |   BR  |       |   BR  |
495   |       |       |       |
496   Y-------Y-------Y-------Y-------
497   |       |       |       |
498   |       |       |       |
499   |       |       |       |
500   Y-------Y-------Y-------Y-------
501   |       |       |       |
502   |   BR  |       |   BR  |
503   |       |       |       |
504   Y-------Y-------Y-------Y-------
505   |       |       |       |
506   |       |       |       |
507   |       |       |       |
508
509   422 chroma samples are sited like:
510   YBR-----Y-------YBR-----Y-------
511   |       |       |       |
512   |       |       |       |
513   |       |       |       |
514   YBR-----Y-------YBR-----Y-------
515   |       |       |       |
516   |       |       |       |
517   |       |       |       |
518   YBR-----Y-------YBR-----Y-------
519   |       |       |       |
520   |       |       |       |
521   |       |       |       |
522   YBR-----Y-------YBR-----Y-------
523   |       |       |       |
524   |       |       |       |
525   |       |       |       |
526
527   We use a resampling filter to shift the original site locations one quarter
528    pixel (at the original chroma resolution) to the right.
529   Then we use a second resampling filter to decimate the chroma planes by two
530    in the vertical direction.*/
531 static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
532                                     unsigned char *_aux) {
533   unsigned char *tmp;
534   int c_w;
535   int c_h;
536   int c_sz;
537   int dst_c_h;
538   int dst_c_sz;
539   int pli;
540   /*Skip past the luma data.*/
541   _dst += _y4m->pic_w * _y4m->pic_h;
542   /*Compute the size of each chroma plane.*/
543   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
544   c_h = _y4m->pic_h;
545   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
546   c_sz = c_w * c_h;
547   dst_c_sz = c_w * dst_c_h;
548   tmp = _aux + 2 * c_sz;
549   for (pli = 1; pli < 3; pli++) {
550     /*In reality, the horizontal and vertical steps could be pipelined, for
551        less memory consumption and better cache performance, but we do them
552        separately for simplicity.*/
553     /*First do horizontal filtering (convert to 422jpeg)*/
554     y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
555     /*Now do the vertical filtering.*/
556     y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
557     _aux += c_sz;
558     _dst += dst_c_sz;
559   }
560 }
561
562 /*420jpeg chroma samples are sited like:
563   Y-------Y-------Y-------Y-------
564   |       |       |       |
565   |   BR  |       |   BR  |
566   |       |       |       |
567   Y-------Y-------Y-------Y-------
568   |       |       |       |
569   |       |       |       |
570   |       |       |       |
571   Y-------Y-------Y-------Y-------
572   |       |       |       |
573   |   BR  |       |   BR  |
574   |       |       |       |
575   Y-------Y-------Y-------Y-------
576   |       |       |       |
577   |       |       |       |
578   |       |       |       |
579
580   411 chroma samples are sited like:
581   YBR-----Y-------Y-------Y-------
582   |       |       |       |
583   |       |       |       |
584   |       |       |       |
585   YBR-----Y-------Y-------Y-------
586   |       |       |       |
587   |       |       |       |
588   |       |       |       |
589   YBR-----Y-------Y-------Y-------
590   |       |       |       |
591   |       |       |       |
592   |       |       |       |
593   YBR-----Y-------Y-------Y-------
594   |       |       |       |
595   |       |       |       |
596   |       |       |       |
597
598   We use a filter to resample at site locations one eighth pixel (at the source
599    chroma plane's horizontal resolution) and five eighths of a pixel to the
600    right.
601   Then we use another filter to decimate the planes by 2 in the vertical
602    direction.*/
603 static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
604                                     unsigned char *_aux) {
605   unsigned char *tmp;
606   int c_w;
607   int c_h;
608   int c_sz;
609   int dst_c_w;
610   int dst_c_h;
611   int dst_c_sz;
612   int tmp_sz;
613   int pli;
614   int y;
615   int x;
616   /*Skip past the luma data.*/
617   _dst += _y4m->pic_w * _y4m->pic_h;
618   /*Compute the size of each chroma plane.*/
619   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
620   c_h = _y4m->pic_h;
621   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_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 = dst_c_w * dst_c_h;
625   tmp_sz = dst_c_w * c_h;
626   tmp = _aux + 2 * c_sz;
627   for (pli = 1; pli < 3; pli++) {
628     /*In reality, the horizontal and vertical steps could be pipelined, for
629        less memory consumption and better cache performance, but we do them
630        separately for simplicity.*/
631     /*First do horizontal filtering (convert to 422jpeg)*/
632     for (y = 0; y < c_h; y++) {
633       /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
634          4-tap Mitchell window.*/
635       for (x = 0; x < OC_MINI(c_w, 1); x++) {
636         tmp[x << 1] = (unsigned char)OC_CLAMPI(
637             0, (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
638                 _aux[OC_MINI(2, c_w - 1)] + 64) >>
639                    7,
640             255);
641         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
642             0, (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
643                 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
644                    7,
645             255);
646       }
647       for (; x < c_w - 2; x++) {
648         tmp[x << 1] =
649             (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] +
650                                          18 * _aux[x + 1] - _aux[x + 2] + 64) >>
651                                             7,
652                                      255);
653         tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
654             0, (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
655                 5 * _aux[x + 2] + 64) >>
656                    7,
657             255);
658       }
659       for (; x < c_w; x++) {
660         tmp[x << 1] = (unsigned char)OC_CLAMPI(
661             0, (_aux[x - 1] + 110 * _aux[x] +
662                 18 * _aux[OC_MINI(x + 1, c_w - 1)] - _aux[c_w - 1] + 64) >>
663                    7,
664             255);
665         if ((x << 1 | 1) < dst_c_w) {
666           tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
667               0,
668               (-3 * _aux[x - 1] + 50 * _aux[x] +
669                86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
670                   7,
671               255);
672         }
673       }
674       tmp += dst_c_w;
675       _aux += c_w;
676     }
677     tmp -= tmp_sz;
678     /*Now do the vertical filtering.*/
679     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
680     _dst += dst_c_sz;
681   }
682 }
683
684 /*Convert 444 to 420jpeg.*/
685 static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
686                                     unsigned char *_aux) {
687   unsigned char *tmp;
688   int c_w;
689   int c_h;
690   int c_sz;
691   int dst_c_w;
692   int dst_c_h;
693   int dst_c_sz;
694   int tmp_sz;
695   int pli;
696   int y;
697   int x;
698   /*Skip past the luma data.*/
699   _dst += _y4m->pic_w * _y4m->pic_h;
700   /*Compute the size of each chroma plane.*/
701   c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
702   c_h = _y4m->pic_h;
703   dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
704   dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
705   c_sz = c_w * c_h;
706   dst_c_sz = dst_c_w * dst_c_h;
707   tmp_sz = dst_c_w * c_h;
708   tmp = _aux + 2 * c_sz;
709   for (pli = 1; pli < 3; pli++) {
710     /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
711     for (y = 0; y < c_h; y++) {
712       for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
713         tmp[x >> 1] =
714             OC_CLAMPI(0, (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
715                           17 * _aux[OC_MINI(2, c_w - 1)] +
716                           3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
717                              7,
718                       255);
719       }
720       for (; x < c_w - 3; x += 2) {
721         tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[x + 3]) -
722                                     17 * (_aux[x - 1] + _aux[x + 2]) +
723                                     78 * (_aux[x] + _aux[x + 1]) + 64) >>
724                                        7,
725                                 255);
726       }
727       for (; x < c_w; x += 2) {
728         tmp[x >> 1] = OC_CLAMPI(
729             0, (3 * (_aux[x - 2] + _aux[c_w - 1]) -
730                 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
731                 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
732                    7,
733             255);
734       }
735       tmp += dst_c_w;
736       _aux += c_w;
737     }
738     tmp -= tmp_sz;
739     /*Now do the vertical filtering.*/
740     y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
741     _dst += dst_c_sz;
742   }
743 }
744
745 /*The image is padded with empty chroma components at 4:2:0.*/
746 static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
747                                      unsigned char *_aux) {
748   int c_sz;
749   (void)_aux;
750   _dst += _y4m->pic_w * _y4m->pic_h;
751   c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
752          ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
753   memset(_dst, 128, c_sz * 2);
754 }
755
756 /*No conversion function needed.*/
757 static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
758                              unsigned char *_aux) {
759   (void)_y4m;
760   (void)_dst;
761   (void)_aux;
762 }
763
764 int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
765                    int only_420) {
766   char buffer[80] = { 0 };
767   int ret;
768   int i;
769   /*Read until newline, or 80 cols, whichever happens first.*/
770   for (i = 0; i < 79; i++) {
771     if (_nskip > 0) {
772       buffer[i] = *_skip++;
773       _nskip--;
774     } else {
775       if (!file_read(buffer + i, 1, _fin)) return -1;
776     }
777     if (buffer[i] == '\n') break;
778   }
779   /*We skipped too much header data.*/
780   if (_nskip > 0) return -1;
781   if (i == 79) {
782     fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
783     return -1;
784   }
785   buffer[i] = '\0';
786   if (memcmp(buffer, "YUV4MPEG", 8)) {
787     fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
788     return -1;
789   }
790   if (buffer[8] != '2') {
791     fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
792   }
793   ret = y4m_parse_tags(_y4m, buffer + 5);
794   if (ret < 0) {
795     fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
796     return ret;
797   }
798   if (_y4m->interlace == '?') {
799     fprintf(stderr,
800             "Warning: Input video interlacing format unknown; "
801             "assuming progressive scan.\n");
802   } else if (_y4m->interlace != 'p') {
803     fprintf(stderr,
804             "Input video is interlaced; "
805             "Only progressive scan handled.\n");
806     return -1;
807   }
808   _y4m->vpx_fmt = VPX_IMG_FMT_I420;
809   _y4m->bps = 12;
810   _y4m->bit_depth = 8;
811   if (strcmp(_y4m->chroma_type, "420") == 0 ||
812       strcmp(_y4m->chroma_type, "420jpeg") == 0) {
813     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
814         _y4m->dst_c_dec_v = 2;
815     _y4m->dst_buf_read_sz =
816         _y4m->pic_w * _y4m->pic_h +
817         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
818     /* Natively supported: no conversion required. */
819     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
820     _y4m->convert = y4m_convert_null;
821   } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
822     _y4m->src_c_dec_h = 2;
823     _y4m->dst_c_dec_h = 2;
824     _y4m->src_c_dec_v = 2;
825     _y4m->dst_c_dec_v = 2;
826     _y4m->dst_buf_read_sz =
827         2 * (_y4m->pic_w * _y4m->pic_h +
828              2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
829     /* Natively supported: no conversion required. */
830     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
831     _y4m->convert = y4m_convert_null;
832     _y4m->bit_depth = 10;
833     _y4m->bps = 15;
834     _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
835     if (only_420) {
836       fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
837       return -1;
838     }
839   } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
840     _y4m->src_c_dec_h = 2;
841     _y4m->dst_c_dec_h = 2;
842     _y4m->src_c_dec_v = 2;
843     _y4m->dst_c_dec_v = 2;
844     _y4m->dst_buf_read_sz =
845         2 * (_y4m->pic_w * _y4m->pic_h +
846              2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
847     /* Natively supported: no conversion required. */
848     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
849     _y4m->convert = y4m_convert_null;
850     _y4m->bit_depth = 12;
851     _y4m->bps = 18;
852     _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
853     if (only_420) {
854       fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
855       return -1;
856     }
857   } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
858     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
859         _y4m->dst_c_dec_v = 2;
860     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
861     /*Chroma filter required: read into the aux buf first.*/
862     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
863         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
864     _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
865   } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
866     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
867         _y4m->dst_c_dec_v = 2;
868     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
869     /*Chroma filter required: read into the aux buf first.
870       We need to make two filter passes, so we need some extra space in the
871        aux buffer.*/
872     _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
873     _y4m->aux_buf_read_sz =
874         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
875     _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
876   } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
877     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
878     _y4m->src_c_dec_v = 1;
879     _y4m->dst_c_dec_v = 2;
880     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
881     /*Chroma filter required: read into the aux buf first.*/
882     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
883         2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
884     _y4m->convert = y4m_convert_422jpeg_420jpeg;
885   } else if (strcmp(_y4m->chroma_type, "422") == 0) {
886     _y4m->src_c_dec_h = 2;
887     _y4m->src_c_dec_v = 1;
888     if (only_420) {
889       _y4m->dst_c_dec_h = 2;
890       _y4m->dst_c_dec_v = 2;
891       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
892       /*Chroma filter required: read into the aux buf first.
893         We need to make two filter passes, so we need some extra space in the
894          aux buffer.*/
895       _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
896       _y4m->aux_buf_sz =
897           _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
898       _y4m->convert = y4m_convert_422_420jpeg;
899     } else {
900       _y4m->vpx_fmt = VPX_IMG_FMT_I422;
901       _y4m->bps = 16;
902       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
903       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
904       _y4m->dst_buf_read_sz =
905           _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
906       /*Natively supported: no conversion required.*/
907       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
908       _y4m->convert = y4m_convert_null;
909     }
910   } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
911     _y4m->src_c_dec_h = 2;
912     _y4m->src_c_dec_v = 1;
913     _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
914     _y4m->bps = 20;
915     _y4m->bit_depth = 10;
916     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
917     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
918     _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
919                                  2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
920     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
921     _y4m->convert = y4m_convert_null;
922     if (only_420) {
923       fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
924       return -1;
925     }
926   } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
927     _y4m->src_c_dec_h = 2;
928     _y4m->src_c_dec_v = 1;
929     _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
930     _y4m->bps = 24;
931     _y4m->bit_depth = 12;
932     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
933     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
934     _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
935                                  2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
936     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
937     _y4m->convert = y4m_convert_null;
938     if (only_420) {
939       fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
940       return -1;
941     }
942   } else if (strcmp(_y4m->chroma_type, "411") == 0) {
943     _y4m->src_c_dec_h = 4;
944     _y4m->dst_c_dec_h = 2;
945     _y4m->src_c_dec_v = 1;
946     _y4m->dst_c_dec_v = 2;
947     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
948     /*Chroma filter required: read into the aux buf first.
949       We need to make two filter passes, so we need some extra space in the
950        aux buffer.*/
951     _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
952     _y4m->aux_buf_sz =
953         _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
954     _y4m->convert = y4m_convert_411_420jpeg;
955   } else if (strcmp(_y4m->chroma_type, "444") == 0) {
956     _y4m->src_c_dec_h = 1;
957     _y4m->src_c_dec_v = 1;
958     if (only_420) {
959       _y4m->dst_c_dec_h = 2;
960       _y4m->dst_c_dec_v = 2;
961       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
962       /*Chroma filter required: read into the aux buf first.
963         We need to make two filter passes, so we need some extra space in the
964          aux buffer.*/
965       _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
966       _y4m->aux_buf_sz =
967           _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
968       _y4m->convert = y4m_convert_444_420jpeg;
969     } else {
970       _y4m->vpx_fmt = VPX_IMG_FMT_I444;
971       _y4m->bps = 24;
972       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
973       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
974       _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
975       /*Natively supported: no conversion required.*/
976       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
977       _y4m->convert = y4m_convert_null;
978     }
979   } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
980     _y4m->src_c_dec_h = 1;
981     _y4m->src_c_dec_v = 1;
982     _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
983     _y4m->bps = 30;
984     _y4m->bit_depth = 10;
985     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
986     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
987     _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
988     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
989     _y4m->convert = y4m_convert_null;
990     if (only_420) {
991       fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
992       return -1;
993     }
994   } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
995     _y4m->src_c_dec_h = 1;
996     _y4m->src_c_dec_v = 1;
997     _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
998     _y4m->bps = 36;
999     _y4m->bit_depth = 12;
1000     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1001     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1002     _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1003     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1004     _y4m->convert = y4m_convert_null;
1005     if (only_420) {
1006       fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1007       return -1;
1008     }
1009   } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1010     _y4m->src_c_dec_h = 1;
1011     _y4m->src_c_dec_v = 1;
1012     if (only_420) {
1013       _y4m->dst_c_dec_h = 2;
1014       _y4m->dst_c_dec_v = 2;
1015       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1016       /*Chroma filter required: read into the aux buf first.
1017         We need to make two filter passes, so we need some extra space in the
1018          aux buffer.
1019         The extra plane also gets read into the aux buf.
1020         It will be discarded.*/
1021       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1022       _y4m->convert = y4m_convert_444_420jpeg;
1023     } else {
1024       _y4m->vpx_fmt = VPX_IMG_FMT_444A;
1025       _y4m->bps = 32;
1026       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1027       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1028       _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1029       /*Natively supported: no conversion required.*/
1030       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1031       _y4m->convert = y4m_convert_null;
1032     }
1033   } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1034     _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1035     _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1036     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1037     /*No extra space required, but we need to clear the chroma planes.*/
1038     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1039     _y4m->convert = y4m_convert_mono_420jpeg;
1040   } else {
1041     fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
1042     return -1;
1043   }
1044   /*The size of the final frame buffers is always computed from the
1045      destination chroma decimation type.*/
1046   _y4m->dst_buf_sz =
1047       _y4m->pic_w * _y4m->pic_h +
1048       2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1049           ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
1050   if (_y4m->bit_depth == 8)
1051     _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
1052   else
1053     _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
1054
1055   if (_y4m->aux_buf_sz > 0)
1056     _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
1057   return 0;
1058 }
1059
1060 void y4m_input_close(y4m_input *_y4m) {
1061   free(_y4m->dst_buf);
1062   free(_y4m->aux_buf);
1063 }
1064
1065 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1066   char frame[6];
1067   int pic_sz;
1068   int c_w;
1069   int c_h;
1070   int c_sz;
1071   int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1072   /*Read and skip the frame header.*/
1073   if (!file_read(frame, 6, _fin)) return 0;
1074   if (memcmp(frame, "FRAME", 5)) {
1075     fprintf(stderr, "Loss of framing in Y4M input data\n");
1076     return -1;
1077   }
1078   if (frame[5] != '\n') {
1079     char c;
1080     int j;
1081     for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1082     }
1083     if (j == 79) {
1084       fprintf(stderr, "Error parsing Y4M frame header\n");
1085       return -1;
1086     }
1087   }
1088   /*Read the frame data that needs no conversion.*/
1089   if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1090     fprintf(stderr, "Error reading Y4M frame data.\n");
1091     return -1;
1092   }
1093   /*Read the frame data that does need conversion.*/
1094   if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1095     fprintf(stderr, "Error reading Y4M frame data.\n");
1096     return -1;
1097   }
1098   /*Now convert the just read frame.*/
1099   (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1100   /*Fill in the frame buffer pointers.
1101     We don't use vpx_img_wrap() because it forces padding for odd picture
1102      sizes, which would require a separate fread call for every row.*/
1103   memset(_img, 0, sizeof(*_img));
1104   /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1105   _img->fmt = _y4m->vpx_fmt;
1106   _img->w = _img->d_w = _y4m->pic_w;
1107   _img->h = _img->d_h = _y4m->pic_h;
1108   _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1109   _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1110   _img->bps = _y4m->bps;
1111
1112   /*Set up the buffer pointers.*/
1113   pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1114   c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1115   c_w *= bytes_per_sample;
1116   c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1117   c_sz = c_w * c_h;
1118   _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1119       _y4m->pic_w * bytes_per_sample;
1120   _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1121   _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1122   _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1123   _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1124   _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
1125   return 1;
1126 }