static void build_flv_meta_data(obs_output_t context, uint8_t **output, size_t *size) { obs_encoder_t vencoder = obs_output_get_video_encoder(context); obs_encoder_t aencoder = obs_output_get_audio_encoder(context); video_t video = obs_encoder_video(vencoder); audio_t audio = obs_encoder_audio(aencoder); char buf[4096]; char *enc = buf; char *end = enc+sizeof(buf); enc_str(&enc, end, "onMetaData"); *enc++ = AMF_ECMA_ARRAY; enc = AMF_EncodeInt32(enc, end, 14); enc_num_val(&enc, end, "duration", 0.0); enc_num_val(&enc, end, "fileSize", 0.0); enc_num_val(&enc, end, "width", (double)video_output_width(video)); enc_num_val(&enc, end, "height", (double)video_output_height(video)); enc_str_val(&enc, end, "videocodecid", "avc1"); enc_num_val(&enc, end, "videodatarate", encoder_bitrate(vencoder)); enc_num_val(&enc, end, "framerate", video_output_framerate(video)); enc_str_val(&enc, end, "audiocodecid", "mp4a"); enc_num_val(&enc, end, "audiodatarate", encoder_bitrate(aencoder)); enc_num_val(&enc, end, "audiosamplerate", (double)audio_output_samplerate(audio)); enc_num_val(&enc, end, "audiosamplesize", 16.0); enc_num_val(&enc, end, "audiochannels", (double)audio_output_channels(audio)); enc_bool_val(&enc, end, "stereo", audio_output_channels(audio) == 2); enc_str_val(&enc, end, "encoder", MODULE_NAME); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; *size = enc-buf; *output = bmemdup(buf, *size); }
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 *libfdk_create(obs_data_t settings, obs_encoder_t encoder) { bool hasFdkHandle = false; libfdk_encoder_t *enc = 0; int bitrate = (int)obs_data_getint(settings, "bitrate") * 1000; int afterburner = obs_data_getbool(settings, "afterburner") ? 1 : 0; audio_t audio = obs_encoder_audio(encoder); int mode = 0; AACENC_ERROR err; if (!bitrate) { blog(LOG_ERROR, "Invalid bitrate"); return NULL; } enc = bzalloc(sizeof(libfdk_encoder_t)); enc->encoder = encoder; enc->channels = (int)audio_output_channels(audio); enc->sample_rate = audio_output_samplerate(audio); switch(enc->channels) { case 1: mode = MODE_1; break; case 2: mode = MODE_2; break; case 3: mode = MODE_1_2; break; case 4: mode = MODE_1_2_1; break; case 5: mode = MODE_1_2_2; break; case 6: mode = MODE_1_2_2_1; break; default: blog(LOG_ERROR, "Invalid channel count"); goto fail; } CHECK_LIBFDK(aacEncOpen(&enc->fdkhandle, 0, enc->channels)); hasFdkHandle = true; CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_AOT, 2)); // MPEG-4 AAC-LC CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_SAMPLERATE, enc->sample_rate)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_CHANNELMODE, mode)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_CHANNELORDER, 1)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_BITRATEMODE, 0)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_BITRATE, bitrate)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_TRANSMUX, 0)); CHECK_LIBFDK(aacEncoder_SetParam(enc->fdkhandle, AACENC_AFTERBURNER, afterburner)); CHECK_LIBFDK(aacEncEncode(enc->fdkhandle, NULL, NULL, NULL, NULL)); CHECK_LIBFDK(aacEncInfo(enc->fdkhandle, &enc->info)); enc->frame_size_bytes = enc->info.frameLength * 2 * enc->channels; enc->packet_buffer_size = enc->channels * 768; if(enc->packet_buffer_size < 8192) enc->packet_buffer_size = 8192; enc->packet_buffer = bmalloc(enc->packet_buffer_size); blog(LOG_INFO, "libfdk_aac encoder created"); return enc; fail: if(hasFdkHandle) aacEncClose(&enc->fdkhandle); if(enc->packet_buffer) bfree(enc->packet_buffer); if(enc) bfree(enc); blog(LOG_WARNING, "libfdk_aac encoder creation failed"); return 0; }