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