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