Exemple #1
0
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;
}
Exemple #2
0
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");
}
Exemple #4
0
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:");
}
Exemple #5
0
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);
}