Mercurial > mplayer.hg
comparison libvo/vo_yuv4mpeg.c @ 4597:4ba62f7d04c6
yuv4mpeg output, by Robert Kesterson <robertk@robertk.com>
author | arpi |
---|---|
date | Sat, 09 Feb 2002 01:25:21 +0000 |
parents | |
children | e406d918e361 |
comparison
equal
deleted
inserted
replaced
4596:c35d7ce151b3 | 4597:4ba62f7d04c6 |
---|---|
1 /* | |
2 * vo_yuv4mpeg.c, yuv4mpeg (mjpegtools) interface | |
3 * | |
4 * Thrown together by | |
5 * Robert Kesterson <robertk@robertk.com> | |
6 * Based on the pgm output plugin, the rgb2rgb postproc filter, divxdec, | |
7 * and probably others. | |
8 * | |
9 * This is undoubtedly incomplete, inaccurate, or just plain wrong. :-) | |
10 * | |
11 */ | |
12 | |
13 #include <stdio.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> | |
16 | |
17 #include "config.h" | |
18 #include "video_out.h" | |
19 #include "video_out_internal.h" | |
20 | |
21 #include <unistd.h> | |
22 #include <stdlib.h> | |
23 #include <stdio.h> | |
24 #include <fcntl.h> | |
25 #include <string.h> | |
26 #include <sys/ioctl.h> | |
27 #include <sys/mman.h> | |
28 #include <signal.h> | |
29 #include <sys/wait.h> | |
30 #include <linux/videodev.h> | |
31 | |
32 | |
33 LIBVO_EXTERN (yuv4mpeg) | |
34 | |
35 static vo_info_t vo_info = | |
36 { | |
37 "yuv4mpeg output for mjpegtools (to \"stream.yuv\")", | |
38 "yuv4mpeg", | |
39 "Robert Kesterson <robertk@robertk.com>", | |
40 "" | |
41 }; | |
42 | |
43 static int image_width; | |
44 static int image_height; | |
45 | |
46 static uint8_t *image = NULL; | |
47 static uint8_t *image_y = NULL; | |
48 static uint8_t *image_u = NULL; | |
49 static uint8_t *image_v = NULL; | |
50 | |
51 static int using_format = 0; | |
52 static FILE *yuv_out; | |
53 int write_bytes; | |
54 | |
55 | |
56 /** | |
57 * | |
58 * height should be a multiple of 2 and width should be a multiple of 2 | |
59 * chrominance data is only taken from every secound line others are ignored | |
60 */ | |
61 #define RGB2YUV_SHIFT 8 | |
62 #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5)) | |
63 #define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5)) | |
64 #define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5)) | |
65 #define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5)) | |
66 #define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5)) | |
67 #define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5)) | |
68 #define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5)) | |
69 #define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5)) | |
70 #define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5)) | |
71 | |
72 static inline void rgb24toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, | |
73 unsigned int width, unsigned int height, | |
74 unsigned int lumStride, unsigned int chromStride, unsigned int srcStride) | |
75 { | |
76 int y; | |
77 const int chromWidth= width>>1; | |
78 for(y=0; y<height; y+=2) | |
79 { | |
80 int i; | |
81 for(i=0; i<chromWidth; i++) | |
82 { | |
83 unsigned int b= src[6*i+0]; | |
84 unsigned int g= src[6*i+1]; | |
85 unsigned int r= src[6*i+2]; | |
86 | |
87 unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16; | |
88 unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128; | |
89 unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128; | |
90 | |
91 udst[i] = U; | |
92 vdst[i] = V; | |
93 ydst[2*i] = Y; | |
94 | |
95 b= src[6*i+3]; | |
96 g= src[6*i+4]; | |
97 r= src[6*i+5]; | |
98 | |
99 Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16; | |
100 ydst[2*i+1] = Y; | |
101 } | |
102 ydst += lumStride; | |
103 src += srcStride; | |
104 | |
105 for(i=0; i<chromWidth; i++) | |
106 { | |
107 unsigned int b= src[6*i+0]; | |
108 unsigned int g= src[6*i+1]; | |
109 unsigned int r= src[6*i+2]; | |
110 | |
111 unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16; | |
112 | |
113 ydst[2*i] = Y; | |
114 | |
115 b= src[6*i+3]; | |
116 g= src[6*i+4]; | |
117 r= src[6*i+5]; | |
118 | |
119 Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16; | |
120 ydst[2*i+1] = Y; | |
121 } | |
122 udst += chromStride; | |
123 vdst += chromStride; | |
124 ydst += lumStride; | |
125 src += srcStride; | |
126 } | |
127 } | |
128 | |
129 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, | |
130 uint32_t d_height, uint32_t fullscreen, char *title, | |
131 uint32_t format, const vo_tune_info_t *tuneinfo) | |
132 { | |
133 image_height = height; | |
134 image_width = width; | |
135 write_bytes = image_width * image_height * 3 / 2; | |
136 using_format = format; | |
137 image = malloc(write_bytes); | |
138 | |
139 yuv_out = fopen("stream.yuv", "wb"); | |
140 if (!yuv_out || image == NULL) | |
141 { | |
142 perror("Can't get memory or file handle to stream.yuv"); | |
143 return -1; | |
144 } | |
145 image_y = image; | |
146 image_u = image_y + image_width * image_height; | |
147 image_v = image_u + (image_width * image_height) / 4; | |
148 | |
149 // This isn't right. | |
150 // But it should work as long as the file isn't interlaced | |
151 // or otherwise unusual (the "Ip A0:0" part). | |
152 fprintf(yuv_out, "YUV4MPEG2 W%d H%d F%ld:%ld Ip A0:0\n", | |
153 image_width, image_height, (long)(vo_fps * 1000000.0), 1000000); | |
154 | |
155 fflush(yuv_out); | |
156 return 0; | |
157 } | |
158 | |
159 static const vo_info_t* get_info(void) | |
160 { | |
161 return &vo_info; | |
162 } | |
163 | |
164 static void draw_osd(void) | |
165 { | |
166 } | |
167 | |
168 static void flip_page (void) | |
169 { | |
170 fprintf(yuv_out, "FRAME\n"); | |
171 if(fwrite(image, 1, write_bytes, yuv_out) != write_bytes) | |
172 perror("Error writing image to output!"); | |
173 return; | |
174 } | |
175 | |
176 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y) | |
177 { | |
178 if(using_format == IMGFMT_YV12) | |
179 { | |
180 int i; | |
181 // copy Y: | |
182 uint8_t *dst = image_y + image_width * y + x; | |
183 uint8_t *src = srcimg[0]; | |
184 for (i = 0; i < h; i++) | |
185 { | |
186 memcpy(dst, src, w); | |
187 src += stride[0]; | |
188 dst += image_width; | |
189 } | |
190 { | |
191 // copy U + V: | |
192 uint8_t *src1 = srcimg[1]; | |
193 uint8_t *src2 = srcimg[2]; | |
194 uint8_t *dstu = image_u + image_width * (y / 2) + (x / 2); | |
195 uint8_t *dstv = image_v + image_width * (y / 2) + (x / 2); | |
196 for (i = 0; i < h / 2; i++) | |
197 { | |
198 memcpy(dstu, src1 , w / 2); | |
199 memcpy(dstv, src2, w / 2); | |
200 src1 += stride[1]; | |
201 src2 += stride[2]; | |
202 dstu += image_width / 2; | |
203 dstv += image_width / 2; | |
204 } | |
205 } | |
206 } | |
207 return 0; | |
208 } | |
209 | |
210 | |
211 static uint32_t draw_frame(uint8_t * src[]) | |
212 { | |
213 switch(using_format) | |
214 { | |
215 case IMGFMT_YV12: | |
216 // gets done in draw_slice | |
217 break; | |
218 case IMGFMT_BGR|24: | |
219 { | |
220 #ifdef GUESS_THIS_ISNT_NEEDED | |
221 int c; | |
222 uint8_t temp; | |
223 //switch BGR to RGB | |
224 for(c = 0; c < image_width * image_height; c++) | |
225 { | |
226 temp = src[0][c * 3]; | |
227 src[0][c * 3] = src[0][c * 3 + 2]; | |
228 src[0][c * 3 + 2] = temp; | |
229 } | |
230 #endif | |
231 } | |
232 // intentional fall-through | |
233 case IMGFMT_RGB|24: | |
234 { | |
235 rgb24toyv12(src[0], image_y, image_u, image_v, | |
236 image_width, image_height, | |
237 image_width, image_width / 2, image_width * 3); | |
238 // RGB2YUV(image_width, image_height, src[0], image_y, image_u, image_v, 1); | |
239 } | |
240 break; | |
241 } | |
242 return 0; | |
243 } | |
244 | |
245 static uint32_t query_format(uint32_t format) | |
246 { | |
247 switch(format){ | |
248 case IMGFMT_YV12: | |
249 case IMGFMT_BGR|24: | |
250 case IMGFMT_RGB|24: | |
251 return 1; | |
252 } | |
253 return 0; | |
254 } | |
255 | |
256 static void uninit(void) | |
257 { | |
258 if(image) | |
259 free(image); | |
260 image = NULL; | |
261 if(yuv_out) | |
262 fclose(yuv_out); | |
263 yuv_out = NULL; | |
264 } | |
265 | |
266 | |
267 static void check_events(void) | |
268 { | |
269 } | |
270 | |
271 | |
272 static uint32_t preinit(const char *arg) | |
273 { | |
274 return 0; | |
275 } | |
276 | |
277 static uint32_t control(uint32_t request, void *data, ...) | |
278 { | |
279 switch (request) { | |
280 case VOCTRL_QUERY_FORMAT: | |
281 return query_format(*((uint32_t*)data)); | |
282 } | |
283 return VO_NOTIMPL; | |
284 } |