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