static void *aac_create(obs_data_t settings, obs_encoder_t encoder) { struct aac_encoder *enc; int bitrate = (int)obs_data_getint(settings, "bitrate"); audio_t audio = obs_encoder_audio(encoder); if (!bitrate) { aac_warn("aac_create", "Invalid bitrate specified"); return NULL; } avcodec_register_all(); enc = bzalloc(sizeof(struct aac_encoder)); enc->encoder = encoder; enc->aac = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!enc->aac) { aac_warn("aac_create", "Couldn't find encoder"); goto fail; } blog(LOG_INFO, "Using ffmpeg \"%s\" aac encoder", enc->aac->name); enc->context = avcodec_alloc_context3(enc->aac); if (!enc->context) { aac_warn("aac_create", "Failed to create codec context"); goto fail; } enc->context->bit_rate = bitrate * 1000; enc->context->channels = (int)audio_output_channels(audio); enc->context->sample_rate = audio_output_samplerate(audio); enc->context->sample_fmt = enc->aac->sample_fmts ? enc->aac->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; init_sizes(enc, audio); /* enable experimental FFmpeg encoder if the only one available */ enc->context->strict_std_compliance = -2; enc->context->flags = CODEC_FLAG_GLOBAL_HEADER; if (initialize_codec(enc)) return enc; fail: aac_destroy(enc); return NULL; }
static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder) { struct aac_encoder *enc; int bitrate = (int)obs_data_get_int(settings, "bitrate"); audio_t *audio = obs_encoder_audio(encoder); avcodec_register_all(); enc = bzalloc(sizeof(struct aac_encoder)); enc->encoder = encoder; enc->aac = avcodec_find_encoder(AV_CODEC_ID_AAC); blog(LOG_INFO, "---------------------------------"); if (!enc->aac) { warn("Couldn't find encoder"); goto fail; } if (!bitrate) { warn("Invalid bitrate specified"); return NULL; } enc->context = avcodec_alloc_context3(enc->aac); if (!enc->context) { warn("Failed to create codec context"); goto fail; } enc->context->bit_rate = bitrate * 1000; enc->context->channels = (int)audio_output_get_channels(audio); enc->context->sample_rate = audio_output_get_sample_rate(audio); enc->context->sample_fmt = enc->aac->sample_fmts ? enc->aac->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; /* if using FFmpeg's AAC encoder, at least set a cutoff value * (recommended by konverter) */ if (strcmp(enc->aac->name, "aac") == 0) { int cutoff1 = 4000 + (int)enc->context->bit_rate / 8; int cutoff2 = 12000 + (int)enc->context->bit_rate / 8; int cutoff3 = enc->context->sample_rate / 2; int cutoff; cutoff = MIN(cutoff1, cutoff2); cutoff = MIN(cutoff, cutoff3); enc->context->cutoff = cutoff; } info("bitrate: %" PRId64 ", channels: %d", enc->context->bit_rate / 1000, enc->context->channels); init_sizes(enc, audio); /* enable experimental FFmpeg encoder if the only one available */ enc->context->strict_std_compliance = -2; enc->context->flags = CODEC_FLAG_GLOBAL_HEADER; if (initialize_codec(enc)) return enc; fail: aac_destroy(enc); return NULL; }
static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder, const char *type, const char *alt) { struct enc_encoder *enc; int bitrate = (int)obs_data_get_int(settings, "bitrate"); audio_t *audio = obs_encoder_audio(encoder); avcodec_register_all(); enc = bzalloc(sizeof(struct enc_encoder)); enc->encoder = encoder; enc->codec = avcodec_find_encoder_by_name(type); enc->type = type; if (!enc->codec && alt) { enc->codec = avcodec_find_encoder_by_name(alt); enc->type = alt; } blog(LOG_INFO, "---------------------------------"); if (!enc->codec) { warn("Couldn't find encoder"); goto fail; } if (!bitrate) { warn("Invalid bitrate specified"); return NULL; } enc->context = avcodec_alloc_context3(enc->codec); if (!enc->context) { warn("Failed to create codec context"); goto fail; } enc->context->bit_rate = bitrate * 1000; enc->context->channels = (int)audio_output_get_channels(audio); enc->context->sample_rate = audio_output_get_sample_rate(audio); enc->context->sample_fmt = enc->codec->sample_fmts ? enc->codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; /* check to make sure sample rate is supported */ if (enc->codec->supported_samplerates) { const int *rate = enc->codec->supported_samplerates; int cur_rate = enc->context->sample_rate; int closest = 0; while (*rate) { int dist = abs(cur_rate - *rate); int closest_dist = abs(cur_rate - closest); if (dist < closest_dist) closest = *rate; rate++; } if (closest) enc->context->sample_rate = closest; } /* if using FFmpeg's AAC encoder, at least set a cutoff value * (recommended by konverter) */ if (strcmp(enc->codec->name, "aac") == 0) { int cutoff1 = 4000 + (int)enc->context->bit_rate / 8; int cutoff2 = 12000 + (int)enc->context->bit_rate / 8; int cutoff3 = enc->context->sample_rate / 2; int cutoff; cutoff = MIN(cutoff1, cutoff2); cutoff = MIN(cutoff, cutoff3); enc->context->cutoff = cutoff; } info("bitrate: %" PRId64 ", channels: %d", enc->context->bit_rate / 1000, enc->context->channels); init_sizes(enc, audio); /* enable experimental FFmpeg encoder if the only one available */ enc->context->strict_std_compliance = -2; enc->context->flags = CODEC_FLAG_GLOBAL_HEADER; if (initialize_codec(enc)) return enc; fail: enc_destroy(enc); return NULL; }
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; int frame_avail = 1; int got_data = 0; int i; int frames_in_layer[MAX_LAYERS] = {0}; clock_t before; clock_t after; int pts = 0; /* PTS starts at 0 */ int frame_duration = 1; /* 1 timebase tick per frame */ parse_command_line(argc, argv, &cfg); // Allocate image buffer if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 32)) die("Failed to allocate image", cfg.g_w, cfg.g_h); set_default_configuration(&cfg); /* Open input file */ if (!(infile = fopen(input_filename, "rb"))) die("Failed to open %s for reading", argv[1]); /* Open output file */ for (i = 0; i < number_spatial_layers; i++) { char file_name[512]; snprintf(file_name, sizeof(file_name), "%s_%d.ivf", output_filename, 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(&codec, &cfg); // skip initial frames for (i = 0; i < number_frames_to_skip; i++) { read_frame(infile, &raw); } before = clock(); // Encoding frames while ((frame_avail || got_data) && frame_cnt <= number_frames_to_code * number_spatial_layers) { int flags = 0; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; int layer = calculate_layer(frame_cnt, number_spatial_layers); int is_I_frame_in_layer = (((frame_cnt - 1) / number_spatial_layers % key_period) == 0); int is_dummy = (frame_cnt == 0); if (is_dummy) { // Dummy frame flags = VPX_EFLAG_FORCE_KF; frame_avail = read_dummy_frame(&raw); } else { // Regular frame // Read a new frame only at the base layer if (layer == 0) frame_avail = read_frame(infile, &raw); switch_to_layer(layer, cfg.g_w, cfg.g_h, &codec); flags = get_flag(is_I_frame_in_layer, layer, INTER_LAYER_PREDICTION_I); } // Actual Encoding if (vpx_codec_encode(&codec, frame_avail ? &raw : NULL, pts, 1, flags, VPX_DL_REALTIME)) die_codec(&codec, "Failed to encode frame"); got_data = 0; // Process data / Get PSNR statistics while ((pkt = vpx_codec_get_cx_data(&codec, &iter))) { got_data = 1; switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: for (i = layer; i < number_spatial_layers; i++) { write_ivf_frame_header(outfile[i], pkt); (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile[i]); frames_in_layer[i]++; } break; case VPX_CODEC_PSNR_PKT: if (frame_cnt != 0) printf( "Processed Frame %d, layer %d, PSNR(Total/Y/U/V): " "%2.3f %2.3f %2.3f %2.3f \n", (frame_cnt - 1) / number_spatial_layers + 1, layer, pkt->data.psnr.psnr[0], pkt->data.psnr.psnr[1], pkt->data.psnr.psnr[2], pkt->data.psnr.psnr[3]); break; default: break; } } frame_cnt++; // TODO(ivan): Modify ts later if(!layer) pts += frame_duration; } // end while after = clock(); printf("Processed %d frames in different resolutions in %ld ms.\n", frame_cnt - 1, (int)(after - before) / (CLOCKS_PER_SEC / 1000)); fclose(infile); 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 < number_spatial_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; }