2
* capture.c, vi: tabstop=4
3
* capture module, controled by timer functions
5
* Copyright (C) 1997-98 Rasca, Berlin
6
* Copyright (C) 2003,04 Karl H. Beckers, Frankfurt
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
* This file contains routines used for capturing individual frames.
24
* Theese routines are called from the record button callback in
25
* the GUI and call themselves again till they are stopped by a stop
26
* button event handler, a timeout, exceeding the maximum number of
27
* frames (see the various VC_... states)
31
#include "../config.h" /* autoconf output */
36
#endif //HAVE_STDINT_H
45
#include <X11/Intrinsic.h>
46
#include <X11/StringDefs.h>
47
#include <X11/XWDFile.h>
48
#include <X11/Xproto.h>
49
#include <X11/Xlibint.h>
50
#include <X11/cursorfont.h>
54
#include <X11/extensions/XShm.h>
57
#include <X11/extensions/xf86dga.h>
62
#include <sys/ioctl.h>
64
#endif //HasVideo4Linux
72
uint16_t mousePointerBlack[] = { 0, 49152, 40960, 36864, 34816, 33792, 33280, 33024, 32896, 32832,
73
33728, 37376, 43264, 51456, 1152, 1152, 576, 576, 448, 0 };
74
uint16_t mousePointerWhite[] = { 0, 0, 16384, 24576, 28672, 30720, 31744, 32256, 32512, 32640, 31744,
75
27648, 17920, 1536, 768, 768, 384, 384, 0, 0 };
78
static void getCurrentPointer(int *x, int *y, Job *mjob) {
79
Window mrootwindow, childwindow;
85
if ( ! (mjob->flags & FLG_NOGUI ) ) {
86
scr = mjob->win_attr.screen;
87
dpy = DisplayOfScreen(scr);
89
dpy = XOpenDisplay(NULL);
91
mrootwindow = DefaultRootWindow(dpy);
93
if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow,
94
x, y, &dummy, &dummy, &dummy)) {
95
if (mjob->flags & FLG_RUN_VERBOSE) {
96
int bla, ev_base, er_base, major, minor;
100
// printf("Mouse pointer at x/y : %i/%i\n", *x, *y);
101
// printf("Relative mouse pointer at x/y : %i/%i\n", (*x - mjob->area->x), (*y - mjob->area->y));
103
// printf("root window pointer: %p - child window pointer: %p\n", &mrootwindow, &childwindow);
104
/* m_atom = XListProperties(dpy, childwindow, &num_atoms);
105
for (bla = 0; bla < num_atoms; bla++) {
106
printf("atom %i name: %s\n", bla, XGetAtomName(dpy,
110
/* xTest = XTestQueryExtension( dpy, &ev_base, &er_base, &major, &minor);
111
if ( xTest = True ) {
114
for (n = 0; n < (XC_num_glyphs - 1); n++) {
117
xCursor = XCreateFontCursor( dpy, n);
118
xTest = XTestCompareCursorWithWindow( dpy, childwindow, xCursor );
119
if (xTest = True ) printf("xTest: %i - glyph: %i\n", (int) xTest, n);
122
printf("XTEST extension not supported\n");
127
printf("couldn't find mouse pointer for disp: %p , rootwindow: %p\n", dpy,
128
RootWindow(dpy, DefaultScreen(dpy)));
133
if ( mjob->flags & FLG_NOGUI ) {
140
static void paintMousePointer(int *x, int *y, Job *mjob, XImage *image) {
141
if ( (*x - mjob->area->x) >= 0 && *x < (mjob->area->width + mjob->area->x) &&
142
(*y - mjob->area->y) >= 0 && *y < (mjob->area->height + mjob->area->y) ) {
144
uint8_t *im_data = image->data;
146
im_data += (image->bytes_per_line * (*y - mjob->area->y)); // shift to right line
147
im_data += (image->bits_per_pixel / 8 * (*x - mjob->area->x)); // shift to right pixel
149
switch(image->bits_per_pixel) {
153
uint16_t bm_b, bm_w, mask;
155
for (line = 0; line < 20; line++ ) {
156
if (mjob->mouseWanted == 1) {
157
bm_b = mousePointerBlack[line];
158
bm_w = mousePointerWhite[line];
160
bm_b = mousePointerWhite[line];
161
bm_w = mousePointerBlack[line];
163
mask = ( 0x0001 << 15 );
165
for (cursor = (uint32_t*) im_data, width = 0;
166
((width + *x) < (mjob->area->width + mjob->area->x)&&width < 16);
168
// Boolean pointer_b_bit, pointer_w_bit;
170
// pointer_b_bit = ( ( bm_b & mask ) > 0 );
171
// pointer_w_bit = ( ( bm_w & mask ) > 0 );
172
// printf("%i ", pointer_b_bit, pointer_w_bit );
174
if ( ( bm_b & mask ) > 0 ) {
175
*cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~
177
} else if ( ( bm_w & mask ) > 0 ) {
178
*cursor |= (image->red_mask | image->green_mask | image->blue_mask );
185
im_data += image->bytes_per_line;
189
case 24: // not sure this can occur at all ..........
190
printf("input image bits_per_pixel %i not implemented with mouse pointer capture ... aborting!\n",
191
image->bits_per_pixel);
192
printf("Please file a bug at http://www.sourceforge.net/projects/xvidcap/\n");
198
uint16_t bm_b, bm_w, mask;
200
for (line = 0; line < 16; line++ ) {
201
if (mjob->mouseWanted == 1) {
202
bm_b = mousePointerBlack[line];
203
bm_w = mousePointerWhite[line];
205
bm_b = mousePointerWhite[line];
206
bm_w = mousePointerBlack[line];
208
mask = ( 0x0001 << 15 );
210
for (cursor = (uint16_t*) im_data, width = 0;
211
((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6);
213
// Boolean pointer_b_bit, pointer_w_bit;
215
// pointer_b_bit = ( ( bm_b & mask ) > 0 );
216
// pointer_w_bit = ( ( bm_w & mask ) > 0 );
217
// printf("%i ", pointer_b_bit, pointer_w_bit );
219
if ( ( bm_b & mask ) > 0 ) {
220
*cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~
222
} else if ( ( bm_w & mask ) > 0 ) {
223
*cursor |= (image->red_mask | image->green_mask | image->blue_mask );
230
im_data += image->bytes_per_line;
237
uint16_t bm_b, bm_w, mask;
239
for (line = 0; line < 16; line++ ) {
240
if (mjob->mouseWanted == 1) {
241
bm_b = mousePointerBlack[line];
242
bm_w = mousePointerWhite[line];
244
bm_b = mousePointerWhite[line];
245
bm_w = mousePointerBlack[line];
247
mask = ( 0x0001 << 15 );
249
for (cursor = im_data, width = 0;
250
((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6);
252
// Boolean pointer_b_bit, pointer_w_bit;
254
// pointer_b_bit = ( ( bm_b & mask ) > 0 );
255
// pointer_w_bit = ( ( bm_w & mask ) > 0 );
256
// printf("%i ", pointer_b_bit, pointer_w_bit );
258
if ( ( bm_b & mask ) > 0 ) {
260
} else if ( ( bm_w & mask ) > 0 ) {
268
im_data += image->bytes_per_line;
273
printf("input image bits_per_pixel %i not supported with mouse pointer capture ... aborting!\n",
274
image->bits_per_pixel);
286
* just read new data in the image structure, the image
287
* structure inclusive the data area must be allocated before
290
XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) {
292
register xGetImageReq *req;
298
GetReq(GetImage, req);
300
* first set up the standard stuff in the request
305
req->width = image->width;
306
req->height = image->height;
307
req->planeMask = AllPlanes;
308
req->format = ZPixmap;
310
if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0 ||
317
nbytes = (long)rep.length << 2;
318
_XReadPad(dpy, image->data, nbytes);
326
* timer callback for capturing
329
TCbCaptureX11(XtPointer xtp, XtIntervalId *id) {
330
Job *job = (Job *) xtp;
331
static char file[PATH_MAX+1];
332
static XImage *image = NULL;
333
static void *fp = NULL;
335
struct timeval curr_time;
340
printf("TCbCapture() pic_no=%d - state=%i\n", job->pic_no, job->state);
342
if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
343
XVC_AddTimeout(job->time_per_frame, job->capture, job);
345
} else if (job->state & VC_REC) {
346
if (job->max_frames && (
347
(job->pic_no - job->start_no )> job->max_frames - 1)) {
348
if (job->flags & FLG_RUN_VERBOSE)
349
printf("Stopped! pic_no=%d max_frames=%d\n",
350
job->pic_no, job->max_frames);
351
if (!(job->flags & FLG_RUN_VERBOSE))
352
XVC_ChangeGUILabel(job->pic_no);
354
if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
357
job->state &= ~VC_STEP;
358
gettimeofday(&curr_time, NULL);
359
time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
361
if ((!(job->flags & FLG_MULTI_IMAGE)) ||
362
((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
363
if ((job->flags & FLG_MULTI_IMAGE) != 0) {
364
sprintf(file, job->file, job->movie_no);
366
sprintf(file, job->file, job->pic_no);
368
fp = (*job->open)(file, job->open_flags);
371
job->state = VC_STOP;
375
if (job->state & VC_START) {
377
* the first time this procedure is started
378
* we must create a new image ..
383
if ( ! (job->flags & FLG_NOGUI ) ) {
384
scr = job->win_attr.screen;
385
dpy = DisplayOfScreen(scr);
387
dpy = XOpenDisplay(NULL);
390
if (job->mouseWanted > 0) {
391
getCurrentPointer(&x, &y, job);
394
image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)),
395
job->area->x, job->area->y,
396
job->area->width, job->area->height, AllPlanes, ZPixmap);
398
printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
399
job->area->height, job->area->x, job->area->y);
400
job->state = VC_STOP;
402
if (job->mouseWanted > 0) {
403
paintMousePointer(&x, &y, job, image);
405
(*job->save) (fp, image, job);
406
job->state &= ~VC_START;
411
/* just read new data in the image structure
413
if (job->mouseWanted > 0) {
414
getCurrentPointer(&x, &y, job);
418
RootWindow(dpy, DefaultScreen(dpy)),
419
image, job->area->x, job->area->y)) {
420
if (job->mouseWanted > 0) {
421
paintMousePointer(&x, &y, job, image);
423
(*job->save) (fp, image, job);
425
printf("XGetZPixmap returned 'False'!\n");
428
if (!(job->flags & FLG_MULTI_IMAGE))
431
/* substract the time we needed for creating and saving
432
* the frame to the file
434
gettimeofday(&curr_time, NULL);
435
time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
436
// update monitor widget, here time is the time the capture took
437
// time == 0 resets led_meter
438
if (! time1) time1 = 1;
439
XVC_FrameMonitor(job, time1);
440
// printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
441
// calculate the remaining time we have till capture of next frame
442
time1 = job->time_per_frame - time1;
445
// get time again because updating frame drop meter took some time
446
gettimeofday(&curr_time, NULL);
447
time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
448
time = job->time_per_frame - time;
453
if (job->flags & FLG_RUN_VERBOSE)
454
printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
455
time, job->time_per_frame, job->pic_no);
457
if ( time < 2 ) time = 2;
459
XVC_AddTimeout(time, job->capture, job);
461
job->pic_no += job->step;
463
XVC_ChangeGUILabel(job->pic_no);
470
orig_state = job->state; // store state here
472
/* may be the last update failed .. so do it here before stop
474
XVC_ChangeGUILabel(job->pic_no);
475
XVC_FrameMonitor(job, 0);
477
job->state = VC_STOP;
479
XDestroyImage(image);
482
/* set the sensitive stuff for the control panel
483
* if we don't autocontinue */
484
if ((orig_state & VC_CONTINUE) == 0)
485
XVC_StopCapture(job);
487
/* clean up the save routines in xtoXXX.c
491
if (job->flags & FLG_MULTI_IMAGE)
496
if ((orig_state & VC_CONTINUE) == 0) {
497
/* after this we're ready to start recording again */
498
job->state |= VC_READY;
501
job->pic_no = job->start_no;
502
job->state &= ~VC_STOP;
503
job->state |= VC_START;
504
job->state |= VC_REC;
505
XVC_StartCapture(job);
509
if ( job->flags & FLG_NOGUI ) {
522
* timer callback for capturing with shared memory
525
TCbCaptureSHM(XtPointer xtp, XtIntervalId *id) {
526
Job *job = (Job *) xtp;
527
static char file[PATH_MAX+1];
528
static XImage *image = NULL;
529
static XShmSegmentInfo shminfo;
530
static void *fp = NULL;
531
Visual *visual = job->win_attr.visual;
532
unsigned int depth = job->win_attr.depth;
534
struct timeval curr_time;
539
printf("TCbCaptureSHM() pic_no=%d flags=%d state=%i\n", job->pic_no, job->flags, job->state);
540
printf("VC_REC %i - VC_STOP %i\n", ( job->state & VC_REC ), (job->state & VC_STOP ) );
542
if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
543
XVC_AddTimeout(job->time_per_frame, job->capture, job);
545
} else if (job->state & VC_REC) {
546
// trace mouse pointer ...
549
if (job->max_frames && (
550
(job->pic_no - job->start_no )> job->max_frames - 1)) {
551
if (job->flags & FLG_RUN_VERBOSE)
552
printf("Stopped! pic_no=%d max_frames=%d\n",
553
job->pic_no, job->max_frames);
554
if (!(job->flags & FLG_RUN_VERBOSE))
555
XVC_ChangeGUILabel(job->pic_no);
557
if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
560
job->state &= ~VC_STEP;
561
gettimeofday(&curr_time, NULL);
562
time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
564
if ((!(job->flags & FLG_MULTI_IMAGE)) ||
565
((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
567
if (job->flags & FLG_MULTI_IMAGE)
568
sprintf(file, job->file, job->movie_no);
570
sprintf(file, job->file, job->pic_no);
571
fp = (*job->open)(file, job->open_flags);
574
job->state = VC_STOP;
578
if (job->state & VC_START) {
580
* the first time this procedure is called so
581
* we must create a new ximage ..
583
if ( ! (job->flags & FLG_NOGUI ) ) {
584
scr = job->win_attr.screen;
585
dpy = DisplayOfScreen(scr);
587
dpy = XOpenDisplay(NULL);
588
scr = DefaultScreenOfDisplay(dpy);
591
if (job->mouseWanted > 0) {
592
getCurrentPointer(&x, &y, job);
595
image = XShmCreateImage(dpy, visual, depth, ZPixmap, NULL,
596
&shminfo, job->area->width, job->area->height);
598
printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
599
job->area->height, job->area->x, job->area->y);
600
job->state = VC_STOP;
601
// CbStop(NULL, NULL, NULL);
604
shminfo.shmid = shmget(IPC_PRIVATE,
605
image->bytes_per_line * image->height, IPC_CREAT|0777);
606
if (shminfo.shmid == -1) {
607
printf("Fatal: Can't get shared memory!\n");
610
shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
611
shminfo.readOnly = False;
613
if (XShmAttach(dpy, &shminfo) == 0) {
614
printf("Fatal: Failed to attach shared memory!\n");
615
/* needs some better error subroutine :) */
619
if (job->mouseWanted > 0) {
620
paintMousePointer(&x, &y, job, image);
624
/* just read new data in the image structure
626
if (job->mouseWanted) {
627
getCurrentPointer(&x, &y, job);
630
if (XShmGetImage(dpy,
631
RootWindow(dpy, DefaultScreen(dpy)),
632
image, job->area->x, job->area->y, AllPlanes)) {
633
if (job->mouseWanted) {
634
paintMousePointer(&x, &y, job, image);
637
(*job->save) (fp, image, job);
638
job->state &= ~VC_START;
640
printf("XShmGetImage() returned 'False'!\n");
642
if (!(job->flags & FLG_MULTI_IMAGE))
644
else if (job->flags & FLG_SYNC) {
645
if (job->open == (void *(*)(char *, char*))fopen)
646
fdatasync(fileno(fp));
649
/* substract the time we needed for creating and saving
650
* the frame to the file
652
gettimeofday(&curr_time, NULL);
653
time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
654
// update monitor widget, here time is the time the capture took
655
// time == 0 resets led_meter
656
if (! time1) time1 = 1;
657
XVC_FrameMonitor(job, time1);
658
// printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
659
// calculate the remaining time we have till capture of next frame
660
time1 = job->time_per_frame - time1;
663
// get time again because updating frame drop meter took some time
664
gettimeofday(&curr_time, NULL);
665
time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
666
time = job->time_per_frame - time;
671
if (job->flags & FLG_RUN_VERBOSE)
672
printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
673
time, job->time_per_frame, job->pic_no);
675
if ( time < 2 ) time = 2;
677
XVC_AddTimeout(time, job->capture, job);
679
job->pic_no += job->step;
681
XVC_ChangeGUILabel(job->pic_no);
688
orig_state = job->state; // store state here
690
// maybe the last update didn't succeed
691
XVC_ChangeGUILabel(job->pic_no);
692
XVC_FrameMonitor(job, 0);
694
job->state = VC_STOP;
696
XShmDetach(dpy, &shminfo);
698
XDestroyImage(image);
700
shmdt(shminfo.shmaddr);
701
shmctl(shminfo.shmid, IPC_RMID, 0);
704
/* set the sensitive stuff for the control panel
705
* if we don't autocontinue */
706
if ((orig_state & VC_CONTINUE) == 0)
707
XVC_StopCapture(job);
712
if (job->flags & FLG_MULTI_IMAGE)
717
if ((orig_state & VC_CONTINUE) == 0) {
718
/* after this we're ready to start recording again */
719
job->state |= VC_READY;
722
job->pic_no = job->start_no;
723
job->state &= ~VC_STOP;
724
job->state |= VC_START;
725
job->state |= VC_REC;
726
XVC_StartCapture(job);
730
if ( job->flags & FLG_NOGUI ) {
740
#endif /* HAVE_SHMAT */
742
#ifdef HasVideo4Linux
744
* timer callback for capturing direct from bttv driver (only linux)
747
#error only for linux
752
TCbCaptureV4L(XtPointer xtp, XtIntervalId id *) {
753
Job *job = (Job *) xtp;
754
static char file[PATH_MAX+1];
755
static XImage *image = NULL;
756
static void *fp = NULL;
757
static VIDEO *video = 0;
759
static struct video_mmap vi_mmap;
760
static struct video_mbuf vi_memb;
761
static struct video_picture vi_pict;
763
struct timeval curr_time;
767
if ( ! (job->flags & FLG_NOGUI ) ) {
768
scr = job->win_attr.screen;
769
dpy = DisplayOfScreen(scr);
771
dpy = XOpenDisplay(NULL);
775
printf("TCbCaptureV4L() pic_no=%d\n", job->pic_no);
777
if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
778
XVC_AddTimeout(job->time_per_frame, job->capture, job);
780
} else if (job->state & VC_REC) {
781
if (job->max_frames && (
782
(job->pic_no - job->start_no )> job->max_frames - 1)) {
783
if (job->flags & FLG_RUN_VERBOSE)
784
printf("Stopped! pic_no=%d max_frames=%d\n",
785
job->pic_no, job->max_frames);
786
if (!(job->flags & FLG_RUN_VERBOSE))
787
XVC_ChangeGUILabel(job->pic_no);
789
if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
792
job->state &= ~VC_STEP;
793
gettimeofday(&curr_time, NULL);
794
time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
796
if ((!(job->flags & FLG_MULTI_IMAGE)) ||
797
((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
798
if (job->flags & FLG_MULTI_IMAGE)
799
sprintf(file, job->file, job->movie_no);
801
sprintf(file, job->file, job->pic_no);
802
fp = (*job->open)(file, job->open_flags);
805
job->state = VC_STOP;
809
if (job->state & VC_START) {
811
* the first time this procedure is started
812
* we must prepare some stuff ..
814
if (!job->bpp) /* use depth of the default window */
815
job->bpp = job->win_attr.depth;
817
sync(); /* remove if your bttv driver runs stable .. */
818
video = video_open(job->video_dev, O_RDWR);
820
perror(job->video_dev);
824
/* read default values for hue, etc.. */
825
ioctl(video->fd, VIDIOCGPICT, &vi_pict);
827
printf("%d->%d %d\n", job->bpp, vi_pict.depth, vi_pict.palette);
830
vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB24;
833
vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB565;
836
vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB555;
839
printf("Fatal: unsupported bpp (%d)\n", job->bpp);
843
ioctl(video->fd, VIDIOCSPICT, &vi_pict);
844
printf("%d->%d %d\n", job->bpp, vi_pict.depth, vi_pict.palette);
848
ioctl(video->fd, VIDIOCGMBUF, &vi_memb);
849
printf("%d %d %d\n", vi_memb.size, vi_memb.frames, vi_memb.offsets);
851
image = (XImage *)XtMalloc(sizeof(XImage));
853
printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
854
job->area->height, job->area->x, job->area->y);
859
image->red_mask = 0xFF0000;
860
image->green_mask = 0x00FF00;
861
image->blue_mask = 0x0000FF;
864
image->red_mask = 0x00F800;
865
image->green_mask = 0x0007E0;
866
image->blue_mask = 0x00001F;
869
image->red_mask = 0x00F800;
870
image->green_mask = 0x0007E0;
871
image->blue_mask = 0x00001F;
874
printf("Fatal: unsupported bpp (%d)\n", job->bpp);
878
image->width = job->area->width;
879
image->height= job->area->height;
880
image->bits_per_pixel = job->bpp;
881
image->bytes_per_line = job->bpp/8 * image->width;
882
image->byte_order = MSBFirst;
883
size = image->width * image->height * job->bpp;
884
video->size = vi_memb.size;
885
video_mmap(video, 1);
886
if (video->mmap == NULL) {
891
vi_mmap.width = image->width;
892
vi_mmap.height= image->height;
894
image->data = video->mmap;
896
/* just read new data in the image structure
898
if (ioctl(video->fd, VIDIOCMCAPTURE, &vi_mmap) < 0) {
899
perror("ioctl(capture)");
900
/* if (vb.frame) vb.frame = 0; else vb.frame = 1; */
903
printf("syncing ..\n");
904
if (ioctl(video->fd, VIDIOCSYNC, vi_mmap.frame) < 0) {
905
perror("ioctl(sync)");
907
printf("synced()\n");
909
(*job->save) (fp, image, job);
910
job->state &= ~VC_START;
912
if (!(job->flags & FLG_MULTI_IMAGE))
915
/* substract the time we needed for creating and saving
916
* the frame to the file
918
gettimeofday(&curr_time, NULL);
919
time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
920
// update monitor widget, here time is the time the capture took
921
// time == 0 resets led_meter
922
if (! time1) time1 = 1;
923
XVC_FrameMonitor(job, time1);
924
// printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
925
// calculate the remaining time we have till capture of next frame
926
time1 = job->time_per_frame - time1;
929
// get time again because updating frame drop meter took some time
930
gettimeofday(&curr_time, NULL);
931
time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
932
time = job->time_per_frame - time;
937
if (job->flags & FLG_RUN_VERBOSE)
938
printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
939
time, job->time_per_frame, job->pic_no);
941
if ( time < 2 ) time = 2;
943
XVC_AddTimeout(time, job->capture, job);
945
job->pic_no += job->step;
947
XVC_ChangeGUILabel(job->pic_no);
954
orig_state = job->state; // store state here
956
// maybe the last update didn't succeed
957
XVC_ChangeGUILabel(job->pic_no);
958
XVC_FrameMonitor(job, 0);
960
job->state = VC_STOP;
962
XtFree((char*)image);
966
video_mmap(video, 0);
971
/* set the sensitive stuff for the control panel
972
* if we don't autocontinue */
973
if ((orig_state & VC_CONTINUE) == 0)
974
XVC_StopCapture(job);
976
/* clean up the save routines in xtoXXX.c
980
if (job->flags & FLG_MULTI_IMAGE)
985
if ((orig_state & VC_CONTINUE) == 0) {
986
/* after this we're ready to start recording again */
987
job->state |= VC_READY;
990
job->pic_no = job->start_no;
991
job->state &= ~VC_STOP;
992
job->state |= VC_START;
993
job->state |= VC_REC;
994
XVC_StartCapture(job);
1000
/* after this we're ready to start recording again */
1001
job->state |= VC_READY;
1003
if ( job->flags & FLG_NOGUI && ( ! is_filename_mutable(job->file) ) ) {
1009
#endif /* HasVideo4Linux */
1013
* direct graphic access
1014
* this doesn't work until now and may be removed in future..!?
1016
* IT HAS ALSO NOT BEEN REWRITTEN FOR GTK GUI SUPPORT
1019
TCbCaptureDGA(XtPointer xtp, XtIntervalId id *) {
1020
Job *job = (Job *) xtp;
1021
static char file[PATH_MAX+1];
1022
static XImage *image = NULL;
1025
static Display *dpy;
1027
struct timeval curr_time;
1030
printf("TCbCaptureDGA() pic_no=%d state=%d\n", job->pic_no, job->state);
1032
if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
1033
XtAppAddTimeOut(XtWidgetToApplicationContext(job->toplevel),
1034
job->time_per_frame, (XtTimerCallbackProc)job->capture, job);
1036
} else if (job->state & VC_REC) {
1037
if (job->max_frames && (
1038
(job->pic_no - job->start_no )> job->max_frames - 1)) {
1039
if (job->flags & FLG_RUN_VERBOSE)
1040
printf("Stopped! pic_no=%d max_frames=%d\n",
1041
job->pic_no, job->max_frames);
1042
if (!(job->flags & FLG_RUN_VERBOSE))
1043
ChangeLabel(job->pic_no);
1046
job->state &= ~VC_STEP;
1047
gettimeofday(&curr_time, NULL);
1048
time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
1050
if ((!(job->flags & FLG_MULTI_IMAGE)) ||
1051
((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
1052
if (job->flags & FLG_MULTI_IMAGE)
1053
sprintf(file, job->file, job->movie_no);
1055
sprintf(file, job->file, job->pic_no);
1056
fp = (*job->open)(file, job->open_flags);
1059
job->state = VC_STOP;
1063
if (job->state & VC_START) {
1065
* the first time this procedure is started
1066
* we must create a new image structure ..
1068
dpy = XtDisplay(job->toplevel);
1069
image = (XImage *)XtMalloc(sizeof(XImage));
1071
printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
1072
job->area->height, job->area->x, job->area->y);
1075
image->width = job->area->width;
1076
image->height= job->area->height;
1077
image->bits_per_pixel = 3 * 8;
1078
image->bytes_per_line = 3 * image->width;
1079
image->byte_order = MSBFirst;
1080
size = image->width * image->height;
1081
{ int width, bank, ram;
1083
XF86DGAGetVideo(dpy, XDefaultScreen(dpy), (char **) &base,
1084
&width, &bank, &ram);
1087
XF86DGADirectVideo(dpy, XDefaultScreen(dpy), XF86DGADirectGraphics);
1088
(*job->save) (fp, image, job);
1089
XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
1090
job->state &= ~VC_START;
1092
/* just read new data in the image structure
1094
XF86DGADirectVideo(dpy, XDefaultScreen(dpy), XF86DGADirectGraphics);
1095
(*job->save) (fp, image, job);
1096
XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
1098
if (!(job->flags & FLG_MULTI_IMAGE))
1101
/* substract the time we needed for creating and saving
1102
* the frame to the file
1104
gettimeofday(&curr_time, NULL);
1105
time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
1106
time = job->time_per_frame - time;
1108
if (job->flags & FLG_RUN_VERBOSE)
1109
printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
1110
time, job->time_per_frame, job->pic_no);
1113
XtAppAddTimeOut(XtWidgetToApplicationContext(job->toplevel),
1114
time, (XtTimerCallbackProc)job->capture, job);
1115
job->pic_no += job->step;
1116
/* update the label if we have time to do this */
1118
ChangeLabel(job->pic_no);
1122
/* may be the last update failed .. so do it here before stop
1124
ChangeLabel(job->pic_no);
1125
job->state = VC_STOP;
1127
XtFree((char*)image);
1130
XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
1131
/* set the sensitive stuff for the control panel
1133
CbStop(NULL, NULL, NULL);
1135
/* clean up the save routines in xtoXXX.c
1138
(*job->clean) (job);
1139
if (job->flags & FLG_MULTI_IMAGE)