Mercurial > libavformat.hg
comparison x11grab.c @ 1582:754781df8033 libavformat
RFC 1 stage: Improve maintainability of the cursoir painting code
- Turned the mouse cursor painting code into a macro for more
maintainability
- Dropped mouse cursor painting in 8bit mode
- Removed log when dropping frames
- Free the shared memory segment on close
(patch by Edouard Gomez)
author | gpoirier |
---|---|
date | Wed, 13 Dec 2006 08:47:14 +0000 |
parents | 90a8061c5f83 |
children | 8c0065795c92 |
comparison
equal
deleted
inserted
replaced
1581:90a8061c5f83 | 1582:754781df8033 |
---|---|
186 break; | 186 break; |
187 case 32: | 187 case 32: |
188 #if 0 | 188 #if 0 |
189 GetColorInfo (image, &c_info); | 189 GetColorInfo (image, &c_info); |
190 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) { | 190 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) { |
191 // byte order is relevant here, not endianness | 191 /* byte order is relevant here, not endianness |
192 // endianness is handled by avcodec, but atm no such thing | 192 * endianness is handled by avcodec, but atm no such thing |
193 // as having ABGR, instead of ARGB in a word. Since we | 193 * as having ABGR, instead of ARGB in a word. Since we |
194 // need this for Solaris/SPARC, but need to do the conversion | 194 * need this for Solaris/SPARC, but need to do the conversion |
195 // for every frame we do it outside of this loop, cf. below | 195 * for every frame we do it outside of this loop, cf. below |
196 // this matches both ARGB32 and ABGR32 | 196 * this matches both ARGB32 and ABGR32 */ |
197 input_pixfmt = PIX_FMT_ARGB32; | 197 input_pixfmt = PIX_FMT_ARGB32; |
198 } else { | 198 } else { |
199 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); | 199 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); |
200 return AVERROR_IO; | 200 return AVERROR_IO; |
201 } | 201 } |
234 fail: | 234 fail: |
235 av_free(st); | 235 av_free(st); |
236 return AVERROR_IO; | 236 return AVERROR_IO; |
237 } | 237 } |
238 | 238 |
239 static const uint16_t mousePointerBlack[] = | 239 static uint16_t mousePointerBlack[] = |
240 { | 240 { |
241 0, 49152, 40960, 36864, 34816, 33792, 33280, 33024, 32896, 32832, | 241 0, 49152, 40960, 36864, 34816, 33792, 33280, 33024, 32896, 32832, |
242 33728, 37376, 43264, 51456, 1152, 1152, 576, 576, 448, 0 | 242 33728, 37376, 43264, 51456, 1152, 1152, 576, 576, 448, 0 |
243 }; | 243 }; |
244 | 244 |
245 static const uint16_t mousePointerWhite[] = | 245 static uint16_t mousePointerWhite[] = |
246 { | 246 { |
247 0, 0, 16384, 24576, 28672, 30720, 31744, 32256, 32512, 32640, 31744, | 247 0, 0, 16384, 24576, 28672, 30720, 31744, 32256, 32512, 32640, 31744, |
248 27648, 17920, 1536, 768, 768, 384, 384, 0, 0 | 248 27648, 17920, 1536, 768, 768, 384, 384, 0, 0 |
249 }; | 249 }; |
250 | 250 |
263 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); | 263 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); |
264 *x = -1; | 264 *x = -1; |
265 *y = -1; | 265 *y = -1; |
266 } | 266 } |
267 } | 267 } |
268 | |
269 #define DRAW_CURSOR_TEMPLATE(type_t) \ | |
270 do { \ | |
271 type_t *cursor; \ | |
272 int width_cursor; \ | |
273 uint16_t bm_b, bm_w, mask; \ | |
274 \ | |
275 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { \ | |
276 if (s->mouse_wanted == 1) { \ | |
277 bm_b = mousePointerBlack[line]; \ | |
278 bm_w = mousePointerWhite[line]; \ | |
279 } else { \ | |
280 bm_b = mousePointerWhite[line]; \ | |
281 bm_w = mousePointerBlack[line]; \ | |
282 } \ | |
283 mask = ( 0x0001 << 15 ); \ | |
284 \ | |
285 for (cursor = (type_t*) im_data, width_cursor = 0; \ | |
286 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); \ | |
287 cursor++, width_cursor++) { \ | |
288 if ( ( bm_b & mask ) > 0 ) { \ | |
289 *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~image->blue_mask )); \ | |
290 } else if ( ( bm_w & mask ) > 0 ) { \ | |
291 *cursor |= (image->red_mask | image->green_mask | image->blue_mask ); \ | |
292 } \ | |
293 mask >>= 1; \ | |
294 } \ | |
295 im_data += image->bytes_per_line; \ | |
296 } \ | |
297 } while (0) | |
268 | 298 |
269 static void | 299 static void |
270 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image) | 300 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image) |
271 { | 301 { |
272 int x_off = s->x_off; | 302 int x_off = s->x_off; |
281 | 311 |
282 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line | 312 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line |
283 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel | 313 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel |
284 | 314 |
285 switch(image->bits_per_pixel) { | 315 switch(image->bits_per_pixel) { |
286 case 32: | 316 case 32: |
287 { | 317 DRAW_CURSOR_TEMPLATE(uint32_t); |
288 uint32_t *cursor; | |
289 int width_cursor; | |
290 uint16_t bm_b, bm_w, mask; | |
291 | |
292 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { | |
293 if (s->mouse_wanted == 1) { | |
294 bm_b = mousePointerBlack[line]; | |
295 bm_w = mousePointerWhite[line]; | |
296 } else { | |
297 bm_b = mousePointerWhite[line]; | |
298 bm_w = mousePointerBlack[line]; | |
299 } | |
300 mask = (0x0001 << 15); | |
301 | |
302 for (cursor = (uint32_t*) im_data, width_cursor = 0; | |
303 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); | |
304 cursor++, width_cursor++) { | |
305 // Boolean pointer_b_bit, pointer_w_bit; | |
306 // pointer_b_bit = ( ( bm_b & mask ) > 0 ); | |
307 // pointer_w_bit = ( ( bm_w & mask ) > 0 ); | |
308 // printf("%i ", pointer_b_bit, pointer_w_bit ); | |
309 if (( bm_b & mask) > 0 ) { | |
310 *cursor &= ( (~image->red_mask) | |
311 & (~image->green_mask) | |
312 & (~image->blue_mask)); | |
313 } else if (( bm_w & mask) > 0 ) { | |
314 *cursor |= ( image->red_mask | |
315 | image->green_mask | |
316 | image->blue_mask ); | |
317 } | |
318 mask >>= 1; | |
319 } | |
320 // printf("\n"); | |
321 im_data += image->bytes_per_line; | |
322 } | |
323 } | |
324 break; | |
325 #if 0 | |
326 case 24: // not sure this can occur at all .......... | |
327 av_log(s1, AV_LOG_ERROR, "input image bits_per_pixel %i not implemented with mouse pointer capture ... aborting!\n", | |
328 image->bits_per_pixel); | |
329 av_log(s1, AV_LOG_ERROR, "Please file a bug at http://www.sourceforge.net/projects/xvidcap/\n"); | |
330 exit(1); | |
331 break; | 318 break; |
332 case 16: | 319 case 16: |
333 { | 320 DRAW_CURSOR_TEMPLATE(uint16_t); |
334 uint16_t *cursor; | |
335 int width; | |
336 uint16_t bm_b, bm_w, mask; | |
337 | |
338 for (line = 0; line < 16; line++) { | |
339 if (mjob->mouseWanted == 1) { | |
340 bm_b = mousePointerBlack[line]; | |
341 bm_w = mousePointerWhite[line]; | |
342 } else { | |
343 bm_b = mousePointerWhite[line]; | |
344 bm_w = mousePointerBlack[line]; | |
345 } | |
346 mask = (0x0001 << 15); | |
347 | |
348 for (cursor = (uint16_t*) im_data, width = 0; | |
349 ((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6); | |
350 cursor++, width++) { | |
351 // Boolean pointer_b_bit, pointer_w_bit; | |
352 // pointer_b_bit = ( ( bm_b & mask ) > 0 ); | |
353 // pointer_w_bit = ( ( bm_w & mask ) > 0 ); | |
354 // printf("%i ", pointer_b_bit, pointer_w_bit ); | |
355 if (( bm_b & mask ) > 0 ) { | |
356 *cursor &= ( (~image->red_mask) | |
357 & (~image->green_mask) | |
358 & (~image->blue_mask)); | |
359 } else if (( bm_w & mask ) > 0 ) { | |
360 *cursor |= ( image->red_mask | |
361 | image->green_mask | |
362 | image->blue_mask ); | |
363 } | |
364 mask >>= 1; | |
365 } | |
366 // printf("\n"); | |
367 | |
368 im_data += image->bytes_per_line; | |
369 } | |
370 } | |
371 break; | |
372 case 8: | |
373 { | |
374 uint8_t *cursor; | |
375 int width; | |
376 uint16_t bm_b, bm_w, mask; | |
377 | |
378 for (line = 0; line < 16; line++ ) { | |
379 if (mjob->mouseWanted == 1) { | |
380 bm_b = mousePointerBlack[line]; | |
381 bm_w = mousePointerWhite[line]; | |
382 } else { | |
383 bm_b = mousePointerWhite[line]; | |
384 bm_w = mousePointerBlack[line]; | |
385 } | |
386 mask = ( 0x0001 << 15 ); | |
387 | |
388 for (cursor = im_data, width = 0; | |
389 ((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6); | |
390 cursor++, width++) { | |
391 // Boolean pointer_b_bit, pointer_w_bit; | |
392 // pointer_b_bit = ( ( bm_b & mask ) > 0 ); | |
393 // pointer_w_bit = ( ( bm_w & mask ) > 0 ); | |
394 // printf("%i ", pointer_b_bit, pointer_w_bit ); | |
395 if ((bm_b & mask) > 0 ) { | |
396 *cursor = 0; | |
397 } else if (( bm_w & mask) > 0 ) { | |
398 *cursor = 1; | |
399 } | |
400 mask >>= 1; | |
401 | |
402 } | |
403 // printf("\n"); | |
404 | |
405 im_data += image->bytes_per_line; | |
406 } | |
407 } | |
408 break; | 321 break; |
409 default: | 322 default: |
410 av_log(s1, AV_LOG_ERROR, "input image bits_per_pixel %i not supported with mouse pointer capture ... aborting!\n", | 323 /* XXX: How do we deal with 24bit and 8bit modes ? */ |
411 image->bits_per_pixel); | 324 break; |
412 exit(1); | |
413 | |
414 #endif | |
415 } | 325 } |
416 } | 326 } |
417 } | 327 } |
418 | 328 |
419 | 329 |
476 for(;;) { | 386 for(;;) { |
477 curtime = av_gettime(); | 387 curtime = av_gettime(); |
478 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; | 388 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; |
479 if (delay <= 0) { | 389 if (delay <= 0) { |
480 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { | 390 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { |
481 av_log(s1, AV_LOG_DEBUG, "grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); | |
482 s->time_frame += int64_t_C(1000000); | 391 s->time_frame += int64_t_C(1000000); |
483 } | 392 } |
484 break; | 393 break; |
485 } | 394 } |
486 ts.tv_sec = delay / 1000000; | 395 ts.tv_sec = delay / 1000000; |
508 int pointer_x, pointer_y; | 417 int pointer_x, pointer_y; |
509 getCurrentPointer(s1, s, &pointer_x, &pointer_y); | 418 getCurrentPointer(s1, s, &pointer_x, &pointer_y); |
510 paintMousePointer(s1, s, &pointer_x, &pointer_y, image); | 419 paintMousePointer(s1, s, &pointer_x, &pointer_y, image); |
511 } | 420 } |
512 | 421 |
513 #warning FIXME - avoid memcpy | 422 |
514 memcpy(pkt->data, image->data, s->frame_size); | 423 /* XXX: avoid memcpy */ |
424 memcpy(pkt->data, image->data, s->frame_size); | |
515 return s->frame_size; | 425 return s->frame_size; |
516 } | 426 } |
517 | 427 |
518 static int x11grab_read_close(AVFormatContext *s1) | 428 static int x11grab_read_close(AVFormatContext *s1) |
519 { | 429 { |
520 X11Grab *x11grab = s1->priv_data; | 430 X11Grab *x11grab = s1->priv_data; |
431 | |
432 /* Free shared mem if necessary */ | |
433 if (x11grab->use_shm) { | |
434 shmdt(x11grab->shminfo.shmaddr); | |
435 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); | |
436 } | |
437 | |
438 /* Free X11 display */ | |
521 XCloseDisplay(x11grab->dpy); | 439 XCloseDisplay(x11grab->dpy); |
522 return 0; | 440 return 0; |
523 } | 441 } |
524 | 442 |
525 AVInputFormat x11_grab_device_demuxer = | 443 AVInputFormat x11_grab_device_demuxer = |
526 { | 444 { |
527 "x11grab", | 445 "x11grab", |
528 "X11 frame graber", | 446 "X11grab", |
529 sizeof(X11Grab), | 447 sizeof(X11Grab), |
530 NULL, | 448 NULL, |
531 x11grab_read_header, | 449 x11grab_read_header, |
532 x11grab_read_packet, | 450 x11grab_read_packet, |
533 x11grab_read_close, | 451 x11grab_read_close, |