YUV420和YUV422的格式转换 - 源码未调试
YUV420和YUV422的格式转换 <br />2008-03-10 19:16:38<br />1 /* <br />2 * Linux VeeJay <br />3 * <br />4 * Copyright(C)2002-2004 Niels Elburg <br />5 * <br />6 * This program is free software; you can r
2008-03-10 19:16:38
1 /*
2 * Linux VeeJay
3 *
4 * Copyright(C)2002-2004 Niels Elburg
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License , or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 */
19 #include
20
21 #ifdef SUPPORT_READ_DV2
22 #include
23 #include
24 #include "vj-dv.h"
25
26 #define NTSC_W 720
27 #define NTSC_H 480
28 #define PAL_W 720
29 #define PAL_H 576
30 #define DV_PAL_SIZE 144000
31 #define DV_NTSC_SIZE 120000
32
33 static dv_decoder_t *vj_dv_decoder;
34 static dv_encoder_t *vj_dv_encoder;
35 static uint8_t *vj_dv_video[3];
36 static uint8_t *vj_dv_encode_buf;
37
38 /* init the dv decoder and decode buffer*/
39 void vj_dv_init(int width, int height)
40 {
41
42 vj_dv_decoder = dv_decoder_new(1, 1, 0);
43 vj_dv_decoder->quality = DV_QUALITY_BEST;
44 vj_dv_video[0] =
45 (uint8_t *) malloc(width * height * 4 * sizeof(uint8_t));
46 vj_dv_video[1] = NULL;
47 vj_dv_video[2] = NULL;
48 memset( vj_dv_video[0], 0, (width*height*4));
49 }
50
51 /* init the dv encoder and encode buffer */
52 void vj_dv_init_encoder(EditList * el)
53 {
54 vj_dv_encoder = dv_encoder_new(0, 0, 0);
55 vj_dv_encoder->isPAL = (el->video_norm == 'p' ? 1 : 0);
56 vj_dv_encoder->is16x9 = FALSE;
57 vj_dv_encoder->vlc_encode_passes = 3;
58 vj_dv_encoder->static_qno = 0;
59 vj_dv_encoder->force_dct = DV_DCT_AUTO;
60 vj_dv_encode_buf =
61 (uint8_t *) malloc(sizeof(uint8_t) * 3 *
62 (vj_dv_encoder->
63 isPAL ? DV_PAL_SIZE : DV_NTSC_SIZE));
64 memset( vj_dv_encode_buf, 0 , (3 *
65 (vj_dv_encoder->
66 isPAL ? DV_PAL_SIZE : DV_NTSC_SIZE)));
67 }
68
69 /* this routine is the same as frame_YUV422_to_YUV420P , unpack
70 * libdv's 4:2:2-packed into 4:2:0 planar
71 * See http://mjpeg.sourceforge.net/ (MJPEG Tools) (lav-common.c)
72 */
73 void yuy2toyv12(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input,
74 int width, int height)
75 {
76
77 int i, j, w2;
78 uint8_t *y, *u, *v;
79
80 w2 = width / 2;
81
82 //I420
83 y = _y;
84 v = _v;
85 u = _u;
86
87 for (i = 0; i < height; i += 4) {
88 /* top field scanline */
89 for (j = 0; j < w2; j++) {
90 /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
91 *(y++) = *(input++);
92 *(u++) = *(input++);
93 *(y++) = *(input++);
94 *(v++) = *(input++);
95 }
96 for (j = 0; j < w2; j++)
97 {
98 *(y++) = *(input++);
99 *(u++) = *(input++);
100 *(y++) = *(input++);
101 *(v++) = *(input++);
102
103 }
104
105 /* next two scanlines, one frome each field , interleaved */
106 for (j = 0; j < w2; j++) {
107 /* skip every second line for U and V */
108 *(y++) = *(input++);
109 input++;
110 *(y++) = *(input++);
111 input++;
112 }
113 /* bottom field scanline*/
114 for (j = 0; j < w2; j++) {
115 /* skip every second line for U and V */
116 *(y++) = *(input++);
117 input++;
118 *(y++) = *(input++);
119 input++;
120 }
121
122 }
123 }
124
125 /* convert 4:2:0 to yuv 4:2:2 */
126 void yuv420p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width,
127 int height)
128 {
129 unsigned int x, y;
130
131
132 for (y = 0; y < height; ++y) {
133 uint8_t *Y = yuv420[0] + y * width;
134 uint8_t *Cb = yuv420[1] + (y / 2) * (width / 2);
135 uint8_t *Cr = yuv420[2] + (y / 2) * (width / 2);
136 for (x = 0; x < width; x += 2) {
137 *(dest + 0) = Y[0];
138 *(dest + 1) = Cb[0];
139 *(dest + 2) = Y[1];
140 *(dest + 3) = Cr[0];
141 dest += 4;
142 Y += 2;
143 ++Cb;
144 ++Cr;
145 }
146 }
147 }
148
149 /* convert 4:2:0 to yuv 4:2:2
150 static void convert_yuv420p_to_yuv422(uint8_t * yuv_in[3],
151 uint8_t * yuv422, int width,
152 int height)
153 {
154 unsigned int x, y;
155 unsigned int i = 0;
156
157 for (y = 0; y < height; ++y) {
158 uint8_t *Y = yuv_in[0] + y * width;
159 uint8_t *Cb = yuv_in[1] + (y / 2) * (width / 2);
160 uint8_t *Cr = yuv_in[2] + (y / 2) * (width / 2);
161 for (x = 0; x < width; x += 2) {
162 *(yuv422 + i) = Y[0];
163 *(yuv422 + i + 1) = Cb[0];
164 *(yuv422 + i + 2) = Y[1];
165 *(yuv422 + i + 3) = Cr[0];
166 i += 4;
167 Y += 2;
168 ++Cb;
169 ++Cr;
170 }
171 }
172 }
173 */
174
175 /* encode frame to dv format, dv frame will be in output_buf */
176 int vj_dv_encode_frame(uint8_t * input_buf[3], uint8_t * output_buf)
177 {
178
179 time_t now = time(NULL);
180 uint8_t *pixels[3];
181
182 if (!input_buf)
183 return 0;
184
185 pixels[0] = (uint8_t *) vj_dv_encode_buf;
186
187 if (vj_dv_encoder->isPAL) {
188 pixels[2] = (uint8_t *) vj_dv_encode_buf + (PAL_W * PAL_H);
189 pixels[1] = (uint8_t *) vj_dv_encode_buf + (PAL_W * PAL_H * 5) / 4;
190 yuv420p_to_yuv422(input_buf,vj_dv_encode_buf, PAL_W, PAL_H);
191 } else {
192 pixels[2] = (uint8_t *) vj_dv_encode_buf + (NTSC_W * NTSC_H);
193 pixels[1] =
194 (uint8_t *) vj_dv_encode_buf + (NTSC_W * NTSC_H * 5) / 4;
195 yuv420p_to_yuv422(input_buf,vj_dv_encode_buf, NTSC_W , NTSC_H);
196 }
197
198 dv_encode_full_frame(vj_dv_encoder, pixels, e_dv_color_yuv,
199 output_buf);
200 dv_encode_metadata(output_buf, vj_dv_encoder->isPAL,
201 vj_dv_encoder->is16x9, &now, 0);
202 dv_encode_timecode(output_buf, vj_dv_encoder->isPAL, 0);
203
204 if(vj_dv_encoder->isPAL) return DV_PAL_SIZE;
205 return DV_NTSC_SIZE;
206 }
207
208 void vj_dv_free_encoder()
209 {
210 dv_encoder_free(vj_dv_encoder);
211 if(vj_dv_encode_buf) free(vj_dv_encode_buf);
212 }
213
214 void vj_dv_free_decoder() {
215 if(vj_dv_video[0]) free(vj_dv_video[0]);
216 dv_decoder_free(vj_dv_decoder);
217 }
218
219 int vj_dv_decode_frame(uint8_t * input_buf, uint8_t * Y,
220 uint8_t * Cb, uint8_t * Cr, int width, int height)
221 {
222
223 int pitches[3];
224
225 if (!input_buf)
226 return 0;
227
228 if (dv_parse_header(vj_dv_decoder, input_buf) < 0)
229 return 0;
230
231 if (!((vj_dv_decoder->num_dif_seqs == 10)
232 || (vj_dv_decoder->num_dif_seqs == 12)))
233 return 0;
234
235 /*
236 switch(vj_dv_decoder->sampling) {
237 case e_dv_sample_411:fprintf(stderr,"sample 411/n"); break;
238 case e_dv_sample_422:fprintf(stderr,"sample 422/n");break;
239 case e_dv_sample_420:fprintf(stderr,"sample 420/n");break;
240 default: fprintf(stderr,"unknown/n");break;
241 }
242 */
243
244 if (vj_dv_decoder->sampling == e_dv_sample_411 ||
245 vj_dv_decoder->sampling == e_dv_sample_422 ||
246 vj_dv_decoder->sampling == e_dv_sample_420) {
247
248 pitches[0] = width * 2;
249 pitches[1] = 0;
250 pitches[2] = 0;
251
252
253 dv_decode_full_frame(vj_dv_decoder, input_buf,
254 e_dv_color_yuv, vj_dv_video, pitches);
255
256 yuy2toyv12(Y, Cb, Cr, vj_dv_video[0], width, height);
257
258 return 1;
259 }
260
261 return 0;
262 }
263
264 #endif
YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。
更多推荐
所有评论(0)