📄 main.cc
字号:
end_program(1); } if (audio_mode) { if (!strcasecmp(audio_mode, "stereo")) { v4l->setAudioMode(VIDEO_SOUND_STEREO); soundchan = Stereo; //Stereo } else if (!strcasecmp(audio_mode, "mono")) { v4l->setAudioMode(VIDEO_SOUND_MONO); soundchan = Mono; //Mono } else { cerr << "Invalid audiomode given. Should be either 'stereo' " << "or 'mono'." << endl; end_program(1); } } else { v4l->setAudioMode(VIDEO_SOUND_MONO); soundchan = Mono; } v4l->setAudioMute(false); if (audio_bitrate == -1) audio_bitrate = 0; if (audio_bitrate) //mp3 compression, Khz+mono/stereo must have been set! { int tmprate = is_valid_audiobitrate(audio_bitrate, soundchan, soundfreq); if (tmprate < 0) { cerr << "Invalid mp3 bitrate given." << endl; list_audiobitrates(); end_program(1); } else if (samplesize == S8) { cerr << "8 Bit mp3 compression is not suported." << endl; end_program(1); } else if (soundfreq == F11) { cerr << "11 Khz mp3 compression is not supported." << endl; end_program(1); } else { ostringstream s; s << "Setting mp3 bitrate to " << tmprate; vcr_notice(s); audio_bitrate = tmprate; } } if (vertical_flip < 0) vertical_flip = 1; //default: flip image vertically if (!keyframes) keyframes = 15; if (keyframes < 1 || keyframes > 30) { cerr << "Keyframes out of range (range is 1..30, default 15)" << endl; end_program(1); } if (fps < 0) fps = 25.0; if (fps > 50.0 || fps < 1.0) { cerr << "Invalid framerate set (range: 1.0-50.0)" << endl; end_program(1); } if (!codec_name) { codec_name = (char*)malloc(80 * sizeof(char)); strcpy(codec_name, "DivX ;-) low-motion"); } if ((temp = is_valid_codec(codec_name)) < 0) { cerr << "Invalid codec name given!" << endl; list_codecs(); end_program(1); } else { ostringstream s; s << "Found codec ID: " << temp; vcr_notice(s); codecID = temp; } if (attributes_str) //attributes set in config file. { char **attrs = split_string(attributes_str); if (!attrs) { cerr << "Couldn't parse 'attributes' in config file." << endl; end_program(1); } int i = 0, success = 1; while (attrs[i]) { if (!add_attribute(attrs[i])) { success = 0; cerr << "Couldn't add codec attribute '" << attrs[i] << "' from config file." << endl; free(attrs[i]); break; } free(attrs[i]); i++; } free(attrs); if (!success) end_program(1); } if (attr_count && !set_attributes(codecID)) { cerr << "Invalid attribute[s] set for this codec!" << endl; cerr << attr_count << endl; list_attributes(codecID); end_program(1); } if (!rectime_str || !set_rectime(rectime_str)) { cerr << "No (or invalid) recording time given. Type 'vcr -h' for " << "help, look for '-t'." << endl; end_program(1); } if (preset && !(temp = is_valid_preset(preset))) { cerr << "Unknown tuner preset given." << endl; list_presets(); end_program(1); } if (preset && (!freqtab || !set_freqtab(freqtab))) { cerr << "Invalid (or no) frequency table given." << endl; list_freqtabs(); end_program(1); } if (preset && !set_tuner_frequency(preset)) { cerr << "Couldn't set tuner for chosen preset (maybe no channel" << " is set in the .vcrrc config file?)" << endl; end_program(1); } if (!rectime) { cerr << "Recording time has not been set." << endl; end_program(1); } if (window_str && !parse_window_string()) { cerr << "Invalid window parameter." << endl; end_program(1); } if (!set_window_size()) //it generates error on stderr itself. { end_program(1); } if (init_sound && initialize_sound(init_sound) < 0) { cerr << "Could not initialize sound recording device." << endl; show_error(); end_program(1); }}shortadd_attribute(const char *attr){ int attr_len = strlen(attr) + 1; char attrname[attr_len], attrval[attr_len]; struct codec_attr new_attr; int val = sscanf(attr,"%[^=]=%s", attrname, attrval); if (val != 2) return 0; new_attr.name = strdup(attrname); new_attr.val = strdup(attrval); attributes = (struct codec_attr*)realloc(attributes, (attr_count + 1) * sizeof(struct codec_attr)); attributes[attr_count++] = new_attr; return 1;}voidclear_attributes(){ if (!attr_count) return; if (attributes) free(attributes); attributes = NULL; attr_count = 0;}shortparse_config_file(){ const char *tmpstr; int tmpint; float tmpfloat; if (!config_file) { char * homedir = get_homedir(NULL); if (homedir) { config_file = (char*)malloc((strlen(homedir) + 20) * sizeof(char)); sprintf(config_file, "%s/.vcrrc", homedir); free(homedir); } else return set_error("Could not find your homedir to search for default config "\ "file (~/.vcrrc)."); } if (cfg_parse_file(config_file) < 0) return set_error("Couldn't parse config file (maybe ~/.vcrrc is missing?)."); if (!codec_name && !attributes_str && !attr_count && (tmpstr = cfg_get_str("defaults", "attributes"))) attributes_str = strdup(tmpstr); if (!codec_name && (tmpstr = cfg_get_str("defaults", "codec"))) codec_name = strdup(tmpstr); if (!keyframes && (tmpint = cfg_get_int("defaults", "keyframes")) > -1) keyframes = tmpint; if (!norm && (tmpstr = cfg_get_str("defaults", "norm"))) norm = strdup(tmpstr); if (!quality && (tmpint = cfg_get_int("defaults", "quality")) > -1) quality = tmpint; if (!input_source && (tmpstr = cfg_get_str("defaults", "source"))) input_source = strdup(tmpstr); if (!audio_mode && (tmpstr = cfg_get_str("defaults", "audiomode"))) audio_mode = strdup(tmpstr); if (!grabdevice && (tmpstr = cfg_get_str("defaults", "grabdevice"))) grabdevice = strdup(tmpstr); if (!audio_freq && (tmpint = cfg_get_int("defaults", "audiofrequency")) > -1) audio_freq = tmpint; if (!audio_size && (tmpint = cfg_get_int("defaults", "audiosamplesize")) > -1) audio_size = tmpint; // 8 or 16 if (!resolution && (tmpint = cfg_get_int("defaults", "resolution")) > -1) resolution = tmpint; if (fps < 0 && (tmpfloat = cfg_get_float("defaults", "framerate")) > -1) fps = tmpfloat; if (!preset && (tmpstr = cfg_get_str("defaults", "channel"))) preset = strdup(tmpstr); if ( (tmpint = cfg_get_int("defaults", "verbose")) > -1) verbose = 1; if (audio_bitrate < 0 && (tmpint = cfg_get_int("defaults", "audiobitrate")) > -1) { audio_bitrate = tmpint; } if (vertical_flip < 0 && (tmpint = cfg_get_int("defaults", "vflip")) > -1) { vertical_flip = !tmpint; } if (!rectime_str && (tmpstr = cfg_get_str("defaults", "rectime"))) rectime_str = strdup(tmpstr); if (!freqtab && (tmpstr = cfg_get_str("defaults", "freqtab"))) freqtab = strdup(tmpstr); if (!window_str && (tmpstr = cfg_get_str("defaults", "window"))) window_str = strdup(tmpstr); if (!codec_preset && (tmpstr = cfg_get_str("defaults", "codec-preset"))) codec_preset = strdup(tmpstr); if (!init_sound && (tmpstr = cfg_get_str("defaults", "init-sound"))) init_sound = strdup(tmpstr); if (!sound_device && (tmpstr = cfg_get_str("defaults", "sound-device"))) sound_device = strdup(tmpstr); if (splitsize < 0 && (tmpint = cfg_get_int("defaults", "splitsize")) > -1) { splitsize = tmpint; } return 0;}char **split_string(const char *tmpvals){ unsigned int i = 0, curval_pos = 0, val_index = 0; char **values = NULL, *tmpval2 = NULL, prev = '\0'; if (!tmpvals) { values = (char**)realloc(values, sizeof(char*)); values[0] = NULL; //last element in the array. return values; } values = (char**)malloc(1 * sizeof(char*)); values[val_index] = (char*)calloc(strlen(tmpvals)+1, sizeof(char)); while (i < strlen(tmpvals)) { char curr = tmpvals[i]; if (prev == '\\') { //previous read char was a backslash. That implies that this //character is treated a 'special' character. Currently only //comma and backslash itself. switch(curr) { case '\\': case ',': values[val_index][curval_pos++] = curr; break; } prev = '\0'; //prevent special char interpr. in next loop ;) } else if (curr == '\\') { prev = '\\'; } else if (curr == ',') //keyword separator { tmpval2 = crop_whitespace(values[val_index]); free(values[val_index]); values[val_index] = tmpval2; curval_pos = 0; values = (char**)realloc(values, ((++val_index)+1) * sizeof(char*)); values[val_index] = (char*)calloc(strlen(tmpvals)+1, sizeof(char)); prev = ','; } else //normal character { values[val_index][curval_pos++] = curr; prev = curr; } i++; } tmpval2 = crop_whitespace(values[val_index]); free(values[val_index]); values[val_index] = tmpval2; values = (char**)realloc(values, ((++val_index)+1) * sizeof(char*)); values[val_index] = NULL; //last element in the array. return values;}/* handle warnings. Currently simply displays warning on stderr. */voidvcr_warning(const char *txt){ cerr << "[WARNING] " << txt << endl;}voidvcr_notice(const char *txt){ if (verbose) cout << "[NOTICE] " << txt << endl;}voidvcr_notice(string& txt){ vcr_notice(txt.c_str());}voidvcr_notice(ostringstream& txt){ vcr_notice(txt.str().c_str());}/* sets global error var and returns -1 */shortset_error(const char*txt){ if (!txt) return -1; error = new char[strlen(txt)+1]; strcpy(error, txt); return -1;}/* show global error on stderr */voidshow_error(){ cerr << error << endl;}intset_rectime(const char *txt){ if (!txt || !strlen(txt)) return 0; char c = txt[strlen(txt)-1]; int mult = 1; switch (c) { case 'H' : case 'h' : mult = 60 * 60; break; // hours case 'M' : case 'm' : mult = 60; break; // minutes case 'S' : case 's' : mult = 1; break; // seconds default: if (!isdigit((int)c)) { cerr << "invalid arg to -t" << endl; end_program(1); } mult = 60; //default => minutes } float o; sscanf(txt, "%f", &o); rectime = (int) (o * mult); if (rectime < 0) rectime = -1; //unltd. time. return rectime;}intmain(int argc, char *argv[]){ int i; prog_name = strdup(argv[0]); cout << endl << "-------------------------------------------------------------" << endl << "VCR " << VERSION << ", (C) 2001 Bram Avontuur (bram@vcr.avontuur.org)" << endl <<#ifdef WANT_V4L_DEBUG "Configured with --with-debug" << endl <<#else "" <<#endif "-------------------------------------------------------------" << endl; init_globals(); parse_arguments(argc, argv); if (want_debug) init_debug(); if (parse_config_file() < 0) { cerr << error << endl; end_program(1); } /* these 'list' checks can only be performed after parsing the config * file. */ if (codec_preset && !strcasecmp(codec_preset, "list")) { list_codec_presets(); exit(0); } if (preset && !strcasecmp(preset, "list")) { list_presets(); exit(0); } if (!filename) { cerr << "No filename argument found. Type 'vcr -h' for instructions." << endl; end_program(1); } //initialize video4linux interface[s] init_v4l(); if (!v4l) { cerr << "Couldn't open v4l device." << endl; end_program(1); } BITMAPINFOHEADER bih; bih.biCompression = 0xffffffff; // just to fill video_codecs list Creators::CreateVideoDecoder(bih, 0, 0); avm::vector<const CodecInfo*> codecList; CodecInfo::Get(codecList); verify_globals(); //display recording info cout << " Filename: " << filename << endl; cout << " Video: codec: " << codec_name << ", quality: " << quality << endl; cout << " "; for (i = 0; i < attr_count; i++) { if (i) cout << ", "; cout << attributes[i].name << " = " << attributes[i].val; } if (!i) cout << "Default attributes will be used."; else cout << "."; cout << endl;// todo: show video size. cout << " time : "; if (rectime > 0) cout << rectime << " s"; else cout << "unlimited"; cout << ", fps: " << fps << ", keyframes: " << keyframes << endl; cout << " size : " << resolution_width << "x" << resolution_height << " (WxH)"; if (window.width != resolution_width || window.height != resolution_height) { cout << " downsized to " << window.width << "x" << window.height << " at offset (" << window.x << "," << window.y << ") (x,y)"; } cout << endl; cout << " Audio: codec: "; if (audio_bitrate) cout << "MP3 @ " << (audio_bitrate * 8) / 1000 << " kbps"; else cout << "none (uncompressed)"; cout << endl; cout << " Out: " << audio_freq << " kHz, " << audio_size << " bits (" << (soundchan == Stereo ? "stereo" : "mono") << ")" << endl; cout << endl << "Starting to record...type q+enter to quit." << endl; signal(SIGINT, stop_record_handler); cap = new CaptureProcess( v4l, filename, (splitsize > -1 ? splitsize * 1024 * 1024 : -1), codecID, quality * 100, keyframes, soundfreq, samplesize, soundchan, videores, rectime, -1, fps, window, (audio_bitrate ? 0x55 : 0), //mp3 codec or uncompressed audio audio_bitrate, vertical_flip, sound_device); short ready = 0; fd_set readfds; struct timeval tv; int old_capdrop = 0, old_compdrop = 0; time_t start_time = time(0); if (start_time == (time_t)-1) { perror("time"); end_program(1); } while (!ready) { int processed, cap_drop = 0, comp_drop = 0, finished; char str[256]; cap->getState(processed, cap_drop, comp_drop, finished); if (verbose) { if (cap_drop > old_capdrop || comp_drop > old_compdrop) { time_t t = time(0); if (cap_drop > old_capdrop) { cerr << ctime(&t) << " Dropped " << (cap_drop - old_capdrop) << " frame(s) in capture" << endl; old_capdrop = cap_drop; } else if (comp_drop > old_compdrop) { cerr << ctime(&t) << " Dropped " << comp_drop - old_compdrop << " frame(s) in encoder" << endl; old_compdrop = comp_drop; } } } if (want_debug) { sprintf(str, "Captured: %d frames, dropped in capture: %d, dropped "\ "in encoder: %d\n", processed, cap_drop, comp_drop); vcr_debug(str); } tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&readfds); FD_SET(0, &readfds); //add stdin if (select(1, &readfds, NULL, NULL, &tv)) { char input[81]; ssize_t readbytes = read(0, (void*)input, 80); if (readbytes > 0) { char cmd = input[0]; if (cmd == 'q') finished = 1; } } ready = finished; if (ready) { cout << "Captured " << processed << " frames." << endl; if (processed) { cout << "\tFrames dropped in capture: " << cap_drop << " (" << cout.precision(4) << (double)(100 * cap_drop / processed) << "%)" << endl << "\tframes dropped in encoder: " << comp_drop << " (" << cout.precision(4) << (double)(100 * comp_drop / processed) << "%)" << endl; } } else sleep(1); } cout << "Exiting.." << endl; end_program(0);}// vim:ts=2:sw=2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -