Merge "respect alignment in arm asm files"
[libvpx.git] / y4minput.c
blobdd51421d783e97c9fa6f1f6af2841774e10442c2
1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
10 * Based on code from the OggTheora software codec source code,
11 * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
13 #include <stdlib.h>
14 #include <string.h>
15 #include "y4minput.h"
17 static int y4m_parse_tags(y4m_input *_y4m,char *_tags){
18 int got_w;
19 int got_h;
20 int got_fps;
21 int got_interlace;
22 int got_par;
23 int got_chroma;
24 char *p;
25 char *q;
26 got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0;
27 for(p=_tags;;p=q){
28 /*Skip any leading spaces.*/
29 while(*p==' ')p++;
30 /*If that's all we have, stop.*/
31 if(p[0]=='\0')break;
32 /*Find the end of this tag.*/
33 for(q=p+1;*q!='\0'&&*q!=' ';q++);
34 /*Process the tag.*/
35 switch(p[0]){
36 case 'W':{
37 if(sscanf(p+1,"%d",&_y4m->pic_w)!=1)return -1;
38 got_w=1;
39 }break;
40 case 'H':{
41 if(sscanf(p+1,"%d",&_y4m->pic_h)!=1)return -1;
42 got_h=1;
43 }break;
44 case 'F':{
45 if(sscanf(p+1,"%d:%d",&_y4m->fps_n,&_y4m->fps_d)!=2){
46 return -1;
48 got_fps=1;
49 }break;
50 case 'I':{
51 _y4m->interlace=p[1];
52 got_interlace=1;
53 }break;
54 case 'A':{
55 if(sscanf(p+1,"%d:%d",&_y4m->par_n,&_y4m->par_d)!=2){
56 return -1;
58 got_par=1;
59 }break;
60 case 'C':{
61 if(q-p>16)return -1;
62 memcpy(_y4m->chroma_type,p+1,q-p-1);
63 _y4m->chroma_type[q-p-1]='\0';
64 got_chroma=1;
65 }break;
66 /*Ignore unknown tags.*/
69 if(!got_w||!got_h||!got_fps)return -1;
70 if(!got_interlace)_y4m->interlace='?';
71 if(!got_par)_y4m->par_n=_y4m->par_d=0;
72 /*Chroma-type is not specified in older files, e.g., those generated by
73 mplayer.*/
74 if(!got_chroma)strcpy(_y4m->chroma_type,"420");
75 return 0;
80 /*All anti-aliasing filters in the following conversion functions are based on
81 one of two window functions:
82 The 6-tap Lanczos window (for down-sampling and shifts):
83 sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
84 0, |t|>=3
85 The 4-tap Mitchell window (for up-sampling):
86 7|t|^3-12|t|^2+16/3, |t|<1
87 -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
88 0, |t|>=2
89 The number of taps is intentionally kept small to reduce computational
90 overhead and limit ringing.
92 The taps from these filters are scaled so that their sum is 1, and the result
93 is scaled by 128 and rounded to integers to create a filter whose
94 intermediate values fit inside 16 bits.
95 Coefficients are rounded in such a way as to ensure their sum is still 128,
96 which is usually equivalent to normal rounding.
98 Conversions which require both horizontal and vertical filtering could
99 have these steps pipelined, for less memory consumption and better cache
100 performance, but we do them separately for simplicity.*/
102 #define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a))
103 #define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a))
104 #define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c)))
106 /*420jpeg chroma samples are sited like:
107 Y-------Y-------Y-------Y-------
108 | | | |
109 | BR | | BR |
110 | | | |
111 Y-------Y-------Y-------Y-------
112 | | | |
113 | | | |
114 | | | |
115 Y-------Y-------Y-------Y-------
116 | | | |
117 | BR | | BR |
118 | | | |
119 Y-------Y-------Y-------Y-------
120 | | | |
121 | | | |
122 | | | |
124 420mpeg2 chroma samples are sited like:
125 Y-------Y-------Y-------Y-------
126 | | | |
127 BR | BR |
128 | | | |
129 Y-------Y-------Y-------Y-------
130 | | | |
131 | | | |
132 | | | |
133 Y-------Y-------Y-------Y-------
134 | | | |
135 BR | BR |
136 | | | |
137 Y-------Y-------Y-------Y-------
138 | | | |
139 | | | |
140 | | | |
142 We use a resampling filter to shift the site locations one quarter pixel (at
143 the chroma plane's resolution) to the right.
144 The 4:2:2 modes look exactly the same, except there are twice as many chroma
145 lines, and they are vertically co-sited with the luma samples in both the
146 mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
147 static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
148 const unsigned char *_src,int _c_w,int _c_h){
149 int y;
150 int x;
151 for(y=0;y<_c_h;y++){
152 /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
153 window.*/
154 for(x=0;x<OC_MINI(_c_w,2);x++){
155 _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[0]-17*_src[OC_MAXI(x-1,0)]+
156 114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
157 _src[OC_MINI(x+3,_c_w-1)]+64)>>7,255);
159 for(;x<_c_w-3;x++){
160 _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
161 114*_src[x]+35*_src[x+1]-9*_src[x+2]+_src[x+3]+64)>>7,255);
163 for(;x<_c_w;x++){
164 _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
165 114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
166 _src[_c_w-1]+64)>>7,255);
168 _dst+=_c_w;
169 _src+=_c_w;
173 /*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
174 static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
175 unsigned char *_aux){
176 int c_w;
177 int c_h;
178 int c_sz;
179 int pli;
180 /*Skip past the luma data.*/
181 _dst+=_y4m->pic_w*_y4m->pic_h;
182 /*Compute the size of each chroma plane.*/
183 c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
184 c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
185 c_sz=c_w*c_h;
186 for(pli=1;pli<3;pli++){
187 y4m_42xmpeg2_42xjpeg_helper(_dst,_aux,c_w,c_h);
188 _dst+=c_sz;
189 _aux+=c_sz;
193 /*This format is only used for interlaced content, but is included for
194 completeness.
196 420jpeg chroma samples are sited like:
197 Y-------Y-------Y-------Y-------
198 | | | |
199 | BR | | BR |
200 | | | |
201 Y-------Y-------Y-------Y-------
202 | | | |
203 | | | |
204 | | | |
205 Y-------Y-------Y-------Y-------
206 | | | |
207 | BR | | BR |
208 | | | |
209 Y-------Y-------Y-------Y-------
210 | | | |
211 | | | |
212 | | | |
214 420paldv chroma samples are sited like:
215 YR------Y-------YR------Y-------
216 | | | |
217 | | | |
218 | | | |
219 YB------Y-------YB------Y-------
220 | | | |
221 | | | |
222 | | | |
223 YR------Y-------YR------Y-------
224 | | | |
225 | | | |
226 | | | |
227 YB------Y-------YB------Y-------
228 | | | |
229 | | | |
230 | | | |
232 We use a resampling filter to shift the site locations one quarter pixel (at
233 the chroma plane's resolution) to the right.
234 Then we use another filter to move the C_r location down one quarter pixel,
235 and the C_b location up one quarter pixel.*/
236 static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
237 unsigned char *_aux){
238 unsigned char *tmp;
239 int c_w;
240 int c_h;
241 int c_sz;
242 int pli;
243 int y;
244 int x;
245 /*Skip past the luma data.*/
246 _dst+=_y4m->pic_w*_y4m->pic_h;
247 /*Compute the size of each chroma plane.*/
248 c_w=(_y4m->pic_w+1)/2;
249 c_h=(_y4m->pic_h+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
250 c_sz=c_w*c_h;
251 tmp=_aux+2*c_sz;
252 for(pli=1;pli<3;pli++){
253 /*First do the horizontal re-sampling.
254 This is the same as the mpeg2 case, except that after the horizontal
255 case, we need to apply a second vertical filter.*/
256 y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
257 _aux+=c_sz;
258 switch(pli){
259 case 1:{
260 /*Slide C_b up a quarter-pel.
261 This is the same filter used above, but in the other order.*/
262 for(x=0;x<c_w;x++){
263 for(y=0;y<OC_MINI(c_h,3);y++){
264 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[0]
265 -9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w]
266 +114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w]
267 +4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64)>>7,255);
269 for(;y<c_h-2;y++){
270 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
271 -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
272 -17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64)>>7,255);
274 for(;y<c_h;y++){
275 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
276 -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
277 -17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64)>>7,255);
279 _dst++;
280 tmp++;
282 _dst+=c_sz-c_w;
283 tmp-=c_w;
284 }break;
285 case 2:{
286 /*Slide C_r down a quarter-pel.
287 This is the same as the horizontal filter.*/
288 for(x=0;x<c_w;x++){
289 for(y=0;y<OC_MINI(c_h,2);y++){
290 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[0]
291 -17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w]
292 +35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w]
293 +tmp[OC_MINI(y+3,c_h-1)*c_w]+64)>>7,255);
295 for(;y<c_h-3;y++){
296 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
297 -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w]
298 -9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64)>>7,255);
300 for(;y<c_h;y++){
301 _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
302 -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w]
303 -9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64)>>7,255);
305 _dst++;
306 tmp++;
308 }break;
310 /*For actual interlaced material, this would have to be done separately on
311 each field, and the shift amounts would be different.
312 C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
313 C_b up 1/8 in the bottom field.
314 The corresponding filters would be:
315 Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
316 Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
320 /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
321 This is used as a helper by several converation routines.*/
322 static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
323 const unsigned char *_src,int _c_w,int _c_h){
324 int y;
325 int x;
326 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
327 for(x=0;x<_c_w;x++){
328 for(y=0;y<OC_MINI(_c_h,2);y+=2){
329 _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(64*_src[0]
330 +78*_src[OC_MINI(1,_c_h-1)*_c_w]
331 -17*_src[OC_MINI(2,_c_h-1)*_c_w]
332 +3*_src[OC_MINI(3,_c_h-1)*_c_w]+64)>>7,255);
334 for(;y<_c_h-3;y+=2){
335 _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]+_src[(y+3)*_c_w])
336 -17*(_src[(y-1)*_c_w]+_src[(y+2)*_c_w])
337 +78*(_src[y*_c_w]+_src[(y+1)*_c_w])+64)>>7,255);
339 for(;y<_c_h;y+=2){
340 _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]
341 +_src[(_c_h-1)*_c_w])-17*(_src[(y-1)*_c_w]
342 +_src[OC_MINI(y+2,_c_h-1)*_c_w])
343 +78*(_src[y*_c_w]+_src[OC_MINI(y+1,_c_h-1)*_c_w])+64)>>7,255);
345 _src++;
346 _dst++;
350 /*420jpeg chroma samples are sited like:
351 Y-------Y-------Y-------Y-------
352 | | | |
353 | BR | | BR |
354 | | | |
355 Y-------Y-------Y-------Y-------
356 | | | |
357 | | | |
358 | | | |
359 Y-------Y-------Y-------Y-------
360 | | | |
361 | BR | | BR |
362 | | | |
363 Y-------Y-------Y-------Y-------
364 | | | |
365 | | | |
366 | | | |
368 422jpeg chroma samples are sited like:
369 Y---BR--Y-------Y---BR--Y-------
370 | | | |
371 | | | |
372 | | | |
373 Y---BR--Y-------Y---BR--Y-------
374 | | | |
375 | | | |
376 | | | |
377 Y---BR--Y-------Y---BR--Y-------
378 | | | |
379 | | | |
380 | | | |
381 Y---BR--Y-------Y---BR--Y-------
382 | | | |
383 | | | |
384 | | | |
386 We use a resampling filter to decimate the chroma planes by two in the
387 vertical direction.*/
388 static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m,unsigned char *_dst,
389 unsigned char *_aux){
390 int c_w;
391 int c_h;
392 int c_sz;
393 int dst_c_w;
394 int dst_c_h;
395 int dst_c_sz;
396 int pli;
397 /*Skip past the luma data.*/
398 _dst+=_y4m->pic_w*_y4m->pic_h;
399 /*Compute the size of each chroma plane.*/
400 c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
401 c_h=_y4m->pic_h;
402 dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
403 dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
404 c_sz=c_w*c_h;
405 dst_c_sz=dst_c_w*dst_c_h;
406 for(pli=1;pli<3;pli++){
407 y4m_422jpeg_420jpeg_helper(_dst,_aux,c_w,c_h);
408 _aux+=c_sz;
409 _dst+=dst_c_sz;
413 /*420jpeg chroma samples are sited like:
414 Y-------Y-------Y-------Y-------
415 | | | |
416 | BR | | BR |
417 | | | |
418 Y-------Y-------Y-------Y-------
419 | | | |
420 | | | |
421 | | | |
422 Y-------Y-------Y-------Y-------
423 | | | |
424 | BR | | BR |
425 | | | |
426 Y-------Y-------Y-------Y-------
427 | | | |
428 | | | |
429 | | | |
431 422 chroma samples are sited like:
432 YBR-----Y-------YBR-----Y-------
433 | | | |
434 | | | |
435 | | | |
436 YBR-----Y-------YBR-----Y-------
437 | | | |
438 | | | |
439 | | | |
440 YBR-----Y-------YBR-----Y-------
441 | | | |
442 | | | |
443 | | | |
444 YBR-----Y-------YBR-----Y-------
445 | | | |
446 | | | |
447 | | | |
449 We use a resampling filter to shift the original site locations one quarter
450 pixel (at the original chroma resolution) to the right.
451 Then we use a second resampling filter to decimate the chroma planes by two
452 in the vertical direction.*/
453 static void y4m_convert_422_420jpeg(y4m_input *_y4m,unsigned char *_dst,
454 unsigned char *_aux){
455 unsigned char *tmp;
456 int c_w;
457 int c_h;
458 int c_sz;
459 int dst_c_h;
460 int dst_c_sz;
461 int pli;
462 /*Skip past the luma data.*/
463 _dst+=_y4m->pic_w*_y4m->pic_h;
464 /*Compute the size of each chroma plane.*/
465 c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
466 c_h=_y4m->pic_h;
467 dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
468 c_sz=c_w*c_h;
469 dst_c_sz=c_w*dst_c_h;
470 tmp=_aux+2*c_sz;
471 for(pli=1;pli<3;pli++){
472 /*In reality, the horizontal and vertical steps could be pipelined, for
473 less memory consumption and better cache performance, but we do them
474 separately for simplicity.*/
475 /*First do horizontal filtering (convert to 422jpeg)*/
476 y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
477 /*Now do the vertical filtering.*/
478 y4m_422jpeg_420jpeg_helper(_dst,tmp,c_w,c_h);
479 _aux+=c_sz;
480 _dst+=dst_c_sz;
484 /*420jpeg chroma samples are sited like:
485 Y-------Y-------Y-------Y-------
486 | | | |
487 | BR | | BR |
488 | | | |
489 Y-------Y-------Y-------Y-------
490 | | | |
491 | | | |
492 | | | |
493 Y-------Y-------Y-------Y-------
494 | | | |
495 | BR | | BR |
496 | | | |
497 Y-------Y-------Y-------Y-------
498 | | | |
499 | | | |
500 | | | |
502 411 chroma samples are sited like:
503 YBR-----Y-------Y-------Y-------
504 | | | |
505 | | | |
506 | | | |
507 YBR-----Y-------Y-------Y-------
508 | | | |
509 | | | |
510 | | | |
511 YBR-----Y-------Y-------Y-------
512 | | | |
513 | | | |
514 | | | |
515 YBR-----Y-------Y-------Y-------
516 | | | |
517 | | | |
518 | | | |
520 We use a filter to resample at site locations one eighth pixel (at the source
521 chroma plane's horizontal resolution) and five eighths of a pixel to the
522 right.
523 Then we use another filter to decimate the planes by 2 in the vertical
524 direction.*/
525 static void y4m_convert_411_420jpeg(y4m_input *_y4m,unsigned char *_dst,
526 unsigned char *_aux){
527 unsigned char *tmp;
528 int c_w;
529 int c_h;
530 int c_sz;
531 int dst_c_w;
532 int dst_c_h;
533 int dst_c_sz;
534 int tmp_sz;
535 int pli;
536 int y;
537 int x;
538 /*Skip past the luma data.*/
539 _dst+=_y4m->pic_w*_y4m->pic_h;
540 /*Compute the size of each chroma plane.*/
541 c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
542 c_h=_y4m->pic_h;
543 dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
544 dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
545 c_sz=c_w*c_h;
546 dst_c_sz=dst_c_w*dst_c_h;
547 tmp_sz=dst_c_w*c_h;
548 tmp=_aux+2*c_sz;
549 for(pli=1;pli<3;pli++){
550 /*In reality, the horizontal and vertical steps could be pipelined, for
551 less memory consumption and better cache performance, but we do them
552 separately for simplicity.*/
553 /*First do horizontal filtering (convert to 422jpeg)*/
554 for(y=0;y<c_h;y++){
555 /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
556 4-tap Mitchell window.*/
557 for(x=0;x<OC_MINI(c_w,1);x++){
558 tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(111*_aux[0]
559 +18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
560 tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(47*_aux[0]
561 +86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
563 for(;x<c_w-2;x++){
564 tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
565 +18*_aux[x+1]-_aux[x+2]+64)>>7,255);
566 tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
567 +86*_aux[x+1]-5*_aux[x+2]+64)>>7,255);
569 for(;x<c_w;x++){
570 tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
571 +18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64)>>7,255);
572 if((x<<1|1)<dst_c_w){
573 tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
574 +86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64)>>7,255);
577 tmp+=dst_c_w;
578 _aux+=c_w;
580 tmp-=tmp_sz;
581 /*Now do the vertical filtering.*/
582 y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
583 _dst+=dst_c_sz;
587 /*Convert 444 to 420jpeg.*/
588 static void y4m_convert_444_420jpeg(y4m_input *_y4m,unsigned char *_dst,
589 unsigned char *_aux){
590 unsigned char *tmp;
591 int c_w;
592 int c_h;
593 int c_sz;
594 int dst_c_w;
595 int dst_c_h;
596 int dst_c_sz;
597 int tmp_sz;
598 int pli;
599 int y;
600 int x;
601 /*Skip past the luma data.*/
602 _dst+=_y4m->pic_w*_y4m->pic_h;
603 /*Compute the size of each chroma plane.*/
604 c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
605 c_h=_y4m->pic_h;
606 dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
607 dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
608 c_sz=c_w*c_h;
609 dst_c_sz=dst_c_w*dst_c_h;
610 tmp_sz=dst_c_w*c_h;
611 tmp=_aux+2*c_sz;
612 for(pli=1;pli<3;pli++){
613 /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
614 for(y=0;y<c_h;y++){
615 for(x=0;x<OC_MINI(c_w,2);x+=2){
616 tmp[x>>1]=OC_CLAMPI(0,(64*_aux[0]+78*_aux[OC_MINI(1,c_w-1)]
617 -17*_aux[OC_MINI(2,c_w-1)]
618 +3*_aux[OC_MINI(3,c_w-1)]+64)>>7,255);
620 for(;x<c_w-3;x+=2){
621 tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[x+3])
622 -17*(_aux[x-1]+_aux[x+2])+78*(_aux[x]+_aux[x+1])+64)>>7,255);
624 for(;x<c_w;x+=2){
625 tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[c_w-1])-
626 17*(_aux[x-1]+_aux[OC_MINI(x+2,c_w-1)])+
627 78*(_aux[x]+_aux[OC_MINI(x+1,c_w-1)])+64)>>7,255);
629 tmp+=dst_c_w;
630 _aux+=c_w;
632 tmp-=tmp_sz;
633 /*Now do the vertical filtering.*/
634 y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
635 _dst+=dst_c_sz;
639 /*The image is padded with empty chroma components at 4:2:0.*/
640 static void y4m_convert_mono_420jpeg(y4m_input *_y4m,unsigned char *_dst,
641 unsigned char *_aux){
642 int c_sz;
643 _dst+=_y4m->pic_w*_y4m->pic_h;
644 c_sz=((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
645 ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
646 memset(_dst,128,c_sz*2);
649 /*No conversion function needed.*/
650 static void y4m_convert_null(y4m_input *_y4m,unsigned char *_dst,
651 unsigned char *_aux){
654 int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip){
655 char buffer[80];
656 int ret;
657 int i;
658 /*Read until newline, or 80 cols, whichever happens first.*/
659 for(i=0;i<79;i++){
660 if(_nskip>0){
661 buffer[i]=*_skip++;
662 _nskip--;
664 else{
665 ret=fread(buffer+i,1,1,_fin);
666 if(ret<1)return -1;
668 if(buffer[i]=='\n')break;
670 /*We skipped too much header data.*/
671 if(_nskip>0)return -1;
672 if(i==79){
673 fprintf(stderr,"Error parsing header; not a YUV2MPEG2 file?\n");
674 return -1;
676 buffer[i]='\0';
677 if(memcmp(buffer,"YUV4MPEG",8)){
678 fprintf(stderr,"Incomplete magic for YUV4MPEG file.\n");
679 return -1;
681 if(buffer[8]!='2'){
682 fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
684 ret=y4m_parse_tags(_y4m,buffer+5);
685 if(ret<0){
686 fprintf(stderr,"Error parsing YUV4MPEG2 header.\n");
687 return ret;
689 if(_y4m->interlace=='?'){
690 fprintf(stderr,"Warning: Input video interlacing format unknown; "
691 "assuming progressive scan.\n");
693 else if(_y4m->interlace!='p'){
694 fprintf(stderr,"Input video is interlaced; "
695 "Only progressive scan handled.\n");
696 return -1;
698 if(strcmp(_y4m->chroma_type,"420")==0||
699 strcmp(_y4m->chroma_type,"420jpeg")==0){
700 _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
701 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h
702 +2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
703 /*Natively supported: no conversion required.*/
704 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
705 _y4m->convert=y4m_convert_null;
707 else if(strcmp(_y4m->chroma_type,"420mpeg2")==0){
708 _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
709 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
710 /*Chroma filter required: read into the aux buf first.*/
711 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=
712 2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
713 _y4m->convert=y4m_convert_42xmpeg2_42xjpeg;
715 else if(strcmp(_y4m->chroma_type,"420paldv")==0){
716 _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
717 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
718 /*Chroma filter required: read into the aux buf first.
719 We need to make two filter passes, so we need some extra space in the
720 aux buffer.*/
721 _y4m->aux_buf_sz=3*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
722 _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
723 _y4m->convert=y4m_convert_42xpaldv_42xjpeg;
725 else if(strcmp(_y4m->chroma_type,"422jpeg")==0){
726 _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
727 _y4m->src_c_dec_v=1;
728 _y4m->dst_c_dec_v=2;
729 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
730 /*Chroma filter required: read into the aux buf first.*/
731 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
732 _y4m->convert=y4m_convert_422jpeg_420jpeg;
734 else if(strcmp(_y4m->chroma_type,"422")==0){
735 _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
736 _y4m->src_c_dec_v=1;
737 _y4m->dst_c_dec_v=2;
738 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
739 /*Chroma filter required: read into the aux buf first.
740 We need to make two filter passes, so we need some extra space in the
741 aux buffer.*/
742 _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
743 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
744 _y4m->convert=y4m_convert_422_420jpeg;
746 else if(strcmp(_y4m->chroma_type,"411")==0){
747 _y4m->src_c_dec_h=4;
748 _y4m->dst_c_dec_h=2;
749 _y4m->src_c_dec_v=1;
750 _y4m->dst_c_dec_v=2;
751 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
752 /*Chroma filter required: read into the aux buf first.
753 We need to make two filter passes, so we need some extra space in the
754 aux buffer.*/
755 _y4m->aux_buf_read_sz=2*((_y4m->pic_w+3)/4)*_y4m->pic_h;
756 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
757 _y4m->convert=y4m_convert_411_420jpeg;
759 else if(strcmp(_y4m->chroma_type,"444")==0){
760 _y4m->src_c_dec_h=1;
761 _y4m->dst_c_dec_h=2;
762 _y4m->src_c_dec_v=1;
763 _y4m->dst_c_dec_v=2;
764 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
765 /*Chroma filter required: read into the aux buf first.
766 We need to make two filter passes, so we need some extra space in the
767 aux buffer.*/
768 _y4m->aux_buf_read_sz=2*_y4m->pic_w*_y4m->pic_h;
769 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
770 _y4m->convert=y4m_convert_444_420jpeg;
772 else if(strcmp(_y4m->chroma_type,"444alpha")==0){
773 _y4m->src_c_dec_h=1;
774 _y4m->dst_c_dec_h=2;
775 _y4m->src_c_dec_v=1;
776 _y4m->dst_c_dec_v=2;
777 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
778 /*Chroma filter required: read into the aux buf first.
779 We need to make two filter passes, so we need some extra space in the
780 aux buffer.
781 The extra plane also gets read into the aux buf.
782 It will be discarded.*/
783 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=3*_y4m->pic_w*_y4m->pic_h;
784 _y4m->convert=y4m_convert_444_420jpeg;
786 else if(strcmp(_y4m->chroma_type,"mono")==0){
787 _y4m->src_c_dec_h=_y4m->src_c_dec_v=0;
788 _y4m->dst_c_dec_h=_y4m->dst_c_dec_v=2;
789 _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
790 /*No extra space required, but we need to clear the chroma planes.*/
791 _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
792 _y4m->convert=y4m_convert_mono_420jpeg;
794 else{
795 fprintf(stderr,"Unknown chroma sampling type: %s\n",_y4m->chroma_type);
796 return -1;
798 /*The size of the final frame buffers is always computed from the
799 destination chroma decimation type.*/
800 _y4m->dst_buf_sz=_y4m->pic_w*_y4m->pic_h
801 +2*((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
802 ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
803 _y4m->dst_buf=(unsigned char *)malloc(_y4m->dst_buf_sz);
804 _y4m->aux_buf=(unsigned char *)malloc(_y4m->aux_buf_sz);
805 return 0;
808 void y4m_input_close(y4m_input *_y4m){
809 free(_y4m->dst_buf);
810 free(_y4m->aux_buf);
813 int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *_img){
814 char frame[6];
815 int pic_sz;
816 int c_w;
817 int c_h;
818 int c_sz;
819 int ret;
820 /*Read and skip the frame header.*/
821 ret=fread(frame,1,6,_fin);
822 if(ret<6)return 0;
823 if(memcmp(frame,"FRAME",5)){
824 fprintf(stderr,"Loss of framing in Y4M input data\n");
825 return -1;
827 if(frame[5]!='\n'){
828 char c;
829 int j;
830 for(j=0;j<79&&fread(&c,1,1,_fin)&&c!='\n';j++);
831 if(j==79){
832 fprintf(stderr,"Error parsing Y4M frame header\n");
833 return -1;
836 /*Read the frame data that needs no conversion.*/
837 if(fread(_y4m->dst_buf,1,_y4m->dst_buf_read_sz,_fin)!=_y4m->dst_buf_read_sz){
838 fprintf(stderr,"Error reading Y4M frame data.\n");
839 return -1;
841 /*Read the frame data that does need conversion.*/
842 if(fread(_y4m->aux_buf,1,_y4m->aux_buf_read_sz,_fin)!=_y4m->aux_buf_read_sz){
843 fprintf(stderr,"Error reading Y4M frame data.\n");
844 return -1;
846 /*Now convert the just read frame.*/
847 (*_y4m->convert)(_y4m,_y4m->dst_buf,_y4m->aux_buf);
848 /*Fill in the frame buffer pointers.
849 We don't use vpx_img_wrap() because it forces padding for odd picture
850 sizes, which would require a separate fread call for every row.*/
851 memset(_img,0,sizeof(*_img));
852 /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
853 _img->fmt=IMG_FMT_I420;
854 _img->w=_img->d_w=_y4m->pic_w;
855 _img->h=_img->d_h=_y4m->pic_h;
856 /*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/
857 _img->x_chroma_shift=1;
858 _img->y_chroma_shift=1;
859 _img->bps=12;
860 /*Set up the buffer pointers.*/
861 pic_sz=_y4m->pic_w*_y4m->pic_h;
862 c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
863 c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
864 c_sz=c_w*c_h;
865 _img->stride[PLANE_Y]=_y4m->pic_w;
866 _img->stride[PLANE_U]=_img->stride[PLANE_V]=c_w;
867 _img->planes[PLANE_Y]=_y4m->dst_buf;
868 _img->planes[PLANE_U]=_y4m->dst_buf+pic_sz;
869 _img->planes[PLANE_V]=_y4m->dst_buf+pic_sz+c_sz;
870 return 1;