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