liblavrec.c

来自「Motion JPEG编解码器源代码」· C语言 代码 · 共 1,916 行 · 第 1/5 页

C
1,916
字号
      lavrec_msg(LAVREC_MSG_ERROR, info,         "More encoding workers (%d) than number of buffers-1 (%d)",         info->num_encoders,         info->MJPG_numbufs-1);      return 0;   }   settings->breq.count = info->MJPG_numbufs;   settings->breq.size = info->MJPG_bufsize*1024;   settings->MJPG_buff = (uint8_t *) malloc(sizeof(uint8_t)*settings->breq.size*settings->breq.count);   if (!settings->MJPG_buff)   {      lavrec_msg (LAVREC_MSG_ERROR, info,         "Malloc error, you\'re probably out of memory");      return 0;   }   lavrec_msg(LAVREC_MSG_INFO, info,      "Created %ld MJPEG-buffers of size %ld KB",      settings->breq.count, settings->breq.size/1024);   /* set up software JPEG-encoding thread */   pthread_mutex_init(&(settings->encoding_mutex), NULL);   for (i=0;i<MJPEG_MAX_BUF;i++)   {      pthread_cond_init(&(settings->buffer_filled[i]), NULL);      pthread_cond_init(&(settings->buffer_completion[i]), NULL);   }   /* queue setup */   pthread_mutex_init(&(settings->queue_mutex), NULL);   pthread_cond_init(&(settings->queue_wait), NULL);   return 1;}/****************************************************** * lavrec_hardware_init() *   Some hardware-MJPEG encoding specific initialization * * return value: 1 on success, 0 on error ******************************************************/static int lavrec_hardware_init(lavrec_t *info){   struct video_capability vc;   struct mjpeg_params bparm;   video_capture_setup *settings = (video_capture_setup *)info->settings;   if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error getting device capabilities: %s", strerror(errno));      return 0;   }   /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */   if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720;   /* Query and set params for capture */   if (ioctl(settings->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error getting video parameters: %s", strerror(errno));      return 0;   }   bparm.input = info->video_src;   bparm.norm = info->video_norm;   bparm.quality = info->quality;   /* Set decimation and image geometry params - only if we have weird options */   if (info->geometry->x != VALUE_NOT_FILLED ||      info->geometry->y != VALUE_NOT_FILLED ||      (info->geometry->h != 0 && info->geometry->h != info->video_norm==1 ? 480 : 576) ||      (info->geometry->w != 0 && info->geometry->w != vc.maxwidth) ||      info->horizontal_decimation != info->vertical_decimation)   {      bparm.decimation = 0;      if(!info->geometry->w) info->geometry->w = ((vc.maxwidth==720&&info->horizontal_decimation!=1)?704:vc.maxwidth);      if(!info->geometry->h) info->geometry->h = info->video_norm==1 ? 480 : 576;      bparm.HorDcm = info->horizontal_decimation;      bparm.VerDcm = (info->vertical_decimation==4) ? 2 : 1;      bparm.TmpDcm = (info->vertical_decimation==1) ? 1 : 2;      bparm.field_per_buff = (info->vertical_decimation==1) ? 2 : 1;      bparm.img_width  = info->geometry->w;      bparm.img_height = info->geometry->h/2;      if (info->geometry->x != VALUE_NOT_FILLED)         bparm.img_x = info->geometry->x;      else         bparm.img_x = (vc.maxwidth - bparm.img_width)/2;      if (info->geometry->y != VALUE_NOT_FILLED)         bparm.img_y = info->geometry->y/2;      else         bparm.img_y = ( (info->video_norm==1 ? 240 : 288) - bparm.img_height)/2;      if (info->geometry->w + bparm.img_x > vc.maxwidth)      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Image width+offset (%d) bigger than maximum (%d)!",            info->geometry->w + bparm.img_x, vc.maxwidth);         return 0;      }      if ((info->geometry->w%(bparm.HorDcm*16))!=0)       {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Image width (%d) not multiple of %d (required for JPEG)!",            info->geometry->w, bparm.HorDcm*16);         return 0;      }      if (info->geometry->h + bparm.img_y > (info->video_norm==1 ? 480 : 576))       {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Image height+offset (%d) bigger than maximum (%d)!",            info->geometry->h + info->geometry->y,            (info->video_norm==1 ? 480 : 576));         return 0;      }      /* RJ: Image height must only be a multiple of 8, but geom_height       * is double the field height       */      if ((info->geometry->h%(bparm.VerDcm*16))!=0)       {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Image height (%d) not multiple of %d (required for JPEG)!",            info->geometry->h, bparm.VerDcm*16);         return 0;      }   }   else   {      bparm.decimation = info->horizontal_decimation;   }   /* Care about field polarity and APP Markers which are needed for AVI    * and Quicktime and may be for other video formats as well    */   if(info->vertical_decimation > 1)   {      /* for vertical decimation > 1 no known video format needs app markers,       * we need also not to care about field polarity       */      bparm.APP_len = 0; /* No markers */   }   else   {      int n;      bparm.APPn = lav_query_APP_marker(info->video_format);      bparm.APP_len = lav_query_APP_length(info->video_format);      /* There seems to be some confusion about what is the even and odd field ... */      /* madmac: 20010810: According to Ronald, this is wrong - changed now to EVEN */      bparm.odd_even = lav_query_polarity(info->video_format) == LAV_INTER_TOP_FIRST;      for(n=0; n<bparm.APP_len && n<60; n++) bparm.APP_data[n] = 0;   }   if (ioctl(settings->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error setting video parameters: %s", strerror(errno));      return 0;   }   settings->width = bparm.img_width/bparm.HorDcm;   settings->height = bparm.img_height/bparm.VerDcm*bparm.field_per_buff;   settings->interlaced = (bparm.field_per_buff>1);   lavrec_msg(LAVREC_MSG_INFO, info,      "Image size will be %dx%d, %d field(s) per buffer",      settings->width, settings->height, bparm.field_per_buff);   /* Request buffers */   settings->breq.count = info->MJPG_numbufs;   settings->breq.size = info->MJPG_bufsize*1024;   if (ioctl(settings->video_fd, MJPIOC_REQBUFS,&(settings->breq)) < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error requesting video buffers: %s", strerror(errno));      return 0;   }   lavrec_msg(LAVREC_MSG_INFO, info,      "Got %ld buffers of size %ld KB", settings->breq.count, settings->breq.size/1024);   /* Map the buffers */   settings->MJPG_buff = mmap(0, settings->breq.count*settings->breq.size,       PROT_READ|PROT_WRITE, MAP_SHARED, settings->video_fd, 0);   if (settings->MJPG_buff == MAP_FAILED)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error mapping video buffers: %s", strerror(errno));      return 0;   }   return 1;}/****************************************************** * lavrec_init() *   initialize, open devices and start streaming * * return value: 1 on success, 0 on error ******************************************************/static int lavrec_init(lavrec_t *info){   struct video_channel vch;   video_capture_setup *settings = (video_capture_setup *)info->settings;   /* are there files to capture to? */   if (info->files) /* yes */   {      /* Handle the limitations of AVI that can only do MAX 2G Byte files */      if (info->max_file_size_mb < 0)      {         if( info->video_format == 'a' || info->video_format == 'A' )            info->max_file_size_mb = MAX_MBYTES_PER_FILE_32;         else            info->max_file_size_mb = MAX_MBYTES_PER_FILE;      }      lavrec_msg(LAVREC_MSG_DEBUG, info,         "Maximum size per file will be %d MB",         info->max_file_size_mb);      if (info->video_captured || info->audio_captured)      {         lavrec_msg(LAVREC_MSG_DEBUG, info,            "Custom audio-/video-capture functions are being ignored for file-capture");      }   }   else /* no, so we need the custom actions */   {      if (!info->video_captured || (!info->audio_captured && info->audio_size))      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "No video files or custom video-/audio-capture functions given");         return 0;      }   }   /* Special settings for single frame captures */   if(info->single_frame)      info->MJPG_numbufs = 4;   /* time lapse/single frame captures don't want audio */   if((info->time_lapse > 1 || info->single_frame) && info->audio_size)   {      lavrec_msg(LAVREC_MSG_DEBUG, info,         "Time lapse or single frame capture mode - audio disabled");      info->audio_size = 0;   }   /* set the sound mixer */   if (info->audio_size && info->audio_level >= 0)      lavrec_set_mixer(info, 1);   /* Initialize the audio system if audio is wanted.    * This involves a fork of the audio task and is done before    * the video device and the output file is opened    */   settings->audio_bps = 0;   if (info->audio_size)   {      if (audio_init(1,info->use_read, info->stereo,info->audio_size,info->audio_rate))      {         lavrec_set_mixer(info, 0);         lavrec_msg(LAVREC_MSG_ERROR, info,            "Error initializing Audio: %s",audio_strerror());         return 0;      }      settings->audio_bps = info->audio_size / 8;      if (info->stereo) settings->audio_bps *= 2;      settings->audio_buffer_size = audio_get_buffer_size();   }   /* back to normal user - only root needed during audio setup */   if (getuid() != geteuid())   {      if (setuid(getuid()) < 0)      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Failed to set effective user-ID: %s",            strerror(errno));         return 0;      }   }   /* open the video device */   settings->video_fd = open(info->video_dev, O_RDWR);   if (settings->video_fd < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error opening video-device (%s): %s",         info->video_dev, strerror(errno));      return 0;   }   /* we might have to autodetect the video-src/norm */   if (lavrec_autodetect_signal(info) == 0)      return 0;   if (info->software_encoding && info->video_src == 3)      vch.channel = 0;   else      vch.channel = info->video_src;   vch.norm = info->video_norm;   if (info->video_norm != 3 && info->video_src != 3)   {      if (ioctl(settings->video_fd, VIDIOCSCHAN, &vch) < 0)      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Error setting channel: %s", strerror(errno));         return 0;      }   }   if (ioctl(settings->video_fd, VIDIOCGCHAN, &vch) < 0)   {      lavrec_msg(LAVREC_MSG_ERROR, info,         "Error getting channel info: %s", strerror(errno));      return 0;   }   settings->has_audio = (vch.flags & VIDEO_VC_AUDIO);   info->video_norm = vch.norm; /* the final norm */   /* set channel if we're tuning */   if (vch.flags & VIDEO_VC_TUNER && info->tuner_frequency)   {      unsigned long outfreq;      outfreq = info->tuner_frequency*16/1000;      if (ioctl(settings->video_fd, VIDIOCSFREQ, &outfreq) < 0)      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Error setting tuner frequency: %s", strerror(errno));         return 0;      }   }   /* Set up tuner audio if this is a tuner. I think this should be done    * AFTER the tuner device is selected    */   if (settings->has_audio)    {      struct video_audio vau;      /* get current */      if (ioctl(settings->video_fd,VIDIOCGAUDIO, &vau) < 0)      {         lavrec_msg(LAVREC_MSG_ERROR, info,            "Error getting tuner audio params: %s", strerror(errno));         return 0;      }      /* unmute so we get sound to record       * this is done without checking current state because the       * current mga driver doesn't report mute state accurately       */      lavrec_msg(LAVREC_MSG_INFO, info, "Unmuting tuner audio...");      vau.flags &= (~VIDEO_AUDIO_MUTE);      if (ioctl(settings->video_fd,VIDIOCSAUDIO, &vau) < 0)      {         lavrec_msg(LAVREC_MSG_INFO, info,            "Error setting tuner audio params: %s", strerror(errno));         return 0;      }   }   /* set state to paused... ugly, but we need it for the software thread */   settings->state = LAVREC_STATE_PAUSED;   /* set up some hardware/software-specific stuff */   if (info->software_encoding)   {      if (!lavrec_software_init(info)) return 0;   }   else   {      if (!lavrec_hardware_init(info)) return 0;   }      /* Try to get a reliable timestamp for Audio */   if (info->audio_size && info->sync_correction > 1)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?