static bool obs_qsv_encode(void *data, struct encoder_frame *frame, struct encoder_packet *packet, bool *received_packet) { struct obs_qsv *obsqsv = data; if (!frame || !packet || !received_packet) return false; EnterCriticalSection(&g_QsvCs); video_t *video = obs_encoder_video(obsqsv->encoder); const struct video_output_info *voi = video_output_get_info(video); mfxBitstream *pBS = NULL; int ret; mfxU64 qsvPTS = frame->pts * 90000 / voi->fps_num; if (frame) ret = qsv_encoder_encode( obsqsv->context, qsvPTS, frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], &pBS); else ret = qsv_encoder_encode( obsqsv->context, qsvPTS, NULL, NULL, 0, 0, &pBS); if (ret < 0) { warn("encode failed"); return false; } parse_packet(obsqsv, packet, pBS, voi->fps_num, received_packet); LeaveCriticalSection(&g_QsvCs); return true; }
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 update_params(struct obs_x264 *obsx264, obs_data_t *settings, char **params) { video_t *video = obs_encoder_video(obsx264->encoder); const struct video_output_info *voi = video_output_get_info(video); struct video_scale_info info; info.format = voi->format; info.colorspace = voi->colorspace; info.range = voi->range; obs_x264_video_info(obsx264, &info); int bitrate = (int)obs_data_get_int(settings, "bitrate"); int buffer_size = (int)obs_data_get_int(settings, "buffer_size"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); int crf = (int)obs_data_get_int(settings, "crf"); int width = (int)obs_encoder_get_width(obsx264->encoder); int height = (int)obs_encoder_get_height(obsx264->encoder); bool use_bufsize = obs_data_get_bool(settings, "use_bufsize"); bool vfr = obs_data_get_bool(settings, "vfr"); bool cbr = obs_data_get_bool(settings, "cbr"); if (keyint_sec) obsx264->params.i_keyint_max = keyint_sec * voi->fps_num / voi->fps_den; if (!use_bufsize) buffer_size = bitrate; obsx264->params.b_vfr_input = vfr; obsx264->params.rc.i_vbv_max_bitrate = bitrate; obsx264->params.rc.i_vbv_buffer_size = buffer_size; obsx264->params.rc.i_bitrate = bitrate; obsx264->params.i_width = width; obsx264->params.i_height = height; obsx264->params.i_fps_num = voi->fps_num; obsx264->params.i_fps_den = voi->fps_den; obsx264->params.pf_log = log_x264; obsx264->params.p_log_private = obsx264; obsx264->params.i_log_level = X264_LOG_WARNING; obsx264->params.vui.i_transfer = get_x264_cs_val(info.colorspace, x264_transfer_names); obsx264->params.vui.i_colmatrix = get_x264_cs_val(info.colorspace, x264_colmatrix_names); obsx264->params.vui.i_colorprim = get_x264_cs_val(info.colorspace, x264_colorprim_names); obsx264->params.vui.b_fullrange = info.range == VIDEO_RANGE_FULL; /* use the new filler method for CBR to allow real-time adjusting of * the bitrate */ if (cbr) { obsx264->params.rc.f_rf_constant = 0.0f; obsx264->params.rc.i_rc_method = X264_RC_ABR; #if X264_BUILD >= 139 obsx264->params.rc.b_filler = true; #else obsx264->params.i_nal_hrd = X264_NAL_HRD_CBR; #endif } else { obsx264->params.rc.i_rc_method = X264_RC_CRF; obsx264->params.rc.f_rf_constant = (float)crf; } if (info.format == VIDEO_FORMAT_NV12) obsx264->params.i_csp = X264_CSP_NV12; else if (info.format == VIDEO_FORMAT_I420) obsx264->params.i_csp = X264_CSP_I420; else if (info.format == VIDEO_FORMAT_I444) obsx264->params.i_csp = X264_CSP_I444; else obsx264->params.i_csp = X264_CSP_NV12; while (*params) set_param(obsx264, *(params++)); info("settings:\n" "\tbitrate: %d\n" "\tbuffer size: %d\n" "\tcrf: %d%s\n" "\tfps_num: %d\n" "\tfps_den: %d\n" "\twidth: %d\n" "\theight: %d\n" "\tkeyint: %d\n" "\tvfr: %s\n" "\tcbr: %s", obsx264->params.rc.i_vbv_max_bitrate, obsx264->params.rc.i_vbv_buffer_size, (int)obsx264->params.rc.f_rf_constant, cbr ? " (0 when CBR is enabled)" : "", voi->fps_num, voi->fps_den, width, height, obsx264->params.i_keyint_max, vfr ? "on" : "off", cbr ? "on" : "off"); }
static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) { video_t *video = obs_encoder_video(obsqsv->encoder); const struct video_output_info *voi = video_output_get_info(video); const char *target_usage = obs_data_get_string(settings, "target_usage"); const char *profile = obs_data_get_string(settings, "profile"); const char *rate_control = obs_data_get_string(settings, "rate_control"); int async_depth = (int)obs_data_get_int(settings, "async_depth"); int target_bitrate = (int)obs_data_get_int(settings, "bitrate"); int max_bitrate = (int)obs_data_get_int(settings, "max_bitrate"); int accuracy = (int)obs_data_get_int(settings, "accuracy"); int convergence = (int)obs_data_get_int(settings, "convergence"); int qpi = (int)obs_data_get_int(settings, "qpi"); int qpp = (int)obs_data_get_int(settings, "qpp"); int qpb = (int)obs_data_get_int(settings, "qpb"); int icq_quality = (int)obs_data_get_int(settings, "icq_quality"); int la_depth = (int)obs_data_get_int(settings, "la_depth"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); bool cbr_override = obs_data_get_bool(settings, "cbr"); int bFrames = 7; int width = (int)obs_encoder_get_width(obsqsv->encoder); int height = (int)obs_encoder_get_height(obsqsv->encoder); if (astrcmpi(target_usage, "quality") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_QUALITY; else if (astrcmpi(target_usage, "balanced") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BALANCED; else if (astrcmpi(target_usage, "speed") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_SPEED; if (astrcmpi(profile, "baseline") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_BASELINE; else if (astrcmpi(profile, "main") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_MAIN; else if (astrcmpi(profile, "high") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_HIGH; /* internal convenience parameter, overrides rate control param * XXX: Deprecated */ if (cbr_override) { warn("\"cbr\" setting has been deprecated for all encoders! " "Please set \"rate_control\" to \"CBR\" instead. " "Forcing CBR mode. " "(Note to all: this is why you shouldn't use strings for " "common settings)"); rate_control = "CBR"; } if (astrcmpi(rate_control, "CBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_CBR; else if (astrcmpi(rate_control, "VBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_VBR; else if (astrcmpi(rate_control, "VCM") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_VCM; else if (astrcmpi(rate_control, "CQP") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_CQP; else if (astrcmpi(rate_control, "AVBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_AVBR; else if (astrcmpi(rate_control, "ICQ") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_ICQ; else if (astrcmpi(rate_control, "LA_ICQ") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_LA_ICQ; else if (astrcmpi(rate_control, "LA") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_LA; obsqsv->params.nAsyncDepth = (mfxU16)async_depth; obsqsv->params.nAccuracy = (mfxU16)accuracy; obsqsv->params.nConvergence = (mfxU16)convergence; obsqsv->params.nQPI = (mfxU16)qpi; obsqsv->params.nQPP = (mfxU16)qpp; obsqsv->params.nQPB = (mfxU16)qpb; obsqsv->params.nLADEPTH = (mfxU16)la_depth; obsqsv->params.nTargetBitRate = (mfxU16)target_bitrate; obsqsv->params.nMaxBitRate = (mfxU16)max_bitrate; obsqsv->params.nWidth = (mfxU16)width; obsqsv->params.nHeight = (mfxU16)height; obsqsv->params.nFpsNum = (mfxU16)voi->fps_num; obsqsv->params.nFpsDen = (mfxU16)voi->fps_den; obsqsv->params.nbFrames = (mfxU16)bFrames; obsqsv->params.nKeyIntSec = (mfxU16)keyint_sec; obsqsv->params.nICQQuality = (mfxU16)icq_quality; info("settings:\n\trate_control: %s", rate_control); if (obsqsv->params.nRateControl != MFX_RATECONTROL_LA_ICQ && obsqsv->params.nRateControl != MFX_RATECONTROL_ICQ && obsqsv->params.nRateControl != MFX_RATECONTROL_CQP) blog(LOG_INFO, "\ttarget_bitrate: %d", (int)obsqsv->params.nTargetBitRate); if (obsqsv->params.nRateControl == MFX_RATECONTROL_VBR || obsqsv->params.nRateControl == MFX_RATECONTROL_VCM) blog(LOG_INFO, "\tmax_bitrate: %d", (int)obsqsv->params.nMaxBitRate); if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || obsqsv->params.nRateControl == MFX_RATECONTROL_ICQ) blog(LOG_INFO, "\tICQ Quality: %d", (int)obsqsv->params.nICQQuality); if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || obsqsv->params.nRateControl == MFX_RATECONTROL_LA) blog(LOG_INFO, "\tLookahead Depth:%d", (int)obsqsv->params.nLADEPTH); if (obsqsv->params.nRateControl == MFX_RATECONTROL_CQP) blog(LOG_INFO, "\tqpi: %d\n" "\tqpb: %d\n" "\tqpp: %d", qpi, qpb, qpp); blog(LOG_INFO, "\tfps_num: %d\n" "\tfps_den: %d\n" "\twidth: %d\n" "\theight: %d", voi->fps_num, voi->fps_den, width, height); info("debug info:"); }
static bool build_flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size, size_t a_idx) { obs_encoder_t *vencoder = obs_output_get_video_encoder(context); obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, a_idx); 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); struct dstr encoder_name = {0}; if (a_idx > 0 && !aencoder) return false; enc_str(&enc, end, "onMetaData"); *enc++ = AMF_ECMA_ARRAY; enc = AMF_EncodeInt32(enc, end, a_idx == 0 ? 14 : 9); enc_num_val(&enc, end, "duration", 0.0); enc_num_val(&enc, end, "fileSize", 0.0); if (a_idx == 0) { enc_num_val(&enc, end, "width", (double)obs_encoder_get_width(vencoder)); enc_num_val(&enc, end, "height", (double)obs_encoder_get_height(vencoder)); enc_str_val(&enc, end, "videocodecid", "avc1"); enc_num_val(&enc, end, "videodatarate", encoder_bitrate(vencoder)); enc_num_val(&enc, end, "framerate", video_output_get_frame_rate(video)); } enc_str_val(&enc, end, "audiocodecid", "mp4a"); enc_num_val(&enc, end, "audiodatarate", encoder_bitrate(aencoder)); enc_num_val(&enc, end, "audiosamplerate", (double)obs_encoder_get_sample_rate(aencoder)); enc_num_val(&enc, end, "audiosamplesize", 16.0); enc_num_val(&enc, end, "audiochannels", (double)audio_output_get_channels(audio)); enc_bool_val(&enc, end, "stereo", audio_output_get_channels(audio) == 2); enc_bool_val(&enc, end, "2.1", audio_output_get_channels(audio) == 3); enc_bool_val(&enc, end, "3.1", audio_output_get_channels(audio) == 4); enc_bool_val(&enc, end, "4.0", audio_output_get_channels(audio) == 4); enc_bool_val(&enc, end, "4.1", audio_output_get_channels(audio) == 5); enc_bool_val(&enc, end, "5.1", audio_output_get_channels(audio) == 6); enc_bool_val(&enc, end, "7.1", audio_output_get_channels(audio) == 8); dstr_printf(&encoder_name, "%s (libobs version ", MODULE_NAME); #ifdef HAVE_OBSCONFIG_H dstr_cat(&encoder_name, OBS_VERSION); #else dstr_catf(&encoder_name, "%d.%d.%d", LIBOBS_API_MAJOR_VER, LIBOBS_API_MINOR_VER, LIBOBS_API_PATCH_VER); #endif dstr_cat(&encoder_name, ")"); enc_str_val(&enc, end, "encoder", encoder_name.array); dstr_free(&encoder_name); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; *size = enc-buf; *output = bmemdup(buf, *size); return true; }
static bool vaapi_update(void *data, obs_data_t *settings) { struct vaapi_encoder *enc = data; const char *device = obs_data_get_string(settings, "vaapi_device"); int profile = (int)obs_data_get_int(settings, "profile"); int bf = (int)obs_data_get_int(settings, "bf"); int level = (int)obs_data_get_int(settings, "level"); int bitrate = (int)obs_data_get_int(settings, "bitrate"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); int qp = (int)obs_data_get_int(settings, "qp"); int quality = (int)obs_data_get_int(settings, "quality"); av_opt_set_int(enc->context->priv_data, "qp", qp, 0); av_opt_set_int(enc->context->priv_data, "quality", quality, 0); video_t * video = obs_encoder_video(enc->encoder); const struct video_output_info *voi = video_output_get_info(video); struct video_scale_info info; info.format = voi->format; info.colorspace = voi->colorspace; info.range = voi->range; vaapi_video_info(enc, &info); enc->context->profile = profile; enc->context->max_b_frames = bf; enc->context->level = level; enc->context->bit_rate = bitrate * 1000; enc->context->width = obs_encoder_get_width(enc->encoder); enc->context->height = obs_encoder_get_height(enc->encoder); enc->context->time_base = (AVRational){voi->fps_den, voi->fps_num}; enc->context->pix_fmt = obs_to_ffmpeg_video_format(info.format); enc->context->colorspace = info.colorspace == VIDEO_CS_709 ? AVCOL_SPC_BT709 : AVCOL_SPC_BT470BG; enc->context->color_range = info.range == VIDEO_RANGE_FULL ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; if (keyint_sec > 0) { enc->context->gop_size = keyint_sec * voi->fps_num / voi->fps_den; } else { enc->context->gop_size = 120; } enc->height = enc->context->height; info("settings:\n" "\tdevice: %s\n" "\tqp: %d\n" "\tquality: %d\n" "\tprofile: %d\n" "\tlevel: %d\n" "\tbitrate: %d\n" "\tkeyint: %d\n" "\twidth: %d\n" "\theight: %d\n" "\tb-frames: %d\n", device, qp, quality, profile, level, bitrate, enc->context->gop_size, enc->context->width, enc->context->height, enc->context->max_b_frames); return vaapi_init_codec(enc, device); }