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