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