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