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