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, &current_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