Merge "Fix kf detection in some slide shows."
[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       }
78       case 'H': {
79         if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
80         got_h = 1;
81         break;
82       }
83       case 'F': {
84         if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
85           return -1;
86         }
87         got_fps = 1;
88         break;
89       }
90       case 'I': {
91         _y4m->interlace = p[1];
92         got_interlace = 1;
93         break;
94       }
95       case 'A': {
96         if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
97           return -1;
98         }
99         got_par = 1;
100         break;
101       }
102       case 'C': {
103         if (q - p > 16) return -1;
104         memcpy(_y4m->chroma_type, p + 1, q - p - 1);
105         _y4m->chroma_type[q - p - 1] = '\0';
106         got_chroma = 1;
107         break;
108       }
109         /*Ignore unknown tags.*/
110     }
111   }
112   if (!got_w || !got_h || !got_fps) return -1;
113   if (!got_interlace) _y4m->interlace = '?';
114   if (!got_par) _y4m->par_n = _y4m->par_d = 0;
115   /*Chroma-type is not specified in older files, e.g., those generated by
116      mplayer.*/
117   if (!got_chroma) strcpy(_y4m->chroma_type, "420");
118   return 0;
119 }
120
121 /*All anti-aliasing filters in the following conversion functions are based on
122    one of two window functions:
123   The 6-tap Lanczos window (for down-sampling and shifts):
124    sinc(\pi*t)*sinc(\pi*t/3), |t|<3  (sinc(t)==sin(t)/t)
125    0,                         |t|>=3
126   The 4-tap Mitchell window (for up-sampling):
127    7|t|^3-12|t|^2+16/3,             |t|<1
128    -(7/3)|x|^3+12|x|^2-20|x|+32/3,  |t|<2
129    0,                               |t|>=2
130   The number of taps is intentionally kept small to reduce computational
131    overhead and limit ringing.
132
133   The taps from these filters are scaled so that their sum is 1, and the
134   result is scaled by 128 and rounded to integers to create a filter whose
135    intermediate values fit inside 16 bits.
136   Coefficients are rounded in such a way as to ensure their sum is still 128,
137    which is usually equivalent to normal rounding.
138
139   Conversions which require both horizontal and vertical filtering could
140    have these steps pipelined, for less memory consumption and better cache
141    performance, but we do them separately for simplicity.*/
142
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 int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
789                    int only_420) {
790   char buffer[80] = { 0 };
791   int ret;
792   int i;
793   /*Read until newline, or 80 cols, whichever happens first.*/
794   for (i = 0; i < 79; i++) {
795     if (_nskip > 0) {
796       buffer[i] = *_skip++;
797       _nskip--;
798     } else {
799       if (!file_read(buffer + i, 1, _fin)) return -1;
800     }
801     if (buffer[i] == '\n') break;
802   }
803   /*We skipped too much header data.*/
804   if (_nskip > 0) return -1;
805   if (i == 79) {
806     fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
807     return -1;
808   }
809   buffer[i] = '\0';
810   if (memcmp(buffer, "YUV4MPEG", 8)) {
811     fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
812     return -1;
813   }
814   if (buffer[8] != '2') {
815     fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
816   }
817   ret = y4m_parse_tags(_y4m, buffer + 5);
818   if (ret < 0) {
819     fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
820     return ret;
821   }
822   if (_y4m->interlace == '?') {
823     fprintf(stderr,
824             "Warning: Input video interlacing format unknown; "
825             "assuming progressive scan.\n");
826   } else if (_y4m->interlace != 'p') {
827     fprintf(stderr,
828             "Input video is interlaced; "
829             "Only progressive scan handled.\n");
830     return -1;
831   }
832   _y4m->vpx_fmt = VPX_IMG_FMT_I420;
833   _y4m->bps = 12;
834   _y4m->bit_depth = 8;
835   if (strcmp(_y4m->chroma_type, "420") == 0 ||
836       strcmp(_y4m->chroma_type, "420jpeg") == 0) {
837     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
838         _y4m->dst_c_dec_v = 2;
839     _y4m->dst_buf_read_sz =
840         _y4m->pic_w * _y4m->pic_h +
841         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
842     /* Natively supported: no conversion required. */
843     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
844     _y4m->convert = y4m_convert_null;
845   } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
846     _y4m->src_c_dec_h = 2;
847     _y4m->dst_c_dec_h = 2;
848     _y4m->src_c_dec_v = 2;
849     _y4m->dst_c_dec_v = 2;
850     _y4m->dst_buf_read_sz =
851         2 * (_y4m->pic_w * _y4m->pic_h +
852              2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
853     /* Natively supported: no conversion required. */
854     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
855     _y4m->convert = y4m_convert_null;
856     _y4m->bit_depth = 10;
857     _y4m->bps = 15;
858     _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
859     if (only_420) {
860       fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
861       return -1;
862     }
863   } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
864     _y4m->src_c_dec_h = 2;
865     _y4m->dst_c_dec_h = 2;
866     _y4m->src_c_dec_v = 2;
867     _y4m->dst_c_dec_v = 2;
868     _y4m->dst_buf_read_sz =
869         2 * (_y4m->pic_w * _y4m->pic_h +
870              2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
871     /* Natively supported: no conversion required. */
872     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
873     _y4m->convert = y4m_convert_null;
874     _y4m->bit_depth = 12;
875     _y4m->bps = 18;
876     _y4m->vpx_fmt = VPX_IMG_FMT_I42016;
877     if (only_420) {
878       fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
879       return -1;
880     }
881   } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
882     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
883         _y4m->dst_c_dec_v = 2;
884     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
885     /*Chroma filter required: read into the aux buf first.*/
886     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
887         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
888     _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
889   } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
890     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
891         _y4m->dst_c_dec_v = 2;
892     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
893     /*Chroma filter required: read into the aux buf first.
894       We need to make two filter passes, so we need some extra space in the
895        aux buffer.*/
896     _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
897     _y4m->aux_buf_read_sz =
898         2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
899     _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
900   } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
901     _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
902     _y4m->src_c_dec_v = 1;
903     _y4m->dst_c_dec_v = 2;
904     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
905     /*Chroma filter required: read into the aux buf first.*/
906     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
907         2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
908     _y4m->convert = y4m_convert_422jpeg_420jpeg;
909   } else if (strcmp(_y4m->chroma_type, "422") == 0) {
910     _y4m->src_c_dec_h = 2;
911     _y4m->src_c_dec_v = 1;
912     if (only_420) {
913       _y4m->dst_c_dec_h = 2;
914       _y4m->dst_c_dec_v = 2;
915       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
916       /*Chroma filter required: read into the aux buf first.
917         We need to make two filter passes, so we need some extra space in the
918          aux buffer.*/
919       _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
920       _y4m->aux_buf_sz =
921           _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
922       _y4m->convert = y4m_convert_422_420jpeg;
923     } else {
924       _y4m->vpx_fmt = VPX_IMG_FMT_I422;
925       _y4m->bps = 16;
926       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
927       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
928       _y4m->dst_buf_read_sz =
929           _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
930       /*Natively supported: no conversion required.*/
931       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
932       _y4m->convert = y4m_convert_null;
933     }
934   } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
935     _y4m->src_c_dec_h = 2;
936     _y4m->src_c_dec_v = 1;
937     _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
938     _y4m->bps = 20;
939     _y4m->bit_depth = 10;
940     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
941     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
942     _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
943                                  2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
944     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
945     _y4m->convert = y4m_convert_null;
946     if (only_420) {
947       fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
948       return -1;
949     }
950   } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
951     _y4m->src_c_dec_h = 2;
952     _y4m->src_c_dec_v = 1;
953     _y4m->vpx_fmt = VPX_IMG_FMT_I42216;
954     _y4m->bps = 24;
955     _y4m->bit_depth = 12;
956     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
957     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
958     _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
959                                  2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
960     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
961     _y4m->convert = y4m_convert_null;
962     if (only_420) {
963       fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
964       return -1;
965     }
966   } else if (strcmp(_y4m->chroma_type, "411") == 0) {
967     _y4m->src_c_dec_h = 4;
968     _y4m->dst_c_dec_h = 2;
969     _y4m->src_c_dec_v = 1;
970     _y4m->dst_c_dec_v = 2;
971     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
972     /*Chroma filter required: read into the aux buf first.
973       We need to make two filter passes, so we need some extra space in the
974        aux buffer.*/
975     _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
976     _y4m->aux_buf_sz =
977         _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
978     _y4m->convert = y4m_convert_411_420jpeg;
979   } else if (strcmp(_y4m->chroma_type, "444") == 0) {
980     _y4m->src_c_dec_h = 1;
981     _y4m->src_c_dec_v = 1;
982     if (only_420) {
983       _y4m->dst_c_dec_h = 2;
984       _y4m->dst_c_dec_v = 2;
985       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
986       /*Chroma filter required: read into the aux buf first.
987         We need to make two filter passes, so we need some extra space in the
988          aux buffer.*/
989       _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
990       _y4m->aux_buf_sz =
991           _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
992       _y4m->convert = y4m_convert_444_420jpeg;
993     } else {
994       _y4m->vpx_fmt = VPX_IMG_FMT_I444;
995       _y4m->bps = 24;
996       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
997       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
998       _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
999       /*Natively supported: no conversion required.*/
1000       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1001       _y4m->convert = y4m_convert_null;
1002     }
1003   } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
1004     _y4m->src_c_dec_h = 1;
1005     _y4m->src_c_dec_v = 1;
1006     _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
1007     _y4m->bps = 30;
1008     _y4m->bit_depth = 10;
1009     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1010     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1011     _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1012     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1013     _y4m->convert = y4m_convert_null;
1014     if (only_420) {
1015       fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1016       return -1;
1017     }
1018   } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
1019     _y4m->src_c_dec_h = 1;
1020     _y4m->src_c_dec_v = 1;
1021     _y4m->vpx_fmt = VPX_IMG_FMT_I44416;
1022     _y4m->bps = 36;
1023     _y4m->bit_depth = 12;
1024     _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1025     _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1026     _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1027     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1028     _y4m->convert = y4m_convert_null;
1029     if (only_420) {
1030       fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1031       return -1;
1032     }
1033   } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1034     _y4m->src_c_dec_h = 1;
1035     _y4m->src_c_dec_v = 1;
1036     if (only_420) {
1037       _y4m->dst_c_dec_h = 2;
1038       _y4m->dst_c_dec_v = 2;
1039       _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1040       /*Chroma filter required: read into the aux buf first.
1041         We need to make two filter passes, so we need some extra space in the
1042          aux buffer.
1043         The extra plane also gets read into the aux buf.
1044         It will be discarded.*/
1045       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1046       _y4m->convert = y4m_convert_444_420jpeg;
1047     } else {
1048       _y4m->vpx_fmt = VPX_IMG_FMT_444A;
1049       _y4m->bps = 32;
1050       _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1051       _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1052       _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1053       /*Natively supported: no conversion required.*/
1054       _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1055       _y4m->convert = y4m_convert_null;
1056     }
1057   } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1058     _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1059     _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1060     _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1061     /*No extra space required, but we need to clear the chroma planes.*/
1062     _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1063     _y4m->convert = y4m_convert_mono_420jpeg;
1064   } else {
1065     fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
1066     return -1;
1067   }
1068   /*The size of the final frame buffers is always computed from the
1069      destination chroma decimation type.*/
1070   _y4m->dst_buf_sz =
1071       _y4m->pic_w * _y4m->pic_h +
1072       2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1073           ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
1074   if (_y4m->bit_depth == 8)
1075     _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
1076   else
1077     _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
1078
1079   if (_y4m->aux_buf_sz > 0)
1080     _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
1081   return 0;
1082 }
1083
1084 void y4m_input_close(y4m_input *_y4m) {
1085   free(_y4m->dst_buf);
1086   free(_y4m->aux_buf);
1087 }
1088
1089 int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
1090   char frame[6];
1091   int pic_sz;
1092   int c_w;
1093   int c_h;
1094   int c_sz;
1095   int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
1096   /*Read and skip the frame header.*/
1097   if (!file_read(frame, 6, _fin)) return 0;
1098   if (memcmp(frame, "FRAME", 5)) {
1099     fprintf(stderr, "Loss of framing in Y4M input data\n");
1100     return -1;
1101   }
1102   if (frame[5] != '\n') {
1103     char c;
1104     int j;
1105     for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1106     }
1107     if (j == 79) {
1108       fprintf(stderr, "Error parsing Y4M frame header\n");
1109       return -1;
1110     }
1111   }
1112   /*Read the frame data that needs no conversion.*/
1113   if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
1114     fprintf(stderr, "Error reading Y4M frame data.\n");
1115     return -1;
1116   }
1117   /*Read the frame data that does need conversion.*/
1118   if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
1119     fprintf(stderr, "Error reading Y4M frame data.\n");
1120     return -1;
1121   }
1122   /*Now convert the just read frame.*/
1123   (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
1124   /*Fill in the frame buffer pointers.
1125     We don't use vpx_img_wrap() because it forces padding for odd picture
1126      sizes, which would require a separate fread call for every row.*/
1127   memset(_img, 0, sizeof(*_img));
1128   /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
1129   _img->fmt = _y4m->vpx_fmt;
1130   _img->w = _img->d_w = _y4m->pic_w;
1131   _img->h = _img->d_h = _y4m->pic_h;
1132   _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1133   _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
1134   _img->bps = _y4m->bps;
1135
1136   /*Set up the buffer pointers.*/
1137   pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
1138   c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
1139   c_w *= bytes_per_sample;
1140   c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1141   c_sz = c_w * c_h;
1142   _img->stride[VPX_PLANE_Y] = _img->stride[VPX_PLANE_ALPHA] =
1143       _y4m->pic_w * bytes_per_sample;
1144   _img->stride[VPX_PLANE_U] = _img->stride[VPX_PLANE_V] = c_w;
1145   _img->planes[VPX_PLANE_Y] = _y4m->dst_buf;
1146   _img->planes[VPX_PLANE_U] = _y4m->dst_buf + pic_sz;
1147   _img->planes[VPX_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1148   _img->planes[VPX_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
1149   return 1;
1150 }