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 + -
显示快捷键?