1 /*
2 * liblavrec - a librarified Linux Audio Video Record-application
3 *
4 * Copyright (C) 2000 Rainer Johanni <Rainer@Johanni.de>
5 * Extended by: Gernot Ziegler <gz@lysator.liu.se>
6 * & Wolfgang Scherr <scherr@net4you.net>
7 * & Ronald Bultje <rbultje@ronald.bitfreak.net>
8 * & many others
9 *
10 * A library for recording MJPEG video from hardware MJPEG
11 * video devices such as the Pinnacle/Miro DC10(+), Iomega
12 * Buz, the Linux Media Labs LML33, the Matrox Marvel G200,
13 * Matrox Marvel G400 and the Rainbow Runner G-series.
14 * Can also be used for video-capture from BTTV-devices
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 */
30
31 #include <config.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <sched.h>
40 #include <signal.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/ioctl.h>
44 #include <sys/mman.h>
45 #include <sys/time.h>
46 #include <sys/resource.h>
47 #include <sys/wait.h>
48 #ifdef __linux
49 #include <sys/statfs.h>
50 #include <sys/vfs.h>
51 #else
52 #include <sys/param.h>
53 #include <sys/mount.h>
54 #endif
55 #include <mjpeg_types.h>
56 #include <stdlib.h>
57
58 /* Because of some really cool feature in video4linux1, also known as
59 * 'not including sys/types.h and sys/time.h', we had to include it
60 * ourselves. In all their intelligence, these people decided to fix
61 * this in the next version (video4linux2) in such a cool way that it
62 * breaks all compilations of old stuff...
63 * The real problem is actually that linux/time.h doesn't use proper
64 * macro checks before defining types like struct timeval. The proper
65 * fix here is to either fuck the kernel header (which is what we do
66 * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
67 * upstream, which I'll consider doing later on. If you get compiler
68 * errors here, check your linux/time.h && sys/time.h header setup.
69 */
70 #define _LINUX_TIME_H
71 #include <linux/videodev.h>
72 #ifdef HAVE_SYS_SOUNDCARD_H
73 #include <sys/soundcard.h>
74 #endif
75
76 #include <videodev_mjpeg.h>
77 #include <pthread.h>
78
79 #include "mjpeg_logging.h"
80 #include "liblavrec.h"
81 #include "lav_io.h"
82 #include "audiolib.h"
83 #include "jpegutils.h"
84
85 /* On some systems MAP_FAILED seems to be missing */
86 #ifndef MAP_FAILED
87 #define MAP_FAILED ( (caddr_t) -1 )
88 #endif
89
90 #define MJPEG_MAX_BUF 256
91
92 #define MIN_QUEUES_NEEDED 2 /* minimal number of queues needed to sync */
93
94 #define NUM_AUDIO_TRIES 500 /* makes 10 seconds with 20 ms pause beetween tries */
95
96 #define MIN_MBYTES_FREE 10 /* Minimum number of Mbytes that should
97 stay free on the file system, this is also
98 only a guess */
99 #define MIN_MBYTES_FREE_OPEN 20 /* Minimum number of Mbytes that have to be
100 free in the filesystem when opening a new file */
101 #define CHECK_INTERVAL 50 /* Interval for checking free space on file system */
102
103 #define VALUE_NOT_FILLED -10000
104
105 struct YUVP_convert
106 {
107 unsigned char *mmap;
108 unsigned char *YUVP_buff;
109 };
110
111 typedef struct {
112 int interlaced; /* is the video interlaced (even/odd-first)? */
113 int width; /* width of the captured frames */
114 int height; /* height of the captured frames */
115 double spvf; /* seconds per video frame */
116 int video_fd; /* file descriptor of open("/dev/video") */
117 int has_audio; /* whether it has an audio ability */
118 struct mjpeg_requestbuffers breq; /* buffer requests */
119 struct mjpeg_sync bsync;
120 struct video_mbuf softreq; /* Software capture (YUV) buffer requests */
121 uint8_t *MJPG_buff; /* the MJPEG buffer */
122 struct video_mmap mm; /* software (YUV) capture info */
123 struct YUVP_convert *YUVP_convert; /* Software (YUVP) info */
124 unsigned char *YUV_buff; /* in case of software encoding: the YUV buffer */
125 lav_file_t *video_file; /* current lav_io.c file we're recording to */
126 lav_file_t *video_file_old; /* previous lav_io.c file we're recording to (finish audio/close) */
127 int num_frames_old;
128
129 uint8_t AUDIO_buff[AUDIO_BUFFER_SIZE]; /* the audio buffer */
130 struct timeval audio_t0;
131 int astat;
132 long audio_offset;
133 struct timeval audio_tmstmp;
134 int mixer_set; /* whether the mixer settings were changed */
135 int audio_bps; /* bytes per second for audio stream */
136 long audio_buffer_size; /* audio stream buffer size */
137 double spas; /* seconds per audio sample */
138 double sync_lim; /* upper limit of 'out-of-sync' - if higher, quit */
139 video_capture_stats* stats; /* the stats */
140
141 uint64_t MBytes_fs_free; /* Free disk space when that was last checked */
142 uint64_t bytes_output_cur; /* Bytes output to the current output file */
143 uint64_t bytes_last_checked; /* Number of bytes that were output when the
144 free space was last checked */
145 int mixer_volume_saved; /* saved recording volume before setting mixer */
146 int mixer_recsrc_saved; /* saved recording source before setting mixer */
147 int mixer_inplev_saved; /* saved output volume before setting mixer */
148
149 /* the JPEG video encoding thread mess */
150 struct encoder_info_s * encoders; /* for software encoding recording */
151 pthread_mutex_t encoding_mutex; /* for software encoding recording */
152 int buffer_valid[MJPEG_MAX_BUF]; /* Non-zero if buffer has been filled */
153 int buffer_completed[MJPEG_MAX_BUF]; /* Non-zero if buffer has been compressed/written */
154 pthread_cond_t buffer_filled[MJPEG_MAX_BUF];
155 pthread_cond_t buffer_completion[MJPEG_MAX_BUF];
156
157 /* thread for correctly timestamping the V4L/YUV buffers */
158 pthread_t software_sync_thread; /* the thread */
159 pthread_mutex_t software_sync_mutex; /* the mutex */
160 sig_atomic_t please_stop_syncing;
161 unsigned long buffers_queued; /* evil hack for BTTV-0.8 */
162 int software_sync_ready[MJPEG_MAX_BUF]; /* whether the frame has already been synced on */
163 pthread_cond_t software_sync_wait[MJPEG_MAX_BUF]; /* wait for frame to be synced on */
164 struct timeval software_sync_timestamp[MJPEG_MAX_BUF];
165
166 /* some mutex/cond stuff to make sure we have enough queues left */
167 pthread_mutex_t queue_mutex;
168 unsigned short queue_left;
169 short is_queued[MJPEG_MAX_BUF];
170 pthread_cond_t queue_wait;
171
172 int output_status;
173
174 pthread_mutex_t state_mutex;
175 int state; /* recording, paused or stoppped */
176
177 pthread_t capture_thread;
178 } video_capture_setup;
179
180
181 /* Identity record for software encoding worker thread...
182 * Given N workers Worker i compresses frame i,i+n,i+2N and so on.
183 * There may not be more workers than there are capture buffers - 1.
184 */
185
186 typedef struct encoder_info_s {
187 lavrec_t *info;
188 unsigned int encoder_id;
189 unsigned int num_encoders;
190 pthread_t thread;
191 } encoder_info_t;
192
193 /* Forward definitions */
194 static int
195 lavrec_queue_buffer (lavrec_t *info, unsigned long *num);
196
197 static int
198 lavrec_handle_audio (lavrec_t *info, struct timeval *timestamp);
199
200
201
202 /******************************************************
203 * lavrec_msg()
204 * simplicity function which will give messages
205 ******************************************************/
206
207 static void lavrec_msg(int type, lavrec_t *info, const char format[], ...) GNUC_PRINTF(3,4);
lavrec_msg(int type,lavrec_t * info,const char format[],...)208 static void lavrec_msg(int type, lavrec_t *info, const char format[], ...)
209 {
210 char buf[1024];
211 va_list args;
212
213 va_start(args, format);
214 vsnprintf(buf, sizeof(buf)-1, format, args);
215 va_end(args);
216
217 if (!info) /* we can't let errors pass without giving notice */
218 mjpeg_error("%s", buf);
219 else if (info->msg_callback)
220 info->msg_callback(type, buf);
221 else if (type == LAVREC_MSG_ERROR)
222 mjpeg_error("%s", buf);
223 }
224
225
226 /******************************************************
227 * lavrec_change_state()
228 * changes the recording state
229 ******************************************************/
230
231 static int
lavrec_change_state_if(lavrec_t * info,int new_state,int require_state)232 lavrec_change_state_if(lavrec_t *info, int new_state, int require_state)
233 {
234 int okay;
235
236 video_capture_setup *settings = (video_capture_setup *)info->settings;
237
238 pthread_mutex_lock(&settings->state_mutex);
239
240 if ((okay = settings->state == require_state) != 0)
241 {
242 settings->state = new_state;
243 if (info->state_changed)
244 info->state_changed(new_state);
245 }
246
247 pthread_mutex_unlock(&settings->state_mutex);
248 return okay;
249 }
250
251 static void
lavrec_change_state(lavrec_t * info,int new_state)252 lavrec_change_state(lavrec_t *info, int new_state)
253 {
254 video_capture_setup *settings = (video_capture_setup *)info->settings;
255
256 pthread_mutex_lock(&settings->state_mutex);
257
258 settings->state = new_state;
259 if (info->state_changed)
260 info->state_changed(new_state);
261
262 pthread_mutex_unlock(&settings->state_mutex);
263 }
264
265
266 /******************************************************
267 * set_mixer()
268 * set the sound mixer:
269 * flag = 1 : set for recording from the line input
270 * flag = 0 : restore previously saved values
271 *
272 * return value: 1 on success, 0 on error
273 ******************************************************/
274
lavrec_set_mixer(lavrec_t * info,int flag)275 static int lavrec_set_mixer(lavrec_t *info, int flag)
276 {
277 int fd, var;
278 unsigned int sound_mixer_read_input;
279 unsigned int sound_mixer_write_input;
280 unsigned int sound_mask_input;
281 video_capture_setup *settings = (video_capture_setup *)info->settings;
282
283 /* Avoid restoring anything when nothing was set */
284 if (flag==0 && settings->mixer_set==0) return 1;
285
286 /* Open the audio device */
287 fd = open(info->mixer_dev, O_RDONLY);
288 if (fd == -1)
289 {
290 lavrec_msg(LAVREC_MSG_WARNING, info,
291 "Unable to open sound mixer \'%s\', try setting the sound mixer with another tool!!!",
292 info->mixer_dev);
293 return 1; /* 0 means error, so although we failed return 1 */
294 }
295
296 switch(info->audio_src)
297 {
298 case 'm':
299 sound_mixer_read_input = SOUND_MIXER_READ_MIC;
300 sound_mixer_write_input = SOUND_MIXER_WRITE_MIC;
301 sound_mask_input = SOUND_MASK_MIC;
302 break;
303 case 'c':
304 sound_mixer_read_input = SOUND_MIXER_READ_CD;
305 sound_mixer_write_input = SOUND_MIXER_WRITE_CD;
306 sound_mask_input = SOUND_MASK_CD;
307 break;
308 case 'l':
309 sound_mixer_read_input = SOUND_MIXER_READ_LINE;
310 sound_mixer_write_input = SOUND_MIXER_WRITE_LINE;
311 sound_mask_input = SOUND_MASK_LINE;
312 break;
313 case '1':
314 sound_mixer_read_input = SOUND_MIXER_READ_LINE1;
315 sound_mixer_write_input = SOUND_MIXER_WRITE_LINE1;
316 sound_mask_input = SOUND_MASK_LINE1;
317 break;
318 case '2':
319 sound_mixer_read_input = SOUND_MIXER_READ_LINE2;
320 sound_mixer_write_input = SOUND_MIXER_WRITE_LINE2;
321 sound_mask_input = SOUND_MASK_LINE2;
322 break;
323 case '3':
324 sound_mixer_read_input = SOUND_MIXER_READ_LINE3;
325 sound_mixer_write_input = SOUND_MIXER_WRITE_LINE3;
326 sound_mask_input = SOUND_MASK_LINE3;
327 break;
328 default:
329 lavrec_msg(LAVREC_MSG_WARNING, info,
330 "Unknown sound source: \'%c\'", info->audio_src);
331 close(fd);
332 return 1; /* 0 means error, so although we failed return 1 */
333 }
334
335 if(flag==1)
336 {
337 int nerr = 0;
338
339 /* Save the values we are going to change */
340 if (settings->mixer_set == 0) {
341 if (ioctl(fd, SOUND_MIXER_READ_VOLUME, &(settings->mixer_volume_saved)) == -1) nerr++;
342 if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &(settings->mixer_recsrc_saved)) == -1) nerr++;
343 if (ioctl(fd, sound_mixer_read_input , &(settings->mixer_inplev_saved)) == -1) nerr++;
344 settings->mixer_set = 1;
345
346 if (nerr)
347 {
348 lavrec_msg (LAVREC_MSG_WARNING, info,
349 "Unable to save sound mixer settings");
350 lavrec_msg (LAVREC_MSG_WARNING, info,
351 "Restore your favorite setting with another tool after capture");
352 settings->mixer_set = 0; /* prevent us from resetting nonsense settings */
353 }
354 }
355
356 /* Set the recording source, audio-level and (if wanted) mute */
357 nerr = 0;
358
359 var = sound_mask_input;
360 if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &var) == -1) nerr++;
361 var = 256*info->audio_level + info->audio_level; /* left and right channel */
362 if (ioctl(fd, sound_mixer_write_input, &var) == -1) nerr++;
363 if(info->mute) {
364 var = 0;
365 if (ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &var) == -1) nerr++;
366 }
367
368 if (nerr)
369 {
370 lavrec_msg (LAVREC_MSG_WARNING, info,
371 "Unable to set the sound mixer correctly");
372 lavrec_msg (LAVREC_MSG_WARNING, info,
373 "Audio capture might not be successfull (try another mixer tool!)");
374 }
375
376 }
377 else
378 {
379 int nerr = 0;
380
381 /* Restore previously saved settings */
382 if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &(settings->mixer_recsrc_saved)) == -1) nerr++;
383 if (ioctl(fd, sound_mixer_write_input, &(settings->mixer_inplev_saved)) == -1) nerr++;
384 if(info->mute)
385 if (ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &(settings->mixer_volume_saved)) == -1) nerr++;
386
387 if (nerr)
388 {
389 lavrec_msg (LAVREC_MSG_WARNING, info,
390 "Unable to restore sound mixer settings");
391 lavrec_msg (LAVREC_MSG_WARNING, info,
392 "Restore your favorite setting with another tool");
393 }
394 settings->mixer_set = 0;
395 }
396
397 close(fd);
398
399 return 1;
400 }
401
402
403 /******************************************************
404 * lavrec_autodetect_signal()
405 * (try to) autodetect signal/norm
406 *
407 * return value: 1 on success, 0 on error
408 ******************************************************/
409
lavrec_autodetect_signal(lavrec_t * info)410 static int lavrec_autodetect_signal(lavrec_t *info)
411 {
412 struct mjpeg_status bstat;
413 int i;
414
415 video_capture_setup *settings = (video_capture_setup *)info->settings;
416
417 lavrec_msg(LAVREC_MSG_INFO, info, "Auto detecting input and norm ...");
418
419 if (info->software_encoding && (info->video_norm==3 || info->video_src==-1))
420 {
421 lavrec_msg(LAVREC_MSG_DEBUG, info,
422 "Using current input signal settings for non-MJPEG card");
423 return 1;
424 }
425
426 if (info->video_src == -1) /* detect video_src && norm */
427 {
428 int n = 0;
429
430 for(i=0;i<2;i++)
431 {
432 lavrec_msg (LAVREC_MSG_INFO, info,
433 "Trying %s ...", (i==2)?"TV tuner":(i==0?"Composite":"S-Video"));
434
435 bstat.input = i;
436 if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0)
437 {
438 lavrec_msg (LAVREC_MSG_ERROR, info,
439 "Error getting video input status: %s",
440 (const char*)strerror(errno));
441 return 0;
442 }
443
444 if (bstat.signal)
445 {
446 lavrec_msg (LAVREC_MSG_INFO, info,
447 "Input present: %s %s",
448 bstat.norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"),
449 bstat.color?"color":"no color");
450 info->video_src = i;
451 info->video_norm = bstat.norm;
452 n++;
453 }
454 else
455 {
456 lavrec_msg (LAVREC_MSG_INFO, info,
457 "No signal ion specified input");
458 }
459 }
460
461 switch(n)
462 {
463 case 0:
464 lavrec_msg (LAVREC_MSG_ERROR, info,
465 "No input signal ... exiting");
466 return 0;
467 case 1:
468 lavrec_msg (LAVREC_MSG_INFO, info,
469 "Detected %s %s",
470 info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"),
471 info->video_src==0?"Composite":(info->video_src==1?"S-Video":"TV tuner"));
472 break;
473 default:
474 lavrec_msg (LAVREC_MSG_ERROR, info,
475 "Input signal on more thn one input source... exiting");
476 return 0;
477 }
478
479 }
480 else if (info->video_norm == 3) /* detect norm only */
481 {
482
483 lavrec_msg (LAVREC_MSG_INFO, info,
484 "Trying to detect norm for %s ...",
485 (info->video_src==2) ? "TV tuner" : (info->video_src==0?"Composite":"S-Video"));
486
487 bstat.input = info->video_src;
488 if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0)
489 {
490 lavrec_msg (LAVREC_MSG_ERROR, info,
491 "Error getting video input status: %s",strerror(errno));
492 return 0;
493 }
494
495 info->video_norm = bstat.norm;
496
497 lavrec_msg (LAVREC_MSG_INFO, info,
498 "Detected %s",
499 info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"));
500 }
501
502 return 1;
503 }
504
505
506 /******************************************************
507 * lavrec_get_free_space()
508 * get the amount of free disk space
509 *
510 * return value: 1 on success, 0 on error
511 ******************************************************/
512
lavrec_get_free_space(video_capture_setup * settings)513 static uint64_t lavrec_get_free_space(video_capture_setup *settings)
514 {
515 uint64_t blocks_per_MB;
516 struct statfs statfs_buf;
517 uint64_t MBytes_fs_free;
518
519 /* check the disk space again */
520 if (statfs(settings->stats->output_filename, &statfs_buf))
521 MBytes_fs_free = 2047; /* some fake value */
522 else
523 {
524 blocks_per_MB = (1024*1024) / statfs_buf.f_bsize;
525 MBytes_fs_free = statfs_buf.f_bavail/blocks_per_MB;
526 }
527 settings->bytes_last_checked = settings->bytes_output_cur;
528
529 return MBytes_fs_free;
530 }
531
532
533 /******************************************************
534 * lavrec_close_files_on_error()
535 * Close the output file(s) if an error occured.
536 * We don't care about further errors.
537 ******************************************************/
538
lavrec_close_files_on_error(lavrec_t * info)539 static void lavrec_close_files_on_error(lavrec_t *info)
540 {
541 video_capture_setup *settings = (video_capture_setup *)info->settings;
542
543 if(settings->output_status > 0 && settings->video_file)
544 {
545 lav_close(settings->video_file);
546 settings->video_file = NULL;
547 }
548 if(settings->output_status > 1 && settings->video_file_old)
549 {
550 lav_close(settings->video_file_old);
551 settings->video_file_old = NULL;
552 }
553
554 lavrec_msg(LAVREC_MSG_WARNING, info, "Closing file(s) and exiting - "
555 "output file(s) my not be readable due to error");
556 }
557
558
559 /******************************************************
560 * lavrec_output_video_frame()
561 * outputs a video frame and does all the file handling
562 * necessary like opening new files and closing old ones.
563 *
564 * return value: 1 on success, 0 on error
565 ******************************************************/
566
567 #define OUTPUT_VIDEO_ERROR_RETURN \
568 if (settings->output_status==2) \
569 { \
570 settings->output_status = 3; \
571 return 1; \
572 } \
573 else \
574 return 0;
575
lavrec_output_video_frame(lavrec_t * info,uint8_t * buff,long size,long count)576 static int lavrec_output_video_frame(lavrec_t *info, uint8_t *buff, long size, long count)
577 {
578 int n;
579 int OpenNewFlag = 0;
580
581 video_capture_setup *settings = (video_capture_setup *)info->settings;
582
583 if(settings->output_status == 3) return 1; /* Only audio is still active */
584
585 /* Check space on filesystem if we have filled it up
586 * or if we have written more than CHECK_INTERVAL bytes since last check
587 */
588 if (settings->output_status > 0)
589 {
590 n = (settings->bytes_output_cur - settings->bytes_last_checked)>>20; /* in MBytes */
591 if( n > CHECK_INTERVAL || n > settings->MBytes_fs_free - MIN_MBYTES_FREE )
592 settings->MBytes_fs_free = lavrec_get_free_space(settings);
593 }
594
595 /* Check if it is time to exit */
596 if (settings->state == LAVREC_STATE_STOP)
597 lavrec_msg(LAVREC_MSG_INFO, info, "Signal caught, stopping recording");
598 if (settings->stats->num_frames * settings->spvf > info->record_time && info->record_time >= 0)
599 {
600 lavrec_msg(LAVREC_MSG_INFO, info,
601 "Recording time reached, stopping");
602 lavrec_change_state(info, LAVREC_STATE_STOP);
603 }
604
605 /* Check if we have to open a new output file */
606 if (settings->output_status > 0 && (settings->bytes_output_cur>>20) > info->max_file_size_mb)
607 {
608 lavrec_msg(LAVREC_MSG_INFO, info,
609 "Max filesize reached, opening next output file");
610 OpenNewFlag = 1;
611 }
612 if( info->max_file_frames > 0 && settings->stats->num_frames % info->max_file_frames == 0)
613 {
614 lavrec_msg(LAVREC_MSG_INFO, info,
615 "Max number of frames reached, opening next output file");
616 OpenNewFlag = 1;
617 }
618 if (settings->output_status > 0 && settings->MBytes_fs_free < MIN_MBYTES_FREE)
619 {
620 lavrec_msg(LAVREC_MSG_INFO, info,
621 "File system is nearly full, trying to open next output file");
622 OpenNewFlag = 1;
623 }
624
625 /* JPEG = always open new file */
626 if (info->video_format == 'j')
627 OpenNewFlag = 1;
628
629 /* If a file is open and we should open a new one or exit, close current file */
630 if (settings->output_status > 0 && (OpenNewFlag || settings->state == LAVREC_STATE_STOP))
631 {
632 if (info->audio_size)
633 {
634 /* Audio is running - flag that the old file should be closed */
635 if(settings->output_status != 1)
636 {
637 /* There happened something bad - the old output file from the
638 * last file change is not closed. We try to close all files and exit
639 */
640 lavrec_msg(LAVREC_MSG_ERROR, info,
641 "Audio too far behind video. Check if audio works correctly!");
642 lavrec_close_files_on_error(info);
643 return -1;
644 }
645 lavrec_msg(LAVREC_MSG_DEBUG, info,
646 "Closing current output file for video, waiting for audio to be filled");
647 settings->video_file_old = settings->video_file;
648 settings->video_file = NULL;
649 settings->num_frames_old = settings->stats->num_frames;
650 if (settings->state == LAVREC_STATE_STOP)
651 {
652 settings->output_status = 3;
653 return 1;
654 }
655 else
656 settings->output_status = 2;
657 }
658 else
659 {
660 if (settings->video_file)
661 {
662 if (lav_close(settings->video_file))
663 {
664 settings->video_file = NULL;
665 lavrec_msg(LAVREC_MSG_ERROR, info,
666 "Error closing video output file %s, may be unuseable due to error",
667 settings->stats->output_filename);
668 return 0;
669 }
670 settings->video_file = NULL;
671 }
672 if (settings->state == LAVREC_STATE_STOP) return 0;
673 }
674 }
675
676 /* Open new output file if needed */
677 if (settings->output_status==0 || OpenNewFlag )
678 {
679 /* Get next filename */
680 if (info->num_files == 0)
681 {
682 sprintf(settings->stats->output_filename, info->files[0],
683 ++settings->stats->current_output_file);
684 }
685 else
686 {
687 if (settings->stats->current_output_file >= info->num_files)
688 {
689 if (info->video_format == 'j')
690 {
691 settings->stats->current_output_file = 0;
692 }
693 else
694 {
695 lavrec_msg(LAVREC_MSG_WARNING, info,
696 "Number of given output files reached");
697 OUTPUT_VIDEO_ERROR_RETURN;
698 }
699 }
700 strncpy(settings->stats->output_filename,
701 info->files[settings->stats->current_output_file++],
702 sizeof(settings->stats->output_filename));
703 }
704 lavrec_msg(LAVREC_MSG_INFO, info,
705 "Opening output file %s", settings->stats->output_filename);
706
707 /* Open next file */
708 settings->video_file = lav_open_output_file(settings->stats->output_filename, info->video_format,
709 settings->width, settings->height, settings->interlaced,
710 (info->video_norm==1? 30000.0/1001.0 : 25.0),
711 info->audio_size, (info->stereo ? 2 : 1), info->audio_rate);
712 if (!settings->video_file)
713 {
714 lavrec_msg(LAVREC_MSG_ERROR, info,
715 "Error opening output file %s: %s", settings->stats->output_filename, lav_strerror());
716 OUTPUT_VIDEO_ERROR_RETURN;
717 }
718
719 if (settings->output_status == 0) settings->output_status = 1;
720
721 /* Check space on filesystem. Exit if not enough space */
722 settings->bytes_output_cur = 0;
723 settings->MBytes_fs_free = lavrec_get_free_space(settings);
724 if(settings->MBytes_fs_free < MIN_MBYTES_FREE_OPEN)
725 {
726 lavrec_msg(LAVREC_MSG_ERROR, info,
727 "Not enough space for opening new output file");
728
729 /* try to close and remove file, don't care about errors */
730 if (settings->video_file)
731 {
732 lav_close(settings->video_file);
733 settings->video_file = NULL;
734 remove(settings->stats->output_filename);
735 }
736 OUTPUT_VIDEO_ERROR_RETURN;
737 }
738 }
739
740 /* Output the frame count times */
741 if (lav_write_frame(settings->video_file,buff,size,count))
742 {
743 /* If an error happened, try to close output files and exit */
744 lavrec_msg(LAVREC_MSG_ERROR, info,
745 "Error writing to output file %s: %s", settings->stats->output_filename, lav_strerror());
746 lavrec_close_files_on_error(info);
747 return 0;
748 }
749
750 /* Update counters. Maybe frame its written only once,
751 * but size*count is the save guess
752 */
753 settings->bytes_output_cur += size*count;
754 settings->stats->num_frames += count;
755
756 /*
757 * If the user has specified flushing of file buffers
758 * flush every time the specified number of unflushed frames has
759 * been reached.
760 */
761
762 if( info->flush_count > 0 && settings->stats->num_frames % info->flush_count == 0)
763 {
764 int fd = lav_fileno( settings->video_file );
765 if( fd >= 0 )
766 #ifdef __linux
767 fdatasync(fd);
768 #else
769 fsync(fd);
770 #endif
771 }
772 return 1;
773 }
774
video_captured(lavrec_t * info,uint8_t * buff,long size,long count)775 static int video_captured(lavrec_t *info, uint8_t *buff, long size, long count)
776 {
777 if (info->files)
778 return lavrec_output_video_frame(info, buff, size, count);
779 else
780 info->video_captured(buff, size, count);
781 return 1;
782 }
783
784
785 /******************************************************
786 * lavrec_output_audio_to_file()
787 * writes audio data to a file
788 *
789 * return value: 1 on success, 0 on error
790 ******************************************************/
791
lavrec_output_audio_to_file(lavrec_t * info,uint8_t * buff,long samps,int old)792 static int lavrec_output_audio_to_file(lavrec_t *info, uint8_t *buff, long samps, int old)
793 {
794 video_capture_setup *settings = (video_capture_setup *)info->settings;
795
796 if(samps==0) return 1;
797
798 /* Output data */
799 if (lav_write_audio(old?settings->video_file_old:settings->video_file,buff,samps))
800 {
801 /* If an error happened, try to close output files and exit */
802 lavrec_msg(LAVREC_MSG_ERROR, info,
803 "Error writing to output file: %s", lav_strerror());
804 lavrec_close_files_on_error(info);
805 return 0;
806 }
807
808 /* update counters */
809 settings->stats->num_asamps += samps;
810 if (!old) settings->bytes_output_cur += samps * settings->audio_bps;
811
812 return 1;
813 }
814
815
816 /******************************************************
817 * lavrec_output_audio_samples()
818 * outputs audio samples to files
819 *
820 * return value: 1 on success, 0 or -1 on error
821 ******************************************************/
822
lavrec_output_audio_samples(lavrec_t * info,uint8_t * buff,long samps)823 static int lavrec_output_audio_samples(lavrec_t *info, uint8_t *buff, long samps)
824 {
825 long diff = 0;
826
827 video_capture_setup *settings = (video_capture_setup *)info->settings;
828
829 /* Safety first */
830 if(!settings->output_status)
831 {
832 lavrec_msg(LAVREC_MSG_ERROR, info,
833 "**INTERNAL ERROR: Output audio but no file open");
834 return -1;
835 }
836
837 if(settings->output_status<2)
838 {
839 /* Normal mode, just output the sample */
840 return lavrec_output_audio_to_file(info, buff, samps, 0);
841 }
842
843 /* if we come here, we have to fill up the old file first */
844 diff = (settings->num_frames_old * settings->spvf -
845 settings->stats->num_asamps * settings->spas) * info->audio_rate;
846
847 if(diff<0)
848 {
849 lavrec_msg(LAVREC_MSG_ERROR, info,
850 "**INTERNAL ERROR: Audio output ahead video output");
851 return -1;
852 }
853
854 if(diff >= samps)
855 {
856 /* All goes to old file */
857 return lavrec_output_audio_to_file(info, buff, samps, 1);
858 }
859
860 /* diff samples go to old file */
861 if (!lavrec_output_audio_to_file(info, buff, diff, 1))
862 return 0;
863
864 /* close old file */
865 lavrec_msg(LAVREC_MSG_DEBUG, info, "Audio is filled - closing old file");
866 if (settings->video_file_old)
867 {
868 if (lav_close(settings->video_file_old))
869 {
870 settings->video_file_old = NULL;
871 lavrec_msg(LAVREC_MSG_ERROR, info,
872 "Error closing video output file, may be unuseable due to error: %s",
873 lav_strerror());
874 return 0;
875 }
876 settings->video_file_old = NULL;
877 }
878
879 /* Check if we are ready */
880 if (settings->output_status==3) return 0;
881
882 /* remaining samples go to new file */
883 settings->output_status = 1;
884 return lavrec_output_audio_to_file(info, buff+diff*settings->audio_bps, samps-diff, 0);
885 }
886
audio_captured(lavrec_t * info,uint8_t * buff,long samps)887 static int audio_captured(lavrec_t *info, uint8_t *buff, long samps)
888 {
889 if (info->files)
890 return lavrec_output_audio_samples(info, buff, samps);
891 else
892 info->audio_captured(buff, samps);
893 return 1;
894 }
895
frame_YUV422_to_planar_42x(uint8_t * output,uint8_t * input,int width,int height,int chroma)896 static void frame_YUV422_to_planar_42x(uint8_t *output, uint8_t *input,
897 int width, int height, int chroma)
898 {
899 int i, j, w2;
900 uint8_t *y, *cb, *cr;
901
902 w2 = width/2;
903 y=output;
904 cb=(output + width*height);
905 cr=(output + (3*width*height)/2);
906
907 for (i=0; i<height;) {
908 /* process two scanlines (one from each field, interleaved) */
909 /* ...top-field scanline */
910 for (j=0; j<w2; j++) {
911 /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
912 *(y++) = *(input++);
913 *(cb++) = *(input++);
914 *(y++) = *(input++);
915 *(cr++) = *(input++);
916 }
917 i++;
918 /* ...bottom-field scanline */
919 for (j=0; j<w2; j++) {
920 /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
921 *(y++) = *(input++);
922 *(cb++) = *(input++);
923 *(y++) = *(input++);
924 *(cr++) = *(input++);
925 }
926 i++;
927 if (chroma == Y4M_CHROMA_422)
928 continue;
929 /* process next two scanlines (one from each field, interleaved) */
930 /* ...top-field scanline */
931 for (j=0; j<w2; j++) {
932 /* skip every second line for U and V */
933 *(y++) = *(input++);
934 input++;
935 *(y++) = *(input++);
936 input++;
937 }
938 i++;
939 /* ...bottom-field scanline */
940 for (j=0; j<w2; j++) {
941 /* skip every second line for U and V */
942 *(y++) = *(input++);
943 input++;
944 *(y++) = *(input++);
945 input++;
946 }
947 i++;
948 }
949 }
950
951 /******************************************************
952 * lavrec_encoding_thread()
953 * The software encoding thread
954 ******************************************************/
955
lavrec_encoding_thread(void * arg)956 static void *lavrec_encoding_thread(void* arg)
957 {
958 encoder_info_t *w_info = (encoder_info_t *)arg;
959 lavrec_t *info = w_info->info;
960 video_capture_setup *settings = (video_capture_setup *)info->settings;
961 struct timeval timestamp[MJPEG_MAX_BUF];
962 int jpegsize;
963 unsigned long current_frame = w_info->encoder_id;
964 unsigned long predecessor_frame;
965 uint8_t * source;
966 uint8_t * buffer=NULL;
967
968 lavrec_msg(LAVREC_MSG_DEBUG, info,
969 "Starting software encoding thread");
970
971 /* Allow easy shutting down by other processes... */
972 /* PTHREAD_CANCEL_ASYNCHRONOUS is evil
973 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
974 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
975 */
976
977 while (settings->state == LAVREC_STATE_RECORDING)
978 {
979 pthread_cleanup_push((void (*)(void*))pthread_mutex_unlock, &settings->encoding_mutex);
980 pthread_mutex_lock(&(settings->encoding_mutex));
981 while (settings->buffer_valid[current_frame] == -1)
982 {
983 lavrec_msg(LAVREC_MSG_DEBUG, info,
984 "Encoding thread: sleeping for new frames (waiting for frame %ld)",
985 current_frame);
986 pthread_cond_wait(&(settings->buffer_filled[current_frame]),
987 &(settings->encoding_mutex));
988 if (settings->please_stop_syncing) {
989 pthread_mutex_unlock(&(settings->encoding_mutex));
990 pthread_exit(NULL);
991 }
992 }
993 memcpy(&(timestamp[current_frame]), &(settings->bsync.timestamp), sizeof(struct timeval));
994
995 if (settings->buffer_valid[current_frame] > 0)
996 {
997 /* There is no cancellation point in this block, but just to make sure... */
998 pthread_cleanup_push((void (*)(void*))pthread_mutex_lock, &settings->encoding_mutex);
999 pthread_mutex_unlock(&(settings->encoding_mutex));
1000
1001 if( settings->YUVP_convert )
1002 {
1003 memcpy( settings->YUVP_convert[current_frame].YUVP_buff, settings->YUVP_convert[current_frame].mmap, (info->geometry->h * info->geometry->w * 2) );
1004 source=settings->YUV_buff + (info->geometry->h * info->geometry->w * 2)*current_frame;
1005 frame_YUV422_to_planar_42x( source, settings->YUVP_convert[current_frame].YUVP_buff, info->geometry->w, info->geometry->h, Y4M_CHROMA_422 );
1006 }
1007 else
1008 {
1009 source=settings->YUV_buff+settings->softreq.offsets[current_frame];
1010 }
1011
1012 jpegsize = encode_jpeg_raw(settings->MJPG_buff+current_frame*settings->breq.size,
1013 settings->breq.size, info->quality, settings->interlaced,
1014 Y4M_CHROMA_422, info->geometry->w, info->geometry->h,
1015 source,
1016 source+(info->geometry->w*info->geometry->h),
1017 source+(info->geometry->w*info->geometry->h*3/2));
1018
1019 if (jpegsize<0)
1020 {
1021 if( buffer != NULL )
1022 {
1023 free( buffer );
1024 buffer=NULL;
1025 }
1026 lavrec_msg(LAVREC_MSG_ERROR, info,
1027 "Error encoding frame to JPEG");
1028 lavrec_change_state(info, LAVREC_STATE_STOP);
1029 pthread_exit(0);
1030 }
1031
1032 pthread_cleanup_pop(1);
1033 }
1034 else
1035 {
1036 jpegsize = 0; /* Just toss the frame */
1037 }
1038
1039
1040 /* Writing of video and audio data is non-reentrant and must
1041 * occur in-order - acquire lock and wait for preceding
1042 * frame's encoder to have completed writing that frames data
1043 *
1044 * Note that we need to queue the buffers in order, too,
1045 * so we need to sync up here even if we're discarding
1046 * the frame.
1047 */
1048 predecessor_frame = ( (current_frame + settings->softreq.frames-1)
1049 % settings->softreq.frames );
1050
1051 while( !settings->buffer_completed[predecessor_frame] )
1052 {
1053 pthread_cond_wait(&(settings->buffer_completion[predecessor_frame]),
1054 &(settings->encoding_mutex));
1055 }
1056
1057 if (jpegsize > 0)
1058 {
1059 if (video_captured(info,
1060 settings->MJPG_buff+(settings->breq.size*current_frame),
1061 jpegsize,
1062 settings->buffer_valid[current_frame]) != 1)
1063 {
1064 if( buffer != NULL )
1065 {
1066 free( buffer );
1067 buffer=NULL;
1068 }
1069 lavrec_msg(LAVREC_MSG_ERROR, info,
1070 "Error writing the frame");
1071 lavrec_change_state(info, LAVREC_STATE_STOP);
1072 pthread_exit(0);
1073 }
1074 }
1075
1076 #if 0
1077 if (!lavrec_queue_buffer(info, ¤t_frame))
1078 {
1079 if( buffer != NULL )
1080 {
1081 free( buffer );
1082 buffer=NULL;
1083 }
1084 if (info->files)
1085 lavrec_close_files_on_error(info);
1086 lavrec_msg(LAVREC_MSG_ERROR, info,
1087 "Error re-queuing buffer: %s", strerror(errno));
1088 lavrec_change_state(info, LAVREC_STATE_STOP);
1089 pthread_exit(0);
1090 }
1091 /* Mark the capture buffer as once again as in progress for capture */
1092 settings->buffer_valid[current_frame] = -1;
1093 #endif
1094 /* hack for BTTV-0.8 - give it a status that tells us to queue it in another thread */
1095 settings->buffer_valid[current_frame] = -2;
1096
1097 if (!lavrec_handle_audio(info, &(timestamp[current_frame])))
1098 lavrec_change_state(info, LAVREC_STATE_STOP);
1099
1100 /* Mark this frame as having completed compression and writing,
1101 * signal any encoders waiting for this completion so they can write
1102 * out their own results, and release lock.
1103 */
1104 settings->buffer_completed[current_frame] = 1;
1105 pthread_cond_broadcast(&(settings->buffer_completion[current_frame]));
1106
1107 current_frame = (current_frame+w_info->num_encoders)%settings->softreq.frames;
1108 pthread_cleanup_pop(1);
1109 }
1110
1111 if( buffer != NULL )
1112 {
1113 free( buffer );
1114 buffer=NULL;
1115 }
1116 pthread_exit(NULL);
1117 return(NULL);
1118 }
1119
get_size_offset(int fd,size_t * length,off_t * offset,unsigned int frame)1120 int get_size_offset( int fd, size_t *length, off_t *offset, unsigned int frame )
1121 {
1122 struct v4l2_buffer buf;
1123 int retval;
1124
1125 buf.index=frame;
1126 buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
1127 retval=ioctl( fd, VIDIOC_QUERYBUF, &buf );
1128 if( retval != 0 )
1129 return retval;
1130
1131 *length=buf.length;
1132 *offset=buf.m.offset;
1133 return 0;
1134 }
1135
set_format_part1(int fd,uint16_t width,uint16_t height)1136 int set_format_part1( int fd, uint16_t width, uint16_t height )
1137 {
1138 struct v4l2_format format;
1139 int retval;
1140
1141 memset( &format, 0, sizeof( format ) );
1142
1143 format.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
1144 retval=ioctl( fd, VIDIOC_G_FMT, &format );
1145 if( retval != 0 )
1146 return retval;
1147
1148 format.fmt.pix.width=width;
1149 format.fmt.pix.height=height;
1150 format.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
1151 format.fmt.pix.field=V4L2_FIELD_ANY;
1152 format.fmt.pix.bytesperline=0;
1153 retval=ioctl( fd, VIDIOC_S_FMT, &format );
1154 if( retval != 0 )
1155 return retval;
1156
1157 return 0;
1158 }
1159
set_format_part2(int fd,unsigned int frame)1160 int set_format_part2( int fd, unsigned int frame )
1161 {
1162 struct v4l2_buffer buf;
1163 int retval;
1164 enum v4l2_buf_type captype=V4L2_BUF_TYPE_VIDEO_CAPTURE;
1165
1166 memset( &buf, 0, sizeof( buf ) );
1167 buf.index=frame;
1168 buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
1169 retval=ioctl( fd, VIDIOC_QUERYBUF, &buf );
1170 if( retval != 0 )
1171 return retval;
1172
1173 retval=ioctl(fd, VIDIOC_QBUF, &buf);
1174 if( retval != 0 )
1175 return retval;
1176
1177 retval=ioctl( fd, VIDIOC_STREAMON, &captype );
1178 if( retval != 0 )
1179 return retval;
1180
1181 return 0;
1182 }
1183
1184 /******************************************************
1185 * lavrec_software_init()
1186 * Some software-MJPEG encoding specific initialization
1187 *
1188 * return value: 1 on success, 0 on error
1189 ******************************************************/
1190
lavrec_software_init(lavrec_t * info)1191 static int lavrec_software_init(lavrec_t *info)
1192 {
1193 struct video_capability vc;
1194 int i;
1195 video_capture_setup *settings = (video_capture_setup *)info->settings;
1196
1197 if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0)
1198 {
1199 lavrec_msg(LAVREC_MSG_ERROR, info,
1200 "Error getting device capabilities: %s", strerror(errno));
1201 return 0;
1202 }
1203 /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */
1204 /*if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720;*/
1205
1206 /* set some "subcapture" options - cropping is done later on (during capture) */
1207 if(!info->geometry->w)
1208 info->geometry->w = ((vc.maxwidth==720&&info->horizontal_decimation!=1)?704:vc.maxwidth)/4;
1209 if(!info->geometry->h)
1210 info->geometry->h = (info->video_norm==1 ? 480 : 576)/4;
1211
1212 if (info->geometry->w > vc.maxwidth)
1213 {
1214 lavrec_msg(LAVREC_MSG_ERROR, info,
1215 "Image width (%d) bigger than maximum (%d)!",
1216 info->geometry->w, vc.maxwidth);
1217 return 0;
1218 }
1219 if ((info->geometry->w%16)!=0)
1220 {
1221 lavrec_msg(LAVREC_MSG_ERROR, info,
1222 "Image width (%d) not multiple of 16 (required for JPEG encoding)!",
1223 info->geometry->w);
1224 return 0;
1225 }
1226 if (info->geometry->h > (info->video_norm==1 ? 480 : 576))
1227 {
1228 lavrec_msg(LAVREC_MSG_ERROR, info,
1229 "Image height (%d) bigger than maximum (%d)!",
1230 info->geometry->h, (info->video_norm==1 ? 480 : 576));
1231 return 0;
1232 }
1233
1234 /* RJ: Image height must only be a multiple of 8, but geom_height
1235 * is double the field height
1236 */
1237 if ((info->geometry->h%16)!=0)
1238 {
1239 lavrec_msg(LAVREC_MSG_ERROR, info,
1240 "Image height (%d) not multiple of 16 (required for JPEG encoding)!",
1241 info->geometry->h);
1242 return 0;
1243 }
1244
1245 settings->mm.width = settings->width = info->geometry->w;
1246 settings->mm.height = settings->height = info->geometry->h;
1247 settings->mm.format = VIDEO_PALETTE_YUV422P;
1248
1249 if (info->geometry->h > (info->video_norm==1?320:384))
1250 settings->interlaced = Y4M_ILACE_TOP_FIRST; /* all interlaced BT8x8 capture seems top-first ?? */
1251 else
1252 settings->interlaced = Y4M_ILACE_NONE;
1253
1254 lavrec_msg(LAVREC_MSG_INFO, info,
1255 "Image size will be %dx%d, %d field(s) per buffer",
1256 info->geometry->w, info->geometry->h,
1257 (settings->interlaced == Y4M_ILACE_NONE)?1:2);
1258
1259 /* request buffer info */
1260 if (ioctl(settings->video_fd, VIDIOCGMBUF, &(settings->softreq)) < 0)
1261 {
1262 lavrec_msg(LAVREC_MSG_ERROR, info,
1263 "Error getting buffer information: %s", strerror(errno));
1264 return 0;
1265 }
1266 if (settings->softreq.frames < MIN_QUEUES_NEEDED)
1267 {
1268 lavrec_msg(LAVREC_MSG_ERROR, info,
1269 "We need at least %d buffers, but we only got %d",
1270 MIN_QUEUES_NEEDED, settings->softreq.frames);
1271 return 0;
1272 }
1273 lavrec_msg(LAVREC_MSG_INFO, info,
1274 "Got %d YUV-buffers of size %d KB", settings->softreq.frames,
1275 settings->softreq.size/(1024*settings->softreq.frames));
1276
1277 if( info->software_encoding == 2 )
1278 {
1279 int loop;
1280 size_t size;
1281 off_t offset;
1282 settings->YUVP_convert=(struct YUVP_convert *) malloc( settings->softreq.frames * sizeof( struct YUVP_convert ) );
1283 if( settings->YUVP_convert == NULL )
1284 {
1285 lavrec_msg (LAVREC_MSG_ERROR, info,
1286 "Malloc error, you\'re probably out of memory");
1287 return 0;
1288 }
1289 settings->YUVP_convert[0].YUVP_buff=(unsigned char *) malloc( settings->mm.width * settings->mm.height * 2 * settings->softreq.frames );
1290 if( settings->YUVP_convert[0].YUVP_buff == NULL )
1291 {
1292 lavrec_msg (LAVREC_MSG_ERROR, info,
1293 "Malloc error for temp buffers, you\'re probably out of memory");
1294 free( settings->YUVP_convert );
1295 return 0;
1296 }
1297
1298 for( loop=1; loop < settings->softreq.frames; loop++ )
1299 settings->YUVP_convert[loop].YUVP_buff=settings->YUVP_convert[0].YUVP_buff + (loop * settings->mm.width * settings->mm.height * 2);
1300
1301 if( set_format_part1( settings->video_fd, settings->mm.width, settings->mm.height ) )
1302 {
1303 free( settings->YUVP_convert[0].YUVP_buff );
1304 free( settings->YUVP_convert );
1305 lavrec_msg( LAVREC_MSG_ERROR, info, "ioctl error on set_format_part1.\n" );
1306 return 0;
1307 }
1308
1309 for( loop=0; loop < settings->softreq.frames; loop++ )
1310 {
1311 if( get_size_offset( settings->video_fd, &size, &offset, loop ) )
1312 {
1313 lavrec_msg( LAVREC_MSG_ERROR, info, "Can't get mmap settings" );
1314 free( settings->YUVP_convert[0].YUVP_buff );
1315 free( settings->YUVP_convert );
1316 return 0;
1317 }
1318 settings->YUVP_convert[loop].mmap=mmap( 0, size, PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd,
1319 offset );
1320 if( settings->YUVP_convert[loop].mmap == NULL )
1321 {
1322 lavrec_msg (LAVREC_MSG_ERROR, info,
1323 "Packed YUV mmap error");
1324 free( settings->YUVP_convert[0].YUVP_buff );
1325 free( settings->YUVP_convert );
1326 return 0;
1327 }
1328 }
1329
1330 settings->YUV_buff=(uint8_t *) malloc( settings->softreq.size * info->num_encoders );
1331 if( settings->YUV_buff == NULL )
1332 {
1333 free( settings->YUVP_convert[0].YUVP_buff );
1334 free( settings->YUVP_convert );
1335 lavrec_msg( LAVREC_MSG_ERROR, info, "malloc error on YUV_buff.\n" );
1336 return 0;
1337 }
1338 }
1339 else
1340 {
1341 settings->YUVP_convert=NULL;
1342 /* Map the buffers */
1343 settings->YUV_buff = mmap(0, settings->softreq.size,
1344 PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, 0);
1345 if (settings->YUV_buff == MAP_FAILED)
1346 {
1347 lavrec_msg(LAVREC_MSG_ERROR, info,
1348 "Error mapping video buffers: %s", strerror(errno));
1349 return 0;
1350 }
1351 }
1352
1353 /* set up buffers for software encoding thread */
1354 if (info->MJPG_numbufs > MJPEG_MAX_BUF)
1355 {
1356 lavrec_msg(LAVREC_MSG_ERROR, info,
1357 "Too many buffers (%d) requested, maximum is %d",
1358 info->MJPG_numbufs, MJPEG_MAX_BUF);
1359 return 0;
1360 }
1361
1362 /* Check number of JPEG compression worker threads is consistent with
1363 * with the number of buffers available
1364 */
1365 if (info->num_encoders > info->MJPG_numbufs-1 )
1366 {
1367 lavrec_msg(LAVREC_MSG_ERROR, info,
1368 "More encoding workers (%d) than number of buffers-1 (%d)",
1369 info->num_encoders,
1370 info->MJPG_numbufs-1);
1371 return 0;
1372 }
1373 settings->breq.count = info->MJPG_numbufs;
1374 settings->breq.size = info->MJPG_bufsize*1024;
1375 settings->MJPG_buff = (uint8_t *) malloc(sizeof(uint8_t)*settings->breq.size*settings->breq.count);
1376 if (!settings->MJPG_buff)
1377 {
1378 if( settings->YUVP_convert )
1379 {
1380 free( settings->YUVP_convert[0].YUVP_buff );
1381 free( settings->YUVP_convert );
1382 }
1383 lavrec_msg (LAVREC_MSG_ERROR, info,
1384 "Malloc error, you\'re probably out of memory");
1385 return 0;
1386 }
1387 lavrec_msg(LAVREC_MSG_INFO, info,
1388 "Created %ld MJPEG-buffers of size %ld KB",
1389 settings->breq.count, settings->breq.size/1024);
1390
1391 /* set up software JPEG-encoding thread */
1392 pthread_mutex_init(&(settings->encoding_mutex), NULL);
1393 for (i=0;i<MJPEG_MAX_BUF;i++)
1394 {
1395 pthread_cond_init(&(settings->buffer_filled[i]), NULL);
1396 pthread_cond_init(&(settings->buffer_completion[i]), NULL);
1397 }
1398
1399 /* queue setup */
1400 pthread_mutex_init(&(settings->queue_mutex), NULL);
1401 pthread_cond_init(&(settings->queue_wait), NULL);
1402
1403 return 1;
1404 }
1405
1406
1407 /******************************************************
1408 * lavrec_hardware_init()
1409 * Some hardware-MJPEG encoding specific initialization
1410 *
1411 * return value: 1 on success, 0 on error
1412 ******************************************************/
1413
lavrec_hardware_init(lavrec_t * info)1414 static int lavrec_hardware_init(lavrec_t *info)
1415 {
1416 struct video_capability vc;
1417 struct mjpeg_params bparm;
1418
1419 video_capture_setup *settings = (video_capture_setup *)info->settings;
1420
1421 if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0)
1422 {
1423 lavrec_msg(LAVREC_MSG_ERROR, info,
1424 "Error getting device capabilities: %s", strerror(errno));
1425 return 0;
1426 }
1427 /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */
1428 if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720;
1429
1430 /* Query and set params for capture */
1431 if (ioctl(settings->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
1432 {
1433 lavrec_msg(LAVREC_MSG_ERROR, info,
1434 "Error getting video parameters: %s", strerror(errno));
1435 return 0;
1436 }
1437 bparm.input = info->video_src;
1438 bparm.norm = info->video_norm;
1439 bparm.quality = info->quality;
1440
1441 /* Set decimation and image geometry params - only if we have weird options */
1442 if (info->geometry->x != VALUE_NOT_FILLED ||
1443 info->geometry->y != VALUE_NOT_FILLED ||
1444 (info->geometry->h != 0 && info->geometry->h != (info->video_norm==1 ? 480 : 576)) ||
1445 (info->geometry->w != 0 && info->geometry->w != vc.maxwidth) ||
1446 info->horizontal_decimation != info->vertical_decimation)
1447 {
1448 bparm.decimation = 0;
1449 if(!info->geometry->w) info->geometry->w = ((vc.maxwidth==720&&info->horizontal_decimation!=1)?704:vc.maxwidth);
1450 if(!info->geometry->h) info->geometry->h = info->video_norm==1 ? 480 : 576;
1451 bparm.HorDcm = info->horizontal_decimation;
1452 bparm.VerDcm = (info->vertical_decimation==4) ? 2 : 1;
1453 bparm.TmpDcm = (info->vertical_decimation==1) ? 1 : 2;
1454 bparm.field_per_buff = (info->vertical_decimation==1) ? 2 : 1;
1455
1456 bparm.img_width = info->geometry->w;
1457 bparm.img_height = info->geometry->h/2;
1458
1459 if (info->geometry->x != VALUE_NOT_FILLED)
1460 bparm.img_x = info->geometry->x;
1461 else
1462 bparm.img_x = (vc.maxwidth - bparm.img_width)/2;
1463
1464 if (info->geometry->y != VALUE_NOT_FILLED)
1465 bparm.img_y = info->geometry->y/2;
1466 else
1467 bparm.img_y = ( (info->video_norm==1 ? 240 : 288) - bparm.img_height)/2;
1468
1469 if (info->geometry->w + bparm.img_x > vc.maxwidth)
1470 {
1471 lavrec_msg(LAVREC_MSG_ERROR, info,
1472 "Image width+offset (%d) bigger than maximum (%d)!",
1473 info->geometry->w + bparm.img_x, vc.maxwidth);
1474 return 0;
1475 }
1476 if ((info->geometry->w%(bparm.HorDcm*16))!=0)
1477 {
1478 lavrec_msg(LAVREC_MSG_ERROR, info,
1479 "Image width (%d) not multiple of %d (required for JPEG)!",
1480 info->geometry->w, bparm.HorDcm*16);
1481 return 0;
1482 }
1483 if (info->geometry->h + bparm.img_y > (info->video_norm==1 ? 480 : 576))
1484 {
1485 lavrec_msg(LAVREC_MSG_ERROR, info,
1486 "Image height+offset (%d) bigger than maximum (%d)!",
1487 info->geometry->h + info->geometry->y,
1488 (info->video_norm==1 ? 480 : 576));
1489 return 0;
1490 }
1491
1492 /* RJ: Image height must only be a multiple of 8, but geom_height
1493 * is double the field height
1494 */
1495 if ((info->geometry->h%(bparm.VerDcm*16))!=0)
1496 {
1497 lavrec_msg(LAVREC_MSG_ERROR, info,
1498 "Image height (%d) not multiple of %d (required for JPEG)!",
1499 info->geometry->h, bparm.VerDcm*16);
1500 return 0;
1501 }
1502
1503 }
1504 else
1505 {
1506 bparm.decimation = info->horizontal_decimation;
1507 }
1508
1509 /* Care about field polarity and APP Markers which are needed for AVI
1510 * and Quicktime and may be for other video formats as well
1511 */
1512 if(info->vertical_decimation > 1)
1513 {
1514 /* for vertical decimation > 1 no known video format needs app markers,
1515 * we need also not to care about field polarity
1516 */
1517 bparm.APP_len = 0; /* No markers */
1518 }
1519 else
1520 {
1521 int n;
1522 bparm.APPn = lav_query_APP_marker(info->video_format);
1523 bparm.APP_len = lav_query_APP_length(info->video_format);
1524
1525 /* There seems to be some confusion about what is the even and odd field ... */
1526 /* madmac: 20010810: According to Ronald, this is wrong - changed now to EVEN */
1527 bparm.odd_even = lav_query_polarity(info->video_format) == Y4M_ILACE_TOP_FIRST;
1528 for(n=0; n<bparm.APP_len && n<60; n++) bparm.APP_data[n] = 0;
1529 }
1530
1531 if (ioctl(settings->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)
1532 {
1533 lavrec_msg(LAVREC_MSG_ERROR, info,
1534 "Error setting video parameters: %s", strerror(errno));
1535 return 0;
1536 }
1537
1538 settings->width = bparm.img_width/bparm.HorDcm;
1539 settings->height = bparm.img_height/bparm.VerDcm*bparm.field_per_buff;
1540 settings->interlaced = (bparm.field_per_buff>1);
1541
1542 lavrec_msg(LAVREC_MSG_INFO, info,
1543 "Image size will be %dx%d, %d field(s) per buffer",
1544 settings->width, settings->height, bparm.field_per_buff);
1545
1546 /* Request buffers */
1547 settings->breq.count = info->MJPG_numbufs;
1548 settings->breq.size = info->MJPG_bufsize*1024;
1549 if (ioctl(settings->video_fd, MJPIOC_REQBUFS,&(settings->breq)) < 0)
1550 {
1551 lavrec_msg(LAVREC_MSG_ERROR, info,
1552 "Error requesting video buffers: %s", strerror(errno));
1553 return 0;
1554 }
1555 lavrec_msg(LAVREC_MSG_INFO, info,
1556 "Got %ld buffers of size %ld KB", settings->breq.count, settings->breq.size/1024);
1557
1558 /* Map the buffers */
1559 settings->MJPG_buff = mmap(0, settings->breq.count*settings->breq.size,
1560 PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, 0);
1561 if (settings->MJPG_buff == MAP_FAILED)
1562 {
1563 lavrec_msg(LAVREC_MSG_ERROR, info,
1564 "Error mapping video buffers: %s", strerror(errno));
1565 return 0;
1566 }
1567
1568 return 1;
1569 }
1570
1571
1572 /******************************************************
1573 * lavrec_init()
1574 * initialize, open devices and start streaming
1575 *
1576 * return value: 1 on success, 0 on error
1577 ******************************************************/
1578
lavrec_init(lavrec_t * info)1579 static int lavrec_init(lavrec_t *info)
1580 {
1581 struct video_channel vch;
1582
1583 video_capture_setup *settings = (video_capture_setup *)info->settings;
1584
1585 /* are there files to capture to? */
1586 if (info->files) /* yes */
1587 {
1588 /*
1589 * If NO filesize limit was specifically given then allow unlimited size.
1590 * ODML extensions will handle the AVI files and Quicktime has had 64bit
1591 * filesizes for a long time
1592 */
1593 if (info->max_file_size_mb < 0)
1594 info->max_file_size_mb = MAX_MBYTES_PER_FILE_64;
1595 lavrec_msg(LAVREC_MSG_DEBUG, info,
1596 "Maximum size per file will be %d MB", info->max_file_size_mb);
1597
1598 if (info->video_captured || info->audio_captured)
1599 {
1600 lavrec_msg(LAVREC_MSG_DEBUG, info,
1601 "Custom audio-/video-capture functions are being ignored for file-capture");
1602 }
1603 }
1604 else /* no, so we need the custom actions */
1605 {
1606 if (!info->video_captured || (!info->audio_captured && info->audio_size))
1607 {
1608 lavrec_msg(LAVREC_MSG_ERROR, info,
1609 "No video files or custom video-/audio-capture functions given");
1610 return 0;
1611 }
1612 }
1613
1614 /* Special settings for single frame captures */
1615 if(info->single_frame)
1616 info->MJPG_numbufs = 4;
1617
1618 /* time lapse/single frame captures don't want audio */
1619 if((info->time_lapse > 1 || info->single_frame) && info->audio_size)
1620 {
1621 lavrec_msg(LAVREC_MSG_DEBUG, info,
1622 "Time lapse or single frame capture mode - audio disabled");
1623 info->audio_size = 0;
1624 }
1625
1626 /* set the sound mixer */
1627 if (info->audio_size && info->audio_level >= 0)
1628 lavrec_set_mixer(info, 1);
1629
1630 /* Initialize the audio system if audio is wanted.
1631 * This involves a fork of the audio task and is done before
1632 * the video device and the output file is opened
1633 */
1634 settings->audio_bps = 0;
1635 if (info->audio_size)
1636 {
1637 if (audio_init(1,info->use_read, info->stereo,info->audio_size,info->audio_rate))
1638 {
1639 lavrec_set_mixer(info, 0);
1640 lavrec_msg(LAVREC_MSG_ERROR, info,
1641 "Error initializing Audio: %s",audio_strerror());
1642 return 0;
1643 }
1644 settings->audio_bps = info->audio_size / 8;
1645 if (info->stereo) settings->audio_bps *= 2;
1646 settings->audio_buffer_size = audio_get_buffer_size();
1647 }
1648
1649 /* back to normal user - only root needed during audio setup */
1650 if (getuid() != geteuid())
1651 {
1652 if (setuid(getuid()) < 0)
1653 {
1654 lavrec_msg(LAVREC_MSG_ERROR, info,
1655 "Failed to set effective user-ID: %s",
1656 strerror(errno));
1657 return 0;
1658 }
1659 }
1660
1661 /* open the video device */
1662 settings->video_fd = open(info->video_dev, O_RDWR);
1663 if (settings->video_fd < 0)
1664 {
1665 lavrec_msg(LAVREC_MSG_ERROR, info,
1666 "Error opening video-device (%s): %s",
1667 info->video_dev, strerror(errno));
1668 return 0;
1669 }
1670
1671 /* we might have to autodetect the video-src/norm */
1672 if (lavrec_autodetect_signal(info) == 0)
1673 return 0;
1674
1675 if (info->software_encoding && info->video_src == -1)
1676 vch.channel = 0;
1677 else
1678 vch.channel = info->video_src;
1679 vch.norm = info->video_norm;
1680 if (info->video_norm != 3 && info->video_src != -1)
1681 {
1682 if (ioctl(settings->video_fd, VIDIOCSCHAN, &vch) < 0)
1683 {
1684 lavrec_msg(LAVREC_MSG_ERROR, info,
1685 "Error setting channel: %s", strerror(errno));
1686 return 0;
1687 }
1688 }
1689 if (ioctl(settings->video_fd, VIDIOCGCHAN, &vch) < 0)
1690 {
1691 lavrec_msg(LAVREC_MSG_ERROR, info,
1692 "Error getting channel info: %s", strerror(errno));
1693 return 0;
1694 }
1695 settings->has_audio = (vch.flags & VIDEO_VC_AUDIO);
1696 info->video_norm = vch.norm; /* the final norm */
1697
1698 /* set channel if we're tuning */
1699 if (vch.flags & VIDEO_VC_TUNER && info->tuner_frequency)
1700 {
1701 unsigned long outfreq;
1702 outfreq = info->tuner_frequency*16/1000;
1703 if (ioctl(settings->video_fd, VIDIOCSFREQ, &outfreq) < 0)
1704 {
1705 lavrec_msg(LAVREC_MSG_ERROR, info,
1706 "Error setting tuner frequency: %s", strerror(errno));
1707 return 0;
1708 }
1709 }
1710
1711 /* Set up tuner audio if this is a tuner. I think this should be done
1712 * AFTER the tuner device is selected
1713 */
1714 if (settings->has_audio)
1715 {
1716 struct video_audio vau;
1717
1718 /* get current */
1719 if (ioctl(settings->video_fd,VIDIOCGAUDIO, &vau) < 0)
1720 {
1721 lavrec_msg(LAVREC_MSG_ERROR, info,
1722 "Error getting tuner audio params: %s", strerror(errno));
1723 return 0;
1724 }
1725 /* unmute so we get sound to record
1726 * this is done without checking current state because the
1727 * current mga driver doesn't report mute state accurately
1728 */
1729 lavrec_msg(LAVREC_MSG_INFO, info, "Unmuting tuner audio...");
1730 vau.flags &= (~VIDEO_AUDIO_MUTE);
1731 if (ioctl(settings->video_fd,VIDIOCSAUDIO, &vau) < 0)
1732 {
1733 lavrec_msg(LAVREC_MSG_INFO, info,
1734 "Error setting tuner audio params: %s", strerror(errno));
1735 return 0;
1736 }
1737 }
1738
1739 /* set state to paused... ugly, but we need it for the software thread */
1740 settings->state = LAVREC_STATE_PAUSED;
1741
1742 /* set up some hardware/software-specific stuff */
1743 if (info->software_encoding)
1744 {
1745 if (!lavrec_software_init(info)) return 0;
1746 }
1747 else
1748 {
1749 if (!lavrec_hardware_init(info)) return 0;
1750 }
1751
1752 /* Try to get a reliable timestamp for Audio */
1753 if (info->audio_size && info->sync_correction > 1)
1754 {
1755 int n,res;
1756
1757 lavrec_msg(LAVREC_MSG_INFO, info, "Getting audio ...");
1758
1759 for(n=0;;n++)
1760 {
1761 if(n > NUM_AUDIO_TRIES)
1762 {
1763 lavrec_msg(LAVREC_MSG_ERROR, info,
1764 "Unable to get audio - exiting ....");
1765 return 0;
1766 }
1767 res = audio_read((unsigned char*)settings->AUDIO_buff,AUDIO_BUFFER_SIZE,0,
1768 &(settings->audio_t0),&(settings->astat));
1769 if (res < 0)
1770 {
1771 lavrec_msg(LAVREC_MSG_ERROR, info,
1772 "Error reading audio: %s",audio_strerror());
1773 return 0;
1774 }
1775 if(res && settings->audio_t0.tv_sec ) break;
1776 usleep(20000);
1777 }
1778 }
1779
1780 /* If we can increase process priority ... no need for R/T though...
1781 * This is mainly useful for running using "at" which otherwise drops the
1782 * priority which causes sporadic audio buffer over-runs
1783 */
1784 if( getpriority(PRIO_PROCESS, 0) > -5 )
1785 setpriority(PRIO_PROCESS, 0, -5 );
1786
1787 /* Seconds per video frame: */
1788 settings->spvf = (info->video_norm==VIDEO_MODE_NTSC) ? 1001./30000. : 0.040;
1789 settings->sync_lim = settings->spvf*1.5;
1790
1791 /* Seconds per audio sample: */
1792 if(info->audio_size)
1793 settings->spas = 1.0/info->audio_rate;
1794 else
1795 settings->spas = 0.;
1796
1797 return 1;
1798 }
1799
1800
1801 /******************************************************
1802 * lavrec_wait_for_start()
1803 * catch audio until we have to stop or record
1804 ******************************************************/
1805
lavrec_wait_for_start(lavrec_t * info)1806 static void lavrec_wait_for_start(lavrec_t *info)
1807 {
1808 int res;
1809
1810 video_capture_setup *settings = (video_capture_setup *)info->settings;
1811
1812 while(settings->state == LAVREC_STATE_PAUSED)
1813 {
1814 usleep(10000);
1815
1816 /* Audio (if on) is allready running, empty buffer to avoid overflow */
1817 if (info->audio_size)
1818 {
1819 while( (res=audio_read((unsigned char*)settings->AUDIO_buff,AUDIO_BUFFER_SIZE,
1820 0,&settings->audio_t0,&settings->astat)) >0 ) /*noop*/;
1821 if(res==0) continue;
1822 if(res<0)
1823 {
1824 lavrec_msg(LAVREC_MSG_ERROR, info,
1825 "Error reading audio: %s", audio_strerror());
1826 lavrec_change_state(info, LAVREC_STATE_STOP); /* stop */
1827 return;
1828 }
1829 }
1830 }
1831 }
1832
1833
1834 /******************************************************
1835 * lavrec_queue_buffer()
1836 * queues a buffer (either MJPEG or YUV)
1837 *
1838 * return value: 1 on success, 0 on error
1839 ******************************************************/
1840
lavrec_queue_buffer(lavrec_t * info,unsigned long * num)1841 static int lavrec_queue_buffer(lavrec_t *info, unsigned long *num)
1842 {
1843 video_capture_setup *settings = (video_capture_setup *)info->settings;
1844
1845 lavrec_msg(LAVREC_MSG_DEBUG, info,
1846 "Queueing frame %lu", *num);
1847 if (info->software_encoding)
1848 {
1849 settings->mm.frame = *num;
1850 pthread_mutex_lock(&(settings->queue_mutex));
1851 if (settings->is_queued[*num] < 0)
1852 {
1853 pthread_mutex_unlock(&(settings->queue_mutex));
1854 return 1;
1855 }
1856 pthread_mutex_unlock(&(settings->queue_mutex));
1857
1858 if( info->software_encoding == 2 )
1859 {
1860 if( set_format_part2( settings->video_fd, *num ) )
1861 return 0;
1862 }
1863 else
1864 {
1865 if (ioctl(settings->video_fd, VIDIOCMCAPTURE, &(settings->mm)) < 0)
1866 return 0;
1867 }
1868
1869 pthread_mutex_lock(&(settings->queue_mutex));
1870 settings->queue_left++;
1871 settings->is_queued[*num] = 1;
1872 settings->buffers_queued++;
1873 pthread_cond_broadcast(&(settings->queue_wait));
1874 pthread_mutex_unlock(&(settings->queue_mutex));
1875 }
1876 else
1877 {
1878 if (ioctl(settings->video_fd, MJPIOC_QBUF_CAPT, num) < 0)
1879 return 0;
1880 }
1881
1882 return 1;
1883 }
1884
1885
1886 /******************************************************
1887 * lavrec_software_sync_thread ()
1888 * software syncing to get correct timestamps
1889 ******************************************************/
1890
lavrec_software_sync_thread(void * arg)1891 static void *lavrec_software_sync_thread(void* arg)
1892 {
1893 lavrec_t *info = (lavrec_t *) arg;
1894 video_capture_setup *settings = (video_capture_setup *)info->settings;
1895 int frame = 0; /* framenum to sync on */
1896 #if 1
1897 unsigned long qframe, i;
1898 #endif
1899
1900 /* Allow easy shutting down by other processes... */
1901 /* PTHREAD_CANCEL_ASYNCHRONOUS is evil
1902 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
1903 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
1904 */
1905 /* FIXME: is the right? Or can we just stop.
1906 * Don't allow cancellation. We need to shutdown in an orderly
1907 * fashion (by noticing that settings->state has changed, to make
1908 * sure we dequeue all queued buffers.
1909 */
1910 pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL );
1911
1912 while (1)
1913 {
1914 /* evil hack for BTTV-0.8 - we need to queue frames here */
1915 /* this cycle is non-onbligatory - we just queue frames as they become available,
1916 * below, we'll wait for queues if we don't have enough of them */
1917 for (i=0;i<settings->softreq.frames;i++)
1918 {
1919 qframe = settings->buffers_queued % settings->softreq.frames;
1920 if (settings->buffer_valid[qframe] == -2)
1921 {
1922 if (!lavrec_queue_buffer(info, &qframe))
1923 {
1924 pthread_mutex_lock(&(settings->software_sync_mutex));
1925 settings->software_sync_ready[qframe] = -1;
1926 pthread_cond_broadcast(&(settings->software_sync_wait[qframe]));
1927 pthread_mutex_unlock(&(settings->software_sync_mutex));
1928 lavrec_msg(LAVREC_MSG_ERROR, info,
1929 "Error re-queueing a buffer (%lu): %s", qframe, strerror(errno));
1930 lavrec_change_state(info, LAVREC_STATE_STOP);
1931 pthread_exit(0);
1932 }
1933 settings->buffer_valid[qframe] = -1;
1934 }
1935 else
1936 break;
1937 }
1938
1939 pthread_mutex_lock(&(settings->encoding_mutex));
1940 while (settings->queue_left < MIN_QUEUES_NEEDED)
1941 {
1942 if (settings->is_queued[frame] <= 0 ||
1943 settings->please_stop_syncing)
1944 break; /* sync on all remaining frames */
1945 #if 0
1946 lavrec_msg(LAVREC_MSG_DEBUG, info,
1947 "Software sync thread: sleeping for new queues (%d)", frame);
1948 pthread_cond_wait(&(settings->queue_wait),
1949 &(settings->queue_mutex));
1950 #else
1951 /* sleep for new buffers to be completed encoding. After that,
1952 * requeue them so we have more than MIN_QUEUES_NEEDED buffers
1953 * free */
1954 qframe = settings->buffers_queued % settings->softreq.frames;
1955 lavrec_msg(LAVREC_MSG_DEBUG, info,
1956 "Software sync thread: sleeping for new queues (%lu) to become available", qframe);
1957 while (settings->buffer_valid[qframe] != -2)
1958 {
1959 pthread_cond_wait(&(settings->buffer_completion[qframe]),
1960 &(settings->encoding_mutex));
1961 if (settings->please_stop_syncing) {
1962 pthread_mutex_unlock(&(settings->encoding_mutex));
1963 pthread_exit(0);
1964 }
1965 }
1966 if (!lavrec_queue_buffer(info, &qframe))
1967 {
1968 pthread_mutex_unlock(&(settings->encoding_mutex));
1969 pthread_mutex_lock(&(settings->software_sync_mutex));
1970 settings->software_sync_ready[qframe] = -1;
1971 pthread_cond_broadcast(&(settings->software_sync_wait[qframe]));
1972 pthread_mutex_unlock(&(settings->software_sync_mutex));
1973 lavrec_msg(LAVREC_MSG_ERROR, info,
1974 "Error re-queueing a buffer (%lu): %s", qframe, strerror(errno));
1975 lavrec_change_state(info, LAVREC_STATE_STOP);
1976 pthread_exit(0);
1977 }
1978 settings->buffer_valid[qframe] = -1;
1979 #endif
1980 }
1981
1982 if (!settings->queue_left)
1983 {
1984 lavrec_msg(LAVREC_MSG_DEBUG, info,
1985 "Software sync thread stopped");
1986 pthread_mutex_unlock(&settings->encoding_mutex);
1987 pthread_exit(NULL);
1988 }
1989 pthread_mutex_unlock(&settings->encoding_mutex);
1990
1991 retry:
1992 if (ioctl(settings->video_fd, VIDIOCSYNC, &frame) < 0)
1993 {
1994 if( errno==EINTR && info->software_encoding )
1995 goto retry; /* BTTV sync got interrupted */
1996 pthread_mutex_lock(&(settings->software_sync_mutex));
1997 settings->software_sync_ready[frame] = -1;
1998 pthread_cond_broadcast(&(settings->software_sync_wait[frame]));
1999 pthread_mutex_unlock(&(settings->software_sync_mutex));
2000 lavrec_msg(LAVREC_MSG_ERROR, info,
2001 "Error syncing on a buffer: %s", strerror(errno));
2002 lavrec_change_state(info, LAVREC_STATE_STOP);
2003 pthread_exit(0);
2004 }
2005 else
2006 {
2007 pthread_mutex_lock(&(settings->software_sync_mutex));
2008 gettimeofday(&(settings->software_sync_timestamp[frame]), NULL);
2009 settings->software_sync_ready[frame] = 1;
2010 pthread_cond_broadcast(&(settings->software_sync_wait[frame]));
2011 pthread_mutex_unlock(&(settings->software_sync_mutex));
2012 }
2013
2014 pthread_mutex_lock(&(settings->queue_mutex));
2015 settings->queue_left--;
2016 settings->is_queued[frame] = 0;
2017 pthread_mutex_unlock(&(settings->queue_mutex));
2018
2019 frame = (frame+1)%settings->softreq.frames;
2020 }
2021 return NULL;
2022 }
2023
2024
2025 /******************************************************
2026 * lavrec_sync_buffer()
2027 * sync on a buffer (either MJPIOC_SYNC or VIDIOCSYNC)
2028 *
2029 * return value: 1 on success, 0 on error
2030 ******************************************************/
2031
lavrec_sync_buffer(lavrec_t * info,struct mjpeg_sync * bsync)2032 static int lavrec_sync_buffer(lavrec_t *info, struct mjpeg_sync *bsync)
2033 {
2034 video_capture_setup *settings = (video_capture_setup *)info->settings;
2035
2036 if (info->software_encoding)
2037 {
2038 bsync->frame = (bsync->frame+1)%settings->softreq.frames;
2039 bsync->seq++;
2040 pthread_mutex_lock(&(settings->software_sync_mutex));
2041 while (settings->software_sync_ready[bsync->frame] == 0)
2042 {
2043 lavrec_msg(LAVREC_MSG_DEBUG, info,
2044 "Software sync client: sleeping for new frames (waiting for frame %ld)",
2045 bsync->frame);
2046 pthread_cond_wait(&(settings->software_sync_wait[bsync->frame]),
2047 &(settings->software_sync_mutex));
2048 }
2049 pthread_mutex_unlock(&(settings->software_sync_mutex));
2050 if (settings->software_sync_ready[bsync->frame] < 0)
2051 {
2052 return 0;
2053 }
2054 memcpy(&(bsync->timestamp), &(settings->software_sync_timestamp[bsync->frame]),
2055 sizeof(struct timeval));
2056 settings->software_sync_ready[bsync->frame] = 0;
2057 }
2058 else
2059 {
2060 if (ioctl(settings->video_fd, MJPIOC_SYNC, bsync) < 0)
2061 {
2062 return 0;
2063 }
2064 }
2065 lavrec_msg(LAVREC_MSG_DEBUG, info,
2066 "Syncing on frame %ld", bsync->frame);
2067
2068 return 1;
2069 }
2070
2071
2072 /******************************************************
2073 * lavrec_handle_audio()
2074 * handle audio and output stats
2075 *
2076 * return value: 1 on success, 0 on error
2077 ******************************************************/
2078
lavrec_handle_audio(lavrec_t * info,struct timeval * timestamp)2079 static int lavrec_handle_audio(lavrec_t *info, struct timeval *timestamp)
2080 {
2081 int x;
2082 int nerr = 0;
2083 video_capture_setup *settings = (video_capture_setup *)info->settings;
2084 video_capture_stats *stats = settings->stats;
2085
2086 while (info->audio_size)
2087 {
2088 /* Only try to read a audio sample if video is ahead - else we might
2089 * get into difficulties when writing the last samples
2090 */
2091 if (settings->output_status < 3 &&
2092 stats->num_frames * settings->spvf <
2093 (stats->num_asamps + settings->audio_buffer_size /
2094 settings->audio_bps) * settings->spas)
2095 break;
2096
2097 x = audio_read((unsigned char*)settings->AUDIO_buff, sizeof(settings->AUDIO_buff),
2098 0, &(settings->audio_tmstmp), &(settings->astat));
2099
2100 if (x == 0) break;
2101 if (x < 0)
2102 {
2103 lavrec_msg(LAVREC_MSG_ERROR, info,
2104 "Error reading audio: %s", audio_strerror());
2105 if (info->files)
2106 lavrec_close_files_on_error(info);
2107 nerr++;
2108 break;
2109 }
2110
2111 if (!(settings->astat))
2112 {
2113 stats->num_aerr++;
2114 stats->stats_changed = 1;
2115 }
2116
2117 /* Adjust for difference at start */
2118 if (settings->audio_offset >= x)
2119 {
2120 settings->audio_offset -= x;
2121 continue;
2122 }
2123 x -= settings->audio_offset;
2124
2125 /* Got an audio sample, write it out */
2126 if (audio_captured(info, settings->AUDIO_buff+settings->audio_offset,
2127 x/settings->audio_bps) != 1)
2128 {
2129 nerr++;
2130 break; /* Done or error occured */
2131 }
2132 settings->audio_offset = 0;
2133
2134 /* calculate time differences beetween audio and video
2135 * tdiff1 is the difference according to the number of frames/samples written
2136 * tdiff2 is the difference according to the timestamps
2137 * (only if audio timestamp is not zero)
2138 */
2139 if(settings->audio_tmstmp.tv_sec)
2140 {
2141 stats->tdiff1 = stats->num_frames * settings->spvf - stats->num_asamps * settings->spas;
2142 stats->tdiff2 = (timestamp->tv_sec - settings->audio_tmstmp.tv_sec)
2143 + (timestamp->tv_usec - settings->audio_tmstmp.tv_usec) * 1.e-6;
2144 }
2145 }
2146
2147 /* output_statistics */
2148 if (info->output_statistics) info->output_statistics(stats);
2149 stats->stats_changed = 0;
2150
2151 stats->prev_sync = stats->cur_sync;
2152
2153 if (nerr) return 0;
2154 return 1;
2155 }
2156
2157
2158 /******************************************************
2159 * lavrec_record()
2160 * record and process video and audio
2161 ******************************************************/
2162
lavrec_record(lavrec_t * info)2163 static void lavrec_record(lavrec_t *info)
2164 {
2165 unsigned long frame_cnt;
2166 int x, write_frame, nerr, nfout;
2167 video_capture_stats stats;
2168 unsigned int first_lost;
2169 double time;
2170 struct timeval first_time;
2171
2172 video_capture_setup *settings = (video_capture_setup *)info->settings;
2173 settings->stats = &stats;
2174 settings->queue_left = 0;
2175
2176 /* basically, this could be done on init, but we need to
2177 * reset some variables when going from pause to play and
2178 * the other way around, so we need to restart it when we
2179 * enter he playing state
2180 */
2181 if (info->software_encoding)
2182 {
2183 for (x=0;x<MJPEG_MAX_BUF;x++)
2184 {
2185 settings->is_queued[x] = 0;
2186 settings->buffer_valid[x] = -1; /* 0 means to just omit the frame, -1 means "in progress",
2187 -2 is an evil hack for BTTV-0.8 */
2188 settings->buffer_completed[x] = 1; /* 1 means compression and writing completed,
2189 0 means in progress */
2190 }
2191 settings->buffers_queued = 0;
2192
2193 if( !(settings->encoders = malloc(info->num_encoders * sizeof(encoder_info_t))) )
2194 {
2195 lavrec_msg (LAVREC_MSG_ERROR, info,
2196 "Malloc error, you\'re probably out of memory");
2197 return;
2198 }
2199 for (x=0; x < info->num_encoders; ++x )
2200 {
2201 settings->encoders[x].info = info;
2202 settings->encoders[x].encoder_id = x;
2203 settings->encoders[x].num_encoders = info->num_encoders;
2204
2205 if ( pthread_create( &(settings->encoders[x].thread), NULL,
2206 lavrec_encoding_thread, (void *) &settings->encoders[x] ) )
2207 {
2208 lavrec_msg(LAVREC_MSG_ERROR, info,
2209 "Failed to create software encoding thread");
2210 lavrec_change_state(info, LAVREC_STATE_STOP);
2211 return;
2212 }
2213 }
2214 lavrec_msg(LAVREC_MSG_INFO, info,
2215 "Created %d software JPEG-encoding process(es)\n",
2216 info->num_encoders);
2217 settings->audio_offset = 0;
2218 }
2219
2220 /* Queue all buffers, this also starts streaming capture */
2221 for (frame_cnt=0;
2222 frame_cnt<(info->software_encoding?settings->softreq.frames:settings->breq.count);
2223 frame_cnt++)
2224 {
2225 if (!lavrec_queue_buffer(info, &frame_cnt))
2226 {
2227 lavrec_msg(LAVREC_MSG_ERROR, info,
2228 "Error queuing buffers: %s", strerror(errno));
2229 lavrec_change_state(info, LAVREC_STATE_STOP);
2230 return;
2231 }
2232 }
2233
2234 /* if we're doing software-encoding, start up the software-sync thread */
2235 if (info->software_encoding)
2236 {
2237 pthread_mutex_init(&(settings->software_sync_mutex), NULL);
2238 for (x=0;x<MJPEG_MAX_BUF;x++)
2239 {
2240 settings->software_sync_ready[x] = 0;
2241 pthread_cond_init(&(settings->software_sync_wait[x]), NULL);
2242 }
2243 settings->please_stop_syncing = 0;
2244
2245 if ( pthread_create( &(settings->software_sync_thread), NULL,
2246 lavrec_software_sync_thread, (void *) info ) )
2247 {
2248 lavrec_msg(LAVREC_MSG_ERROR, info,
2249 "Failed to create software sync thread");
2250 lavrec_change_state(info, LAVREC_STATE_STOP);
2251 }
2252 }
2253
2254 /* reset the counter(s) */
2255 nerr = 0;
2256 write_frame = 1;
2257 first_lost = 0;
2258 stats.stats_changed = 0;
2259 stats.num_syncs = 0;
2260 stats.num_lost = 0;
2261 stats.num_frames = 0;
2262 stats.num_asamps = 0;
2263 stats.num_ins = 0;
2264 stats.num_del = 0;
2265 stats.num_aerr = 0;
2266 stats.tdiff1 = 0.;
2267 stats.tdiff2 = 0.;
2268 if (info->software_encoding);
2269 settings->bsync.frame = -1;
2270 gettimeofday( &(stats.prev_sync), NULL );
2271
2272 /* The video capture loop */
2273 while (settings->state == LAVREC_STATE_RECORDING)
2274 {
2275 /* sync on a frame */
2276 if (!lavrec_sync_buffer(info, &(settings->bsync)))
2277 {
2278 if (info->files)
2279 lavrec_close_files_on_error(info);
2280 lavrec_msg(LAVREC_MSG_ERROR, info,
2281 "Error syncing on a buffer: %s", strerror(errno));
2282 nerr++;
2283 }
2284 stats.num_syncs++;
2285
2286 gettimeofday( &(stats.cur_sync), NULL );
2287 if(stats.num_syncs==1)
2288 {
2289 first_time = settings->bsync.timestamp;
2290 first_lost = settings->bsync.seq;
2291 if(info->audio_size && info->sync_correction > 1)
2292 {
2293 /* Get time difference beetween audio and video in bytes */
2294 settings->audio_offset = ((first_time.tv_usec-settings->audio_t0.tv_usec)*1.e-6 +
2295 first_time.tv_sec-settings->audio_t0.tv_sec - settings->spvf)*info->audio_rate;
2296 settings->audio_offset *= settings->audio_bps; /* convert to bytes */
2297 }
2298 else
2299 settings->audio_offset = 0;
2300 }
2301
2302 time = settings->bsync.timestamp.tv_sec - first_time.tv_sec
2303 + 1.e-6*(settings->bsync.timestamp.tv_usec - first_time.tv_usec)
2304 + settings->spvf; /* for first frame */
2305
2306
2307 /* Should we write a frame? */
2308 if(info->single_frame)
2309 {
2310 lavrec_change_state_if(info, LAVREC_STATE_PAUSED, LAVREC_STATE_RECORDING);
2311 write_frame = 1;
2312 nfout = 1; /* always output frame only once */
2313 }
2314 else if(info->time_lapse > 1)
2315 {
2316
2317 write_frame = (stats.num_syncs % info->time_lapse) == 0;
2318 nfout = 1; /* always output frame only once */
2319
2320 }
2321 else /* normal capture */
2322 {
2323
2324 nfout = 1;
2325 frame_cnt = settings->bsync.seq - stats.num_syncs - first_lost + 1; /* total lost frames */
2326 if (info->sync_correction > 0)
2327 nfout += frame_cnt - stats.num_lost; /* lost since last sync */
2328 stats.stats_changed = (stats.num_lost != frame_cnt);
2329 stats.num_lost = frame_cnt;
2330
2331 /* Check if we have to insert/delete frames to stay in sync */
2332 if (info->sync_correction > 1)
2333 {
2334 if( stats.tdiff1 - stats.tdiff2 < -settings->sync_lim)
2335 {
2336 nfout++;
2337 stats.num_ins++;
2338 stats.stats_changed = 1;
2339 stats.tdiff1 += settings->spvf;
2340 }
2341 if( stats.tdiff1 - stats.tdiff2 > settings->sync_lim)
2342 {
2343 nfout--;
2344 stats.num_del++;
2345 stats.stats_changed = 1;
2346 stats.tdiff1 -= settings->spvf;
2347 }
2348 }
2349 }
2350
2351 /* write it out */
2352 if (info->software_encoding)
2353 {
2354 pthread_mutex_lock(&(settings->encoding_mutex));
2355 settings->buffer_valid[settings->bsync.frame] = write_frame?nfout:0;
2356 settings->buffer_completed[settings->bsync.frame] = 0;
2357 pthread_cond_broadcast(&(settings->buffer_filled[settings->bsync.frame]));
2358 pthread_mutex_unlock(&(settings->encoding_mutex));
2359 }
2360 else if(write_frame && nfout > 0)
2361 {
2362 if (video_captured(info,
2363 settings->MJPG_buff+settings->bsync.frame*settings->breq.size,
2364 settings->bsync.length, nfout) != 1)
2365 nerr++; /* Done or error occured */
2366
2367 /* Re-queue the buffer */
2368 if (!lavrec_queue_buffer(info, &(settings->bsync.frame)))
2369 {
2370 if (info->files)
2371 lavrec_close_files_on_error(info);
2372 lavrec_msg(LAVREC_MSG_ERROR, info,
2373 "Error re-queuing buffer: %s", strerror(errno));
2374 nerr++;
2375 }
2376
2377 if (!lavrec_handle_audio(info, &(settings->bsync.timestamp)))
2378 nerr++;
2379 }
2380
2381 /* if (nerr++) we need to stop and quit */
2382 if (nerr) lavrec_change_state(info, LAVREC_STATE_STOP);
2383 }
2384
2385 if (info->software_encoding)
2386 {
2387 pthread_mutex_lock(&settings->encoding_mutex);
2388 settings->please_stop_syncing = 1; /* Ask the software sync thread to stop */
2389 for (x=0;x<settings->softreq.frames;x++)
2390 pthread_cond_broadcast(&settings->buffer_completion[x]);
2391 pthread_mutex_unlock(&settings->encoding_mutex);
2392
2393 for (x = 0; x < info->num_encoders; x++)
2394 {
2395 lavrec_msg(LAVREC_MSG_DEBUG, info,
2396 "Joining encoding thread %d", x);
2397 pthread_cancel( settings->encoders[x].thread );
2398 pthread_join( settings->encoders[x].thread, NULL );
2399 }
2400 free(settings->encoders);
2401
2402 lavrec_msg(LAVREC_MSG_DEBUG, info,
2403 "Joining software sync thread");
2404 pthread_join(settings->software_sync_thread, NULL);
2405
2406 for (x=0;x<MJPEG_MAX_BUF;x++)
2407 {
2408 pthread_cond_destroy(&(settings->software_sync_wait[x]));
2409 }
2410 pthread_mutex_destroy(&(settings->software_sync_mutex));
2411 }
2412 else
2413 {
2414 /* cancel all queued buffers (now this is much nicer!) */
2415 x = -1;
2416 if (ioctl(settings->video_fd, MJPIOC_QBUF_CAPT, &x) < 0)
2417 {
2418 lavrec_msg(LAVREC_MSG_ERROR, info,
2419 "Error resetting buffer-queue: %s", strerror(errno));
2420 }
2421 }
2422 }
2423
2424
2425 /******************************************************
2426 * lavrec_recording_cycle()
2427 * the main cycle for recording video
2428 ******************************************************/
2429
lavrec_recording_cycle(lavrec_t * info)2430 static void lavrec_recording_cycle(lavrec_t *info)
2431 {
2432 video_capture_setup *settings = (video_capture_setup *)info->settings;
2433
2434 while (1)
2435 {
2436 if (settings->state == LAVREC_STATE_PAUSED)
2437 lavrec_wait_for_start(info);
2438 else if (settings->state == LAVREC_STATE_RECORDING)
2439 lavrec_record(info);
2440 else
2441 break;
2442 }
2443 }
2444
2445
2446 /******************************************************
2447 * lavrec_capture_thread()
2448 * the video/audio capture thread
2449 ******************************************************/
2450
lavrec_capture_thread(void * arg)2451 static void *lavrec_capture_thread(void *arg)
2452 {
2453 lavrec_t *info = (lavrec_t*)arg;
2454 video_capture_setup *settings = (video_capture_setup *)info->settings;
2455
2456 lavrec_recording_cycle(info);
2457
2458 /* shutdown video/audio and close */
2459 if (info->audio_size)
2460 audio_shutdown();
2461
2462 /* certainty for all :-) */
2463 if (settings->video_file)
2464 {
2465 lav_close(settings->video_file);
2466 settings->video_file = NULL;
2467 }
2468 if (settings->video_file_old)
2469 {
2470 lav_close(settings->video_file_old);
2471 settings->video_file_old = NULL;
2472 }
2473
2474 /* reset mixer */
2475 if (info->audio_size)
2476 lavrec_set_mixer(info, 0);
2477
2478 /* Re-mute tuner audio if this is a tuner */
2479 if (settings->has_audio) {
2480 struct video_audio vau;
2481
2482 lavrec_msg(LAVREC_MSG_INFO, info,
2483 "Re-muting tuner audio...");
2484 vau.flags |= VIDEO_AUDIO_MUTE;
2485 if (ioctl(settings->video_fd,VIDIOCSAUDIO,&vau) < 0)
2486 {
2487 lavrec_msg(LAVREC_MSG_ERROR, info,
2488 "Error resetting tuner audio params: %s", strerror(errno));
2489 }
2490 }
2491
2492 /* and at last, we need to get rid of the video device */
2493 close(settings->video_fd);
2494
2495 /* just to be sure */
2496 if (settings->state != LAVREC_STATE_STOP)
2497 lavrec_change_state(info, LAVREC_STATE_STOP);
2498
2499 pthread_exit(NULL);
2500 return NULL;
2501 }
2502
2503
2504 /******************************************************
2505 * lavrec_malloc()
2506 * malloc a pointer and set default options
2507 *
2508 * return value: a pointer to lavrec_t or NULL
2509 ******************************************************/
2510
lavrec_malloc(void)2511 lavrec_t *lavrec_malloc(void)
2512 {
2513 lavrec_t *info;
2514 video_capture_setup * settings;
2515
2516 info = (lavrec_t *)malloc(sizeof(lavrec_t));
2517 if (!info)
2518 {
2519 lavrec_msg (LAVREC_MSG_ERROR, NULL,
2520 "Malloc error, you\'re probably out of memory");
2521 return NULL;
2522 }
2523
2524 /* let's set some default values now */
2525 info->video_format = '\0';
2526 info->video_norm = 3;
2527 info->video_src = -1;
2528 info->software_encoding = 0;
2529 info->num_encoders = 0; /* this should be set to the number of processors */
2530 info->horizontal_decimation = 4;
2531 info->vertical_decimation = 4;
2532 info->geometry = (rect *)malloc(sizeof(rect));
2533 if (!(info->geometry))
2534 {
2535 lavrec_msg (LAVREC_MSG_ERROR, NULL,
2536 "Malloc error, you\'re probably out of memory");
2537 return NULL;
2538 }
2539 info->geometry->x = VALUE_NOT_FILLED;
2540 info->geometry->y = VALUE_NOT_FILLED;
2541 info->geometry->w = 0;
2542 info->geometry->h = 0;
2543 info->quality = 50;
2544 info->record_time = -1;
2545 info->tuner_frequency = 0;
2546 info->video_dev = "/dev/video";
2547
2548 info->audio_size = 16;
2549 info->audio_rate = 44100;
2550 info->stereo = 0;
2551 info->audio_level = -1;
2552 info->mute = 0;
2553 info->audio_src = 'l';
2554 info->use_read = 0;
2555 info->audio_dev = "/dev/dsp";
2556 info->mixer_dev = "/dev/mixer";
2557
2558 info->single_frame = 0;
2559 info->time_lapse = 1;
2560 info->sync_correction = 2;
2561 info->MJPG_numbufs = 64;
2562 info->MJPG_bufsize = 256;
2563
2564 info->files = NULL;
2565 info->num_files = 0;
2566 info->flush_count = 60;
2567 info->output_statistics = NULL;
2568 info->audio_captured = NULL;
2569 info->video_captured = NULL;
2570 info->msg_callback = NULL;
2571 info->state_changed = NULL;
2572 info->max_file_size_mb = -1; /*(0x4000000>>20);*/ /* Safety first ;-) */
2573 info->settings = (void *)malloc(sizeof(video_capture_setup));
2574 if (!(info->settings))
2575 {
2576 lavrec_msg (LAVREC_MSG_ERROR, NULL,
2577 "Malloc error, you\'re probably out of memory");
2578 return NULL;
2579 }
2580
2581 settings = (video_capture_setup*)(info->settings);
2582
2583 pthread_mutex_init(&settings->state_mutex, 0);
2584 settings->state = LAVREC_STATE_STOP;
2585 settings->output_status = 0;
2586 settings->video_file = NULL;
2587 settings->video_file_old = NULL;
2588
2589 return info;
2590 }
2591
2592
2593 /******************************************************
2594 * lavrec_main()
2595 * the whole video-capture cycle
2596 *
2597 * Basic setup:
2598 * * this function initializes the devices,
2599 * sets up the whole thing and then forks
2600 * the main task and returns control to the
2601 * main app. It can then start recording by
2602 * calling lavrec_start():
2603 *
2604 * 1) setup/initialize/open devices (state: STOP)
2605 * 2) wait for lavrec_start() (state: PAUSE)
2606 * 3) record (state: RECORD)
2607 * 4) stop/deinitialize/close (state: STOP)
2608 *
2609 * * it should be possible to switch from RECORD
2610 * to PAUSE and the other way around. When
2611 * STOP, we stop and close the devices, so
2612 * then you need to re-call this function.
2613 *
2614 * return value: 1 on succes, 0 on error
2615 ******************************************************/
2616
lavrec_main(lavrec_t * info)2617 int lavrec_main(lavrec_t *info)
2618 {
2619 video_capture_setup *settings = (video_capture_setup *)info->settings;
2620
2621 int ret;
2622 struct sched_param schedparam;
2623
2624 /* Flush the Linux File buffers to disk */
2625 sync();
2626
2627 /* start with initing */
2628 if (!lavrec_init(info))
2629 return 0;
2630
2631 /* Now we're ready to go move to Real-time scheduling... */
2632 schedparam.sched_priority = 1;
2633 if(setpriority(PRIO_PROCESS, 0, -15)) { /* Give myself maximum priority */
2634 lavrec_msg(LAVREC_MSG_WARNING, info,
2635 "Unable to set negative priority for main thread");
2636 }
2637 if( (ret = pthread_setschedparam( pthread_self(), SCHED_FIFO, &schedparam ) ) ) {
2638 lavrec_msg(LAVREC_MSG_WARNING, info,
2639 "Pthread Real-time scheduling for main thread could not be enabled");
2640 }
2641
2642 /* now, set state to pause and catch audio until started */
2643 /* lavrec_change_state(info, LAVREC_STATE_PAUSED); */
2644 settings->state = LAVREC_STATE_PAUSED;
2645
2646 /* fork ourselves to return control to the main app */
2647 if( pthread_create( &(settings->capture_thread), NULL,
2648 lavrec_capture_thread, (void*)info) )
2649 {
2650 lavrec_msg(LAVREC_MSG_ERROR, info,
2651 "Failed to create thread");
2652 return 0;
2653 }
2654
2655 return 1;
2656 }
2657
2658
2659 /******************************************************
2660 * lavrec_start()
2661 * start recording (only call when ready!)
2662 *
2663 * return value: 1 on succes, 0 on error
2664 ******************************************************/
2665
lavrec_start(lavrec_t * info)2666 int lavrec_start(lavrec_t *info)
2667 {
2668 video_capture_setup *settings = (video_capture_setup *)info->settings;
2669
2670 if (!lavrec_change_state_if(info, LAVREC_STATE_RECORDING, LAVREC_STATE_PAUSED))
2671 {
2672 lavrec_msg(LAVREC_MSG_WARNING, info,
2673 "Not ready for capture (state = %d)!", settings->state);
2674 return 0;
2675 }
2676
2677 return 1;
2678 }
2679
2680
2681 /******************************************************
2682 * lavrec_pause()
2683 * pause recording (you can call play to continue)
2684 *
2685 * return value: 1 on succes, 0 on error
2686 ******************************************************/
2687
lavrec_pause(lavrec_t * info)2688 int lavrec_pause(lavrec_t *info)
2689 {
2690 if (!lavrec_change_state_if(info, LAVREC_STATE_PAUSED, LAVREC_STATE_RECORDING))
2691 {
2692 lavrec_msg(LAVREC_MSG_WARNING, info,
2693 "Not recording!");
2694 return 0;
2695 }
2696 return 1;
2697 }
2698
2699
2700 /******************************************************
2701 * lavrec_stop()
2702 * stop recording
2703 *
2704 * return value: 1 on succes, 0 on error
2705 ******************************************************/
2706
lavrec_stop(lavrec_t * info)2707 int lavrec_stop(lavrec_t *info)
2708 {
2709 video_capture_setup *settings = (video_capture_setup *)info->settings;
2710
2711 int okay = lavrec_change_state_if(info, LAVREC_STATE_STOP, LAVREC_STATE_RECORDING)
2712 || lavrec_change_state_if(info, LAVREC_STATE_STOP, LAVREC_STATE_PAUSED);
2713
2714 if (!okay)
2715 {
2716 lavrec_msg(LAVREC_MSG_DEBUG, info,
2717 "We weren't even initialized!");
2718 lavrec_change_state(info, LAVREC_STATE_STOP);
2719 return 0;
2720 }
2721
2722 lavrec_change_state(info, LAVREC_STATE_STOP);
2723
2724 pthread_join( settings->capture_thread, NULL );
2725
2726 return 1;
2727 }
2728
2729
2730 /******************************************************
2731 * lavrec_free()
2732 * free() the struct
2733 *
2734 * return value: 1 on succes, 0 on error
2735 ******************************************************/
2736
lavrec_free(lavrec_t * info)2737 int lavrec_free(lavrec_t *info)
2738 {
2739 video_capture_setup *settings = (video_capture_setup *)info->settings;
2740
2741 if (settings->state != LAVREC_STATE_STOP)
2742 {
2743 lavrec_msg(LAVREC_MSG_WARNING, info,
2744 "We're not stopped yet, use lavrec_stop() first!");
2745 return 0;
2746 }
2747
2748 pthread_mutex_destroy(&settings->state_mutex);
2749 free(settings);
2750 free(info->geometry);
2751 free(info);
2752 return 1;
2753 }
2754
2755
2756 /******************************************************
2757 * lavrec_busy()
2758 * Wait until capturing is finished
2759 ******************************************************/
2760
lavrec_busy(lavrec_t * info)2761 void lavrec_busy(lavrec_t *info)
2762 {
2763 pthread_join( ((video_capture_setup*)(info->settings))->capture_thread, NULL);
2764 }
2765