Mercurial > libavformat.hg
comparison x11grab.c @ 1584:33997fca4b0d libavformat
RFC 3&4 stage: FFmpeg style aint't my style
- Tabs are 4 width
- No tabs allowed
(patch by Edouard Gomez)
author | gpoirier |
---|---|
date | Wed, 13 Dec 2006 08:48:56 +0000 |
parents | 8c0065795c92 |
children | 14c185883eab |
comparison
equal
deleted
inserted
replaced
1583:8c0065795c92 | 1584:33997fca4b0d |
---|---|
6 * FFmpeg integration: | 6 * FFmpeg integration: |
7 * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org> | 7 * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org> |
8 * Edouard Gomez <ed.gomez@free.fr> | 8 * Edouard Gomez <ed.gomez@free.fr> |
9 * | 9 * |
10 * This file contains code from grab.c: | 10 * This file contains code from grab.c: |
11 * Copyright (c) 2000-2001 Fabrice Bellard | 11 * Copyright (c) 2000-2001 Fabrice Bellard |
12 * | 12 * |
13 * This file contains code from the xvidcap project: | 13 * This file contains code from the xvidcap project: |
14 * Copyright (C) 1997-1998 Rasca, Berlin | 14 * Copyright (C) 1997-1998 Rasca, Berlin |
15 * 2003-2004 Karl H. Beckers, Frankfurt | 15 * 2003-2004 Karl H. Beckers, Frankfurt |
16 * | 16 * |
46 #include <sys/shm.h> | 46 #include <sys/shm.h> |
47 #include <X11/extensions/XShm.h> | 47 #include <X11/extensions/XShm.h> |
48 | 48 |
49 typedef struct | 49 typedef struct |
50 { | 50 { |
51 Display *dpy; | 51 Display *dpy; |
52 int frame_format; | 52 int frame_format; |
53 int frame_size; | 53 int frame_size; |
54 int frame_rate; | 54 int frame_rate; |
55 int frame_rate_base; | 55 int frame_rate_base; |
56 int64_t time_frame; | 56 int64_t time_frame; |
57 | 57 |
58 int height; | 58 int height; |
59 int width; | 59 int width; |
60 int x_off; | 60 int x_off; |
61 int y_off; | 61 int y_off; |
62 XImage *image; | 62 XImage *image; |
63 int use_shm; | 63 int use_shm; |
64 XShmSegmentInfo shminfo; | 64 XShmSegmentInfo shminfo; |
65 int mouse_wanted; | 65 int mouse_wanted; |
66 } X11Grab; | 66 } X11Grab; |
67 | 67 |
68 static int | 68 static int |
69 x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) | 69 x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
70 { | 70 { |
71 X11Grab *x11grab = s1->priv_data; | 71 X11Grab *x11grab = s1->priv_data; |
72 Display *dpy; | 72 Display *dpy; |
73 AVStream *st = NULL; | 73 AVStream *st = NULL; |
74 int width, height; | 74 int width, height; |
75 int frame_rate, frame_rate_base, frame_size; | 75 int frame_rate, frame_rate_base, frame_size; |
76 int input_pixfmt; | 76 int input_pixfmt; |
77 XImage *image; | 77 XImage *image; |
78 int x_off=0; int y_off = 0; | 78 int x_off=0; int y_off = 0; |
79 int use_shm; | 79 int use_shm; |
80 | 80 |
81 dpy = XOpenDisplay(NULL); | 81 dpy = XOpenDisplay(NULL); |
82 if(!dpy) { | 82 if(!dpy) { |
83 goto fail; | 83 goto fail; |
84 } | 84 } |
85 | 85 |
86 sscanf(ap->device, "x11:%d,%d", &x_off, &y_off); | 86 sscanf(ap->device, "x11:%d,%d", &x_off, &y_off); |
87 av_log(s1, AV_LOG_INFO, "device: %s -> x: %d y: %d width: %d height: %d\n", ap->device, x_off, y_off, ap->width, ap->height); | 87 av_log(s1, AV_LOG_INFO, "device: %s -> x: %d y: %d width: %d height: %d\n", ap->device, x_off, y_off, ap->width, ap->height); |
88 | 88 |
89 if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { | 89 if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { |
90 av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n"); | 90 av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n"); |
91 return AVERROR_IO; | 91 return AVERROR_IO; |
92 } | 92 } |
93 | 93 |
94 width = ap->width; | 94 width = ap->width; |
95 height = ap->height; | 95 height = ap->height; |
96 frame_rate = ap->time_base.den; | 96 frame_rate = ap->time_base.den; |
97 frame_rate_base = ap->time_base.num; | 97 frame_rate_base = ap->time_base.num; |
98 | 98 |
99 st = av_new_stream(s1, 0); | 99 st = av_new_stream(s1, 0); |
100 if (!st) { | 100 if (!st) { |
101 return -ENOMEM; | 101 return -ENOMEM; |
102 } | 102 } |
103 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ | 103 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ |
104 | 104 |
105 use_shm = XShmQueryExtension(dpy); | 105 use_shm = XShmQueryExtension(dpy); |
106 av_log(s1, AV_LOG_INFO, "shared memory extension %s\n", use_shm ? "found" : "not found"); | 106 av_log(s1, AV_LOG_INFO, "shared memory extension %s\n", use_shm ? "found" : "not found"); |
107 | 107 |
108 if(use_shm) { | 108 if(use_shm) { |
109 int scr = XDefaultScreen(dpy); | 109 int scr = XDefaultScreen(dpy); |
110 image = XShmCreateImage(dpy, | 110 image = XShmCreateImage(dpy, |
111 DefaultVisual(dpy, scr), | 111 DefaultVisual(dpy, scr), |
112 DefaultDepth(dpy, scr), | 112 DefaultDepth(dpy, scr), |
113 ZPixmap, | 113 ZPixmap, |
114 NULL, | 114 NULL, |
115 &x11grab->shminfo, | 115 &x11grab->shminfo, |
116 ap->width, ap->height); | 116 ap->width, ap->height); |
117 x11grab->shminfo.shmid = shmget(IPC_PRIVATE, | 117 x11grab->shminfo.shmid = shmget(IPC_PRIVATE, |
118 image->bytes_per_line * image->height, | 118 image->bytes_per_line * image->height, |
119 IPC_CREAT|0777); | 119 IPC_CREAT|0777); |
120 if (x11grab->shminfo.shmid == -1) { | 120 if (x11grab->shminfo.shmid == -1) { |
121 av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); | 121 av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); |
122 return -ENOMEM; | 122 return -ENOMEM; |
123 } | 123 } |
124 x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); | 124 x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); |
125 x11grab->shminfo.readOnly = False; | 125 x11grab->shminfo.readOnly = False; |
126 | 126 |
127 if (!XShmAttach(dpy, &x11grab->shminfo)) { | 127 if (!XShmAttach(dpy, &x11grab->shminfo)) { |
128 av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); | 128 av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); |
129 /* needs some better error subroutine :) */ | 129 /* needs some better error subroutine :) */ |
130 return AVERROR_IO; | 130 return AVERROR_IO; |
131 } | 131 } |
132 } else { | 132 } else { |
133 image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), | 133 image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), |
134 x_off,y_off, | 134 x_off,y_off, |
135 ap->width,ap->height, | 135 ap->width,ap->height, |
136 AllPlanes, ZPixmap); | 136 AllPlanes, ZPixmap); |
137 } | 137 } |
138 | 138 |
139 switch (image->bits_per_pixel) { | 139 switch (image->bits_per_pixel) { |
140 case 8: | 140 case 8: |
141 av_log (s1, AV_LOG_DEBUG, "8 bit pallete\n"); | 141 av_log (s1, AV_LOG_DEBUG, "8 bit pallete\n"); |
142 input_pixfmt = PIX_FMT_PAL8; | 142 input_pixfmt = PIX_FMT_PAL8; |
143 break; | 143 break; |
144 case 16: | 144 case 16: |
145 if ( image->red_mask == 0xF800 && image->green_mask == 0x07E0 | 145 if ( image->red_mask == 0xF800 && image->green_mask == 0x07E0 |
146 && image->blue_mask == 0x1F ) { | 146 && image->blue_mask == 0x1F ) { |
147 av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); | 147 av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); |
148 input_pixfmt = PIX_FMT_RGB565; | 148 input_pixfmt = PIX_FMT_RGB565; |
149 } else if ( image->red_mask == 0x7C00 && | 149 } else if ( image->red_mask == 0x7C00 && |
150 image->green_mask == 0x03E0 && | 150 image->green_mask == 0x03E0 && |
151 image->blue_mask == 0x1F ) { | 151 image->blue_mask == 0x1F ) { |
152 av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); | 152 av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); |
153 input_pixfmt = PIX_FMT_RGB555; | 153 input_pixfmt = PIX_FMT_RGB555; |
154 } else { | 154 } else { |
155 av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); | 155 av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); |
156 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); | 156 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); |
157 return AVERROR_IO; | 157 return AVERROR_IO; |
158 } | 158 } |
159 break; | 159 break; |
160 case 24: | 160 case 24: |
161 if ( image->red_mask == 0xFF0000 && | 161 if ( image->red_mask == 0xFF0000 && |
162 image->green_mask == 0xFF00 | 162 image->green_mask == 0xFF00 |
163 && image->blue_mask == 0xFF ) { | 163 && image->blue_mask == 0xFF ) { |
164 input_pixfmt = PIX_FMT_BGR24; | 164 input_pixfmt = PIX_FMT_BGR24; |
165 } else if ( image->red_mask == 0xFF && image->green_mask == 0xFF00 | 165 } else if ( image->red_mask == 0xFF && image->green_mask == 0xFF00 |
166 && image->blue_mask == 0xFF0000 ) { | 166 && image->blue_mask == 0xFF0000 ) { |
167 input_pixfmt = PIX_FMT_RGB24; | 167 input_pixfmt = PIX_FMT_RGB24; |
168 } else { | 168 } else { |
169 av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); | 169 av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); |
170 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); | 170 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); |
171 return AVERROR_IO; | 171 return AVERROR_IO; |
172 } | 172 } |
173 break; | 173 break; |
174 case 32: | 174 case 32: |
175 #if 0 | 175 #if 0 |
176 GetColorInfo (image, &c_info); | 176 GetColorInfo (image, &c_info); |
177 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) { | 177 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) { |
178 /* byte order is relevant here, not endianness | 178 /* byte order is relevant here, not endianness |
179 * endianness is handled by avcodec, but atm no such thing | 179 * endianness is handled by avcodec, but atm no such thing |
180 * as having ABGR, instead of ARGB in a word. Since we | 180 * as having ABGR, instead of ARGB in a word. Since we |
181 * need this for Solaris/SPARC, but need to do the conversion | 181 * need this for Solaris/SPARC, but need to do the conversion |
182 * for every frame we do it outside of this loop, cf. below | 182 * for every frame we do it outside of this loop, cf. below |
183 * this matches both ARGB32 and ABGR32 */ | 183 * this matches both ARGB32 and ABGR32 */ |
184 input_pixfmt = PIX_FMT_ARGB32; | 184 input_pixfmt = PIX_FMT_ARGB32; |
185 } else { | 185 } else { |
186 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); | 186 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); |
187 return AVERROR_IO; | 187 return AVERROR_IO; |
188 } | 188 } |
189 #endif | 189 #endif |
190 input_pixfmt = PIX_FMT_RGBA32; | 190 input_pixfmt = PIX_FMT_RGBA32; |
191 break; | 191 break; |
192 default: | 192 default: |
193 av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); | 193 av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); |
194 return -1; | 194 return -1; |
195 } | 195 } |
196 | 196 |
197 frame_size = width * height * image->bits_per_pixel/8; | 197 frame_size = width * height * image->bits_per_pixel/8; |
198 x11grab->frame_size = frame_size; | 198 x11grab->frame_size = frame_size; |
199 x11grab->dpy = dpy; | 199 x11grab->dpy = dpy; |
200 x11grab->width = ap->width; | 200 x11grab->width = ap->width; |
201 x11grab->height = ap->height; | 201 x11grab->height = ap->height; |
202 x11grab->frame_rate = frame_rate; | 202 x11grab->frame_rate = frame_rate; |
203 x11grab->frame_rate_base = frame_rate_base; | 203 x11grab->frame_rate_base = frame_rate_base; |
204 x11grab->time_frame = av_gettime() * frame_rate / frame_rate_base; | 204 x11grab->time_frame = av_gettime() * frame_rate / frame_rate_base; |
205 x11grab->x_off = x_off; | 205 x11grab->x_off = x_off; |
206 x11grab->y_off = y_off; | 206 x11grab->y_off = y_off; |
207 x11grab->image = image; | 207 x11grab->image = image; |
208 x11grab->use_shm = use_shm; | 208 x11grab->use_shm = use_shm; |
209 x11grab->mouse_wanted = 1; | 209 x11grab->mouse_wanted = 1; |
210 | 210 |
211 st->codec->codec_type = CODEC_TYPE_VIDEO; | 211 st->codec->codec_type = CODEC_TYPE_VIDEO; |
212 st->codec->codec_id = CODEC_ID_RAWVIDEO; | 212 st->codec->codec_id = CODEC_ID_RAWVIDEO; |
213 st->codec->width = width; | 213 st->codec->width = width; |
214 st->codec->height = height; | 214 st->codec->height = height; |
215 st->codec->pix_fmt = input_pixfmt; | 215 st->codec->pix_fmt = input_pixfmt; |
216 st->codec->time_base.den = frame_rate; | 216 st->codec->time_base.den = frame_rate; |
217 st->codec->time_base.num = frame_rate_base; | 217 st->codec->time_base.num = frame_rate_base; |
218 st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8; | 218 st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8; |
219 | 219 |
220 return 0; | 220 return 0; |
221 fail: | 221 fail: |
222 av_free(st); | 222 av_free(st); |
223 return AVERROR_IO; | 223 return AVERROR_IO; |
224 } | 224 } |
225 | 225 |
226 static void | 226 static void |
227 getCurrentPointer(AVFormatContext *s1, X11Grab *s, int *x, int *y) | 227 getCurrentPointer(AVFormatContext *s1, X11Grab *s, int *x, int *y) |
228 { | 228 { |
229 Window mrootwindow, childwindow; | 229 Window mrootwindow, childwindow; |
230 int dummy; | 230 int dummy; |
231 Display *dpy = s->dpy; | 231 Display *dpy = s->dpy; |
232 | 232 |
233 mrootwindow = DefaultRootWindow(dpy); | 233 mrootwindow = DefaultRootWindow(dpy); |
234 | 234 |
235 if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, | 235 if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, |
236 x, y, &dummy, &dummy, (unsigned int*)&dummy)) { | 236 x, y, &dummy, &dummy, (unsigned int*)&dummy)) { |
237 } else { | 237 } else { |
238 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); | 238 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); |
239 *x = -1; | 239 *x = -1; |
240 *y = -1; | 240 *y = -1; |
241 } | 241 } |
242 } | 242 } |
243 | 243 |
244 #define DRAW_CURSOR_TEMPLATE(type_t) \ | 244 #define DRAW_CURSOR_TEMPLATE(type_t) \ |
245 do { \ | 245 do { \ |
246 type_t *cursor; \ | 246 type_t *cursor; \ |
247 int width_cursor; \ | 247 int width_cursor; \ |
248 uint16_t bm_b, bm_w, mask; \ | 248 uint16_t bm_b, bm_w, mask; \ |
249 \ | 249 \ |
250 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { \ | 250 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { \ |
251 if (s->mouse_wanted == 1) { \ | 251 if (s->mouse_wanted == 1) { \ |
252 bm_b = mousePointerBlack[line]; \ | 252 bm_b = mousePointerBlack[line]; \ |
253 bm_w = mousePointerWhite[line]; \ | 253 bm_w = mousePointerWhite[line]; \ |
254 } else { \ | 254 } else { \ |
255 bm_b = mousePointerWhite[line]; \ | 255 bm_b = mousePointerWhite[line]; \ |
256 bm_w = mousePointerBlack[line]; \ | 256 bm_w = mousePointerBlack[line]; \ |
257 } \ | 257 } \ |
258 mask = ( 0x0001 << 15 ); \ | 258 mask = ( 0x0001 << 15 ); \ |
259 \ | 259 \ |
260 for (cursor = (type_t*) im_data, width_cursor = 0; \ | 260 for (cursor = (type_t*) im_data, width_cursor = 0; \ |
261 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); \ | 261 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); \ |
262 cursor++, width_cursor++) { \ | 262 cursor++, width_cursor++) { \ |
263 if ( ( bm_b & mask ) > 0 ) { \ | 263 if ( ( bm_b & mask ) > 0 ) { \ |
264 *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~image->blue_mask )); \ | 264 *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~image->blue_mask )); \ |
265 } else if ( ( bm_w & mask ) > 0 ) { \ | 265 } else if ( ( bm_w & mask ) > 0 ) { \ |
266 *cursor |= (image->red_mask | image->green_mask | image->blue_mask ); \ | 266 *cursor |= (image->red_mask | image->green_mask | image->blue_mask ); \ |
267 } \ | 267 } \ |
268 mask >>= 1; \ | 268 mask >>= 1; \ |
269 } \ | 269 } \ |
270 im_data += image->bytes_per_line; \ | 270 im_data += image->bytes_per_line; \ |
271 } \ | 271 } \ |
272 } while (0) | 272 } while (0) |
273 | 273 |
274 static void | 274 static void |
275 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image) | 275 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image) |
276 { | 276 { |
277 static const uint16_t const mousePointerBlack[] = | 277 static const uint16_t const mousePointerBlack[] = |
278 { | 278 { |
279 0, 49152, 40960, 36864, 34816, | 279 0, 49152, 40960, 36864, 34816, |
280 33792, 33280, 33024, 32896, 32832, | 280 33792, 33280, 33024, 32896, 32832, |
281 33728, 37376, 43264, 51456, 1152, | 281 33728, 37376, 43264, 51456, 1152, |
282 1152, 576, 576, 448, 0 | 282 1152, 576, 576, 448, 0 |
283 }; | 283 }; |
284 | 284 |
285 static const uint16_t const mousePointerWhite[] = | 285 static const uint16_t const mousePointerWhite[] = |
286 { | 286 { |
287 0, 0, 16384, 24576, 28672, | 287 0, 0, 16384, 24576, 28672, |
288 30720, 31744, 32256, 32512, 32640, | 288 30720, 31744, 32256, 32512, 32640, |
289 31744, 27648, 17920, 1536, 768, | 289 31744, 27648, 17920, 1536, 768, |
290 768, 384, 384, 0, 0 | 290 768, 384, 384, 0, 0 |
291 }; | 291 }; |
292 | 292 |
293 int x_off = s->x_off; | 293 int x_off = s->x_off; |
294 int y_off = s->y_off; | 294 int y_off = s->y_off; |
295 int width = s->width; | 295 int width = s->width; |
296 int height = s->height; | 296 int height = s->height; |
297 | 297 |
298 if ( (*x - x_off) >= 0 && *x < (width + x_off) | 298 if ( (*x - x_off) >= 0 && *x < (width + x_off) |
299 && (*y - y_off) >= 0 && *y < (height + y_off) ) { | 299 && (*y - y_off) >= 0 && *y < (height + y_off) ) { |
300 int line; | 300 int line; |
301 uint8_t *im_data = (uint8_t*)image->data; | 301 uint8_t *im_data = (uint8_t*)image->data; |
302 | 302 |
303 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line | 303 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line |
304 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel | 304 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel |
305 | 305 |
306 switch(image->bits_per_pixel) { | 306 switch(image->bits_per_pixel) { |
307 case 32: | 307 case 32: |
308 DRAW_CURSOR_TEMPLATE(uint32_t); | 308 DRAW_CURSOR_TEMPLATE(uint32_t); |
309 break; | 309 break; |
310 case 16: | 310 case 16: |
311 DRAW_CURSOR_TEMPLATE(uint16_t); | 311 DRAW_CURSOR_TEMPLATE(uint16_t); |
312 break; | 312 break; |
313 default: | 313 default: |
314 /* XXX: How do we deal with 24bit and 8bit modes ? */ | 314 /* XXX: How do we deal with 24bit and 8bit modes ? */ |
315 break; | 315 break; |
316 } | 316 } |
317 } | 317 } |
318 } | 318 } |
319 | 319 |
320 | 320 |
321 /* | 321 /* |
322 * just read new data in the image structure, the image | 322 * just read new data in the image structure, the image |
323 * structure inclusive the data area must be allocated before | 323 * structure inclusive the data area must be allocated before |
324 */ | 324 */ |
325 static int | 325 static int |
326 XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) | 326 XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) |
327 { | 327 { |
328 xGetImageReply rep; | 328 xGetImageReply rep; |
329 xGetImageReq *req; | 329 xGetImageReq *req; |
330 long nbytes; | 330 long nbytes; |
331 | 331 |
332 if (!image) { | 332 if (!image) { |
333 return False; | 333 return False; |
334 } | 334 } |
335 | 335 |
336 LockDisplay(dpy); | 336 LockDisplay(dpy); |
337 GetReq(GetImage, req); | 337 GetReq(GetImage, req); |
338 | 338 |
339 /* First set up the standard stuff in the request */ | 339 /* First set up the standard stuff in the request */ |
340 req->drawable = d; | 340 req->drawable = d; |
341 req->x = x; | 341 req->x = x; |
342 req->y = y; | 342 req->y = y; |
343 req->width = image->width; | 343 req->width = image->width; |
344 req->height = image->height; | 344 req->height = image->height; |
345 req->planeMask = (unsigned int)AllPlanes; | 345 req->planeMask = (unsigned int)AllPlanes; |
346 req->format = ZPixmap; | 346 req->format = ZPixmap; |
347 | 347 |
348 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.length) { | 348 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.length) { |
349 UnlockDisplay(dpy); | 349 UnlockDisplay(dpy); |
350 SyncHandle(); | 350 SyncHandle(); |
351 return False; | 351 return False; |
352 } | 352 } |
353 | 353 |
354 nbytes = (long)rep.length << 2; | 354 nbytes = (long)rep.length << 2; |
355 _XReadPad(dpy, image->data, nbytes); | 355 _XReadPad(dpy, image->data, nbytes); |
356 | 356 |
357 UnlockDisplay(dpy); | 357 UnlockDisplay(dpy); |
358 SyncHandle(); | 358 SyncHandle(); |
359 return True; | 359 return True; |
360 } | 360 } |
361 | 361 |
362 static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) | 362 static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) |
363 { | 363 { |
364 X11Grab *s = s1->priv_data; | 364 X11Grab *s = s1->priv_data; |
365 Display *dpy = s->dpy; | 365 Display *dpy = s->dpy; |
366 XImage *image = s->image; | 366 XImage *image = s->image; |
367 int x_off = s->x_off; | 367 int x_off = s->x_off; |
368 int y_off = s->y_off; | 368 int y_off = s->y_off; |
369 | 369 |
370 int64_t curtime, delay; | 370 int64_t curtime, delay; |
371 struct timespec ts; | 371 struct timespec ts; |
372 | 372 |
373 /* Calculate the time of the next frame */ | 373 /* Calculate the time of the next frame */ |
374 s->time_frame += int64_t_C(1000000); | 374 s->time_frame += int64_t_C(1000000); |
375 | 375 |
376 /* wait based on the frame rate */ | 376 /* wait based on the frame rate */ |
377 for(;;) { | 377 for(;;) { |
378 curtime = av_gettime(); | 378 curtime = av_gettime(); |
379 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; | 379 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; |
380 if (delay <= 0) { | 380 if (delay <= 0) { |
381 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { | 381 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { |
382 s->time_frame += int64_t_C(1000000); | 382 s->time_frame += int64_t_C(1000000); |
383 } | 383 } |
384 break; | 384 break; |
385 } | 385 } |
386 ts.tv_sec = delay / 1000000; | 386 ts.tv_sec = delay / 1000000; |
387 ts.tv_nsec = (delay % 1000000) * 1000; | 387 ts.tv_nsec = (delay % 1000000) * 1000; |
388 nanosleep(&ts, NULL); | 388 nanosleep(&ts, NULL); |
389 } | 389 } |
390 | 390 |
391 if (av_new_packet(pkt, s->frame_size) < 0) { | 391 if (av_new_packet(pkt, s->frame_size) < 0) { |
392 return AVERROR_IO; | 392 return AVERROR_IO; |
393 } | 393 } |
394 | 394 |
395 pkt->pts = curtime & ((1LL << 48) - 1); | 395 pkt->pts = curtime & ((1LL << 48) - 1); |
396 | 396 |
397 if(s->use_shm) { | 397 if(s->use_shm) { |
398 if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { | 398 if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { |
399 av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); | 399 av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); |
400 } | 400 } |
401 } else { | 401 } else { |
402 if (!XGetZPixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { | 402 if (!XGetZPixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { |
403 av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); | 403 av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); |
404 } | 404 } |
405 } | 405 } |
406 | 406 |
407 { | 407 { |
408 int pointer_x, pointer_y; | 408 int pointer_x, pointer_y; |
409 getCurrentPointer(s1, s, &pointer_x, &pointer_y); | 409 getCurrentPointer(s1, s, &pointer_x, &pointer_y); |
410 paintMousePointer(s1, s, &pointer_x, &pointer_y, image); | 410 paintMousePointer(s1, s, &pointer_x, &pointer_y, image); |
411 } | 411 } |
412 | 412 |
413 | 413 |
414 /* XXX: avoid memcpy */ | 414 /* XXX: avoid memcpy */ |
415 memcpy(pkt->data, image->data, s->frame_size); | 415 memcpy(pkt->data, image->data, s->frame_size); |
416 return s->frame_size; | 416 return s->frame_size; |
417 } | 417 } |
418 | 418 |
419 static int x11grab_read_close(AVFormatContext *s1) | 419 static int x11grab_read_close(AVFormatContext *s1) |
420 { | 420 { |
421 X11Grab *x11grab = s1->priv_data; | 421 X11Grab *x11grab = s1->priv_data; |
422 | 422 |
423 /* Detach cleanly from shared mem */ | 423 /* Detach cleanly from shared mem */ |
424 if (x11grab->use_shm) { | 424 if (x11grab->use_shm) { |
425 XShmDetach(x11grab->dpy, &x11grab->shminfo); | 425 XShmDetach(x11grab->dpy, &x11grab->shminfo); |
426 shmdt(x11grab->shminfo.shmaddr); | 426 shmdt(x11grab->shminfo.shmaddr); |
427 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); | 427 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); |
428 } | 428 } |
429 | 429 |
430 /* Destroy X11 image */ | 430 /* Destroy X11 image */ |
431 if (x11grab->image) { | 431 if (x11grab->image) { |
432 XDestroyImage(x11grab->image); | 432 XDestroyImage(x11grab->image); |
433 x11grab->image = NULL; | 433 x11grab->image = NULL; |
434 } | 434 } |
435 | 435 |
436 /* Free X11 display */ | 436 /* Free X11 display */ |
437 XCloseDisplay(x11grab->dpy); | 437 XCloseDisplay(x11grab->dpy); |
438 return 0; | 438 return 0; |
439 } | 439 } |
440 | 440 |
441 AVInputFormat x11_grab_device_demuxer = | 441 AVInputFormat x11_grab_device_demuxer = |
442 { | 442 { |
443 "x11grab", | 443 "x11grab", |
444 "X11grab", | 444 "X11grab", |
445 sizeof(X11Grab), | 445 sizeof(X11Grab), |
446 NULL, | 446 NULL, |
447 x11grab_read_header, | 447 x11grab_read_header, |
448 x11grab_read_packet, | 448 x11grab_read_packet, |
449 x11grab_read_close, | 449 x11grab_read_close, |
450 .flags = AVFMT_NOFILE, | 450 .flags = AVFMT_NOFILE, |
451 }; | 451 }; |