blob: a1dca10cdfeedd433e9c967d0169c4bb696666ec [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
Johann123e8a62017-12-28 14:40:49 -0800128 The taps from these filters are scaled so that their sum is 1, and the
129 result is scaled by 128 and rounded to integers to create a filter whose
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400130 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.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700137#define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
138#define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
139#define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400140
141/*420jpeg chroma samples are sited like:
142 Y-------Y-------Y-------Y-------
143 | | | |
144 | BR | | BR |
145 | | | |
146 Y-------Y-------Y-------Y-------
147 | | | |
148 | | | |
149 | | | |
150 Y-------Y-------Y-------Y-------
151 | | | |
152 | BR | | BR |
153 | | | |
154 Y-------Y-------Y-------Y-------
155 | | | |
156 | | | |
157 | | | |
158
159 420mpeg2 chroma samples are sited like:
160 Y-------Y-------Y-------Y-------
161 | | | |
162 BR | BR |
163 | | | |
164 Y-------Y-------Y-------Y-------
165 | | | |
166 | | | |
167 | | | |
168 Y-------Y-------Y-------Y-------
169 | | | |
170 BR | BR |
171 | | | |
172 Y-------Y-------Y-------Y-------
173 | | | |
174 | | | |
175 | | | |
176
177 We use a resampling filter to shift the site locations one quarter pixel (at
178 the chroma plane's resolution) to the right.
179 The 4:2:2 modes look exactly the same, except there are twice as many chroma
180 lines, and they are vertically co-sited with the luma samples in both the
181 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
182static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
clang-format6c4d83e2016-08-08 19:03:30 -0700183 const unsigned char *_src, int _c_w,
184 int _c_h) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400185 int y;
186 int x;
John Koleszarc6b90392012-07-13 15:21:29 -0700187 for (y = 0; y < _c_h; y++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400188 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
189 window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700190 for (x = 0; x < OC_MINI(_c_w, 2); x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700191 _dst[x] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700192 0,
193 (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)] + _src[OC_MINI(x + 3, _c_w - 1)] +
196 64) >>
197 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700198 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(
clang-format4eafefe2017-09-04 12:51:20 -0700202 0,
203 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
204 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
205 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700206 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400207 }
John Koleszarc6b90392012-07-13 15:21:29 -0700208 for (; x < _c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700209 _dst[x] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700210 0,
211 (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
212 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
213 9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
214 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700215 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400216 }
John Koleszarc6b90392012-07-13 15:21:29 -0700217 _dst += _c_w;
218 _src += _c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400219 }
220}
221
222/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700223static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
224 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400225 int c_w;
226 int c_h;
227 int c_sz;
228 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400229 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700230 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400231 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700232 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
233 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
234 c_sz = c_w * c_h;
235 for (pli = 1; pli < 3; pli++) {
236 y4m_42xmpeg2_42xjpeg_helper(_dst, _aux, c_w, c_h);
237 _dst += c_sz;
238 _aux += c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400239 }
240}
241
242/*This format is only used for interlaced content, but is included for
243 completeness.
244
245 420jpeg chroma samples are sited like:
246 Y-------Y-------Y-------Y-------
247 | | | |
248 | BR | | BR |
249 | | | |
250 Y-------Y-------Y-------Y-------
251 | | | |
252 | | | |
253 | | | |
254 Y-------Y-------Y-------Y-------
255 | | | |
256 | BR | | BR |
257 | | | |
258 Y-------Y-------Y-------Y-------
259 | | | |
260 | | | |
261 | | | |
262
263 420paldv chroma samples are sited like:
264 YR------Y-------YR------Y-------
265 | | | |
266 | | | |
267 | | | |
268 YB------Y-------YB------Y-------
269 | | | |
270 | | | |
271 | | | |
272 YR------Y-------YR------Y-------
273 | | | |
274 | | | |
275 | | | |
276 YB------Y-------YB------Y-------
277 | | | |
278 | | | |
279 | | | |
280
281 We use a resampling filter to shift the site locations one quarter pixel (at
282 the chroma plane's resolution) to the right.
283 Then we use another filter to move the C_r location down one quarter pixel,
284 and the C_b location up one quarter pixel.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700285static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
286 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400287 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700288 int c_w;
289 int c_h;
290 int c_sz;
291 int pli;
292 int y;
293 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400294 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700295 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400296 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700297 c_w = (_y4m->pic_w + 1) / 2;
298 c_h = (_y4m->pic_h + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
299 c_sz = c_w * c_h;
300 tmp = _aux + 2 * c_sz;
301 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400302 /*First do the horizontal re-sampling.
303 This is the same as the mpeg2 case, except that after the horizontal
304 case, we need to apply a second vertical filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700305 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
306 _aux += c_sz;
307 switch (pli) {
308 case 1: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400309 /*Slide C_b up a quarter-pel.
310 This is the same filter used above, but in the other order.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700311 for (x = 0; x < c_w; x++) {
312 for (y = 0; y < OC_MINI(c_h, 3); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700313 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700314 0,
315 (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
316 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
317 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
318 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
319 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700320 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400321 }
John Koleszarc6b90392012-07-13 15:21:29 -0700322 for (; y < c_h - 2; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700323 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700324 0,
325 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
326 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
327 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
328 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700329 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400330 }
John Koleszarc6b90392012-07-13 15:21:29 -0700331 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700332 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700333 0,
334 (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
335 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
336 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
337 4 * tmp[(c_h - 1) * c_w] + 64) >>
338 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700339 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400340 }
341 _dst++;
342 tmp++;
343 }
John Koleszarc6b90392012-07-13 15:21:29 -0700344 _dst += c_sz - c_w;
345 tmp -= c_w;
clang-format6c4d83e2016-08-08 19:03:30 -0700346 } break;
John Koleszarc6b90392012-07-13 15:21:29 -0700347 case 2: {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400348 /*Slide C_r down a quarter-pel.
349 This is the same as the horizontal filter.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700350 for (x = 0; x < c_w; x++) {
351 for (y = 0; y < OC_MINI(c_h, 2); y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700352 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
353 0,
354 (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
355 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
356 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
357 tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
358 7,
359 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400360 }
John Koleszarc6b90392012-07-13 15:21:29 -0700361 for (; y < c_h - 3; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700362 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700363 0,
364 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
365 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
366 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
367 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700368 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400369 }
John Koleszarc6b90392012-07-13 15:21:29 -0700370 for (; y < c_h; y++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700371 _dst[y * c_w] = (unsigned char)OC_CLAMPI(
372 0,
373 (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
374 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
375 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
376 64) >>
377 7,
378 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400379 }
380 _dst++;
381 tmp++;
382 }
clang-format6c4d83e2016-08-08 19:03:30 -0700383 } break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400384 }
385 /*For actual interlaced material, this would have to be done separately on
386 each field, and the shift amounts would be different.
387 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
388 C_b up 1/8 in the bottom field.
389 The corresponding filters would be:
390 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
391 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
392 }
393}
394
395/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
396 This is used as a helper by several converation routines.*/
397static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
clang-format6c4d83e2016-08-08 19:03:30 -0700398 const unsigned char *_src, int _c_w,
399 int _c_h) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400400 int y;
401 int x;
402 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700403 for (x = 0; x < _c_w; x++) {
404 for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700405 _dst[(y >> 1) * _c_w] =
clang-format4eafefe2017-09-04 12:51:20 -0700406 OC_CLAMPI(0,
407 (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
408 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
409 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
410 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700411 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400412 }
John Koleszarc6b90392012-07-13 15:21:29 -0700413 for (; y < _c_h - 3; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700414 _dst[(y >> 1) * _c_w] =
clang-format4eafefe2017-09-04 12:51:20 -0700415 OC_CLAMPI(0,
416 (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
417 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
418 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
419 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700420 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400421 }
John Koleszarc6b90392012-07-13 15:21:29 -0700422 for (; y < _c_h; y += 2) {
clang-format6c4d83e2016-08-08 19:03:30 -0700423 _dst[(y >> 1) * _c_w] = OC_CLAMPI(
424 0,
425 (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
426 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
427 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
428 64) >>
429 7,
430 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400431 }
432 _src++;
433 _dst++;
434 }
435}
436
437/*420jpeg chroma samples are sited like:
438 Y-------Y-------Y-------Y-------
439 | | | |
440 | BR | | BR |
441 | | | |
442 Y-------Y-------Y-------Y-------
443 | | | |
444 | | | |
445 | | | |
446 Y-------Y-------Y-------Y-------
447 | | | |
448 | BR | | BR |
449 | | | |
450 Y-------Y-------Y-------Y-------
451 | | | |
452 | | | |
453 | | | |
454
455 422jpeg chroma samples are sited like:
456 Y---BR--Y-------Y---BR--Y-------
457 | | | |
458 | | | |
459 | | | |
460 Y---BR--Y-------Y---BR--Y-------
461 | | | |
462 | | | |
463 | | | |
464 Y---BR--Y-------Y---BR--Y-------
465 | | | |
466 | | | |
467 | | | |
468 Y---BR--Y-------Y---BR--Y-------
469 | | | |
470 | | | |
471 | | | |
472
473 We use a resampling filter to decimate the chroma planes by two in the
474 vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700475static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
476 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400477 int c_w;
478 int c_h;
479 int c_sz;
480 int dst_c_w;
481 int dst_c_h;
482 int dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400483 int pli;
484 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700485 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400486 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700487 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
488 c_h = _y4m->pic_h;
489 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
490 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
491 c_sz = c_w * c_h;
492 dst_c_sz = dst_c_w * dst_c_h;
493 for (pli = 1; pli < 3; pli++) {
494 y4m_422jpeg_420jpeg_helper(_dst, _aux, c_w, c_h);
495 _aux += c_sz;
496 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400497 }
498}
499
500/*420jpeg chroma samples are sited like:
501 Y-------Y-------Y-------Y-------
502 | | | |
503 | BR | | BR |
504 | | | |
505 Y-------Y-------Y-------Y-------
506 | | | |
507 | | | |
508 | | | |
509 Y-------Y-------Y-------Y-------
510 | | | |
511 | BR | | BR |
512 | | | |
513 Y-------Y-------Y-------Y-------
514 | | | |
515 | | | |
516 | | | |
517
518 422 chroma samples are sited like:
519 YBR-----Y-------YBR-----Y-------
520 | | | |
521 | | | |
522 | | | |
523 YBR-----Y-------YBR-----Y-------
524 | | | |
525 | | | |
526 | | | |
527 YBR-----Y-------YBR-----Y-------
528 | | | |
529 | | | |
530 | | | |
531 YBR-----Y-------YBR-----Y-------
532 | | | |
533 | | | |
534 | | | |
535
536 We use a resampling filter to shift the original site locations one quarter
537 pixel (at the original chroma resolution) to the right.
538 Then we use a second resampling filter to decimate the chroma planes by two
539 in the vertical direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700540static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
541 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400542 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700543 int c_w;
544 int c_h;
545 int c_sz;
546 int dst_c_h;
547 int dst_c_sz;
548 int pli;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400549 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700550 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400551 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700552 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
553 c_h = _y4m->pic_h;
554 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
555 c_sz = c_w * c_h;
556 dst_c_sz = c_w * dst_c_h;
557 tmp = _aux + 2 * c_sz;
558 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400559 /*In reality, the horizontal and vertical steps could be pipelined, for
560 less memory consumption and better cache performance, but we do them
561 separately for simplicity.*/
562 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700563 y4m_42xmpeg2_42xjpeg_helper(tmp, _aux, c_w, c_h);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400564 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700565 y4m_422jpeg_420jpeg_helper(_dst, tmp, c_w, c_h);
566 _aux += c_sz;
567 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400568 }
569}
570
571/*420jpeg chroma samples are sited like:
572 Y-------Y-------Y-------Y-------
573 | | | |
574 | BR | | BR |
575 | | | |
576 Y-------Y-------Y-------Y-------
577 | | | |
578 | | | |
579 | | | |
580 Y-------Y-------Y-------Y-------
581 | | | |
582 | BR | | BR |
583 | | | |
584 Y-------Y-------Y-------Y-------
585 | | | |
586 | | | |
587 | | | |
588
589 411 chroma samples are sited like:
590 YBR-----Y-------Y-------Y-------
591 | | | |
592 | | | |
593 | | | |
594 YBR-----Y-------Y-------Y-------
595 | | | |
596 | | | |
597 | | | |
598 YBR-----Y-------Y-------Y-------
599 | | | |
600 | | | |
601 | | | |
602 YBR-----Y-------Y-------Y-------
603 | | | |
604 | | | |
605 | | | |
606
607 We use a filter to resample at site locations one eighth pixel (at the source
608 chroma plane's horizontal resolution) and five eighths of a pixel to the
609 right.
610 Then we use another filter to decimate the planes by 2 in the vertical
611 direction.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700612static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
613 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400614 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700615 int c_w;
616 int c_h;
617 int c_sz;
618 int dst_c_w;
619 int dst_c_h;
620 int dst_c_sz;
621 int tmp_sz;
622 int pli;
623 int y;
624 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400625 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700626 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400627 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700628 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
629 c_h = _y4m->pic_h;
630 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
631 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
632 c_sz = c_w * c_h;
633 dst_c_sz = dst_c_w * dst_c_h;
634 tmp_sz = dst_c_w * c_h;
635 tmp = _aux + 2 * c_sz;
636 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400637 /*In reality, the horizontal and vertical steps could be pipelined, for
638 less memory consumption and better cache performance, but we do them
639 separately for simplicity.*/
640 /*First do horizontal filtering (convert to 422jpeg)*/
John Koleszarc6b90392012-07-13 15:21:29 -0700641 for (y = 0; y < c_h; y++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400642 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
643 4-tap Mitchell window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700644 for (x = 0; x < OC_MINI(c_w, 1); x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700645 tmp[x << 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700646 0,
647 (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
648 _aux[OC_MINI(2, c_w - 1)] + 64) >>
649 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700650 255);
651 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700652 0,
653 (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
654 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
655 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700656 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400657 }
John Koleszarc6b90392012-07-13 15:21:29 -0700658 for (; x < c_w - 2; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700659 tmp[x << 1] =
clang-format4eafefe2017-09-04 12:51:20 -0700660 (unsigned char)OC_CLAMPI(0,
661 (_aux[x - 1] + 110 * _aux[x] +
662 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
663 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700664 255);
665 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700666 0,
667 (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
668 5 * _aux[x + 2] + 64) >>
669 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700670 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400671 }
John Koleszarc6b90392012-07-13 15:21:29 -0700672 for (; x < c_w; x++) {
clang-format6c4d83e2016-08-08 19:03:30 -0700673 tmp[x << 1] = (unsigned char)OC_CLAMPI(
clang-format4eafefe2017-09-04 12:51:20 -0700674 0,
675 (_aux[x - 1] + 110 * _aux[x] + 18 * _aux[OC_MINI(x + 1, c_w - 1)] -
676 _aux[c_w - 1] + 64) >>
677 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700678 255);
John Koleszarc6b90392012-07-13 15:21:29 -0700679 if ((x << 1 | 1) < dst_c_w) {
clang-format6c4d83e2016-08-08 19:03:30 -0700680 tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
681 0,
682 (-3 * _aux[x - 1] + 50 * _aux[x] +
683 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
684 7,
685 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400686 }
687 }
John Koleszarc6b90392012-07-13 15:21:29 -0700688 tmp += dst_c_w;
689 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400690 }
John Koleszarc6b90392012-07-13 15:21:29 -0700691 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400692 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700693 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
694 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400695 }
696}
697
698/*Convert 444 to 420jpeg.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700699static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
700 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400701 unsigned char *tmp;
clang-format6c4d83e2016-08-08 19:03:30 -0700702 int c_w;
703 int c_h;
704 int c_sz;
705 int dst_c_w;
706 int dst_c_h;
707 int dst_c_sz;
708 int tmp_sz;
709 int pli;
710 int y;
711 int x;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400712 /*Skip past the luma data.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700713 _dst += _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400714 /*Compute the size of each chroma plane.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700715 c_w = (_y4m->pic_w + _y4m->src_c_dec_h - 1) / _y4m->src_c_dec_h;
716 c_h = _y4m->pic_h;
717 dst_c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
718 dst_c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
719 c_sz = c_w * c_h;
720 dst_c_sz = dst_c_w * dst_c_h;
721 tmp_sz = dst_c_w * c_h;
722 tmp = _aux + 2 * c_sz;
723 for (pli = 1; pli < 3; pli++) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400724 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700725 for (y = 0; y < c_h; y++) {
726 for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700727 tmp[x >> 1] = OC_CLAMPI(0,
728 (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
729 17 * _aux[OC_MINI(2, c_w - 1)] +
730 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
731 7,
732 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400733 }
John Koleszarc6b90392012-07-13 15:21:29 -0700734 for (; x < c_w - 3; x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700735 tmp[x >> 1] = OC_CLAMPI(0,
736 (3 * (_aux[x - 2] + _aux[x + 3]) -
737 17 * (_aux[x - 1] + _aux[x + 2]) +
738 78 * (_aux[x] + _aux[x + 1]) + 64) >>
739 7,
clang-format6c4d83e2016-08-08 19:03:30 -0700740 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400741 }
John Koleszarc6b90392012-07-13 15:21:29 -0700742 for (; x < c_w; x += 2) {
clang-format4eafefe2017-09-04 12:51:20 -0700743 tmp[x >> 1] =
744 OC_CLAMPI(0,
745 (3 * (_aux[x - 2] + _aux[c_w - 1]) -
746 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
747 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
748 7,
749 255);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400750 }
John Koleszarc6b90392012-07-13 15:21:29 -0700751 tmp += dst_c_w;
752 _aux += c_w;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400753 }
John Koleszarc6b90392012-07-13 15:21:29 -0700754 tmp -= tmp_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400755 /*Now do the vertical filtering.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700756 y4m_422jpeg_420jpeg_helper(_dst, tmp, dst_c_w, c_h);
757 _dst += dst_c_sz;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400758 }
759}
760
761/*The image is padded with empty chroma components at 4:2:0.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700762static void y4m_convert_mono_420jpeg(y4m_input *_y4m, unsigned char *_dst,
763 unsigned char *_aux) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400764 int c_sz;
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700765 (void)_aux;
John Koleszarc6b90392012-07-13 15:21:29 -0700766 _dst += _y4m->pic_w * _y4m->pic_h;
767 c_sz = ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
768 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
769 memset(_dst, 128, c_sz * 2);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400770}
771
772/*No conversion function needed.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700773static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
774 unsigned char *_aux) {
Yaowu Xu618e7ef2014-07-11 16:27:21 -0700775 (void)_y4m;
776 (void)_dst;
777 (void)_aux;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400778}
779
John Koleszar8dd82872013-05-06 11:01:35 -0700780int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
781 int only_420) {
clang-format6c4d83e2016-08-08 19:03:30 -0700782 char buffer[80] = { 0 };
783 int ret;
784 int i;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400785 /*Read until newline, or 80 cols, whichever happens first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700786 for (i = 0; i < 79; i++) {
787 if (_nskip > 0) {
788 buffer[i] = *_skip++;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400789 _nskip--;
John Koleszarc6b90392012-07-13 15:21:29 -0700790 } else {
James Zerndf0829f2014-02-12 16:30:43 -0800791 if (!file_read(buffer + i, 1, _fin)) return -1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400792 }
clang-format6c4d83e2016-08-08 19:03:30 -0700793 if (buffer[i] == '\n') break;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400794 }
795 /*We skipped too much header data.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700796 if (_nskip > 0) return -1;
John Koleszarc6b90392012-07-13 15:21:29 -0700797 if (i == 79) {
798 fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400799 return -1;
800 }
John Koleszarc6b90392012-07-13 15:21:29 -0700801 buffer[i] = '\0';
802 if (memcmp(buffer, "YUV4MPEG", 8)) {
803 fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400804 return -1;
805 }
John Koleszarc6b90392012-07-13 15:21:29 -0700806 if (buffer[8] != '2') {
807 fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400808 }
John Koleszarc6b90392012-07-13 15:21:29 -0700809 ret = y4m_parse_tags(_y4m, buffer + 5);
810 if (ret < 0) {
811 fprintf(stderr, "Error parsing YUV4MPEG2 header.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400812 return ret;
813 }
John Koleszarc6b90392012-07-13 15:21:29 -0700814 if (_y4m->interlace == '?') {
clang-format6c4d83e2016-08-08 19:03:30 -0700815 fprintf(stderr,
816 "Warning: Input video interlacing format unknown; "
John Koleszarc6b90392012-07-13 15:21:29 -0700817 "assuming progressive scan.\n");
818 } else if (_y4m->interlace != 'p') {
clang-format6c4d83e2016-08-08 19:03:30 -0700819 fprintf(stderr,
820 "Input video is interlaced; "
John Koleszarc6b90392012-07-13 15:21:29 -0700821 "Only progressive scan handled.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400822 return -1;
823 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700824 _y4m->aom_fmt = AOM_IMG_FMT_I420;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700825 _y4m->bps = 12;
826 _y4m->bit_depth = 8;
John Koleszarc6b90392012-07-13 15:21:29 -0700827 if (strcmp(_y4m->chroma_type, "420") == 0 ||
828 strcmp(_y4m->chroma_type, "420jpeg") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700829 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
830 _y4m->dst_c_dec_v = 2;
831 _y4m->dst_buf_read_sz =
832 _y4m->pic_w * _y4m->pic_h +
833 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700834 /* Natively supported: no conversion required. */
John Koleszarc6b90392012-07-13 15:21:29 -0700835 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
836 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700837 } else if (strcmp(_y4m->chroma_type, "420p10") == 0) {
838 _y4m->src_c_dec_h = 2;
839 _y4m->dst_c_dec_h = 2;
840 _y4m->src_c_dec_v = 2;
841 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700842 _y4m->dst_buf_read_sz =
843 2 * (_y4m->pic_w * _y4m->pic_h +
844 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700845 /* Natively supported: no conversion required. */
846 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
847 _y4m->convert = y4m_convert_null;
848 _y4m->bit_depth = 10;
849 _y4m->bps = 15;
Yaowu Xuf883b422016-08-30 14:01:10 -0700850 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700851 if (only_420) {
852 fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n");
853 return -1;
854 }
855 } else if (strcmp(_y4m->chroma_type, "420p12") == 0) {
856 _y4m->src_c_dec_h = 2;
857 _y4m->dst_c_dec_h = 2;
858 _y4m->src_c_dec_v = 2;
859 _y4m->dst_c_dec_v = 2;
clang-format6c4d83e2016-08-08 19:03:30 -0700860 _y4m->dst_buf_read_sz =
861 2 * (_y4m->pic_w * _y4m->pic_h +
862 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700863 /* Natively supported: no conversion required. */
864 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
865 _y4m->convert = y4m_convert_null;
866 _y4m->bit_depth = 12;
867 _y4m->bps = 18;
Yaowu Xuf883b422016-08-30 14:01:10 -0700868 _y4m->aom_fmt = AOM_IMG_FMT_I42016;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700869 if (only_420) {
870 fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n");
871 return -1;
872 }
John Koleszarc6b90392012-07-13 15:21:29 -0700873 } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700874 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
875 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700876 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400877 /*Chroma filter required: read into the aux buf first.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700878 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
clang-format6c4d83e2016-08-08 19:03:30 -0700879 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700880 _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
881 } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
clang-format6c4d83e2016-08-08 19:03:30 -0700882 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
883 _y4m->dst_c_dec_v = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700884 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400885 /*Chroma filter required: read into the aux buf first.
886 We need to make two filter passes, so we need some extra space in the
887 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700888 _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
clang-format6c4d83e2016-08-08 19:03:30 -0700889 _y4m->aux_buf_read_sz =
890 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
John Koleszarc6b90392012-07-13 15:21:29 -0700891 _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
892 } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
893 _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
894 _y4m->src_c_dec_v = 1;
895 _y4m->dst_c_dec_v = 2;
896 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400897 /*Chroma filter required: read into the aux buf first.*/
clang-format6c4d83e2016-08-08 19:03:30 -0700898 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
899 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700900 _y4m->convert = y4m_convert_422jpeg_420jpeg;
901 } else if (strcmp(_y4m->chroma_type, "422") == 0) {
John Koleszar8dd82872013-05-06 11:01:35 -0700902 _y4m->src_c_dec_h = 2;
John Koleszarc6b90392012-07-13 15:21:29 -0700903 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700904 if (only_420) {
905 _y4m->dst_c_dec_h = 2;
906 _y4m->dst_c_dec_v = 2;
907 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
908 /*Chroma filter required: read into the aux buf first.
909 We need to make two filter passes, so we need some extra space in the
910 aux buffer.*/
911 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700912 _y4m->aux_buf_sz =
913 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700914 _y4m->convert = y4m_convert_422_420jpeg;
915 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700916 _y4m->aom_fmt = AOM_IMG_FMT_I422;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700917 _y4m->bps = 16;
John Koleszar8dd82872013-05-06 11:01:35 -0700918 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
919 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
clang-format6c4d83e2016-08-08 19:03:30 -0700920 _y4m->dst_buf_read_sz =
921 _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700922 /*Natively supported: no conversion required.*/
923 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
924 _y4m->convert = y4m_convert_null;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700925 }
926 } else if (strcmp(_y4m->chroma_type, "422p10") == 0) {
927 _y4m->src_c_dec_h = 2;
928 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700929 _y4m->aom_fmt = AOM_IMG_FMT_I42216;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700930 _y4m->bps = 20;
931 _y4m->bit_depth = 10;
932 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
933 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
934 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
935 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
936 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
937 _y4m->convert = y4m_convert_null;
938 if (only_420) {
939 fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n");
940 return -1;
941 }
942 } else if (strcmp(_y4m->chroma_type, "422p12") == 0) {
943 _y4m->src_c_dec_h = 2;
944 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -0700945 _y4m->aom_fmt = AOM_IMG_FMT_I42216;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700946 _y4m->bps = 24;
947 _y4m->bit_depth = 12;
948 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
949 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
950 _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h +
951 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h);
952 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
953 _y4m->convert = y4m_convert_null;
954 if (only_420) {
955 fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n");
956 return -1;
957 }
John Koleszarc6b90392012-07-13 15:21:29 -0700958 } else if (strcmp(_y4m->chroma_type, "411") == 0) {
959 _y4m->src_c_dec_h = 4;
960 _y4m->dst_c_dec_h = 2;
961 _y4m->src_c_dec_v = 1;
962 _y4m->dst_c_dec_v = 2;
963 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -0400964 /*Chroma filter required: read into the aux buf first.
965 We need to make two filter passes, so we need some extra space in the
966 aux buffer.*/
John Koleszarc6b90392012-07-13 15:21:29 -0700967 _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700968 _y4m->aux_buf_sz =
969 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszarc6b90392012-07-13 15:21:29 -0700970 _y4m->convert = y4m_convert_411_420jpeg;
971 } else if (strcmp(_y4m->chroma_type, "444") == 0) {
972 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -0700973 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -0700974 if (only_420) {
975 _y4m->dst_c_dec_h = 2;
976 _y4m->dst_c_dec_v = 2;
977 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
978 /*Chroma filter required: read into the aux buf first.
979 We need to make two filter passes, so we need some extra space in the
980 aux buffer.*/
981 _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
clang-format6c4d83e2016-08-08 19:03:30 -0700982 _y4m->aux_buf_sz =
983 _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -0700984 _y4m->convert = y4m_convert_444_420jpeg;
985 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -0700986 _y4m->aom_fmt = AOM_IMG_FMT_I444;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700987 _y4m->bps = 24;
John Koleszar8dd82872013-05-06 11:01:35 -0700988 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
989 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
990 _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
991 /*Natively supported: no conversion required.*/
992 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
993 _y4m->convert = y4m_convert_null;
994 }
Deb Mukherjee5820c5d2014-06-12 16:53:13 -0700995 } else if (strcmp(_y4m->chroma_type, "444p10") == 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 = 30;
1000 _y4m->bit_depth = 10;
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 444p10 to 420jpeg\n");
1008 return -1;
1009 }
1010 } else if (strcmp(_y4m->chroma_type, "444p12") == 0) {
1011 _y4m->src_c_dec_h = 1;
1012 _y4m->src_c_dec_v = 1;
Yaowu Xuf883b422016-08-30 14:01:10 -07001013 _y4m->aom_fmt = AOM_IMG_FMT_I44416;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001014 _y4m->bps = 36;
1015 _y4m->bit_depth = 12;
1016 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1017 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1018 _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h;
1019 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1020 _y4m->convert = y4m_convert_null;
1021 if (only_420) {
1022 fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n");
1023 return -1;
1024 }
John Koleszarc6b90392012-07-13 15:21:29 -07001025 } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
1026 _y4m->src_c_dec_h = 1;
John Koleszarc6b90392012-07-13 15:21:29 -07001027 _y4m->src_c_dec_v = 1;
John Koleszar8dd82872013-05-06 11:01:35 -07001028 if (only_420) {
1029 _y4m->dst_c_dec_h = 2;
1030 _y4m->dst_c_dec_v = 2;
1031 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
1032 /*Chroma filter required: read into the aux buf first.
1033 We need to make two filter passes, so we need some extra space in the
1034 aux buffer.
1035 The extra plane also gets read into the aux buf.
1036 It will be discarded.*/
1037 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
1038 _y4m->convert = y4m_convert_444_420jpeg;
1039 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07001040 _y4m->aom_fmt = AOM_IMG_FMT_444A;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001041 _y4m->bps = 32;
John Koleszar8dd82872013-05-06 11:01:35 -07001042 _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
1043 _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
1044 _y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
1045 /*Natively supported: no conversion required.*/
1046 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1047 _y4m->convert = y4m_convert_null;
1048 }
John Koleszarc6b90392012-07-13 15:21:29 -07001049 } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
1050 _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
1051 _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
1052 _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001053 /*No extra space required, but we need to clear the chroma planes.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001054 _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
1055 _y4m->convert = y4m_convert_mono_420jpeg;
1056 } else {
1057 fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001058 return -1;
1059 }
1060 /*The size of the final frame buffers is always computed from the
1061 destination chroma decimation type.*/
clang-format6c4d83e2016-08-08 19:03:30 -07001062 _y4m->dst_buf_sz =
1063 _y4m->pic_w * _y4m->pic_h +
1064 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
1065 ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001066 if (_y4m->bit_depth == 8)
Yaowu Xua0af4162014-10-08 08:38:15 -07001067 _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001068 else
Yaowu Xua0af4162014-10-08 08:38:15 -07001069 _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz);
Jim Bankoskie35c54e2014-08-19 09:00:44 -07001070
1071 if (_y4m->aux_buf_sz > 0)
1072 _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001073 return 0;
1074}
1075
John Koleszarc6b90392012-07-13 15:21:29 -07001076void y4m_input_close(y4m_input *_y4m) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001077 free(_y4m->dst_buf);
1078 free(_y4m->aux_buf);
1079}
1080
Yaowu Xuf883b422016-08-30 14:01:10 -07001081int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, aom_image_t *_img) {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001082 char frame[6];
clang-format6c4d83e2016-08-08 19:03:30 -07001083 int pic_sz;
1084 int c_w;
1085 int c_h;
1086 int c_sz;
1087 int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001088 /*Read and skip the frame header.*/
James Zerndf0829f2014-02-12 16:30:43 -08001089 if (!file_read(frame, 6, _fin)) return 0;
John Koleszarc6b90392012-07-13 15:21:29 -07001090 if (memcmp(frame, "FRAME", 5)) {
1091 fprintf(stderr, "Loss of framing in Y4M input data\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001092 return -1;
1093 }
John Koleszarc6b90392012-07-13 15:21:29 -07001094 if (frame[5] != '\n') {
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001095 char c;
clang-format6c4d83e2016-08-08 19:03:30 -07001096 int j;
1097 for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
1098 }
John Koleszarc6b90392012-07-13 15:21:29 -07001099 if (j == 79) {
1100 fprintf(stderr, "Error parsing Y4M frame header\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001101 return -1;
1102 }
1103 }
1104 /*Read the frame data that needs no conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001105 if (!file_read(_y4m->dst_buf, _y4m->dst_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001106 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001107 return -1;
1108 }
1109 /*Read the frame data that does need conversion.*/
James Zerndf0829f2014-02-12 16:30:43 -08001110 if (!file_read(_y4m->aux_buf, _y4m->aux_buf_read_sz, _fin)) {
John Koleszarc6b90392012-07-13 15:21:29 -07001111 fprintf(stderr, "Error reading Y4M frame data.\n");
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001112 return -1;
1113 }
1114 /*Now convert the just read frame.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001115 (*_y4m->convert)(_y4m, _y4m->dst_buf, _y4m->aux_buf);
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001116 /*Fill in the frame buffer pointers.
Yaowu Xuf883b422016-08-30 14:01:10 -07001117 We don't use aom_img_wrap() because it forces padding for odd picture
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001118 sizes, which would require a separate fread call for every row.*/
John Koleszarc6b90392012-07-13 15:21:29 -07001119 memset(_img, 0, sizeof(*_img));
Yaowu Xuc27fc142016-08-22 16:08:15 -07001120 /*Y4M has the planes in Y'CbCr order, which libaom calls Y, U, and V.*/
Yaowu Xuf883b422016-08-30 14:01:10 -07001121 _img->fmt = _y4m->aom_fmt;
John Koleszarc6b90392012-07-13 15:21:29 -07001122 _img->w = _img->d_w = _y4m->pic_w;
1123 _img->h = _img->d_h = _y4m->pic_h;
John Koleszar8dd82872013-05-06 11:01:35 -07001124 _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
1125 _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001126 _img->bps = _y4m->bps;
John Koleszar8dd82872013-05-06 11:01:35 -07001127
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001128 /*Set up the buffer pointers.*/
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001129 pic_sz = _y4m->pic_w * _y4m->pic_h * bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001130 c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001131 c_w *= bytes_per_sample;
John Koleszarc6b90392012-07-13 15:21:29 -07001132 c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
1133 c_sz = c_w * c_h;
Yaowu Xuf883b422016-08-30 14:01:10 -07001134 _img->stride[AOM_PLANE_Y] = _img->stride[AOM_PLANE_ALPHA] =
Deb Mukherjee5820c5d2014-06-12 16:53:13 -07001135 _y4m->pic_w * bytes_per_sample;
Yaowu Xuf883b422016-08-30 14:01:10 -07001136 _img->stride[AOM_PLANE_U] = _img->stride[AOM_PLANE_V] = c_w;
1137 _img->planes[AOM_PLANE_Y] = _y4m->dst_buf;
1138 _img->planes[AOM_PLANE_U] = _y4m->dst_buf + pic_sz;
1139 _img->planes[AOM_PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
1140 _img->planes[AOM_PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
Timothy B. Terriberryc4d7e5e2010-10-27 16:04:02 -07001141 return 1;
Timothy B. Terriberry44d89492010-05-26 18:27:51 -04001142}