liblavrec.c
来自「Motion JPEG编解码器源代码」· C语言 代码 · 共 1,916 行 · 第 1/5 页
C
1,916 行
if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &(settings->mixer_recsrc_saved)) == -1) nerr++; if (ioctl(fd, sound_mixer_write_input, &(settings->mixer_inplev_saved)) == -1) nerr++; if(info->mute) if (ioctl(fd, SOUND_MIXER_WRITE_VOLUME, &(settings->mixer_volume_saved)) == -1) nerr++; if (nerr) { lavrec_msg (LAVREC_MSG_WARNING, info, "Unable to restore sound mixer settings"); lavrec_msg (LAVREC_MSG_WARNING, info, "Restore your favorite setting with another tool"); } settings->mixer_set = 0; } close(fd); return 1;}/****************************************************** * lavrec_autodetect_signal() * (try to) autodetect signal/norm * * return value: 1 on success, 0 on error ******************************************************/static int lavrec_autodetect_signal(lavrec_t *info){ struct mjpeg_status bstat; int i; video_capture_setup *settings = (video_capture_setup *)info->settings; lavrec_msg(LAVREC_MSG_INFO, info, "Auto detecting input and norm ..."); if (info->software_encoding && (info->video_norm==3 || info->video_src==3)) { lavrec_msg(LAVREC_MSG_DEBUG, info, "Using current input signal settings for non-MJPEG card"); return 1; } if (info->video_src == 3) /* detect video_src && norm */ { int n = 0; for(i=0;i<2;i++) { lavrec_msg (LAVREC_MSG_INFO, info, "Trying %s ...", (i==2)?"TV tuner":(i==0?"Composite":"S-Video")); bstat.input = i; if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0) { lavrec_msg (LAVREC_MSG_ERROR, info, "Error getting video input status: %s", (const char*)strerror(errno)); return 0; } if (bstat.signal) { lavrec_msg (LAVREC_MSG_INFO, info, "Input present: %s %s", bstat.norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"), bstat.color?"color":"no color"); info->video_src = i; info->video_norm = bstat.norm; n++; } else { lavrec_msg (LAVREC_MSG_INFO, info, "No signal ion specified input"); } } switch(n) { case 0: lavrec_msg (LAVREC_MSG_ERROR, info, "No input signal ... exiting"); return 0; case 1: lavrec_msg (LAVREC_MSG_INFO, info, "Detected %s %s", info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM"), info->video_src==0?"Composite":(info->video_src==1?"S-Video":"TV tuner")); break; default: lavrec_msg (LAVREC_MSG_ERROR, info, "Input signal on more thn one input source... exiting"); return 0; } } else if (info->video_norm == 3) /* detect norm only */ { lavrec_msg (LAVREC_MSG_INFO, info, "Trying to detect norm for %s ...", (info->video_src==2) ? "TV tuner" : (info->video_src==0?"Composite":"S-Video")); bstat.input = info->video_src; if (ioctl(settings->video_fd,MJPIOC_G_STATUS,&bstat) < 0) { lavrec_msg (LAVREC_MSG_ERROR, info, "Error getting video input status: %s",strerror(errno)); return 0; } info->video_norm = bstat.norm; lavrec_msg (LAVREC_MSG_INFO, info, "Detected %s", info->video_norm==0? "PAL":(info->video_norm==1?"NTSC":"SECAM")); } return 1;}/****************************************************** * lavrec_get_free_space() * get the amount of free disk space * * return value: 1 on success, 0 on error ******************************************************/static uint64_t lavrec_get_free_space(video_capture_setup *settings){ uint64_t blocks_per_MB; struct statfs statfs_buf; uint64_t MBytes_fs_free; /* check the disk space again */ if (statfs(settings->stats->output_filename, &statfs_buf)) { /* some error happened */ MBytes_fs_free = MAX_MBYTES_PER_FILE; /* some fake value */ } else { blocks_per_MB = (1024*1024) / statfs_buf.f_bsize; MBytes_fs_free = statfs_buf.f_bavail/blocks_per_MB; } settings->bytes_last_checked = settings->bytes_output_cur; return MBytes_fs_free;}/****************************************************** * lavrec_close_files_on_error() * Close the output file(s) if an error occured. * We don't care about further errors. ******************************************************/ static void lavrec_close_files_on_error(lavrec_t *info){ video_capture_setup *settings = (video_capture_setup *)info->settings; if(settings->output_status > 0 && settings->video_file) { lav_close(settings->video_file); settings->video_file = NULL; } if(settings->output_status > 1 && settings->video_file_old) { lav_close(settings->video_file_old); settings->video_file_old = NULL; } lavrec_msg(LAVREC_MSG_WARNING, info, "Closing file(s) and exiting - " "output file(s) my not be readable due to error");}/****************************************************** * lavrec_output_video_frame() * outputs a video frame and does all the file handling * necessary like opening new files and closing old ones. * * return value: 1 on success, 0 on error ******************************************************/#define OUTPUT_VIDEO_ERROR_RETURN \if (settings->output_status==2) \{ \ settings->output_status = 3; \ return 1; \} \else \ return 0;static int lavrec_output_video_frame(lavrec_t *info, uint8_t *buff, long size, long count){ int n; int OpenNewFlag = 0; video_capture_setup *settings = (video_capture_setup *)info->settings; if(settings->output_status == 3) return 1; /* Only audio is still active */ /* Check space on filesystem if we have filled it up * or if we have written more than CHECK_INTERVAL bytes since last check */ if (settings->output_status > 0) { n = (settings->bytes_output_cur - settings->bytes_last_checked)>>20; /* in MBytes */ if( n > CHECK_INTERVAL || n > settings->MBytes_fs_free - MIN_MBYTES_FREE ) settings->MBytes_fs_free = lavrec_get_free_space(settings); } /* Check if it is time to exit */ if (settings->state == LAVREC_STATE_STOP) lavrec_msg(LAVREC_MSG_INFO, info, "Signal caught, stopping recording"); if (settings->stats->num_frames * settings->spvf > info->record_time && info->record_time >= 0) { lavrec_msg(LAVREC_MSG_INFO, info, "Recording time reached, stopping"); lavrec_change_state(info, LAVREC_STATE_STOP); } /* Check if we have to open a new output file */ if (settings->output_status > 0 && (settings->bytes_output_cur>>20) > info->max_file_size_mb) { lavrec_msg(LAVREC_MSG_INFO, info, "Max filesize reached, opening next output file"); OpenNewFlag = 1; } if( info->max_file_frames > 0 && settings->stats->num_frames % info->max_file_frames == 0) { lavrec_msg(LAVREC_MSG_INFO, info, "Max number of frames reached, opening next output file"); OpenNewFlag = 1; } if (settings->output_status > 0 && settings->MBytes_fs_free < MIN_MBYTES_FREE) { lavrec_msg(LAVREC_MSG_INFO, info, "File system is nearly full, trying to open next output file"); OpenNewFlag = 1; } /* JPEG = always open new file */ if (info->video_format == 'j') OpenNewFlag = 1; /* If a file is open and we should open a new one or exit, close current file */ if (settings->output_status > 0 && (OpenNewFlag || settings->state == LAVREC_STATE_STOP)) { if (info->audio_size) { /* Audio is running - flag that the old file should be closed */ if(settings->output_status != 1) { /* There happened something bad - the old output file from the * last file change is not closed. We try to close all files and exit */ lavrec_msg(LAVREC_MSG_ERROR, info, "Audio too far behind video. Check if audio works correctly!"); lavrec_close_files_on_error(info); return -1; } lavrec_msg(LAVREC_MSG_DEBUG, info, "Closing current output file for video, waiting for audio to be filled"); settings->video_file_old = settings->video_file; settings->video_file = NULL; settings->num_frames_old = settings->stats->num_frames; if (settings->state == LAVREC_STATE_STOP) { settings->output_status = 3; return 1; } else settings->output_status = 2; } else { if (settings->video_file) { if (lav_close(settings->video_file)) { settings->video_file = NULL; lavrec_msg(LAVREC_MSG_ERROR, info, "Error closing video output file %s, may be unuseable due to error", settings->stats->output_filename); return 0; } settings->video_file = NULL; } if (settings->state == LAVREC_STATE_STOP) return 0; } } /* Open new output file if needed */ if (settings->output_status==0 || OpenNewFlag ) { /* Get next filename */ if (info->num_files == 0) { sprintf(settings->stats->output_filename, info->files[0], ++settings->stats->current_output_file); } else { if (settings->stats->current_output_file >= info->num_files) { if (info->video_format == 'j') { settings->stats->current_output_file = 0; } else { lavrec_msg(LAVREC_MSG_WARNING, info, "Number of given output files reached"); OUTPUT_VIDEO_ERROR_RETURN; } } strncpy(settings->stats->output_filename, info->files[settings->stats->current_output_file++], sizeof(settings->stats->output_filename)); } lavrec_msg(LAVREC_MSG_INFO, info, "Opening output file %s", settings->stats->output_filename); /* Open next file */ settings->video_file = lav_open_output_file(settings->stats->output_filename, info->video_format, settings->width, settings->height, settings->interlaced, (info->video_norm==1? 30000.0/1001.0 : 25.0), info->audio_size, (info->stereo ? 2 : 1), info->audio_rate); if (!settings->video_file) { lavrec_msg(LAVREC_MSG_ERROR, info, "Error opening output file %s: %s", settings->stats->output_filename, lav_strerror()); OUTPUT_VIDEO_ERROR_RETURN; } if (settings->output_status == 0) settings->output_status = 1; /* Check space on filesystem. Exit if not enough space */ settings->bytes_output_cur = 0; settings->MBytes_fs_free = lavrec_get_free_space(settings); if(settings->MBytes_fs_free < MIN_MBYTES_FREE_OPEN) { lavrec_msg(LAVREC_MSG_ERROR, info, "Not enough space for opening new output file"); /* try to close and remove file, don't care about errors */ if (settings->video_file) { lav_close(settings->video_file); settings->video_file = NULL; remove(settings->stats->output_filename); } OUTPUT_VIDEO_ERROR_RETURN; } } /* Output the frame count times */ if (lav_write_frame(settings->video_file,buff,size,count)) { /* If an error happened, try to close output files and exit */ lavrec_msg(LAVREC_MSG_ERROR, info, "Error writing to output file %s: %s", settings->stats->output_filename, lav_strerror()); lavrec_close_files_on_error(info); return 0; } /* Update counters. Maybe frame its written only once, * but size*count is the save guess */ settings->bytes_output_cur += size*count; settings->stats->num_frames += count; /* * If the user has specified flushing of file buffers * flush every time the specified number of unflushed frames has * been reached. */ if( info->flush_count > 0 && settings->stats->num_frames % info->flush_count == 0)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?