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