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