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