blob: e009042b2254ac551275903ba3df9ff0f2f2e18c [file] [log] [blame]
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001/*
Yaowu Xu9c01aa12016-09-01 14:32:49 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04003 *
Yaowu Xu9c01aa12016-09-01 14:32:49 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040010 *
Yaowu Xu9c01aa12016-09-01 14:32:49 -070011 * Based on code from the OggTheora software codec source code,
12 * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040013 */
James Zerndf0829f2014-02-12 16:30:43 -080014#include <errno.h>
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040015#include <stdlib.h>
16#include <string.h>
James Zerndf0829f2014-02-12 16:30:43 -080017
Yaowu Xuf883b422016-08-30 14:01:10 -070018#include "aom/aom_integer.h"
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040019#include "y4minput.h"
20
James Zerndf0829f2014-02-12 16:30:43 -080021// Reads 'size' bytes from 'file' into 'buf' with some fault tolerance.
22// Returns true on success.
23static int file_read(void *buf, size_t size, FILE *file) {
24 const int kMaxRetries = 5;
25 int retry_count = 0;
James Zernd5866982014-03-15 12:35:44 -070026 int file_error;
James Zerndf0829f2014-02-12 16:30:43 -080027 size_t len = 0;
28 do {
clang-format6c4d83e2016-08-08 19:03:30 -070029 const size_t n = fread((uint8_t *)buf + len, 1, size - len, file);
James Zerndf0829f2014-02-12 16:30:43 -080030 len += n;
James Zernd5866982014-03-15 12:35:44 -070031 file_error = ferror(file);
32 if (file_error) {
James Zerndf0829f2014-02-12 16:30:43 -080033 if (errno == EINTR || errno == EAGAIN) {
James Zerndf0829f2014-02-12 16:30:43 -080034 clearerr(file);
35 continue;
36 } else {
37 fprintf(stderr, "Error reading file: %u of %u bytes read, %d: %s\n",
38 (uint32_t)len, (uint32_t)size, errno, strerror(errno));
39 return 0;
40 }
41 }
James Zernd5866982014-03-15 12:35:44 -070042 } while (!feof(file) && len < size && ++retry_count < kMaxRetries);
43
44 if (!feof(file) && len != size) {
clang-format6c4d83e2016-08-08 19:03:30 -070045 fprintf(stderr,
46 "Error reading file: %u of %u bytes read,"
47 " error: %d, retries: %d, %d: %s\n",
48 (uint32_t)len, (uint32_t)size, file_error, retry_count, errno,
49 strerror(errno));
James Zernd5866982014-03-15 12:35:44 -070050 }
James Zerndf0829f2014-02-12 16:30:43 -080051 return len == size;
52}
53
John Koleszarc6b90392012-07-13 15:21:29 -070054static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
clang-format6c4d83e2016-08-08 19:03:30 -070055 int got_w;
56 int got_h;
57 int got_fps;
58 int got_interlace;
59 int got_par;
60 int got_chroma;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040061 char *p;
62 char *q;
John Koleszarc6b90392012-07-13 15:21:29 -070063 got_w = got_h = got_fps = got_interlace = got_par = got_chroma = 0;
64 for (p = _tags;; p = q) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040065 /*Skip any leading spaces.*/
James Zerne0c265e2016-07-19 20:46:39 -070066 while (*p == ' ') p++;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040067 /*If that's all we have, stop.*/
James Zerne0c265e2016-07-19 20:46:39 -070068 if (p[0] == '\0') break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040069 /*Find the end of this tag.*/
James Zerne0c265e2016-07-19 20:46:39 -070070 for (q = p + 1; *q != '\0' && *q != ' '; q++) {
71 }
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040072 /*Process the tag.*/
John Koleszarc6b90392012-07-13 15:21:29 -070073 switch (p[0]) {
74 case 'W': {
clang-format6c4d83e2016-08-08 19:03:30 -070075 if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -070076 got_w = 1;
clang-format6c4d83e2016-08-08 19:03:30 -070077 } break;
John Koleszarc6b90392012-07-13 15:21:29 -070078 case 'H': {
clang-format6c4d83e2016-08-08 19:03:30 -070079 if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -070080 got_h = 1;
clang-format6c4d83e2016-08-08 19:03:30 -070081 } break;
John Koleszarc6b90392012-07-13 15:21:29 -070082 case 'F': {
83 if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040084 return -1;
85 }
John Koleszarc6b90392012-07-13 15:21:29 -070086 got_fps = 1;
clang-format6c4d83e2016-08-08 19:03:30 -070087 } break;
John Koleszarc6b90392012-07-13 15:21:29 -070088 case 'I': {
89 _y4m->interlace = p[1];
90 got_interlace = 1;
clang-format6c4d83e2016-08-08 19:03:30 -070091 } break;
John Koleszarc6b90392012-07-13 15:21:29 -070092 case 'A': {
93 if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -040094 return -1;
95 }
John Koleszarc6b90392012-07-13 15:21:29 -070096 got_par = 1;
clang-format6c4d83e2016-08-08 19:03:30 -070097 } break;
John Koleszarc6b90392012-07-13 15:21:29 -070098 case 'C': {
clang-format6c4d83e2016-08-08 19:03:30 -070099 if (q - p > 16) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -0700100 memcpy(_y4m->chroma_type, p + 1, q - p - 1);
101 _y4m->chroma_type[q - p - 1] = '\0';
102 got_chroma = 1;
clang-format6c4d83e2016-08-08 19:03:30 -0700103 } break;
104 /*Ignore unknown tags.*/
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400105 }
106 }
clang-format6c4d83e2016-08-08 19:03:30 -0700107 if (!got_w || !got_h || !got_fps) return -1;
108 if (!got_interlace) _y4m->interlace = '?';
109 if (!got_par) _y4m->par_n = _y4m->par_d = 0;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400110 /*Chroma-type is not specified in older files, e.g., those generated by
111 mplayer.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700112 if (!got_chroma) strcpy(_y4m->chroma_type, "420");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400113 return 0;
114}
115
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400116/*All anti-aliasing filters in the following conversion functions are based on
117 one of two window functions:
118 The 6-tap Lanczos window (for down-sampling and shifts):
119 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
120 0, |t|>=3
121 The 4-tap Mitchell window (for up-sampling):
122 7|t|^3-12|t|^2+16/3, |t|<1
123 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
124 0, |t|>=2
125 The number of taps is intentionally kept small to reduce computational
126 overhead and limit ringing.
127
128 The taps from these filters are scaled so that their sum is 1, and the result
129 is scaled by 128 and rounded to integers to create a filter whose
130 intermediate values fit inside 16 bits.
131 Coefficients are rounded in such a way as to ensure their sum is still 128,
132 which is usually equivalent to normal rounding.
133
134 Conversions which require both horizontal and vertical filtering could
135 have these steps pipelined, for less memory consumption and better cache
136 performance, but we do them separately for simplicity.*/
137
clang-format6c4d83e2016-08-08 19:03:30 -0700138#define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
139#define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
140#define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400141
142/*420jpeg chroma samples are sited like:
143 Y-------Y-------Y-------Y-------
144 | | | |
145 | BR | | BR |
146 | | | |
147 Y-------Y-------Y-------Y-------
148 | | | |
149 | | | |
150 | | | |
151 Y-------Y-------Y-------Y-------
152 | | | |
153 | BR | | BR |
154 | | | |
155 Y-------Y-------Y-------Y-------
156 | | | |
157 | | | |
158 | | | |
159
160 420mpeg2 chroma samples are sited like:
161 Y-------Y-------Y-------Y-------
162 | | | |
163 BR | BR |
164 | | | |
165 Y-------Y-------Y-------Y-------
166 | | | |
167 | | | |
168 | | | |
169 Y-------Y-------Y-------Y-------
170 | | | |
171 BR | BR |
172 | | | |
173 Y-------Y-------Y-------Y-------
174 | | | |
175 | | | |
176 | | | |
177
178 We use a resampling filter to shift the site locations one quarter pixel (at
179 the chroma plane's resolution) to the right.
180 The 4:2:2 modes look exactly the same, except there are twice as many chroma
181 lines, and they are vertically co-sited with the luma samples in both the
182 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
183static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
clang-format6c4d83e2016-08-08 19:03:30 -0700184 const unsigned char *_src, int _c_w,
185 int _c_h) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400186 int y;
187 int x;
John Koleszarc6b90392012-07-13 15:21:29 -0700188 for (y = 0; y < _c_h; y++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400189 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
190 window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700191 for (x = 0; x < OC_MINI(_c_w, 2); x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700192 _dst[x] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700193 0,
194 (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
195 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
196 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[OC_MINI(x + 3, _c_w - 1)] +
197 64) >>
198 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700199 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400200 }
John Koleszarc6b90392012-07-13 15:21:29 -0700201 for (; x < _c_w - 3; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700202 _dst[x] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700203 0,
204 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
205 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
206 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700207 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400208 }
John Koleszarc6b90392012-07-13 15:21:29 -0700209 for (; x < _c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700210 _dst[x] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700211 0,
212 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
213 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
214 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
215 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700216 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400217 }
John Koleszarc6b90392012-07-13 15:21:29 -0700218 _dst += _c_w;
219 _src += _c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400220 }
221}
222
223/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700224static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
225 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400226 int c_w;
227 int c_h;
228 int c_sz;
229 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400230 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700231 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400232 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700233 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
234 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
235 c_sz = c_w * c_h;
236 for (pli = 1; pli < 3; pli++) {
237 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
238 _dst += c_sz;
239 _aux += c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400240 }
241}
242
243/*This format is only used for interlaced content, but is included for
244 completeness.
245
246 420jpeg chroma samples are sited like:
247 Y-------Y-------Y-------Y-------
248 | | | |
249 | BR | | BR |
250 | | | |
251 Y-------Y-------Y-------Y-------
252 | | | |
253 | | | |
254 | | | |
255 Y-------Y-------Y-------Y-------
256 | | | |
257 | BR | | BR |
258 | | | |
259 Y-------Y-------Y-------Y-------
260 | | | |
261 | | | |
262 | | | |
263
264 420paldv chroma samples are sited like:
265 YR------Y-------YR------Y-------
266 | | | |
267 | | | |
268 | | | |
269 YB------Y-------YB------Y-------
270 | | | |
271 | | | |
272 | | | |
273 YR------Y-------YR------Y-------
274 | | | |
275 | | | |
276 | | | |
277 YB------Y-------YB------Y-------
278 | | | |
279 | | | |
280 | | | |
281
282 We use a resampling filter to shift the site locations one quarter pixel (at
283 the chroma plane's resolution) to the right.
284 Then we use another filter to move the C_r location down one quarter pixel,
285 and the C_b location up one quarter pixel.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700286static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
287 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400288 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700289 int c_w;
290 int c_h;
291 int c_sz;
292 int pli;
293 int y;
294 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400295 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700296 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400297 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700298 c_w = (_y4m->pic_w + 1) / 2;
299 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
300 c_sz = c_w * c_h;
301 tmp = _aux + 2 * c_sz;
302 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400303 /*First do the horizontal re-sampling.
304 This is the same as the mpeg2 case, except that after the horizontal
305 case, we need to apply a second vertical filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700306 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
307 _aux += c_sz;
308 switch (pli) {
309 case 1: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400310 /*Slide C_b up a quarter-pel.
311 This is the same filter used above, but in the other order.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700312 for (x = 0; x < c_w; x++) {
313 for (y = 0; y < OC_MINI(c_h, 3); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700314 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700315 0,
316 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
317 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
318 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
319 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
320 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700321 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400322 }
John Koleszarc6b90392012-07-13 15:21:29 -0700323 for (; y < c_h - 2; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700324 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700325 0,
326 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
327 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
328 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
329 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700330 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400331 }
John Koleszarc6b90392012-07-13 15:21:29 -0700332 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700333 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700334 0,
335 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
336 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
337 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
338 4 * tmp[(c_h - 1) * c_w] + 64) >>
339 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700340 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400341 }
342 _dst++;
343 tmp++;
344 }
John Koleszarc6b90392012-07-13 15:21:29 -0700345 _dst += c_sz - c_w;
346 tmp -= c_w;
clang-format6c4d83e2016-08-08 19:03:30 -0700347 } break;
John Koleszarc6b90392012-07-13 15:21:29 -0700348 case 2: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400349 /*Slide C_r down a quarter-pel.
350 This is the same as the horizontal filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700351 for (x = 0; x < c_w; x++) {
352 for (y = 0; y < OC_MINI(c_h, 2); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700353 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
354 0,
355 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
356 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
357 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
358 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
359 7,
360 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400361 }
John Koleszarc6b90392012-07-13 15:21:29 -0700362 for (; y < c_h - 3; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700363 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700364 0,
365 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
366 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
367 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
368 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700369 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400370 }
John Koleszarc6b90392012-07-13 15:21:29 -0700371 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700372 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
373 0,
374 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
375 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
376 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
377 64) >>
378 7,
379 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400380 }
381 _dst++;
382 tmp++;
383 }
clang-format6c4d83e2016-08-08 19:03:30 -0700384 } break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400385 }
386 /*For actual interlaced material, this would have to be done separately on
387 each field, and the shift amounts would be different.
388 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
389 C_b up 1/8 in the bottom field.
390 The corresponding filters would be:
391 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
392 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
393 }
394}
395
396/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
397 This is used as a helper by several converation routines.*/
398static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
clang-format6c4d83e2016-08-08 19:03:30 -0700399 const unsigned char *_src, int _c_w,
400 int _c_h) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400401 int y;
402 int x;
403 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700404 for (x = 0; x < _c_w; x++) {
405 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700406 _dst[(y >> 1) * _c_w] =
clang-format4eafefe2017-09-04 12:51:20 -0700407 OC_CLAMPI(0,
408 (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
409 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
410 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
411 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700412 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400413 }
John Koleszarc6b90392012-07-13 15:21:29 -0700414 for (; y < _c_h - 3; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700415 _dst[(y >> 1) * _c_w] =
clang-format4eafefe2017-09-04 12:51:20 -0700416 OC_CLAMPI(0,
417 (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
418 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
419 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
420 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700421 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400422 }
John Koleszarc6b90392012-07-13 15:21:29 -0700423 for (; y < _c_h; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700424 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
425 0,
426 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
427 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
428 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
429 64) >>
430 7,
431 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400432 }
433 _src++;
434 _dst++;
435 }
436}
437
438/*420jpeg chroma samples are sited like:
439 Y-------Y-------Y-------Y-------
440 | | | |
441 | BR | | BR |
442 | | | |
443 Y-------Y-------Y-------Y-------
444 | | | |
445 | | | |
446 | | | |
447 Y-------Y-------Y-------Y-------
448 | | | |
449 | BR | | BR |
450 | | | |
451 Y-------Y-------Y-------Y-------
452 | | | |
453 | | | |
454 | | | |
455
456 422jpeg chroma samples are sited like:
457 Y---BR--Y-------Y---BR--Y-------
458 | | | |
459 | | | |
460 | | | |
461 Y---BR--Y-------Y---BR--Y-------
462 | | | |
463 | | | |
464 | | | |
465 Y---BR--Y-------Y---BR--Y-------
466 | | | |
467 | | | |
468 | | | |
469 Y---BR--Y-------Y---BR--Y-------
470 | | | |
471 | | | |
472 | | | |
473
474 We use a resampling filter to decimate the chroma planes by two in the
475 vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700476static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
477 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400478 int c_w;
479 int c_h;
480 int c_sz;
481 int dst_c_w;
482 int dst_c_h;
483 int dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400484 int pli;
485 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700486 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400487 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700488 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
489 c_h = _y4m->pic_h;
490 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
491 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
492 c_sz = c_w * c_h;
493 dst_c_sz = dst_c_w * dst_c_h;
494 for (pli = 1; pli < 3; pli++) {
495 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
496 _aux += c_sz;
497 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400498 }
499}
500
501/*420jpeg chroma samples are sited like:
502 Y-------Y-------Y-------Y-------
503 | | | |
504 | BR | | BR |
505 | | | |
506 Y-------Y-------Y-------Y-------
507 | | | |
508 | | | |
509 | | | |
510 Y-------Y-------Y-------Y-------
511 | | | |
512 | BR | | BR |
513 | | | |
514 Y-------Y-------Y-------Y-------
515 | | | |
516 | | | |
517 | | | |
518
519 422 chroma samples are sited like:
520 YBR-----Y-------YBR-----Y-------
521 | | | |
522 | | | |
523 | | | |
524 YBR-----Y-------YBR-----Y-------
525 | | | |
526 | | | |
527 | | | |
528 YBR-----Y-------YBR-----Y-------
529 | | | |
530 | | | |
531 | | | |
532 YBR-----Y-------YBR-----Y-------
533 | | | |
534 | | | |
535 | | | |
536
537 We use a resampling filter to shift the original site locations one quarter
538 pixel (at the original chroma resolution) to the right.
539 Then we use a second resampling filter to decimate the chroma planes by two
540 in the vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700541static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
542 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400543 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700544 int c_w;
545 int c_h;
546 int c_sz;
547 int dst_c_h;
548 int dst_c_sz;
549 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400550 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700551 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400552 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700553 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
554 c_h = _y4m->pic_h;
555 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
556 c_sz = c_w * c_h;
557 dst_c_sz = c_w * dst_c_h;
558 tmp = _aux + 2 * c_sz;
559 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400560 /*In reality, the horizontal and vertical steps could be pipelined, for
561 less memory consumption and better cache performance, but we do them
562 separately for simplicity.*/
563 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700564 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400565 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700566 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
567 _aux += c_sz;
568 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400569 }
570}
571
572/*420jpeg chroma samples are sited like:
573 Y-------Y-------Y-------Y-------
574 | | | |
575 | BR | | BR |
576 | | | |
577 Y-------Y-------Y-------Y-------
578 | | | |
579 | | | |
580 | | | |
581 Y-------Y-------Y-------Y-------
582 | | | |
583 | BR | | BR |
584 | | | |
585 Y-------Y-------Y-------Y-------
586 | | | |
587 | | | |
588 | | | |
589
590 411 chroma samples are sited like:
591 YBR-----Y-------Y-------Y-------
592 | | | |
593 | | | |
594 | | | |
595 YBR-----Y-------Y-------Y-------
596 | | | |
597 | | | |
598 | | | |
599 YBR-----Y-------Y-------Y-------
600 | | | |
601 | | | |
602 | | | |
603 YBR-----Y-------Y-------Y-------
604 | | | |
605 | | | |
606 | | | |
607
608 We use a filter to resample at site locations one eighth pixel (at the source
609 chroma plane's horizontal resolution) and five eighths of a pixel to the
610 right.
611 Then we use another filter to decimate the planes by 2 in the vertical
612 direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700613static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
614 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400615 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700616 int c_w;
617 int c_h;
618 int c_sz;
619 int dst_c_w;
620 int dst_c_h;
621 int dst_c_sz;
622 int tmp_sz;
623 int pli;
624 int y;
625 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400626 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700627 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400628 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700629 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
630 c_h = _y4m->pic_h;
631 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
632 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
633 c_sz = c_w * c_h;
634 dst_c_sz = dst_c_w * dst_c_h;
635 tmp_sz = dst_c_w * c_h;
636 tmp = _aux + 2 * c_sz;
637 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400638 /*In reality, the horizontal and vertical steps could be pipelined, for
639 less memory consumption and better cache performance, but we do them
640 separately for simplicity.*/
641 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700642 for (y = 0; y < c_h; y++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400643 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
644 4-tap Mitchell window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700645 for (x = 0; x < OC_MINI(c_w, 1); x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700646 tmp[x << 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700647 0,
648 (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
649 _aux[OC_MINI(2, c_w - 1)] + 64) >>
650 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700651 255);
652 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700653 0,
654 (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
655 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
656 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700657 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400658 }
John Koleszarc6b90392012-07-13 15:21:29 -0700659 for (; x < c_w - 2; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700660 tmp[x << 1] =
clang-format4eafefe2017-09-04 12:51:20 -0700661 (unsigned char)OC_CLAMPI(0,
662 (_aux[x - 1] + 110 * _aux[x] +
663 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
664 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700665 255);
666 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700667 0,
668 (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
669 5 * _aux[x + 2] + 64) >>
670 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700671 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400672 }
John Koleszarc6b90392012-07-13 15:21:29 -0700673 for (; x < c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700674 tmp[x << 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700675 0,
676 (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
677 _aux[c_w - 1] + 64) >>
678 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700679 255);
John Koleszarc6b90392012-07-13 15:21:29 -0700680 if ((x << 1 | 1) < dst_c_w) {
clang-format6c4d83e2016-08-08 19:03:30 -0700681 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
682 0,
683 (-3 * _aux[x - 1] + 50 * _aux[x] +
684 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
685 7,
686 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400687 }
688 }
John Koleszarc6b90392012-07-13 15:21:29 -0700689 tmp += dst_c_w;
690 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400691 }
John Koleszarc6b90392012-07-13 15:21:29 -0700692 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400693 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700694 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
695 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400696 }
697}
698
699/*Convert 444 to 420jpeg.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700700static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
701 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400702 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700703 int c_w;
704 int c_h;
705 int c_sz;
706 int dst_c_w;
707 int dst_c_h;
708 int dst_c_sz;
709 int tmp_sz;
710 int pli;
711 int y;
712 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400713 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700714 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400715 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700716 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
717 c_h = _y4m->pic_h;
718 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
719 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
720 c_sz = c_w * c_h;
721 dst_c_sz = dst_c_w * dst_c_h;
722 tmp_sz = dst_c_w * c_h;
723 tmp = _aux + 2 * c_sz;
724 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400725 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700726 for (y = 0; y < c_h; y++) {
727 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700728 tmp[x >> 1] = OC_CLAMPI(0,
729 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
730 17 * _aux[OC_MINI(2, c_w - 1)] +
731 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
732 7,
733 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400734 }
John Koleszarc6b90392012-07-13 15:21:29 -0700735 for (; x < c_w - 3; x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700736 tmp[x >> 1] = OC_CLAMPI(0,
737 (3 * (_aux[x - 2] + _aux[x + 3]) -
738 17 * (_aux[x - 1] + _aux[x + 2]) +
739 78 * (_aux[x] + _aux[x + 1]) + 64) >>
740 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700741 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400742 }
John Koleszarc6b90392012-07-13 15:21:29 -0700743 for (; x < c_w; x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700744 tmp[x >> 1] =
745 OC_CLAMPI(0,
746 (3 * (_aux[x - 2] + _aux[c_w - 1]) -
747 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
748 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
749 7,
750 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400751 }
John Koleszarc6b90392012-07-13 15:21:29 -0700752 tmp += dst_c_w;
753 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400754 }
John Koleszarc6b90392012-07-13 15:21:29 -0700755 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400756 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700757 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
758 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400759 }
760}
761
762/*The image is padded with empty chroma components at 4:2:0.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700763static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
764 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400765 int c_sz;
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700766 (void)_aux;
John Koleszarc6b90392012-07-13 15:21:29 -0700767 _dst += _y4m->pic_w * _y4m->pic_h;
768 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
769 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
770 memset(_dst, 128, c_sz * 2);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400771}
772
773/*No conversion function needed.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700774static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
775 unsigned char *_aux) {
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700776 (void)_y4m;
777 (void)_dst;
778 (void)_aux;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400779}
780
John Koleszar8dd82872013-05-06 11:01:35 -0700781int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
782 int only_420) {
clang-format6c4d83e2016-08-08 19:03:30 -0700783 char buffer[80] = { 0 };
784 int ret;
785 int i;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400786 /*Read until newline, or 80 cols, whichever happens first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700787 for (i = 0; i < 79; i++) {
788 if (_nskip > 0) {
789 buffer[i] = *_skip++;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400790 _nskip--;
John Koleszarc6b90392012-07-13 15:21:29 -0700791 } else {
James Zerndf0829f2014-02-12 16:30:43 -0800792 if (!file_read(buffer + i, 1, _fin)) return -1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400793 }
clang-format6c4d83e2016-08-08 19:03:30 -0700794 if (buffer[i] == '\n') break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400795 }
796 /*We skipped too much header data.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700797 if (_nskip > 0) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -0700798 if (i == 79) {
799 fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400800 return -1;
801 }
John Koleszarc6b90392012-07-13 15:21:29 -0700802 buffer[i] = '\0';
803 if (memcmp(buffer, "YUV4MPEG", 8)) {
804 fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400805 return -1;
806 }
John Koleszarc6b90392012-07-13 15:21:29 -0700807 if (buffer[8] != '2') {
808 fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400809 }
John Koleszarc6b90392012-07-13 15:21:29 -0700810 ret = y4m_parse_tags(_y4m, buffer + 5);
811 if (ret < 0) {
812 fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400813 return ret;
814 }
John Koleszarc6b90392012-07-13 15:21:29 -0700815 if (_y4m->interlace == '?') {
clang-format6c4d83e2016-08-08 19:03:30 -0700816 fprintf(stderr,
817 "Warning: Input video interlacing format unknown; "
John Koleszarc6b90392012-07-13 15:21:29 -0700818 "assuming progressive scan.\n");
819 } else if (_y4m->interlace != 'p') {
clang-format6c4d83e2016-08-08 19:03:30 -0700820 fprintf(stderr,
821 "Input video is interlaced; "
John Koleszarc6b90392012-07-13 15:21:29 -0700822 "Only progressive scan handled.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400823 return -1;
824 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700825 _y4m->aom_fmt = AOM_IMG_FMT_I420;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700826 _y4m->bps = 12;
827 _y4m->bit_depth = 8;
John Koleszarc6b90392012-07-13 15:21:29 -0700828 if (strcmp(_y4m->chroma_type, "420") == 0 ||
829 strcmp(_y4m->chroma_type, "420jpeg") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700830 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
831 _y4m->dst_c_dec_v = 2;
832 _y4m->dst_buf_read_sz =
833 _y4m->pic_w * _y4m->pic_h +
834 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700835 /* Natively supported: no conversion required. */
John Koleszarc6b90392012-07-13 15:21:29 -0700836 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
837 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700838 } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
839 _y4m->src_c_dec_h = 2;
840 _y4m->dst_c_dec_h = 2;
841 _y4m->src_c_dec_v = 2;
842 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700843 _y4m->dst_buf_read_sz =
844 2 * (_y4m->pic_w * _y4m->pic_h +
845 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700846 /* Natively supported: no conversion required. */
847 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
848 _y4m->convert = y4m_convert_null;
849 _y4m->bit_depth = 10;
850 _y4m->bps = 15;
Yaowu Xuf883b422016-08-30 14:01:10 -0700851 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700852 if (only_420) {
853 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
854 return -1;
855 }
856 } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
857 _y4m->src_c_dec_h = 2;
858 _y4m->dst_c_dec_h = 2;
859 _y4m->src_c_dec_v = 2;
860 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700861 _y4m->dst_buf_read_sz =
862 2 * (_y4m->pic_w * _y4m->pic_h +
863 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700864 /* Natively supported: no conversion required. */
865 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
866 _y4m->convert = y4m_convert_null;
867 _y4m->bit_depth = 12;
868 _y4m->bps = 18;
Yaowu Xuf883b422016-08-30 14:01:10 -0700869 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700870 if (only_420) {
871 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
872 return -1;
873 }
John Koleszarc6b90392012-07-13 15:21:29 -0700874 } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700875 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
876 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700877 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400878 /*Chroma filter required: read into the aux buf first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700879 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
clang-format6c4d83e2016-08-08 19:03:30 -0700880 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700881 _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
882 } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700883 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
884 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700885 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400886 /*Chroma filter required: read into the aux buf first.
887 We need to make two filter passes, so we need some extra space in the
888 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700889 _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
clang-format6c4d83e2016-08-08 19:03:30 -0700890 _y4m->aux_buf_read_sz =
891 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700892 _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
893 } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
894 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
895 _y4m->src_c_dec_v = 1;
896 _y4m->dst_c_dec_v = 2;
897 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400898 /*Chroma filter required: read into the aux buf first.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700899 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
900 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700901 _y4m->convert = y4m_convert_422jpeg_420jpeg;
902 } else if (strcmp(_y4m->chroma_type, "422") == 0) {
John Koleszar8dd82872013-05-06 11:01:35 -0700903 _y4m->src_c_dec_h = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700904 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700905 if (only_420) {
906 _y4m->dst_c_dec_h = 2;
907 _y4m->dst_c_dec_v = 2;
908 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
909 /*Chroma filter required: read into the aux buf first.
910 We need to make two filter passes, so we need some extra space in the
911 aux buffer.*/
912 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700913 _y4m->aux_buf_sz =
914 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700915 _y4m->convert = y4m_convert_422_420jpeg;
916 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700917 _y4m->aom_fmt = AOM_IMG_FMT_I422;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700918 _y4m->bps = 16;
John Koleszar8dd82872013-05-06 11:01:35 -0700919 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
920 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
clang-format6c4d83e2016-08-08 19:03:30 -0700921 _y4m->dst_buf_read_sz =
922 _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700923 /*Natively supported: no conversion required.*/
924 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
925 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700926 }
927 } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
928 _y4m->src_c_dec_h = 2;
929 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700930 _y4m->aom_fmt = AOM_IMG_FMT_I42216;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700931 _y4m->bps = 20;
932 _y4m->bit_depth = 10;
933 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
934 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
935 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
936 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
937 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
938 _y4m->convert = y4m_convert_null;
939 if (only_420) {
940 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
941 return -1;
942 }
943 } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
944 _y4m->src_c_dec_h = 2;
945 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700946 _y4m->aom_fmt = AOM_IMG_FMT_I42216;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700947 _y4m->bps = 24;
948 _y4m->bit_depth = 12;
949 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
950 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
951 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
952 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
953 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
954 _y4m->convert = y4m_convert_null;
955 if (only_420) {
956 fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
957 return -1;
958 }
John Koleszarc6b90392012-07-13 15:21:29 -0700959 } else if (strcmp(_y4m->chroma_type, "411") == 0) {
960 _y4m->src_c_dec_h = 4;
961 _y4m->dst_c_dec_h = 2;
962 _y4m->src_c_dec_v = 1;
963 _y4m->dst_c_dec_v = 2;
964 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400965 /*Chroma filter required: read into the aux buf first.
966 We need to make two filter passes, so we need some extra space in the
967 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700968 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700969 _y4m->aux_buf_sz =
970 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700971 _y4m->convert = y4m_convert_411_420jpeg;
972 } else if (strcmp(_y4m->chroma_type, "444") == 0) {
973 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -0700974 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700975 if (only_420) {
976 _y4m->dst_c_dec_h = 2;
977 _y4m->dst_c_dec_v = 2;
978 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
979 /*Chroma filter required: read into the aux buf first.
980 We need to make two filter passes, so we need some extra space in the
981 aux buffer.*/
982 _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700983 _y4m->aux_buf_sz =
984 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700985 _y4m->convert = y4m_convert_444_420jpeg;
986 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700987 _y4m->aom_fmt = AOM_IMG_FMT_I444;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700988 _y4m->bps = 24;
John Koleszar8dd82872013-05-06 11:01:35 -0700989 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
990 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
991 _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
992 /*Natively supported: no conversion required.*/
993 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
994 _y4m->convert = y4m_convert_null;
995 }
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700996 } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
997 _y4m->src_c_dec_h = 1;
998 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700999 _y4m->aom_fmt = AOM_IMG_FMT_I44416;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001000 _y4m->bps = 30;
1001 _y4m->bit_depth = 10;
1002 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1003 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1004 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1005 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1006 _y4m->convert = y4m_convert_null;
1007 if (only_420) {
1008 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
1009 return -1;
1010 }
1011 } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
1012 _y4m->src_c_dec_h = 1;
1013 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -07001014 _y4m->aom_fmt = AOM_IMG_FMT_I44416;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001015 _y4m->bps = 36;
1016 _y4m->bit_depth = 12;
1017 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1018 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1019 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1020 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1021 _y4m->convert = y4m_convert_null;
1022 if (only_420) {
1023 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1024 return -1;
1025 }
John Koleszarc6b90392012-07-13 15:21:29 -07001026 } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1027 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -07001028 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -07001029 if (only_420) {
1030 _y4m->dst_c_dec_h = 2;
1031 _y4m->dst_c_dec_v = 2;
1032 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1033 /*Chroma filter required: read into the aux buf first.
1034 We need to make two filter passes, so we need some extra space in the
1035 aux buffer.
1036 The extra plane also gets read into the aux buf.
1037 It will be discarded.*/
1038 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1039 _y4m->convert = y4m_convert_444_420jpeg;
1040 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07001041 _y4m->aom_fmt = AOM_IMG_FMT_444A;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001042 _y4m->bps = 32;
John Koleszar8dd82872013-05-06 11:01:35 -07001043 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1044 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1045 _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1046 /*Natively supported: no conversion required.*/
1047 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1048 _y4m->convert = y4m_convert_null;
1049 }
John Koleszarc6b90392012-07-13 15:21:29 -07001050 } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1051 _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1052 _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1053 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001054 /*No extra space required, but we need to clear the chroma planes.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001055 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1056 _y4m->convert = y4m_convert_mono_420jpeg;
1057 } else {
1058 fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001059 return -1;
1060 }
1061 /*The size of the final frame buffers is always computed from the
1062 destination chroma decimation type.*/
clang-format6c4d83e2016-08-08 19:03:30 -07001063 _y4m->dst_buf_sz =
1064 _y4m->pic_w * _y4m->pic_h +
1065 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1066 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001067 if (_y4m->bit_depth == 8)
Yaowu Xua0af4162014-10-08 08:38:15 -07001068 _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001069 else
Yaowu Xua0af4162014-10-08 08:38:15 -07001070 _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
Jim Bankoskie35c54e2014-08-19 09:00:44 -07001071
1072 if (_y4m->aux_buf_sz > 0)
1073 _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001074 return 0;
1075}
1076
John Koleszarc6b90392012-07-13 15:21:29 -07001077void y4m_input_close(y4m_input *_y4m) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001078 free(_y4m->dst_buf);
1079 free(_y4m->aux_buf);
1080}
1081
Yaowu Xuf883b422016-08-30 14:01:10 -07001082int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, aom_image_t *_img) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001083 char frame[6];
clang-format6c4d83e2016-08-08 19:03:30 -07001084 int pic_sz;
1085 int c_w;
1086 int c_h;
1087 int c_sz;
1088 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001089 /*Read and skip the frame header.*/
James Zerndf0829f2014-02-12 16:30:43 -08001090 if (!file_read(frame, 6, _fin)) return 0;
John Koleszarc6b90392012-07-13 15:21:29 -07001091 if (memcmp(frame, "FRAME", 5)) {
1092 fprintf(stderr, "Loss of framing in Y4M input data\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001093 return -1;
1094 }
John Koleszarc6b90392012-07-13 15:21:29 -07001095 if (frame[5] != '\n') {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001096 char c;
clang-format6c4d83e2016-08-08 19:03:30 -07001097 int j;
1098 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1099 }
John Koleszarc6b90392012-07-13 15:21:29 -07001100 if (j == 79) {
1101 fprintf(stderr, "Error parsing Y4M frame header\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001102 return -1;
1103 }
1104 }
1105 /*Read the frame data that needs no conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001106 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001107 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001108 return -1;
1109 }
1110 /*Read the frame data that does need conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001111 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001112 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001113 return -1;
1114 }
1115 /*Now convert the just read frame.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001116 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001117 /*Fill in the frame buffer pointers.
Yaowu Xuf883b422016-08-30 14:01:10 -07001118 We don't use aom_img_wrap() because it forces padding for odd picture
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001119 sizes, which would require a separate fread call for every row.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001120 memset(_img, 0, sizeof(*_img));
Yaowu Xuc27fc142016-08-22 16:08:15 -07001121 /*Y4M has the planes in Y'CbCr order, which libaom calls Y, U, and V.*/
Yaowu Xuf883b422016-08-30 14:01:10 -07001122 _img->fmt = _y4m->aom_fmt;
John Koleszarc6b90392012-07-13 15:21:29 -07001123 _img->w = _img->d_w = _y4m->pic_w;
1124 _img->h = _img->d_h = _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -07001125 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1126 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001127 _img->bps = _y4m->bps;
John Koleszar8dd82872013-05-06 11:01:35 -07001128
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001129 /*Set up the buffer pointers.*/
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001130 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001131 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001132 c_w *= bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001133 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1134 c_sz = c_w * c_h;
Yaowu Xuf883b422016-08-30 14:01:10 -07001135 _img->stride[AOM_PLANE_Y] = _img->stride[AOM_PLANE_ALPHA] =
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001136 _y4m->pic_w * bytes_per_sample;
Yaowu Xuf883b422016-08-30 14:01:10 -07001137 _img->stride[AOM_PLANE_U] = _img->stride[AOM_PLANE_V] = c_w;
1138 _img->planes[AOM_PLANE_Y] = _y4m->dst_buf;
1139 _img->planes[AOM_PLANE_U] = _y4m->dst_buf + pic_sz;
1140 _img->planes[AOM_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1141 _img->planes[AOM_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
Timothy B. Terriberryc4d7e5e2010-10-27 16:04:02 -07001142 return 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001143}