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