static void usage_exit() { int i; fprintf(stderr, "Usage: %s <options> src_filename dst_filename\n", exec_name); fprintf(stderr, "\n_options:\n"); arg_show_usage(stdout, main_args); fprintf(stderr, "\n_encoder Global Options:\n"); arg_show_usage(stdout, global_args); fprintf(stderr, "\n_rate Control Options:\n"); arg_show_usage(stdout, rc_args); fprintf(stderr, "\n_twopass Rate Control Options:\n"); arg_show_usage(stdout, rc_twopass_args); fprintf(stderr, "\n_keyframe Placement Options:\n"); arg_show_usage(stdout, kf_args); #if CONFIG_VP8_ENCODER fprintf(stderr, "\n_vp8 Specific Options:\n"); arg_show_usage(stdout, vp8_args); #endif fprintf(stderr, "\n" "Included encoders:\n" "\n"); for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++) fprintf(stderr, " %-6s - %s\n", codecs[i].name, vpx_codec_iface_name(codecs[i].iface)); exit(EXIT_FAILURE); }
static void usage_exit() { int i; fprintf(stderr, "Usage: %s <options> filename\n\n" "Options:\n", exec_name); arg_show_usage(stderr, all_args); #if CONFIG_VP8_DECODER fprintf(stderr, "\nVP8 Postprocessing Options:\n"); arg_show_usage(stderr, vp8_pp_args); #endif fprintf(stderr, "\nOutput File Patterns:\n\n" " The -o argument specifies the name of the file(s) to " "write to. If the\n argument does not include any escape " "characters, the output will be\n written to a single file. " "Otherwise, the filename will be calculated by\n expanding " "the following escape characters:\n"); fprintf(stderr, "\n\t%%w - Frame width" "\n\t%%h - Frame height" "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)" "\n\n Pattern arguments are only supported in conjunction " "with the --yv12 and\n --i420 options. If the -o option is " "not specified, the output will be\n directed to stdout.\n" ); fprintf(stderr, "\nIncluded decoders:\n\n"); for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) fprintf(stderr, " %-6s - %s\n", ifaces[i].name, vpx_codec_iface_name(ifaces[i].iface())); exit(EXIT_FAILURE); }
int main(int argc, char **argv) { int frame_cnt = 0; FILE *outfile = NULL; vpx_codec_ctx_t codec; VpxVideoReader *reader = NULL; const VpxInterface *decoder = NULL; const VpxVideoInfo *info = NULL; exec_name = argv[0]; if (argc != 3) die("Invalid number of arguments."); reader = vpx_video_reader_open(argv[1]); if (!reader) die("Failed to open %s for reading.", argv[1]); if (!(outfile = fopen(argv[2], "wb"))) die("Failed to open %s for writing.", argv[2]); info = vpx_video_reader_get_info(reader); decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); if (!decoder) die("Unknown input codec."); printf("Using %s\n", vpx_codec_iface_name(decoder->interface())); if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0)) die_codec(&codec, "Failed to initialize decoder."); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; vpx_image_t *img = NULL; size_t frame_size = 0; const unsigned char *frame = vpx_video_reader_get_frame(reader, &frame_size); if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) die_codec(&codec, "Failed to decode frame."); while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { vpx_img_write(img, outfile); ++frame_cnt; } } printf("Processed %d frames.\n", frame_cnt); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", info->frame_width, info->frame_height, argv[2]); vpx_video_reader_close(reader); fclose(outfile); return EXIT_SUCCESS; }
int main(int argc, char **argv) { int frame_cnt = 0; FILE *outfile = NULL; vpx_codec_ctx_t codec; VpxVideoReader *reader = NULL; const VpxVideoInfo *info = NULL; const VpxInterface *decoder = NULL; exec_name = argv[0]; if (argc != 3) die("Invalid number of arguments."); reader = vpx_video_reader_open(argv[1]); if (!reader) die("Failed to open %s for reading.", argv[1]); if (!(outfile = fopen(argv[2], "wb"))) die("Failed to open %s for writing.", argv[2]); info = vpx_video_reader_get_info(reader); decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); if (!decoder) die("Unknown input codec."); printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) die_codec(&codec, "Failed to initialize decoder"); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; vpx_image_t *img = NULL; size_t frame_size = 0; const unsigned char *frame = vpx_video_reader_get_frame(reader, &frame_size); if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) die_codec(&codec, "Failed to decode frame"); while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { unsigned char digest[16]; get_image_md5(img, digest); print_md5(outfile, digest); fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h, ++frame_cnt); } } printf("Processed %d frames.\n", frame_cnt); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); vpx_video_reader_close(reader); fclose(outfile); return EXIT_SUCCESS; }
Stream* create_stream(uint8_t *header, size_t net_packet_size, size_t net_buf_size) { Stream *stream = (Stream*)malloc(sizeof(Stream)); size_t *size_t_ptr; uint8_t *uint8_t_ptr; stream->net_packet_size = net_packet_size; stream->net_buf_fill = 0; stream->net_buf_size = net_buf_size; proc_info("Net Buf Size %u", (unsigned int)stream->net_buf_size); stream->net_buf = (uint8_t*)calloc(stream->net_buf_size, sizeof(uint8_t)); stream->reader = vpx_video_stream_reader_open(header); if (!stream->reader) proc_die("Failed to create new stream"); stream->info = vpx_video_stream_reader_get_info(stream->reader); proc_info("Frame Width %u\n", stream->info->frame_width); proc_info("Frame Height %u\n", stream->info->frame_height); // proc_info("Frame Count %u\n", stream->info->frame_count); // stream->gl_luma_buf_fill = 0; // stream->gl_luma_buf_size = stream->info->frame_width * stream->info->frame_height; // // proc_info("GL Buf Size %u", (unsigned int)stream->gl_buf_size); // stream->gl_luma_buf = (uint8_t*)calloc(stream->gl_luma_buf_size, sizeof(uint8_t)); // // stream->gl_chromaB_buf_fill = 0; // stream->gl_chromaB_buf_size = stream->info->frame_width/2 * stream->info->frame_height/2; // // proc_info("GL Buf Size %u", (unsigned int)stream->gl_buf_size); // stream->gl_chromaB_buf = (uint8_t*)calloc(stream->gl_chromaB_buf_size, sizeof(uint8_t)); // // stream->gl_chromaR_buf_fill = 0; // stream->gl_chromaR_buf_size = stream->info->frame_width/2 * stream->info->frame_height/2; // // proc_info("GL Buf Size %u", (unsigned int)stream->gl_buf_size); // stream->gl_chromaR_buf = (uint8_t*)calloc(stream->gl_chromaR_buf_size, sizeof(uint8_t)); stream->decoder = get_vpx_decoder_by_fourcc(stream->info->codec_fourcc); if (!stream->decoder) proc_die("Unknown input codec."); printf("Using %s\r\n", vpx_codec_iface_name(stream->decoder->codec_interface())); if (vpx_codec_dec_init(&stream->codec, stream->decoder->codec_interface(), NULL, 0)) die_codec(&stream->codec, "Failed to initialize decoder."); // stream->postproc = (vp8_postproc_cfg_t){ // VP8_DEBLOCK | VP8_DEMACROBLOCK, // 4, // strength of deblocking, valid range [0, 16] // 0 // }; // // if(vpx_codec_control(&stream->codec, VP8_SET_POSTPROC, &stream->postproc)) // die_codec(&stream->codec, "Failed to turn on postproc"); return stream; }
int vp8Encoder::initilize(int frameWidth, int frameHeight) { //display_width = frameWidth; //display_height = frameHeight; pthread_mutex_lock (&mCodecLock); frame_cnt = 0; vpx_codec_enc_cfg_t cfg; int cpu_used = 8; int static_threshold = 1200; vpx_codec_enc_config_default(interface, &cfg, 0); LOGD("Using %s\n",vpx_codec_iface_name(interface)); cfg.rc_target_bitrate = 10*frameWidth * frameHeight * cfg.rc_target_bitrate / cfg.g_w / cfg.g_h; LOGD("Encoder cfg.rc_target_bitrate=%d", cfg.rc_target_bitrate); cfg.g_w = display_width; cfg.g_h = display_height; /*cfg.g_timebase.num = 1; cfg.g_timebase.den = (int) 10000000; cfg.rc_end_usage = VPX_CBR; cfg.g_pass = VPX_RC_ONE_PASS; cfg.g_lag_in_frames = 0; cfg.rc_min_quantizer = 20; cfg.rc_max_quantizer = 50; cfg.rc_dropframe_thresh = 1; cfg.rc_buf_optimal_sz = 1000; cfg.rc_buf_initial_sz = 1000; cfg.rc_buf_sz = 1000; cfg.g_error_resilient = 1; cfg.kf_mode = VPX_KF_DISABLED; cfg.kf_max_dist = 999999; cfg.g_threads = 1;*/ vpx_codec_enc_init(&encoder, interface, &cfg, 0); /*vpx_codec_control_(&encoder, VP8E_SET_CPUUSED, cpu_used); vpx_codec_control_(&encoder, VP8E_SET_STATIC_THRESHOLD, static_threshold); vpx_codec_control_(&encoder, VP8E_SET_ENABLEAUTOALTREF, 0); */ vpx_img_alloc(&raw, VPX_IMG_FMT_I420, display_width, display_height, 1); //create_packetizer(&x, XOR, fec_numerator, fec_denominator); //sDecoder->initilize(); pthread_mutex_unlock (&mCodecLock); return 0; }
static void dec_init(MSFilter *f) { DecState *s = (DecState *)ms_new0(DecState, 1); s->iface = vpx_codec_vp8_dx(); ms_message("Using %s", vpx_codec_iface_name(s->iface)); s->last_error_reported_time = 0; s->yuv_width = 0; s->yuv_height = 0; s->yuv_msg = 0; ms_queue_init(&s->q); s->first_image_decoded = FALSE; s->avpf_enabled = FALSE; s->freeze_on_error = TRUE; f->data = s; ms_average_fps_init(&s->fps, "VP8 decoder: FPS: %f"); }
static void dec_init(MSFilter *f) { DecState *s=(DecState *)ms_new(DecState,1); ms_message("Using %s\n",vpx_codec_iface_name(interface)); /* Initialize codec */ if(vpx_codec_dec_init(&s->codec, interface, NULL, 0)) ms_error("Failed to initialize decoder"); s->curframe = NULL; s->last_error_reported_time = 0; s->yuv_width = 0; s->yuv_height = 0; s->yuv_msg = 0; ms_queue_init(&s->q); s->first_image_decoded = FALSE; f->data = s; ms_video_init_average_fps(&s->fps, "VP8 decoder: FPS: %f"); }
HRESULT InitVPXEncoder(vpx_codec_enc_cfg_t * vpxConfig, vpx_codec_ctx_t * vpxCodec, unsigned int width, unsigned int height) { //vpx_codec_ctx_t codec; vpx_codec_err_t res; printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx())); /* Populate encoder configuration */ res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), vpxConfig, 0); if (res) { printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res)); return -1; } else { vpx_img_alloc(&_rawImage, VIDEO_INPUT_FORMAT, WIDTH, HEIGHT, 0); vpxConfig->g_w = width; vpxConfig->g_h = height; vpxConfig->rc_target_bitrate = 5000; // in kbps. vpxConfig->rc_min_quantizer = 20; // 50; vpxConfig->rc_max_quantizer = 30; // 60; vpxConfig->g_pass = VPX_RC_ONE_PASS; vpxConfig->rc_end_usage = VPX_CBR; //vpxConfig->kf_min_dist = 50; //vpxConfig->kf_max_dist = 50; //vpxConfig->kf_mode = VPX_KF_DISABLED; vpxConfig->g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; vpxConfig->g_lag_in_frames = 0; vpxConfig->rc_resize_allowed = 0; /* Initialize codec */ if (vpx_codec_enc_init(vpxCodec, (vpx_codec_vp8_cx()), vpxConfig, 0)) { printf("Failed to initialize libvpx encoder.\n"); return -1; } else { return S_OK; } } }
static void enc_init(MSFilter *f) { vpx_codec_err_t res; MSVideoSize vsize; EncState *s=(EncState *)ms_new0(EncState,1); ms_message("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ res = vpx_codec_enc_config_default(interface, &s->cfg, 0); if(res) { ms_error("Failed to get config: %s\n", vpx_codec_err_to_string(res)); } if (ms_get_cpu_count() > 1) s->vconf_list = &multicore_vp8_conf_list[0]; else s->vconf_list = &vp8_conf_list[0]; MS_VIDEO_SIZE_ASSIGN(vsize, CIF); s->vconf = ms_video_find_best_configuration_for_size(s->vconf_list, vsize); s->frame_count = 0; s->cfg.g_w = s->vconf.vsize.width; s->cfg.g_h = s->vconf.vsize.height; /* encoder automatically places keyframes */ s->cfg.kf_mode = VPX_KF_AUTO; s->cfg.kf_max_dist = 300; s->cfg.rc_target_bitrate = ((float)s->vconf.required_bitrate)*0.92/1024.0; //0.9=take into account IP/UDP/RTP overhead, in average. s->cfg.g_pass = VPX_RC_ONE_PASS; /* -p 1 */ s->cfg.g_timebase.num = 1; s->cfg.g_timebase.den = s->vconf.fps; s->cfg.rc_end_usage = VPX_CBR; /* --end-usage=cbr */ #if TARGET_IPHONE_SIMULATOR s->cfg.g_threads = 1; /*workaround to remove crash on ipad simulator*/ #else s->cfg.g_threads = ms_get_cpu_count(); #endif ms_message("VP8 g_threads=%d", s->cfg.g_threads); s->cfg.rc_undershoot_pct = 95; /* --undershoot-pct=95 */ s->cfg.g_error_resilient = 1; s->cfg.g_lag_in_frames = 0; s->mtu=ms_get_payload_max_size()-1;/*-1 for the vp8 payload header*/ f->data = s; }
int VPXEncoder::InitEncoder(unsigned int width, unsigned int height) { _vpxCodec = new vpx_codec_ctx_t(); _rawImage = new vpx_image_t(); _width = width; _height = height; vpx_codec_enc_cfg_t vpxConfig; vpx_codec_err_t res; printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx())); /* Populate encoder configuration */ res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), &vpxConfig, 0); if (res) { printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res)); return -1; } else { vpx_img_alloc(_rawImage, VPX_IMG_FMT_I420, width, height, 0); vpxConfig.g_w = width; vpxConfig.g_h = height; vpxConfig.rc_target_bitrate = 300; // 5000; // in kbps. vpxConfig.rc_min_quantizer = 20; // 50; vpxConfig.rc_max_quantizer = 30; // 60; vpxConfig.g_pass = VPX_RC_ONE_PASS; vpxConfig.rc_end_usage = VPX_CBR; vpxConfig.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; vpxConfig.g_lag_in_frames = 0; vpxConfig.rc_resize_allowed = 0; vpxConfig.kf_max_dist = 20; /* Initialize codec */ if (vpx_codec_enc_init(_vpxCodec, (vpx_codec_vp8_cx()), &vpxConfig, 0)) { printf("Failed to initialize libvpx encoder.\n"); return -1; } } }
static void enc_init(MSFilter *f) { EncState *s = (EncState *)ms_new0(EncState, 1); MSVideoSize vsize; s->iface = vpx_codec_vp8_cx(); ms_message("Using %s", vpx_codec_iface_name(s->iface)); s->vconf_list = &vp8_conf_list[0]; MS_VIDEO_SIZE_ASSIGN(vsize, CIF); s->vconf = ms_video_find_best_configuration_for_size(s->vconf_list, vsize, ms_factory_get_cpu_count(f->factory)); s->frame_count = 0; s->last_fir_seq_nr = -1; #ifdef PICTURE_ID_ON_16_BITS s->picture_id = (ortp_random() & 0x7FFF) | 0x8000; #else s->picture_id = ortp_random() & 0x007F; #endif s->avpf_enabled = FALSE; enc_reset_frames_state(s); f->data = s; }
static void usage_exit(void) { int i; printf("Usage: %s <options>\n\n" "Options:\n" "\t--codec <name>\tCodec to use (default=%s)\n" "\t-h <height>\tHeight of the simulated video frame, in pixels\n" "\t-w <width> \tWidth of the simulated video frame, in pixels\n" "\t-v \tVerbose mode (show individual segment sizes)\n" "\t--help \tShow this message\n" "\n" "Included decoders:\n" "\n", exec_name, ifaces[0].name); for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) printf(" %-6s - %s\n", ifaces[i].name, vpx_codec_iface_name(ifaces[i].iface)); exit(EXIT_FAILURE); }
static void enc_init(MSFilter *f) { vpx_codec_err_t res; EncState *s=(EncState *)ms_new0(EncState,1); ms_message("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ res = vpx_codec_enc_config_default(interface, &s->cfg, 0); if(res) { ms_error("Failed to get config: %s\n", vpx_codec_err_to_string(res)); } s->width = MS_VIDEO_SIZE_CIF_W; s->height = MS_VIDEO_SIZE_CIF_H; s->bitrate=256000; s->frame_count = 0; s->cfg.g_w = s->width; s->cfg.g_h = s->height; /* encoder automatically places keyframes */ s->cfg.kf_mode = VPX_KF_AUTO; s->cfg.kf_max_dist = 300; s->cfg.rc_target_bitrate = ((float)s->bitrate)*0.92/1024.0; //0.9=take into account IP/UDP/RTP overhead, in average. s->cfg.g_pass = VPX_RC_ONE_PASS; /* -p 1 */ s->fps=15; s->cfg.g_timebase.num = 1; s->cfg.g_timebase.den = s->fps; s->cfg.rc_end_usage = VPX_CBR; /* --end-usage=cbr */ s->cfg.g_threads = ms_get_cpu_count(); ms_message("VP8 g_threads=%d", s->cfg.g_threads); s->cfg.rc_undershoot_pct = 95; /* --undershoot-pct=95 */ s->cfg.g_error_resilient = 1; s->cfg.g_lag_in_frames = 0; s->mtu=ms_get_payload_max_size()-1;/*-1 for the vp8 payload header*/ f->data = s; }
int main(int argc, char **argv) { FILE *infile, *outfile; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_cnt = 0; unsigned char file_hdr[IVF_FILE_HDR_SZ]; unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; vpx_image_t raw; vpx_codec_err_t ret; int width,height; int y_size; int frame_avail; int got_data; int flags = 0; width = 640; height = 360; infile = fopen("../cuc_ieschool_640x360_yuv420p.yuv", "rb"); outfile = fopen("cuc_ieschool.ivf", "wb"); if(infile==NULL||outfile==NULL){ printf("Error open files.\n"); return -1; } if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)){ printf("Fail to allocate image\n"); return -1; } printf("Using %s\n",vpx_codec_iface_name(interface)); //Populate encoder configuration ret = vpx_codec_enc_config_default(interface, &cfg, 0); if(ret) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(ret)); return -1; } cfg.rc_target_bitrate =800; cfg.g_w = width; cfg.g_h = height; write_ivf_file_header(outfile, &cfg, 0); //Initialize codec if(vpx_codec_enc_init(&codec, interface, &cfg, 0)){ printf("Failed to initialize encoder\n"); return -1; } frame_avail = 1; got_data = 0; y_size=cfg.g_w*cfg.g_h; while(frame_avail || got_data) { vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; if(fread(raw.planes[0], 1, y_size*3/2, infile)!=y_size*3/2){ frame_avail=0; } if(frame_avail){ //Encode ret=vpx_codec_encode(&codec,&raw,frame_cnt,1,flags,VPX_DL_REALTIME); }else{ //Flush Encoder ret=vpx_codec_encode(&codec,NULL,frame_cnt,1,flags,VPX_DL_REALTIME); } if(ret){ printf("Failed to encode frame\n"); return -1; } got_data = 0; while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { got_data = 1; switch(pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: write_ivf_frame_header(outfile, pkt); fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,outfile); break; default: break; } } printf("Succeed encode frame: %5d\n",frame_cnt); frame_cnt++; } fclose(infile); vpx_codec_destroy(&codec); //Try to rewrite the file header with the actual frame count if(!fseek(outfile, 0, SEEK_SET)) write_ivf_file_header(outfile, &cfg, frame_cnt-1); fclose(outfile); return 0; }
int main(int argc, char **argv) { FILE *infile = NULL; int w, h; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; vpx_image_t raw; vpx_codec_err_t res; vpx_fixed_buf_t stats; const VpxInterface *encoder = NULL; const int fps = 30; // TODO(dkovalev) add command line argument const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument const char *const codec_arg = argv[1]; const char *const width_arg = argv[2]; const char *const height_arg = argv[3]; const char *const infile_arg = argv[4]; const char *const outfile_arg = argv[5]; exec_name = argv[0]; if (argc != 6) die("Invalid number of arguments."); encoder = get_vpx_encoder_by_name(codec_arg); if (!encoder) die("Unsupported codec."); w = strtol(width_arg, NULL, 0); h = strtol(height_arg, NULL, 0); if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0) die("Invalid frame size: %dx%d", w, h); if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1)) die("Failed to allocate image", w, h); printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); // Configuration res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) die_codec(&codec, "Failed to get default codec config."); cfg.g_w = w; cfg.g_h = h; cfg.g_timebase.num = 1; cfg.g_timebase.den = fps; cfg.rc_target_bitrate = bitrate; if (!(infile = fopen(infile_arg, "rb"))) die("Failed to open %s for reading", infile_arg); // Pass 0 cfg.g_pass = VPX_RC_FIRST_PASS; stats = pass0(&raw, infile, encoder, &cfg); // Pass 1 rewind(infile); cfg.g_pass = VPX_RC_LAST_PASS; cfg.rc_twopass_stats_in = stats; pass1(&raw, infile, outfile_arg, encoder, &cfg); free(stats.buf); vpx_img_free(&raw); fclose(infile); return EXIT_SUCCESS; }
// TODO(tomfinegan): Improve command line parsing and add args for bitrate/fps. int main(int argc, char **argv) { FILE *infile = NULL; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_count = 0; vpx_image_t raw; vpx_codec_err_t res; VpxVideoInfo info = { 0, 0, 0, { 0, 0 } }; VpxVideoWriter *writer = NULL; const VpxInterface *encoder = NULL; const int fps = 30; const int bitrate = 200; int keyframe_interval = 0; int max_frames = 0; int frames_encoded = 0; const char *codec_arg = NULL; const char *width_arg = NULL; const char *height_arg = NULL; const char *infile_arg = NULL; const char *outfile_arg = NULL; const char *keyframe_interval_arg = NULL; exec_name = argv[0]; if (argc != 9) die("Invalid number of arguments"); codec_arg = argv[1]; width_arg = argv[2]; height_arg = argv[3]; infile_arg = argv[4]; outfile_arg = argv[5]; keyframe_interval_arg = argv[6]; max_frames = (int)strtol(argv[8], NULL, 0); encoder = get_vpx_encoder_by_name(codec_arg); if (!encoder) die("Unsupported codec."); info.codec_fourcc = encoder->fourcc; info.frame_width = (int)strtol(width_arg, NULL, 0); info.frame_height = (int)strtol(height_arg, NULL, 0); info.time_base.numerator = 1; info.time_base.denominator = fps; if (info.frame_width <= 0 || info.frame_height <= 0 || (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) { die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); } if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, info.frame_height, 1)) { die("Failed to allocate image."); } keyframe_interval = (int)strtol(keyframe_interval_arg, NULL, 0); if (keyframe_interval < 0) die("Invalid keyframe interval value."); printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) die_codec(&codec, "Failed to get default codec config."); cfg.g_w = info.frame_width; cfg.g_h = info.frame_height; cfg.g_timebase.num = info.time_base.numerator; cfg.g_timebase.den = info.time_base.denominator; cfg.rc_target_bitrate = bitrate; cfg.g_error_resilient = (vpx_codec_er_flags_t)strtoul(argv[7], NULL, 0); writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info); if (!writer) die("Failed to open %s for writing.", outfile_arg); if (!(infile = fopen(infile_arg, "rb"))) die("Failed to open %s for reading.", infile_arg); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) die_codec(&codec, "Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { int flags = 0; if (keyframe_interval > 0 && frame_count % keyframe_interval == 0) flags |= VPX_EFLAG_FORCE_KF; encode_frame(&codec, &raw, frame_count++, flags, writer); frames_encoded++; if (max_frames > 0 && frames_encoded >= max_frames) break; } // Flush encoder. while (encode_frame(&codec, NULL, -1, 0, writer)) { } printf("\n"); fclose(infile); printf("Processed %d frames.\n", frame_count); vpx_img_free(&raw); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); vpx_video_writer_close(writer); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile, *outfile[MAX_LAYERS]; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_cnt = 0; vpx_image_t raw; vpx_codec_err_t res; unsigned int width; unsigned int height; int frame_avail; int got_data; int flags = 0; int i; int pts = 0; // PTS starts at 0 int frame_duration = 1; // 1 timebase tick per frame int layering_mode = 0; int frames_in_layer[MAX_LAYERS] = {0}; int layer_flags[MAX_PERIODICITY] = {0}; // Check usage and arguments if (argc < 9) die("Usage: %s <infile> <outfile> <width> <height> <rate_num> " " <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]); width = strtol (argv[3], NULL, 0); height = strtol (argv[4], NULL, 0); if (width < 16 || width%2 || height <16 || height%2) die ("Invalid resolution: %d x %d", width, height); if (!sscanf(argv[7], "%d", &layering_mode)) die ("Invalid mode %s", argv[7]); if (layering_mode<0 || layering_mode>6) die ("Invalid mode (0..6) %s", argv[7]); if (argc != 8+mode_to_num_layers[layering_mode]) die ("Invalid number of arguments"); if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 1)) die ("Failed to allocate image", width, height); printf("Using %s\n",vpx_codec_iface_name(interface)); // Populate encoder configuration res = vpx_codec_enc_config_default(interface, &cfg, 0); if(res) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); return EXIT_FAILURE; } // Update the default configuration with our settings cfg.g_w = width; cfg.g_h = height; // Timebase format e.g. 30fps: numerator=1, demoninator=30 if (!sscanf (argv[5], "%d", &cfg.g_timebase.num )) die ("Invalid timebase numerator %s", argv[5]); if (!sscanf (argv[6], "%d", &cfg.g_timebase.den )) die ("Invalid timebase denominator %s", argv[6]); for (i=8; i<8+mode_to_num_layers[layering_mode]; i++) if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-8])) die ("Invalid data rate %s", argv[i]); // Real time parameters cfg.rc_dropframe_thresh = 0; cfg.rc_end_usage = VPX_CBR; cfg.rc_resize_allowed = 0; cfg.rc_min_quantizer = 4; cfg.rc_max_quantizer = 63; cfg.rc_undershoot_pct = 98; cfg.rc_overshoot_pct = 100; cfg.rc_buf_initial_sz = 500; cfg.rc_buf_optimal_sz = 600; cfg.rc_buf_sz = 1000; // Enable error resilient mode cfg.g_error_resilient = 1; cfg.g_lag_in_frames = 0; cfg.kf_mode = VPX_KF_DISABLED; // Disable automatic keyframe placement cfg.kf_min_dist = cfg.kf_max_dist = 1000; // Temporal scaling parameters: // NOTE: The 3 prediction frames cannot be used interchangeably due to // differences in the way they are handled throughout the code. The // frames should be allocated to layers in the order LAST, GF, ARF. // Other combinations work, but may produce slightly inferior results. switch (layering_mode) { case 0: { // 2-layers, 2-frame period int ids[2] = {0,1}; cfg.ts_number_layers = 2; cfg.ts_periodicity = 2; cfg.ts_rate_decimator[0] = 2; cfg.ts_rate_decimator[1] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); #if 1 // 0=L, 1=GF, Intra-layer prediction enabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF; #else // 0=L, 1=GF, Intra-layer prediction disabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST; #endif break; } case 1: { // 2-layers, 3-frame period int ids[3] = {0,1,1}; cfg.ts_number_layers = 2; cfg.ts_periodicity = 3; cfg.ts_rate_decimator[0] = 3; cfg.ts_rate_decimator[1] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); // 0=L, 1=GF, Intra-layer prediction enabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; layer_flags[1] = layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; break; } case 2: { // 3-layers, 6-frame period int ids[6] = {0,2,2,1,2,2}; cfg.ts_number_layers = 3; cfg.ts_periodicity = 6; cfg.ts_rate_decimator[0] = 6; cfg.ts_rate_decimator[1] = 3; cfg.ts_rate_decimator[2] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; layer_flags[1] = layer_flags[2] = layer_flags[4] = layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; break; } case 3: { // 3-layers, 4-frame period int ids[4] = {0,2,1,2}; cfg.ts_number_layers = 3; cfg.ts_periodicity = 4; cfg.ts_rate_decimator[0] = 4; cfg.ts_rate_decimator[1] = 2; cfg.ts_rate_decimator[2] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; layer_flags[1] = layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; break; } case 4: { // 3-layers, 4-frame period int ids[4] = {0,2,1,2}; cfg.ts_number_layers = 3; cfg.ts_periodicity = 4; cfg.ts_rate_decimator[0] = 4; cfg.ts_rate_decimator[1] = 2; cfg.ts_rate_decimator[2] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, // disabled in layer 2 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; layer_flags[1] = layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; break; } case 5: { // 3-layers, 4-frame period int ids[4] = {0,2,1,2}; cfg.ts_number_layers = 3; cfg.ts_periodicity = 4; cfg.ts_rate_decimator[0] = 4; cfg.ts_rate_decimator[1] = 2; cfg.ts_rate_decimator[2] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; layer_flags[1] = layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; break; } case 6: { // NOTE: Probably of academic interest only // 5-layers, 16-frame period int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4}; cfg.ts_number_layers = 5; cfg.ts_periodicity = 16; cfg.ts_rate_decimator[0] = 16; cfg.ts_rate_decimator[1] = 8; cfg.ts_rate_decimator[2] = 4; cfg.ts_rate_decimator[3] = 2; cfg.ts_rate_decimator[4] = 1; memcpy(cfg.ts_layer_id, ids, sizeof(ids)); layer_flags[0] = VPX_EFLAG_FORCE_KF; layer_flags[1] = layer_flags[3] = layer_flags[5] = layer_flags[7] = layer_flags[9] = layer_flags[11] = layer_flags[13] = layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY; layer_flags[2] = layer_flags[6] = layer_flags[10] = layer_flags[14] = 0; layer_flags[4] = layer_flags[12] = VP8_EFLAG_NO_REF_LAST; layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ENTROPY; break; } default: break; } // Open input file if(!(infile = fopen(argv[1], "rb"))) die("Failed to open %s for reading", argv[1]); // Open an output file for each stream for (i=0; i<cfg.ts_number_layers; i++) { char file_name[512]; sprintf (file_name, "%s_%d.ivf", argv[2], i); if (!(outfile[i] = fopen(file_name, "wb"))) die("Failed to open %s for writing", file_name); write_ivf_file_header(outfile[i], &cfg, 0); } // Initialize codec if (vpx_codec_enc_init (&codec, interface, &cfg, 0)) die_codec (&codec, "Failed to initialize encoder"); // Cap CPU & first I-frame size vpx_codec_control (&codec, VP8E_SET_CPUUSED, -6); vpx_codec_control (&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 600); frame_avail = 1; while (frame_avail || got_data) { vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; flags = layer_flags[frame_cnt % cfg.ts_periodicity]; frame_avail = read_frame(infile, &raw); if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags, VPX_DL_REALTIME)) die_codec(&codec, "Failed to encode frame"); // Reset KF flag layer_flags[0] &= ~VPX_EFLAG_FORCE_KF; got_data = 0; while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { got_data = 1; switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; i<cfg.ts_number_layers; i++) { write_ivf_frame_header(outfile[i], pkt); if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile[i])); frames_in_layer[i]++; } break; default: break; } printf (pkt->kind == VPX_CODEC_CX_FRAME_PKT && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); fflush (stdout); } frame_cnt++; pts += frame_duration; } printf ("\n"); fclose (infile); printf ("Processed %d frames.\n",frame_cnt-1); if (vpx_codec_destroy(&codec)) die_codec (&codec, "Failed to destroy codec"); // Try to rewrite the output file headers with the actual frame count for (i=0; i<cfg.ts_number_layers; i++) { if (!fseek(outfile[i], 0, SEEK_SET)) write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]); fclose (outfile[i]); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { int frame_cnt = 0; FILE *outfile = NULL; vpx_codec_ctx_t codec; const VpxInterface *decoder = NULL; VpxVideoReader *reader = NULL; const VpxVideoInfo *info = NULL; int n = 0; int m = 0; int is_range = 0; char *nptr = NULL; exec_name = argv[0]; if (argc != 4) die("Invalid number of arguments."); reader = vpx_video_reader_open(argv[1]); if (!reader) die("Failed to open %s for reading.", argv[1]); if (!(outfile = fopen(argv[2], "wb"))) die("Failed to open %s for writing.", argv[2]); n = strtol(argv[3], &nptr, 0); m = strtol(nptr + 1, NULL, 0); is_range = (*nptr == '-'); if (!n || !m || (*nptr != '-' && *nptr != '/')) die("Couldn't parse pattern %s.\n", argv[3]); info = vpx_video_reader_get_info(reader); decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); if (!decoder) die("Unknown input codec."); printf("Using %s\n", vpx_codec_iface_name(decoder->interface())); if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0)) die_codec(&codec, "Failed to initialize decoder."); while (vpx_video_reader_read_frame(reader)) { vpx_codec_iter_t iter = NULL; vpx_image_t *img = NULL; size_t frame_size = 0; int skip; const unsigned char *frame = vpx_video_reader_get_frame(reader, &frame_size); if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) die_codec(&codec, "Failed to decode frame."); ++frame_cnt; skip = (is_range && frame_cnt >= n && frame_cnt <= m) || (!is_range && m - (frame_cnt - 1) % m <= n); if (!skip) { putc('.', stdout); while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) vpx_img_write(img, outfile); } else { putc('X', stdout); } fflush(stdout); } printf("Processed %d frames.\n", frame_cnt); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", info->frame_width, info->frame_height, argv[2]); vpx_video_reader_close(reader); fclose(outfile); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile, *outfile; vpx_codec_ctx_t codec; vpx_codec_iface_t *iface; int flags = 0, frame_cnt = 0; unsigned char file_hdr[IVF_FILE_HDR_SZ]; unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; unsigned char frame[256 * 1024]; if (argc != 3) die("Usage: %s <infile> <outfile>\n", argv[0]); if (!(infile = fopen(argv[1], "rb"))) die("Failed to open %s for reading", argv[1]); if (!(outfile = fopen(argv[2], "wb"))) die("Failed to open %s for writing", argv[2]); if (!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ && file_hdr[0] == 'D' && file_hdr[1] == 'K' && file_hdr[2] == 'I' && file_hdr[3] == 'F')) die("%s is not an IVF file.", argv[1]); iface = get_codec_interface(mem_get_le32(file_hdr + 8)); if (!iface) die("Unknown FOURCC code."); printf("Using %s\n", vpx_codec_iface_name(iface)); if (vpx_codec_dec_init(&codec, iface, NULL, flags)) die_codec(&codec, "Failed to initialize decoder"); while (fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) { const int frame_size = mem_get_le32(frame_hdr); vpx_codec_iter_t iter = NULL; vpx_image_t *img; if (frame_size > sizeof(frame)) die("Frame %d data too big for example code buffer", frame_size); if (fread(frame, 1, frame_size, infile) != frame_size) die("Failed to read complete frame"); if (vpx_codec_decode(&codec, frame, frame_size, NULL, 0)) die_codec(&codec, "Failed to decode frame"); while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { unsigned char digest[16]; get_image_md5(img, digest); print_md5(outfile, digest); fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h, ++frame_cnt); } } printf("Processed %d frames.\n", frame_cnt); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); fclose(outfile); fclose(infile); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile, *outfile; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_cnt = 0; vpx_image_t raw; vpx_codec_err_t res; long width; long height; int frame_avail; int got_data; int flags = 0; /* Open files */ if(argc!=5) die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]); width = strtol(argv[1], NULL, 0); height = strtol(argv[2], NULL, 0); if(width < 16 || width%2 || height <16 || height%2) die("Invalid resolution: %ldx%ld", width, height); if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)) die("Faile to allocate image", width, height); if(!(outfile = fopen(argv[4], "wb"))) die("Failed to open %s for writing", argv[4]); printf("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ res = vpx_codec_enc_config_default(interface, &cfg, 0); if(res) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); return EXIT_FAILURE; } /* Update the default configuration with our settings */ cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate / cfg.g_w / cfg.g_h; cfg.g_w = width; cfg.g_h = height; write_ivf_file_header(outfile, &cfg, 0); /* Open input file for this encoding pass */ if(!(infile = fopen(argv[3], "rb"))) die("Failed to open %s for reading", argv[3]); /* Initialize codec */ if(vpx_codec_enc_init(&codec, interface, &cfg, 0)) die_codec(&codec, "Failed to initialize encoder"); frame_avail = 1; got_data = 0; while(frame_avail || got_data) { vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; if(frame_cnt + 1 == 22) { // vpx_roi_map_t roi; // int i; // // roi.rows = cfg.g_h/16; // roi.cols = cfg.g_w/16; // // roi.delta_q[0] = 0; // roi.delta_q[1] = -2; // roi.delta_q[2] = -4; // roi.delta_q[3] = -6; // // roi.delta_lf[0] = 0; // roi.delta_lf[1] = 1; // roi.delta_lf[2] = 2; // roi.delta_lf[3] = 3; // // roi.static_threshold[0] = 1500; // roi.static_threshold[1] = 1000; // roi.static_threshold[2] = 500; // roi.static_threshold[3] = 0; // // /* generate an ROI map for example */ // roi.roi_map = malloc(roi.rows * roi.cols); // for(i=0;i<roi.rows*roi.cols;i++) // roi.roi_map[i] = i & 3; // // if(vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi)) // die_codec(&codec, "Failed to set ROI map"); // // free(roi.roi_map); // } else if(frame_cnt + 1 == 33) { // vpx_active_map_t active; // int i; // // active.rows = cfg.g_h/16; // active.cols = cfg.g_w/16; // // /* generate active map for example */ // active.active_map = malloc(active.rows * active.cols); // for(i=0;i<active.rows*active.cols;i++) // active.active_map[i] = i & 1; // // if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active)) // die_codec(&codec, "Failed to set active map"); // // free(active.active_map); // } else if(frame_cnt + 1 == 44) { // vpx_active_map_t active; // // active.rows = cfg.g_h/16; // active.cols = cfg.g_w/16; // // /* pass in null map to disable active_map*/ // active.active_map = NULL; // // if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active)) // die_codec(&codec, "Failed to set active map"); // } // frame_avail = read_frame(infile, &raw); if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt, 1, flags, VPX_DL_REALTIME)) die_codec(&codec, "Failed to encode frame"); got_data = 0; while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { got_data = 1; switch(pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: write_ivf_frame_header(outfile, pkt); if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile)); break; default: break; } printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); fflush(stdout); } frame_cnt++; } printf("\n"); fclose(infile); printf("Processed %d frames.\n",frame_cnt-1); if(vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); /* Try to rewrite the file header with the actual frame count */ if(!fseek(outfile, 0, SEEK_SET)) write_ivf_file_header(outfile, &cfg, frame_cnt-1); fclose(outfile); return EXIT_SUCCESS; }
// Initialize encoder, given setup in the encoder parameters bool LumaEncoder::initialize(const char *outputFile, const unsigned int w, const unsigned int h, bool verbose) { // Initialize base. Creates a Matroska file for writing LumaEncoderBase::initialize(outputFile, w, h); // Adjust profile for the specified bit depth (0-1 for 8 bits, and 2-3 for higher bit depths) if (m_params.profile > 1 && m_params.bitDepth == 8) m_params.profile -=2; if (m_params.profile < 2 && m_params.bitDepth > 8) m_params.profile +=2; // Initialize quantizer m_quant.setQuantizer(m_params.ptf, m_params.ptfBitDepth, m_params.colorSpace, m_params.colorBitDepth); // Add attachments with meta data to Matroska file unsigned int *buffer1 = new unsigned int; *buffer1 = m_params.ptfBitDepth; m_writer.addAttachment(430, (const binary*)buffer1, sizeof(unsigned int), "PTF bit depth"); unsigned int *buffer2 = new unsigned int; *buffer2 = m_params.colorBitDepth; m_writer.addAttachment(431, (const binary*)buffer2, sizeof(unsigned int), "Color bit depth"); LumaQuantizer::ptf_t *buffer3 = new LumaQuantizer::ptf_t; *buffer3 = m_params.ptf; m_writer.addAttachment(432, (const binary*)buffer3, sizeof(LumaQuantizer::ptf_t), "PTF description"); LumaQuantizer::colorSpace_t *buffer4 = new LumaQuantizer::colorSpace_t; *buffer4 = m_params.colorSpace; m_writer.addAttachment(433, (const binary*)buffer4, sizeof(LumaQuantizer::colorSpace_t), "Color space"); float *buffer5 = new float[m_quant.getSize()]; memcpy((void*)buffer5, (void*)m_quant.getMapping(), (m_quant.getSize())*sizeof(float)); m_writer.addAttachment(434, (const binary*)buffer5, (m_quant.getSize())*sizeof(float), "PTF"); float *buffer6 = new float; *buffer6 = m_params.preScaling; m_writer.addAttachment(435, (const binary*)buffer6, sizeof(float), "Scaling"); m_writer.writeAttachments(); // Framerate for timecodes m_writer.setFramerate(m_params.fps); m_writer.setVerbose(verbose); // Initialize VPX codec vpx_codec_err_t res; vpx_codec_enc_cfg_t cfg; const vpx_codec_iface_t *(*const vpx_encoder)() = &vpx_codec_vp9_cx; if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0) throw LumaException("Invalid frame size"); if (m_params.profile == 0 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I420, w, h, 32)) throw LumaException("Failed to allocate 8 bit 420 image"); else if (m_params.profile == 1 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I444, w, h, 32)) throw LumaException("Failed to allocate 8 bit 444 image"); else if (m_params.profile == 2 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I42016, w, h, 32)) throw LumaException("Failed to allocate 16 bit 420 image"); else if (m_params.profile == 3 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I44416, w, h, 32)) throw LumaException("Failed to allocate 16 bit 444 image"); res = vpx_codec_enc_config_default(vpx_encoder(), &cfg, 0); if (res) throw LumaException("Failed to get default codec config"); cfg.g_threads = 6; cfg.rc_min_quantizer = m_params.quantizerScale; cfg.rc_max_quantizer = m_params.quantizerScale; cfg.g_w = w; cfg.g_h = h; cfg.g_timebase.num = 1; cfg.g_timebase.den = 25; cfg.rc_target_bitrate = m_params.bitrate; cfg.g_error_resilient = 0; cfg.g_pass = VPX_RC_ONE_PASS; cfg.rc_end_usage = VPX_VBR; cfg.g_lag_in_frames = 0; cfg.rc_end_usage = VPX_Q; cfg.kf_max_dist = 25; cfg.kf_mode = VPX_KF_AUTO; cfg.g_profile = m_params.profile; fprintf(stderr, "Encoding options:\n"); fprintf(stderr, "--------------------------------------------------------\n"); fprintf(stderr, "Transfer function (PTF): %s\n", m_quant.name(m_params.ptf).c_str()); fprintf(stderr, "Color space: %s\n", m_quant.name(m_params.colorSpace).c_str()); fprintf(stderr, "PTF bit depth: %d\n", m_params.ptfBitDepth); fprintf(stderr, "Color bit depth: %d\n", m_params.colorBitDepth); fprintf(stderr, "Encoding profile: %d (4%d%d)\n", m_params.profile, (m_params.profile%2==0) ? 2 : 4, (m_params.profile%2==0) ? 2 : 4); fprintf(stderr, "Encoding bit depth: "); if (m_params.bitDepth == 8 || m_params.profile < 2) { cfg.g_bit_depth = VPX_BITS_8; fprintf(stderr, "8\n"); } else if (m_params.bitDepth == 10) { cfg.g_bit_depth = VPX_BITS_10; fprintf(stderr, "10\n"); } else { cfg.g_bit_depth = VPX_BITS_12; fprintf(stderr, "12\n"); } fprintf(stderr, "Codec: %s\n", vpx_codec_iface_name(vpx_encoder())); fprintf(stderr, "Output: %s\n", outputFile); fprintf(stderr, "--------------------------------------------------------\n\n"); int flags = m_params.profile < 2 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH; if (vpx_codec_enc_init(&m_codec, vpx_encoder(), &cfg, flags)) throw LumaException("Failed to initialize vpxEncoder\n"); if (m_params.lossLess && vpx_codec_control_(&m_codec, VP9E_SET_LOSSLESS, 1)) throw LumaException("Failed to use lossless mode\n"); m_initialized = true; return true; }
int main(int argc, char **argv) { FILE *infile = NULL; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_count = 0; vpx_image_t raw; vpx_codec_err_t res; VpxVideoInfo info; VpxVideoWriter *writer = NULL; const VpxInterface *encoder = NULL; const int fps = 2; // TODO(dkovalev) add command line argument const double bits_per_pixel_per_frame = 0.067; exec_name = argv[0]; if (argc != 6) die("Invalid number of arguments"); memset(&info, 0, sizeof(info)); encoder = get_vpx_encoder_by_name(argv[1]); if (encoder == NULL) { die("Unsupported codec."); } assert(encoder != NULL); info.codec_fourcc = encoder->fourcc; info.frame_width = strtol(argv[2], NULL, 0); info.frame_height = strtol(argv[3], NULL, 0); info.time_base.numerator = 1; info.time_base.denominator = fps; if (info.frame_width <= 0 || info.frame_height <= 0 || (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) { die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); } if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, info.frame_height, 1)) { die("Failed to allocate image."); } printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) die_codec(&codec, "Failed to get default codec config."); cfg.g_w = info.frame_width; cfg.g_h = info.frame_height; cfg.g_timebase.num = info.time_base.numerator; cfg.g_timebase.den = info.time_base.denominator; cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w * cfg.g_h * fps / 1000); cfg.g_lag_in_frames = 0; writer = vpx_video_writer_open(argv[5], kContainerIVF, &info); if (!writer) die("Failed to open %s for writing.", argv[5]); if (!(infile = fopen(argv[4], "rb"))) die("Failed to open %s for reading.", argv[4]); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) die_codec(&codec, "Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { ++frame_count; if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) { set_roi_map(&cfg, &codec); } else if (frame_count == 33) { set_active_map(&cfg, &codec); } else if (frame_count == 44) { unset_active_map(&cfg, &codec); } encode_frame(&codec, &raw, frame_count, writer); } // Flush encoder. while (encode_frame(&codec, NULL, -1, writer)) {} printf("\n"); fclose(infile); printf("Processed %d frames.\n", frame_count); vpx_img_free(&raw); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); vpx_video_writer_close(writer); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile, *outfile; vpx_codec_ctx_t codec; int flags = 0, frame_cnt = 0; unsigned char file_hdr[IVF_FILE_HDR_SZ]; unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; unsigned char frame[256*1024]; vpx_codec_err_t res; int n, m, is_range; // (void)res; /* Open files */ if(argc!=4) // die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]); // { // char *nptr; // n = strtol(argv[3], &nptr, 0); // m = strtol(nptr+1, NULL, 0); // is_range = *nptr == '-'; // if(!n || !m || (*nptr != '-' && *nptr != '/')) // die("Couldn't parse pattern %s\n", argv[3]); // } // if(!(infile = fopen(argv[1], "rb"))) die("Failed to open %s for reading", argv[1]); if(!(outfile = fopen(argv[2], "wb"))) die("Failed to open %s for writing", argv[2]); /* Read file header */ if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I' && file_hdr[3]=='F')) die("%s is not an IVF file.", argv[1]); printf("Using %s\n",vpx_codec_iface_name(interface)); /* Initialize codec */ if(vpx_codec_dec_init(&codec, interface, NULL, flags)) die_codec(&codec, "Failed to initialize decoder"); /* Read each frame */ while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) { int frame_sz = mem_get_le32(frame_hdr); vpx_codec_iter_t iter = NULL; vpx_image_t *img; frame_cnt++; if(frame_sz > sizeof(frame)) die("Frame %d data too big for example code buffer", frame_sz); if(fread(frame, 1, frame_sz, infile) != frame_sz) die("Frame %d failed to read complete frame", frame_cnt); if((is_range && frame_cnt >= n && frame_cnt <= m) // ||(!is_range && m - (frame_cnt-1)%m <= n)) { // putc('X', stdout); // continue; // } // putc('.', stdout); // fflush(stdout); // /* Decode the frame */ if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0)) die_codec(&codec, "Failed to decode frame"); /* Write decoded data to disk */ while((img = vpx_codec_get_frame(&codec, &iter))) { unsigned int plane, y; for(plane=0; plane < 3; plane++) { unsigned char *buf =img->planes[plane]; for(y=0; y<img->d_h >> (plane?1:0); y++) { if(fwrite(buf, 1, img->d_w >> (plane?1:0), outfile)); buf += img->stride[plane]; } } } } printf("Processed %d frames.\n",frame_cnt); if(vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); fclose(outfile); fclose(infile); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile = NULL; // Encoder vpx_codec_ctx_t ecodec = {0}; vpx_codec_enc_cfg_t cfg = {0}; unsigned int frame_in = 0; vpx_image_t raw; vpx_codec_err_t res; VpxVideoInfo info = {0}; VpxVideoWriter *writer = NULL; const VpxInterface *encoder = NULL; // Test encoder/decoder mismatch. int test_decode = 1; // Decoder vpx_codec_ctx_t dcodec; unsigned int frame_out = 0; // The frame number to set reference frame on unsigned int update_frame_num = 0; int mismatch_seen = 0; const int fps = 30; const int bitrate = 500; const char *width_arg = NULL; const char *height_arg = NULL; const char *infile_arg = NULL; const char *outfile_arg = NULL; unsigned int limit = 0; exec_name = argv[0]; if (argc < 6) die("Invalid number of arguments"); width_arg = argv[1]; height_arg = argv[2]; infile_arg = argv[3]; outfile_arg = argv[4]; encoder = get_vpx_encoder_by_name("vp9"); if (!encoder) die("Unsupported codec."); update_frame_num = atoi(argv[5]); // In VP9, the reference buffers (cm->buffer_pool->frame_bufs[i].buf) are // allocated while calling vpx_codec_encode(), thus, setting reference for // 1st frame isn't supported. if (update_frame_num <= 1) die("Couldn't parse frame number '%s'\n", argv[5]); if (argc > 6) { limit = atoi(argv[6]); if (update_frame_num > limit) die("Update frame number couldn't larger than limit\n"); } info.codec_fourcc = encoder->fourcc; info.frame_width = strtol(width_arg, NULL, 0); info.frame_height = strtol(height_arg, NULL, 0); info.time_base.numerator = 1; info.time_base.denominator = fps; if (info.frame_width <= 0 || info.frame_height <= 0 || (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) { die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); } if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, info.frame_height, 1)) { die("Failed to allocate image."); } printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) die_codec(&ecodec, "Failed to get default codec config."); cfg.g_w = info.frame_width; cfg.g_h = info.frame_height; cfg.g_timebase.num = info.time_base.numerator; cfg.g_timebase.den = info.time_base.denominator; cfg.rc_target_bitrate = bitrate; cfg.g_lag_in_frames = 3; writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info); if (!writer) die("Failed to open %s for writing.", outfile_arg); if (!(infile = fopen(infile_arg, "rb"))) die("Failed to open %s for reading.", infile_arg); if (vpx_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0)) die_codec(&ecodec, "Failed to initialize encoder"); // Disable alt_ref. if (vpx_codec_control(&ecodec, VP8E_SET_ENABLEAUTOALTREF, 0)) die_codec(&ecodec, "Failed to set enable auto alt ref"); if (test_decode) { const VpxInterface *decoder = get_vpx_decoder_by_name("vp9"); if (vpx_codec_dec_init(&dcodec, decoder->codec_interface(), NULL, 0)) die_codec(&dcodec, "Failed to initialize decoder."); } // Encode frames. while (vpx_img_read(&raw, infile)) { if (limit && frame_in >= limit) break; if (update_frame_num > 1 && frame_out + 1 == update_frame_num) { vpx_ref_frame_t ref; ref.frame_type = VP8_LAST_FRAME; ref.img = raw; // Set reference frame in encoder. if (vpx_codec_control(&ecodec, VP8_SET_REFERENCE, &ref)) die_codec(&ecodec, "Failed to set reference frame"); printf(" <SET_REF>"); // If set_reference in decoder is commented out, the enc/dec mismatch // would be seen. if (test_decode) { if (vpx_codec_control(&dcodec, VP8_SET_REFERENCE, &ref)) die_codec(&dcodec, "Failed to set reference frame"); } } encode_frame(&ecodec, &cfg, &raw, frame_in, writer, test_decode, &dcodec, &frame_out, &mismatch_seen); frame_in++; if (mismatch_seen) break; } // Flush encoder. if (!mismatch_seen) while (encode_frame(&ecodec, &cfg, NULL, frame_in, writer, test_decode, &dcodec, &frame_out, &mismatch_seen)) {} printf("\n"); fclose(infile); printf("Processed %d frames.\n", frame_out); if (test_decode) { if (!mismatch_seen) printf("Encoder/decoder results are matching.\n"); else printf("Encoder/decoder results are NOT matching.\n"); } if (test_decode) if (vpx_codec_destroy(&dcodec)) die_codec(&dcodec, "Failed to destroy decoder"); vpx_img_free(&raw); if (vpx_codec_destroy(&ecodec)) die_codec(&ecodec, "Failed to destroy encoder."); vpx_video_writer_close(writer); return EXIT_SUCCESS; }
static void parse_command_line(int argc, const char **argv_, AppInput *app_input, SvcContext *svc_ctx, vpx_codec_enc_cfg_t *enc_cfg) { struct arg arg; char **argv, **argi, **argj; vpx_codec_err_t res; // initialize SvcContext with parameters that will be passed to vpx_svc_init svc_ctx->log_level = SVC_LOG_DEBUG; svc_ctx->spatial_layers = default_spatial_layers; svc_ctx->encoding_mode = default_encoding_mode; // start with default encoder configuration res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0); if (res) { die("Failed to get config: %s\n", vpx_codec_err_to_string(res)); } // update enc_cfg with app default values enc_cfg->g_w = default_width; enc_cfg->g_h = default_height; enc_cfg->g_timebase.num = default_timebase_num; enc_cfg->g_timebase.den = default_timebase_den; enc_cfg->rc_target_bitrate = default_bitrate; enc_cfg->kf_min_dist = default_kf_dist; enc_cfg->kf_max_dist = default_kf_dist; // initialize AppInput with default values app_input->frames_to_code = default_frames_to_code; app_input->frames_to_skip = default_frames_to_skip; // process command line options argv = argv_dup(argc - 1, argv_ + 1); for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { arg.argv_step = 1; if (arg_match(&arg, &encoding_mode_arg, argi)) { svc_ctx->encoding_mode = arg_parse_enum_or_int(&arg); } else if (arg_match(&arg, &frames_arg, argi)) { app_input->frames_to_code = arg_parse_uint(&arg); } else if (arg_match(&arg, &width_arg, argi)) { enc_cfg->g_w = arg_parse_uint(&arg); } else if (arg_match(&arg, &height_arg, argi)) { enc_cfg->g_h = arg_parse_uint(&arg); } else if (arg_match(&arg, &timebase_arg, argi)) { enc_cfg->g_timebase = arg_parse_rational(&arg); } else if (arg_match(&arg, &bitrate_arg, argi)) { enc_cfg->rc_target_bitrate = arg_parse_uint(&arg); } else if (arg_match(&arg, &skip_frames_arg, argi)) { app_input->frames_to_skip = arg_parse_uint(&arg); } else if (arg_match(&arg, &layers_arg, argi)) { svc_ctx->spatial_layers = arg_parse_uint(&arg); } else if (arg_match(&arg, &kf_dist_arg, argi)) { enc_cfg->kf_min_dist = arg_parse_uint(&arg); enc_cfg->kf_max_dist = enc_cfg->kf_min_dist; } else if (arg_match(&arg, &scale_factors_arg, argi)) { vpx_svc_set_scale_factors(svc_ctx, arg.val); } else if (arg_match(&arg, &quantizers_arg, argi)) { vpx_svc_set_quantizers(svc_ctx, arg.val); } else { ++argj; } } // Check for unrecognized options for (argi = argv; *argi; ++argi) if (argi[0][0] == '-' && strlen(argi[0]) > 1) die("Error: Unrecognized option %s\n", *argi); if (argv[0] == NULL || argv[1] == 0) { usage_exit(); } app_input->input_ctx.filename = argv[0]; app_input->output_filename = argv[1]; free(argv); if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 || enc_cfg->g_h % 2) die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h); printf( "Codec %s\nframes: %d, skip: %d\n" "mode: %d, layers: %d\n" "width %d, height: %d,\n" "num: %d, den: %d, bitrate: %d,\n" "gop size: %d\n", vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code, app_input->frames_to_skip, svc_ctx->encoding_mode, svc_ctx->spatial_layers, enc_cfg->g_w, enc_cfg->g_h, enc_cfg->g_timebase.num, enc_cfg->g_timebase.den, enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist); }
int main(int argc, char **argv) { VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_cnt = 0; vpx_image_t raw; vpx_codec_err_t res; unsigned int width; unsigned int height; int speed; int frame_avail; int got_data; int flags = 0; unsigned int i; int pts = 0; // PTS starts at 0. int frame_duration = 1; // 1 timebase tick per frame. int layering_mode = 0; int layer_flags[VPX_TS_MAX_PERIODICITY] = {0}; int flag_periodicity = 1; #if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION) vpx_svc_layer_id_t layer_id = {0, 0}; #else vpx_svc_layer_id_t layer_id = {0}; #endif const VpxInterface *encoder = NULL; FILE *infile = NULL; struct RateControlMetrics rc; int64_t cx_time = 0; const int min_args_base = 11; #if CONFIG_VP9_HIGHBITDEPTH vpx_bit_depth_t bit_depth = VPX_BITS_8; int input_bit_depth = 8; const int min_args = min_args_base + 1; #else const int min_args = min_args_base; #endif // CONFIG_VP9_HIGHBITDEPTH double sum_bitrate = 0.0; double sum_bitrate2 = 0.0; double framerate = 30.0; exec_name = argv[0]; // Check usage and arguments. if (argc < min_args) { #if CONFIG_VP9_HIGHBITDEPTH die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> " "<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]); #else die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> " "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]); #endif // CONFIG_VP9_HIGHBITDEPTH } encoder = get_vpx_encoder_by_name(argv[3]); if (!encoder) die("Unsupported codec."); printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); width = strtol(argv[4], NULL, 0); height = strtol(argv[5], NULL, 0); if (width < 16 || width % 2 || height < 16 || height % 2) { die("Invalid resolution: %d x %d", width, height); } layering_mode = strtol(argv[10], NULL, 0); if (layering_mode < 0 || layering_mode > 12) { die("Invalid layering mode (0..12) %s", argv[10]); } if (argc != min_args + mode_to_num_layers[layering_mode]) { die("Invalid number of arguments"); } #if CONFIG_VP9_HIGHBITDEPTH switch (strtol(argv[argc-1], NULL, 0)) { case 8: bit_depth = VPX_BITS_8; input_bit_depth = 8; break; case 10: bit_depth = VPX_BITS_10; input_bit_depth = 10; break; case 12: bit_depth = VPX_BITS_12; input_bit_depth = 12; break; default: die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]); } if (!vpx_img_alloc(&raw, bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016, width, height, 32)) { die("Failed to allocate image", width, height); } #else if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) { die("Failed to allocate image", width, height); } #endif // CONFIG_VP9_HIGHBITDEPTH // Populate encoder configuration. res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); return EXIT_FAILURE; } // Update the default configuration with our settings. cfg.g_w = width; cfg.g_h = height; #if CONFIG_VP9_HIGHBITDEPTH if (bit_depth != VPX_BITS_8) { cfg.g_bit_depth = bit_depth; cfg.g_input_bit_depth = input_bit_depth; cfg.g_profile = 2; } #endif // CONFIG_VP9_HIGHBITDEPTH // Timebase format e.g. 30fps: numerator=1, demoninator = 30. cfg.g_timebase.num = strtol(argv[6], NULL, 0); cfg.g_timebase.den = strtol(argv[7], NULL, 0); speed = strtol(argv[8], NULL, 0); if (speed < 0) { die("Invalid speed setting: must be positive"); } for (i = min_args_base; (int)i < min_args_base + mode_to_num_layers[layering_mode]; ++i) { rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0); if (strncmp(encoder->name, "vp8", 3) == 0) cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11]; else if (strncmp(encoder->name, "vp9", 3) == 0) cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11]; } // Real time parameters. cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0); cfg.rc_end_usage = VPX_CBR; cfg.rc_min_quantizer = 2; cfg.rc_max_quantizer = 56; if (strncmp(encoder->name, "vp9", 3) == 0) cfg.rc_max_quantizer = 52; cfg.rc_undershoot_pct = 50; cfg.rc_overshoot_pct = 50; cfg.rc_buf_initial_sz = 500; cfg.rc_buf_optimal_sz = 600; cfg.rc_buf_sz = 1000; // Disable dynamic resizing by default. cfg.rc_resize_allowed = 0; // Use 1 thread as default. cfg.g_threads = 1; // Enable error resilient mode. cfg.g_error_resilient = 1; cfg.g_lag_in_frames = 0; cfg.kf_mode = VPX_KF_AUTO; // Disable automatic keyframe placement. cfg.kf_min_dist = cfg.kf_max_dist = 3000; cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; set_temporal_layer_pattern(layering_mode, &cfg, layer_flags, &flag_periodicity); set_rate_control_metrics(&rc, &cfg); // Target bandwidth for the whole stream. // Set to layer_target_bitrate for highest layer (total bitrate). cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1]; // Open input file. if (!(infile = fopen(argv[1], "rb"))) { die("Failed to open %s for reading", argv[1]); } framerate = cfg.g_timebase.den / cfg.g_timebase.num; // Open an output file for each stream. for (i = 0; i < cfg.ts_number_layers; ++i) { char file_name[PATH_MAX]; VpxVideoInfo info; info.codec_fourcc = encoder->fourcc; info.frame_width = cfg.g_w; info.frame_height = cfg.g_h; info.time_base.numerator = cfg.g_timebase.num; info.time_base.denominator = cfg.g_timebase.den; snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i); outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info); if (!outfile[i]) die("Failed to open %s for writing", file_name); assert(outfile[i] != NULL); } // No spatial layers in this encoder. cfg.ss_number_layers = 1; // Initialize codec. #if CONFIG_VP9_HIGHBITDEPTH if (vpx_codec_enc_init( &codec, encoder->codec_interface(), &cfg, bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH)) #else if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) #endif // CONFIG_VP9_HIGHBITDEPTH die_codec(&codec, "Failed to initialize encoder"); // configuration for vp8/vp9 if (strncmp(encoder->name, "vp8", 3) == 0) { vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff); vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0); } else if (strncmp(encoder->name, "vp9", 3) == 0) { vpx_svc_extra_cfg_t svc_params; vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed); vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3); vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0); vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0); vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0); vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0); vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1)); if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) die_codec(&codec, "Failed to set SVC"); for (i = 0; i < cfg.ts_number_layers; ++i) { svc_params.max_quantizers[i] = cfg.rc_max_quantizer; svc_params.min_quantizers[i] = cfg.rc_min_quantizer; } svc_params.scaling_factor_num[0] = cfg.g_h; svc_params.scaling_factor_den[0] = cfg.g_h; vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params); }
int main(int argc, char **argv) { FILE *infile, *outfile; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_cnt = 0; vpx_image_t raw; vpx_codec_err_t res; long width; long height; int frame_avail; int got_data; int flags = 0; /* Open files */ if(argc!=5) die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]); width = strtol(argv[1], NULL, 0); height = strtol(argv[2], NULL, 0); if(width < 16 || width%2 || height <16 || height%2) die("Invalid resolution: %ldx%ld", width, height); if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)) die("Faile to allocate image", width, height); if(!(outfile = fopen(argv[4], "wb"))) die("Failed to open %s for writing", argv[4]); printf("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ // res = vpx_codec_enc_config_default(interface, &cfg, 0); // if(res) { // printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); // return EXIT_FAILURE; // } // /* Update the default configuration with our settings */ // cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate // / cfg.g_w / cfg.g_h; // cfg.g_w = width; // cfg.g_h = height; // write_ivf_file_header(outfile, &cfg, 0); /* Open input file for this encoding pass */ if(!(infile = fopen(argv[3], "rb"))) die("Failed to open %s for reading", argv[3]); /* Initialize codec */ // if(vpx_codec_enc_init(&codec, interface, &cfg, 0)) // die_codec(&codec, "Failed to initialize encoder"); // frame_avail = 1; got_data = 0; while(frame_avail || got_data) { vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; frame_avail = read_frame(infile, &raw); // if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt, // 1, flags, VPX_DL_REALTIME)) // die_codec(&codec, "Failed to encode frame"); // got_data = 0; while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { got_data = 1; switch(pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: // write_ivf_frame_header(outfile, pkt); // if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, // outfile)); // break; // default: break; } printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"."); fflush(stdout); } frame_cnt++; } printf("\n"); fclose(infile); printf("Processed %d frames.\n",frame_cnt-1); if(vpx_codec_destroy(&codec)) // die_codec(&codec, "Failed to destroy codec"); // /* Try to rewrite the file header with the actual frame count */ if(!fseek(outfile, 0, SEEK_SET)) write_ivf_file_header(outfile, &cfg, frame_cnt-1); fclose(outfile); return EXIT_SUCCESS; }
int main(int argc, char **argv) { vpx_codec_ctx_t decoder; vpx_codec_iface_t *iface = ifaces[0].iface; vpx_codec_iter_t iter; vpx_codec_dec_cfg_t cfg; vpx_codec_err_t res = VPX_CODEC_OK; unsigned int alloc_sz = 0; unsigned int w = 352; unsigned int h = 288; int i; exec_name = argv[0]; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--codec")) { if (i + 1 < argc) { int j, k = -1; i++; for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++) if (!strcmp(ifaces[j].name, argv[i])) k = j; if (k >= 0) iface = ifaces[k].iface; else usage_error("Error: Unrecognized argument (%s) to --codec\n", argv[i]); } else usage_error("Error: Option --codec requires argument.\n"); } else if (!strcmp(argv[i], "-v")) verbose = 1; else if (!strcmp(argv[i], "-h")) if (i + 1 < argc) { h = atoi(argv[++i]); } else usage_error("Error: Option -h requires argument.\n"); else if (!strcmp(argv[i], "-w")) if (i + 1 < argc) { w = atoi(argv[++i]); } else usage_error("Error: Option -w requires argument.\n"); else if (!strcmp(argv[i], "--help")) usage_exit(); else usage_error("Error: Unrecognized option %s\n\n", argv[i]); } if (argc == 1) printf("Using built-in defaults. For options, rerun with --help\n\n"); /* XMA mode is not supported on all decoders! */ if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA)) { printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface)); return EXIT_FAILURE; } /* The codec knows how much memory to allocate based on the size of the * encoded frames. This data can be parsed from the bitstream with * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise, * a fixed size can be used that will be the upper limit on the frame * size the decoder can decode. */ cfg.w = w; cfg.h = h; /* Initialize the decoder in XMA mode. */ if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA)) { printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } /* Iterate through the list of memory maps, allocating them with the * requested alignment. */ iter = NULL; do { vpx_codec_mmap_t mmap; unsigned int align; res = vpx_codec_get_mem_map(&decoder, &mmap, &iter); align = mmap.align ? mmap.align - 1 : 0; if (!res) { if (verbose) printf("Allocating segment %u, size %lu, align %u %s\n", mmap.id, mmap.sz, mmap.align, mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : ""); if (mmap.flags & VPX_CODEC_MEM_ZERO) mmap.priv = calloc(1, mmap.sz + align); else mmap.priv = malloc(mmap.sz + align); mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align); mmap.dtor = my_mem_dtor; alloc_sz += mmap.sz + align; if (vpx_codec_set_mem_map(&decoder, &mmap, 1)) { printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } } else if (res != VPX_CODEC_LIST_END) { printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } } while (res != VPX_CODEC_LIST_END); printf("%s\n %d bytes external memory required for %dx%d.\n", decoder.name, alloc_sz, cfg.w, cfg.h); vpx_codec_destroy(&decoder); return EXIT_SUCCESS; }
int main(int argc, char **argv) { FILE *infile = NULL; vpx_codec_ctx_t codec; vpx_codec_enc_cfg_t cfg; int frame_count = 0; vpx_image_t raw; vpx_codec_err_t res; VpxVideoInfo info; VpxVideoWriter *writer = NULL; const VpxInterface *encoder = NULL; int update_frame_num = 0; const int fps = 30; // TODO(dkovalev) add command line argument const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument vp8_zero(codec); vp8_zero(cfg); vp8_zero(info); exec_name = argv[0]; if (argc != 6) die("Invalid number of arguments"); // TODO(dkovalev): add vp9 support and rename the file accordingly encoder = get_vpx_encoder_by_name("vp8"); if (!encoder) die("Unsupported codec."); update_frame_num = atoi(argv[5]); if (!update_frame_num) die("Couldn't parse frame number '%s'\n", argv[5]); info.codec_fourcc = encoder->fourcc; info.frame_width = (int)strtol(argv[1], NULL, 0); info.frame_height = (int)strtol(argv[2], NULL, 0); info.time_base.numerator = 1; info.time_base.denominator = fps; if (info.frame_width <= 0 || info.frame_height <= 0 || (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) { die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); } if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, info.frame_height, 1)) { die("Failed to allocate image."); } printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); if (res) die_codec(&codec, "Failed to get default codec config."); cfg.g_w = info.frame_width; cfg.g_h = info.frame_height; cfg.g_timebase.num = info.time_base.numerator; cfg.g_timebase.den = info.time_base.denominator; cfg.rc_target_bitrate = bitrate; writer = vpx_video_writer_open(argv[4], kContainerIVF, &info); if (!writer) die("Failed to open %s for writing.", argv[4]); if (!(infile = fopen(argv[3], "rb"))) die("Failed to open %s for reading.", argv[3]); if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) die_codec(&codec, "Failed to initialize encoder"); // Encode frames. while (vpx_img_read(&raw, infile)) { if (frame_count + 1 == update_frame_num) { vpx_ref_frame_t ref; ref.frame_type = VP8_LAST_FRAME; ref.img = raw; if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref)) die_codec(&codec, "Failed to set reference frame"); } encode_frame(&codec, &raw, frame_count++, writer); } // Flush encoder. while (encode_frame(&codec, NULL, -1, writer)) { } printf("\n"); fclose(infile); printf("Processed %d frames.\n", frame_count); vpx_img_free(&raw); if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); vpx_video_writer_close(writer); return EXIT_SUCCESS; }