blob: 1919189245870b6ac0c99db0107d3e63a538aadf [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(
193 0, (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
194 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
195 9 * _src[OC_MINI(x + 2, _c_w - 1)] +
196 _src[OC_MINI(x + 3, _c_w - 1)] + 64) >>
197 7,
198 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400199 }
John Koleszarc6b90392012-07-13 15:21:29 -0700200 for (; x < _c_w - 3; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700201 _dst[x] = (unsigned char)OC_CLAMPI(
202 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
203 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
204 7,
205 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400206 }
John Koleszarc6b90392012-07-13 15:21:29 -0700207 for (; x < _c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700208 _dst[x] = (unsigned char)OC_CLAMPI(
209 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
210 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
211 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
212 7,
213 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400214 }
John Koleszarc6b90392012-07-13 15:21:29 -0700215 _dst += _c_w;
216 _src += _c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400217 }
218}
219
220/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700221static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
222 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400223 int c_w;
224 int c_h;
225 int c_sz;
226 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400227 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700228 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400229 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700230 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
231 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
232 c_sz = c_w * c_h;
233 for (pli = 1; pli < 3; pli++) {
234 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
235 _dst += c_sz;
236 _aux += c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400237 }
238}
239
240/*This format is only used for interlaced content, but is included for
241 completeness.
242
243 420jpeg chroma samples are sited like:
244 Y-------Y-------Y-------Y-------
245 | | | |
246 | BR | | BR |
247 | | | |
248 Y-------Y-------Y-------Y-------
249 | | | |
250 | | | |
251 | | | |
252 Y-------Y-------Y-------Y-------
253 | | | |
254 | BR | | BR |
255 | | | |
256 Y-------Y-------Y-------Y-------
257 | | | |
258 | | | |
259 | | | |
260
261 420paldv chroma samples are sited like:
262 YR------Y-------YR------Y-------
263 | | | |
264 | | | |
265 | | | |
266 YB------Y-------YB------Y-------
267 | | | |
268 | | | |
269 | | | |
270 YR------Y-------YR------Y-------
271 | | | |
272 | | | |
273 | | | |
274 YB------Y-------YB------Y-------
275 | | | |
276 | | | |
277 | | | |
278
279 We use a resampling filter to shift the site locations one quarter pixel (at
280 the chroma plane's resolution) to the right.
281 Then we use another filter to move the C_r location down one quarter pixel,
282 and the C_b location up one quarter pixel.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700283static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
284 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400285 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700286 int c_w;
287 int c_h;
288 int c_sz;
289 int pli;
290 int y;
291 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400292 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700293 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400294 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700295 c_w = (_y4m->pic_w + 1) / 2;
296 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
297 c_sz = c_w * c_h;
298 tmp = _aux + 2 * c_sz;
299 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400300 /*First do the horizontal re-sampling.
301 This is the same as the mpeg2 case, except that after the horizontal
302 case, we need to apply a second vertical filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700303 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
304 _aux += c_sz;
305 switch (pli) {
306 case 1: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400307 /*Slide C_b up a quarter-pel.
308 This is the same filter used above, but in the other order.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700309 for (x = 0; x < c_w; x++) {
310 for (y = 0; y < OC_MINI(c_h, 3); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700311 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
312 0, (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
313 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
314 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
315 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
316 7,
317 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400318 }
John Koleszarc6b90392012-07-13 15:21:29 -0700319 for (; y < c_h - 2; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700320 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
321 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
322 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
323 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
324 7,
325 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400326 }
John Koleszarc6b90392012-07-13 15:21:29 -0700327 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700328 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
329 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
330 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
331 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
332 4 * tmp[(c_h - 1) * c_w] + 64) >>
333 7,
334 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400335 }
336 _dst++;
337 tmp++;
338 }
John Koleszarc6b90392012-07-13 15:21:29 -0700339 _dst += c_sz - c_w;
340 tmp -= c_w;
clang-format6c4d83e2016-08-08 19:03:30 -0700341 } break;
John Koleszarc6b90392012-07-13 15:21:29 -0700342 case 2: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400343 /*Slide C_r down a quarter-pel.
344 This is the same as the horizontal filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700345 for (x = 0; x < c_w; x++) {
346 for (y = 0; y < OC_MINI(c_h, 2); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700347 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
348 0,
349 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
350 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
351 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
352 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
353 7,
354 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400355 }
John Koleszarc6b90392012-07-13 15:21:29 -0700356 for (; y < c_h - 3; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700357 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
358 0, (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
359 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
360 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
361 7,
362 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400363 }
John Koleszarc6b90392012-07-13 15:21:29 -0700364 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700365 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
366 0,
367 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
368 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
369 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
370 64) >>
371 7,
372 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400373 }
374 _dst++;
375 tmp++;
376 }
clang-format6c4d83e2016-08-08 19:03:30 -0700377 } break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400378 }
379 /*For actual interlaced material, this would have to be done separately on
380 each field, and the shift amounts would be different.
381 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
382 C_b up 1/8 in the bottom field.
383 The corresponding filters would be:
384 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
385 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
386 }
387}
388
389/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
390 This is used as a helper by several converation routines.*/
391static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
clang-format6c4d83e2016-08-08 19:03:30 -0700392 const unsigned char *_src, int _c_w,
393 int _c_h) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400394 int y;
395 int x;
396 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700397 for (x = 0; x < _c_w; x++) {
398 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700399 _dst[(y >> 1) * _c_w] =
400 OC_CLAMPI(0, (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
401 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
402 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
403 7,
404 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400405 }
John Koleszarc6b90392012-07-13 15:21:29 -0700406 for (; y < _c_h - 3; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700407 _dst[(y >> 1) * _c_w] =
408 OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
409 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
410 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
411 7,
412 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400413 }
John Koleszarc6b90392012-07-13 15:21:29 -0700414 for (; y < _c_h; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700415 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
416 0,
417 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
418 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
419 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
420 64) >>
421 7,
422 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400423 }
424 _src++;
425 _dst++;
426 }
427}
428
429/*420jpeg chroma samples are sited like:
430 Y-------Y-------Y-------Y-------
431 | | | |
432 | BR | | BR |
433 | | | |
434 Y-------Y-------Y-------Y-------
435 | | | |
436 | | | |
437 | | | |
438 Y-------Y-------Y-------Y-------
439 | | | |
440 | BR | | BR |
441 | | | |
442 Y-------Y-------Y-------Y-------
443 | | | |
444 | | | |
445 | | | |
446
447 422jpeg chroma samples are sited like:
448 Y---BR--Y-------Y---BR--Y-------
449 | | | |
450 | | | |
451 | | | |
452 Y---BR--Y-------Y---BR--Y-------
453 | | | |
454 | | | |
455 | | | |
456 Y---BR--Y-------Y---BR--Y-------
457 | | | |
458 | | | |
459 | | | |
460 Y---BR--Y-------Y---BR--Y-------
461 | | | |
462 | | | |
463 | | | |
464
465 We use a resampling filter to decimate the chroma planes by two in the
466 vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700467static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
468 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400469 int c_w;
470 int c_h;
471 int c_sz;
472 int dst_c_w;
473 int dst_c_h;
474 int dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400475 int pli;
476 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700477 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400478 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700479 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
480 c_h = _y4m->pic_h;
481 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
482 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
483 c_sz = c_w * c_h;
484 dst_c_sz = dst_c_w * dst_c_h;
485 for (pli = 1; pli < 3; pli++) {
486 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
487 _aux += c_sz;
488 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400489 }
490}
491
492/*420jpeg chroma samples are sited like:
493 Y-------Y-------Y-------Y-------
494 | | | |
495 | BR | | BR |
496 | | | |
497 Y-------Y-------Y-------Y-------
498 | | | |
499 | | | |
500 | | | |
501 Y-------Y-------Y-------Y-------
502 | | | |
503 | BR | | BR |
504 | | | |
505 Y-------Y-------Y-------Y-------
506 | | | |
507 | | | |
508 | | | |
509
510 422 chroma samples are sited like:
511 YBR-----Y-------YBR-----Y-------
512 | | | |
513 | | | |
514 | | | |
515 YBR-----Y-------YBR-----Y-------
516 | | | |
517 | | | |
518 | | | |
519 YBR-----Y-------YBR-----Y-------
520 | | | |
521 | | | |
522 | | | |
523 YBR-----Y-------YBR-----Y-------
524 | | | |
525 | | | |
526 | | | |
527
528 We use a resampling filter to shift the original site locations one quarter
529 pixel (at the original chroma resolution) to the right.
530 Then we use a second resampling filter to decimate the chroma planes by two
531 in the vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700532static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
533 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400534 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700535 int c_w;
536 int c_h;
537 int c_sz;
538 int dst_c_h;
539 int dst_c_sz;
540 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400541 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700542 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400543 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700544 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
545 c_h = _y4m->pic_h;
546 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
547 c_sz = c_w * c_h;
548 dst_c_sz = c_w * dst_c_h;
549 tmp = _aux + 2 * c_sz;
550 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400551 /*In reality, the horizontal and vertical steps could be pipelined, for
552 less memory consumption and better cache performance, but we do them
553 separately for simplicity.*/
554 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700555 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400556 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700557 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
558 _aux += c_sz;
559 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400560 }
561}
562
563/*420jpeg chroma samples are sited like:
564 Y-------Y-------Y-------Y-------
565 | | | |
566 | BR | | BR |
567 | | | |
568 Y-------Y-------Y-------Y-------
569 | | | |
570 | | | |
571 | | | |
572 Y-------Y-------Y-------Y-------
573 | | | |
574 | BR | | BR |
575 | | | |
576 Y-------Y-------Y-------Y-------
577 | | | |
578 | | | |
579 | | | |
580
581 411 chroma samples are sited like:
582 YBR-----Y-------Y-------Y-------
583 | | | |
584 | | | |
585 | | | |
586 YBR-----Y-------Y-------Y-------
587 | | | |
588 | | | |
589 | | | |
590 YBR-----Y-------Y-------Y-------
591 | | | |
592 | | | |
593 | | | |
594 YBR-----Y-------Y-------Y-------
595 | | | |
596 | | | |
597 | | | |
598
599 We use a filter to resample at site locations one eighth pixel (at the source
600 chroma plane's horizontal resolution) and five eighths of a pixel to the
601 right.
602 Then we use another filter to decimate the planes by 2 in the vertical
603 direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700604static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
605 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400606 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700607 int c_w;
608 int c_h;
609 int c_sz;
610 int dst_c_w;
611 int dst_c_h;
612 int dst_c_sz;
613 int tmp_sz;
614 int pli;
615 int y;
616 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400617 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700618 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400619 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700620 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
621 c_h = _y4m->pic_h;
622 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
623 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
624 c_sz = c_w * c_h;
625 dst_c_sz = dst_c_w * dst_c_h;
626 tmp_sz = dst_c_w * c_h;
627 tmp = _aux + 2 * c_sz;
628 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400629 /*In reality, the horizontal and vertical steps could be pipelined, for
630 less memory consumption and better cache performance, but we do them
631 separately for simplicity.*/
632 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700633 for (y = 0; y < c_h; y++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400634 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
635 4-tap Mitchell window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700636 for (x = 0; x < OC_MINI(c_w, 1); x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700637 tmp[x << 1] = (unsigned char)OC_CLAMPI(
638 0, (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
639 _aux[OC_MINI(2, c_w - 1)] + 64) >>
640 7,
641 255);
642 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
643 0, (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
644 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
645 7,
646 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400647 }
John Koleszarc6b90392012-07-13 15:21:29 -0700648 for (; x < c_w - 2; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700649 tmp[x << 1] =
650 (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] +
651 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
652 7,
653 255);
654 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
655 0, (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
656 5 * _aux[x + 2] + 64) >>
657 7,
658 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400659 }
John Koleszarc6b90392012-07-13 15:21:29 -0700660 for (; x < c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700661 tmp[x << 1] = (unsigned char)OC_CLAMPI(
662 0, (_aux[x - 1] + 110 * _aux[x] +
663 18 * _aux[OC_MINI(x + 1, c_w - 1)] - _aux[c_w - 1] + 64) >>
664 7,
665 255);
John Koleszarc6b90392012-07-13 15:21:29 -0700666 if ((x << 1 | 1) < dst_c_w) {
clang-format6c4d83e2016-08-08 19:03:30 -0700667 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
668 0,
669 (-3 * _aux[x - 1] + 50 * _aux[x] +
670 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
671 7,
672 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400673 }
674 }
John Koleszarc6b90392012-07-13 15:21:29 -0700675 tmp += dst_c_w;
676 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400677 }
John Koleszarc6b90392012-07-13 15:21:29 -0700678 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400679 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700680 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
681 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400682 }
683}
684
685/*Convert 444 to 420jpeg.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700686static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
687 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400688 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700689 int c_w;
690 int c_h;
691 int c_sz;
692 int dst_c_w;
693 int dst_c_h;
694 int dst_c_sz;
695 int tmp_sz;
696 int pli;
697 int y;
698 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400699 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700700 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400701 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700702 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
703 c_h = _y4m->pic_h;
704 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
705 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
706 c_sz = c_w * c_h;
707 dst_c_sz = dst_c_w * dst_c_h;
708 tmp_sz = dst_c_w * c_h;
709 tmp = _aux + 2 * c_sz;
710 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400711 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700712 for (y = 0; y < c_h; y++) {
713 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700714 tmp[x >> 1] =
715 OC_CLAMPI(0, (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
716 17 * _aux[OC_MINI(2, c_w - 1)] +
717 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
718 7,
719 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400720 }
John Koleszarc6b90392012-07-13 15:21:29 -0700721 for (; x < c_w - 3; x += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700722 tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[x + 3]) -
723 17 * (_aux[x - 1] + _aux[x + 2]) +
724 78 * (_aux[x] + _aux[x + 1]) + 64) >>
725 7,
726 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400727 }
John Koleszarc6b90392012-07-13 15:21:29 -0700728 for (; x < c_w; x += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700729 tmp[x >> 1] = OC_CLAMPI(
730 0, (3 * (_aux[x - 2] + _aux[c_w - 1]) -
731 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
732 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
733 7,
734 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400735 }
John Koleszarc6b90392012-07-13 15:21:29 -0700736 tmp += dst_c_w;
737 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400738 }
John Koleszarc6b90392012-07-13 15:21:29 -0700739 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400740 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700741 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
742 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400743 }
744}
745
746/*The image is padded with empty chroma components at 4:2:0.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700747static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
748 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400749 int c_sz;
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700750 (void)_aux;
John Koleszarc6b90392012-07-13 15:21:29 -0700751 _dst += _y4m->pic_w * _y4m->pic_h;
752 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
753 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
754 memset(_dst, 128, c_sz * 2);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400755}
756
757/*No conversion function needed.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700758static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
759 unsigned char *_aux) {
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700760 (void)_y4m;
761 (void)_dst;
762 (void)_aux;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400763}
764
John Koleszar8dd82872013-05-06 11:01:35 -0700765int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
766 int only_420) {
clang-format6c4d83e2016-08-08 19:03:30 -0700767 char buffer[80] = { 0 };
768 int ret;
769 int i;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400770 /*Read until newline, or 80 cols, whichever happens first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700771 for (i = 0; i < 79; i++) {
772 if (_nskip > 0) {
773 buffer[i] = *_skip++;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400774 _nskip--;
John Koleszarc6b90392012-07-13 15:21:29 -0700775 } else {
James Zerndf0829f2014-02-12 16:30:43 -0800776 if (!file_read(buffer + i, 1, _fin)) return -1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400777 }
clang-format6c4d83e2016-08-08 19:03:30 -0700778 if (buffer[i] == '\n') break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400779 }
780 /*We skipped too much header data.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700781 if (_nskip > 0) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -0700782 if (i == 79) {
783 fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400784 return -1;
785 }
John Koleszarc6b90392012-07-13 15:21:29 -0700786 buffer[i] = '\0';
787 if (memcmp(buffer, "YUV4MPEG", 8)) {
788 fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400789 return -1;
790 }
John Koleszarc6b90392012-07-13 15:21:29 -0700791 if (buffer[8] != '2') {
792 fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400793 }
John Koleszarc6b90392012-07-13 15:21:29 -0700794 ret = y4m_parse_tags(_y4m, buffer + 5);
795 if (ret < 0) {
796 fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400797 return ret;
798 }
John Koleszarc6b90392012-07-13 15:21:29 -0700799 if (_y4m->interlace == '?') {
clang-format6c4d83e2016-08-08 19:03:30 -0700800 fprintf(stderr,
801 "Warning: Input video interlacing format unknown; "
John Koleszarc6b90392012-07-13 15:21:29 -0700802 "assuming progressive scan.\n");
803 } else if (_y4m->interlace != 'p') {
clang-format6c4d83e2016-08-08 19:03:30 -0700804 fprintf(stderr,
805 "Input video is interlaced; "
John Koleszarc6b90392012-07-13 15:21:29 -0700806 "Only progressive scan handled.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400807 return -1;
808 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700809 _y4m->aom_fmt = AOM_IMG_FMT_I420;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700810 _y4m->bps = 12;
811 _y4m->bit_depth = 8;
John Koleszarc6b90392012-07-13 15:21:29 -0700812 if (strcmp(_y4m->chroma_type, "420") == 0 ||
813 strcmp(_y4m->chroma_type, "420jpeg") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700814 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
815 _y4m->dst_c_dec_v = 2;
816 _y4m->dst_buf_read_sz =
817 _y4m->pic_w * _y4m->pic_h +
818 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700819 /* Natively supported: no conversion required. */
John Koleszarc6b90392012-07-13 15:21:29 -0700820 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
821 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700822 } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
823 _y4m->src_c_dec_h = 2;
824 _y4m->dst_c_dec_h = 2;
825 _y4m->src_c_dec_v = 2;
826 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700827 _y4m->dst_buf_read_sz =
828 2 * (_y4m->pic_w * _y4m->pic_h +
829 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700830 /* Natively supported: no conversion required. */
831 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
832 _y4m->convert = y4m_convert_null;
833 _y4m->bit_depth = 10;
834 _y4m->bps = 15;
Yaowu Xuf883b422016-08-30 14:01:10 -0700835 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700836 if (only_420) {
837 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
838 return -1;
839 }
840 } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
841 _y4m->src_c_dec_h = 2;
842 _y4m->dst_c_dec_h = 2;
843 _y4m->src_c_dec_v = 2;
844 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700845 _y4m->dst_buf_read_sz =
846 2 * (_y4m->pic_w * _y4m->pic_h +
847 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700848 /* Natively supported: no conversion required. */
849 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
850 _y4m->convert = y4m_convert_null;
851 _y4m->bit_depth = 12;
852 _y4m->bps = 18;
Yaowu Xuf883b422016-08-30 14:01:10 -0700853 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700854 if (only_420) {
855 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
856 return -1;
857 }
John Koleszarc6b90392012-07-13 15:21:29 -0700858 } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700859 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
860 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700861 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400862 /*Chroma filter required: read into the aux buf first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700863 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
clang-format6c4d83e2016-08-08 19:03:30 -0700864 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700865 _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
866 } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700867 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
868 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700869 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400870 /*Chroma filter required: read into the aux buf first.
871 We need to make two filter passes, so we need some extra space in the
872 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700873 _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
clang-format6c4d83e2016-08-08 19:03:30 -0700874 _y4m->aux_buf_read_sz =
875 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700876 _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
877 } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
878 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
879 _y4m->src_c_dec_v = 1;
880 _y4m->dst_c_dec_v = 2;
881 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400882 /*Chroma filter required: read into the aux buf first.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700883 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
884 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700885 _y4m->convert = y4m_convert_422jpeg_420jpeg;
886 } else if (strcmp(_y4m->chroma_type, "422") == 0) {
John Koleszar8dd82872013-05-06 11:01:35 -0700887 _y4m->src_c_dec_h = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700888 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700889 if (only_420) {
890 _y4m->dst_c_dec_h = 2;
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_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700897 _y4m->aux_buf_sz =
898 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700899 _y4m->convert = y4m_convert_422_420jpeg;
900 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700901 _y4m->aom_fmt = AOM_IMG_FMT_I422;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700902 _y4m->bps = 16;
John Koleszar8dd82872013-05-06 11:01:35 -0700903 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
904 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
clang-format6c4d83e2016-08-08 19:03:30 -0700905 _y4m->dst_buf_read_sz =
906 _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700907 /*Natively supported: no conversion required.*/
908 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
909 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700910 }
911 } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
912 _y4m->src_c_dec_h = 2;
913 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700914 _y4m->aom_fmt = AOM_IMG_FMT_I42216;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700915 _y4m->bps = 20;
916 _y4m->bit_depth = 10;
917 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
918 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
919 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
920 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
921 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
922 _y4m->convert = y4m_convert_null;
923 if (only_420) {
924 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
925 return -1;
926 }
927 } else if (strcmp(_y4m->chroma_type, "422p12") == 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 = 24;
932 _y4m->bit_depth = 12;
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 422p12 to 420jpeg\n");
941 return -1;
942 }
John Koleszarc6b90392012-07-13 15:21:29 -0700943 } else if (strcmp(_y4m->chroma_type, "411") == 0) {
944 _y4m->src_c_dec_h = 4;
945 _y4m->dst_c_dec_h = 2;
946 _y4m->src_c_dec_v = 1;
947 _y4m->dst_c_dec_v = 2;
948 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400949 /*Chroma filter required: read into the aux buf first.
950 We need to make two filter passes, so we need some extra space in the
951 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700952 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700953 _y4m->aux_buf_sz =
954 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700955 _y4m->convert = y4m_convert_411_420jpeg;
956 } else if (strcmp(_y4m->chroma_type, "444") == 0) {
957 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -0700958 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700959 if (only_420) {
960 _y4m->dst_c_dec_h = 2;
961 _y4m->dst_c_dec_v = 2;
962 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
963 /*Chroma filter required: read into the aux buf first.
964 We need to make two filter passes, so we need some extra space in the
965 aux buffer.*/
966 _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700967 _y4m->aux_buf_sz =
968 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700969 _y4m->convert = y4m_convert_444_420jpeg;
970 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700971 _y4m->aom_fmt = AOM_IMG_FMT_I444;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700972 _y4m->bps = 24;
John Koleszar8dd82872013-05-06 11:01:35 -0700973 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
974 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
975 _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
976 /*Natively supported: no conversion required.*/
977 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
978 _y4m->convert = y4m_convert_null;
979 }
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700980 } else if (strcmp(_y4m->chroma_type, "444p10") == 0) {
981 _y4m->src_c_dec_h = 1;
982 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700983 _y4m->aom_fmt = AOM_IMG_FMT_I44416;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700984 _y4m->bps = 30;
985 _y4m->bit_depth = 10;
986 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
987 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
988 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
989 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
990 _y4m->convert = y4m_convert_null;
991 if (only_420) {
992 fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n");
993 return -1;
994 }
995 } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
996 _y4m->src_c_dec_h = 1;
997 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700998 _y4m->aom_fmt = AOM_IMG_FMT_I44416;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700999 _y4m->bps = 36;
1000 _y4m->bit_depth = 12;
1001 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1002 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1003 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1004 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1005 _y4m->convert = y4m_convert_null;
1006 if (only_420) {
1007 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1008 return -1;
1009 }
John Koleszarc6b90392012-07-13 15:21:29 -07001010 } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1011 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -07001012 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -07001013 if (only_420) {
1014 _y4m->dst_c_dec_h = 2;
1015 _y4m->dst_c_dec_v = 2;
1016 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1017 /*Chroma filter required: read into the aux buf first.
1018 We need to make two filter passes, so we need some extra space in the
1019 aux buffer.
1020 The extra plane also gets read into the aux buf.
1021 It will be discarded.*/
1022 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1023 _y4m->convert = y4m_convert_444_420jpeg;
1024 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07001025 _y4m->aom_fmt = AOM_IMG_FMT_444A;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001026 _y4m->bps = 32;
John Koleszar8dd82872013-05-06 11:01:35 -07001027 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1028 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1029 _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1030 /*Natively supported: no conversion required.*/
1031 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1032 _y4m->convert = y4m_convert_null;
1033 }
John Koleszarc6b90392012-07-13 15:21:29 -07001034 } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1035 _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1036 _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1037 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001038 /*No extra space required, but we need to clear the chroma planes.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001039 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1040 _y4m->convert = y4m_convert_mono_420jpeg;
1041 } else {
1042 fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001043 return -1;
1044 }
1045 /*The size of the final frame buffers is always computed from the
1046 destination chroma decimation type.*/
clang-format6c4d83e2016-08-08 19:03:30 -07001047 _y4m->dst_buf_sz =
1048 _y4m->pic_w * _y4m->pic_h +
1049 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1050 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001051 if (_y4m->bit_depth == 8)
Yaowu Xua0af4162014-10-08 08:38:15 -07001052 _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001053 else
Yaowu Xua0af4162014-10-08 08:38:15 -07001054 _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
Jim Bankoskie35c54e2014-08-19 09:00:44 -07001055
1056 if (_y4m->aux_buf_sz > 0)
1057 _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001058 return 0;
1059}
1060
John Koleszarc6b90392012-07-13 15:21:29 -07001061void y4m_input_close(y4m_input *_y4m) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001062 free(_y4m->dst_buf);
1063 free(_y4m->aux_buf);
1064}
1065
Yaowu Xuf883b422016-08-30 14:01:10 -07001066int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, aom_image_t *_img) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001067 char frame[6];
clang-format6c4d83e2016-08-08 19:03:30 -07001068 int pic_sz;
1069 int c_w;
1070 int c_h;
1071 int c_sz;
1072 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001073 /*Read and skip the frame header.*/
James Zerndf0829f2014-02-12 16:30:43 -08001074 if (!file_read(frame, 6, _fin)) return 0;
John Koleszarc6b90392012-07-13 15:21:29 -07001075 if (memcmp(frame, "FRAME", 5)) {
1076 fprintf(stderr, "Loss of framing in Y4M input data\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001077 return -1;
1078 }
John Koleszarc6b90392012-07-13 15:21:29 -07001079 if (frame[5] != '\n') {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001080 char c;
clang-format6c4d83e2016-08-08 19:03:30 -07001081 int j;
1082 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1083 }
John Koleszarc6b90392012-07-13 15:21:29 -07001084 if (j == 79) {
1085 fprintf(stderr, "Error parsing Y4M frame header\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001086 return -1;
1087 }
1088 }
1089 /*Read the frame data that needs no conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001090 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001091 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001092 return -1;
1093 }
1094 /*Read the frame data that does need conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001095 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001096 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001097 return -1;
1098 }
1099 /*Now convert the just read frame.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001100 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001101 /*Fill in the frame buffer pointers.
Yaowu Xuf883b422016-08-30 14:01:10 -07001102 We don't use aom_img_wrap() because it forces padding for odd picture
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001103 sizes, which would require a separate fread call for every row.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001104 memset(_img, 0, sizeof(*_img));
Yaowu Xuc27fc142016-08-22 16:08:15 -07001105 /*Y4M has the planes in Y'CbCr order, which libaom calls Y, U, and V.*/
Yaowu Xuf883b422016-08-30 14:01:10 -07001106 _img->fmt = _y4m->aom_fmt;
John Koleszarc6b90392012-07-13 15:21:29 -07001107 _img->w = _img->d_w = _y4m->pic_w;
1108 _img->h = _img->d_h = _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -07001109 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1110 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001111 _img->bps = _y4m->bps;
John Koleszar8dd82872013-05-06 11:01:35 -07001112
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001113 /*Set up the buffer pointers.*/
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001114 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001115 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001116 c_w *= bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001117 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1118 c_sz = c_w * c_h;
Yaowu Xuf883b422016-08-30 14:01:10 -07001119 _img->stride[AOM_PLANE_Y] = _img->stride[AOM_PLANE_ALPHA] =
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001120 _y4m->pic_w * bytes_per_sample;
Yaowu Xuf883b422016-08-30 14:01:10 -07001121 _img->stride[AOM_PLANE_U] = _img->stride[AOM_PLANE_V] = c_w;
1122 _img->planes[AOM_PLANE_Y] = _y4m->dst_buf;
1123 _img->planes[AOM_PLANE_U] = _y4m->dst_buf + pic_sz;
1124 _img->planes[AOM_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1125 _img->planes[AOM_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
Timothy B. Terriberryc4d7e5e2010-10-27 16:04:02 -07001126 return 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001127}