Exemple #1
0
static inline void ep_write_param(struct dstr *shader, struct ep_param *param,
		struct darray *used_params)
{
	if (param->written)
		return;

	if (param->is_const) {
		dstr_cat(shader, "const ");
	} else if (param->is_uniform) {
		struct dstr new;
		dstr_init_copy(&new, param->name);
		darray_push_back(sizeof(struct dstr), used_params, &new);

		dstr_cat(shader, "uniform ");
	}

	dstr_cat(shader, param->type);
	dstr_cat(shader, " ");
	dstr_cat(shader, param->name);

	if (param->array_count)
		dstr_catf(shader, "[%u]", param->array_count);

	dstr_cat(shader, ";\n");

	param->written = true;
}
static inline void write_thread_trace(struct exception_handler_data *data,
		THREADENTRY32 *entry)
{
	bool crash_thread = entry->th32ThreadID == GetCurrentThreadId();
	struct stack_trace trace = {0};
	struct stack_trace *ptrace;
	HANDLE thread;

	if (entry->th32OwnerProcessID != GetCurrentProcessId())
		return;

	thread = OpenThread(THREAD_ALL_ACCESS, false, entry->th32ThreadID);
	if (!thread)
		return;

	trace.context.ContextFlags = CONTEXT_ALL;
	GetThreadContext(thread, &trace.context);
	init_instruction_data(&trace);

	dstr_catf(&data->str, "\r\nThread %lX%s\r\n"TRACE_TOP,
			entry->th32ThreadID,
			crash_thread ? " (Crashed)" : "");

	ptrace = crash_thread ? &data->main_trace : &trace;

	while (walk_stack(data, thread, ptrace));

	CloseHandle(thread);
}
static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd)
{
	obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
	obs_encoder_t *aencoders[MAX_AUDIO_MIXES];
	int num_tracks = 0;

	for (;;) {
		obs_encoder_t *aencoder = obs_output_get_audio_encoder(
				stream->output, num_tracks);
		if (!aencoder)
			break;

		aencoders[num_tracks] = aencoder;
		num_tracks++;
	}

	dstr_init_move_array(cmd, obs_module_file(FFMPEG_MUX));
	dstr_insert_ch(cmd, 0, '\"');
	dstr_cat(cmd, "\" \"");
	dstr_cat_dstr(cmd, &stream->path);
	dstr_catf(cmd, "\" %d %d ", vencoder ? 1 : 0, num_tracks);

	if (vencoder)
		add_video_encoder_params(stream, cmd, vencoder);

	if (num_tracks) {
		dstr_cat(cmd, "aac ");

		for (int i = 0; i < num_tracks; i++) {
			add_audio_encoder_params(cmd, aencoders[i]);
		}
	}
}
static BOOL CALLBACK enum_monitor_props(HMONITOR handle, HDC hdc, LPRECT rect,
                                        LPARAM param)
{
    UNUSED_PARAMETER(hdc);
    UNUSED_PARAMETER(rect);

    obs_property_t *monitor_list = (obs_property_t*)param;
    MONITORINFO mi;
    size_t monitor_id = 0;
    struct dstr monitor_desc = { 0 };
    struct dstr resolution = { 0 };
    struct dstr format_string = { 0 };

    monitor_id = obs_property_list_item_count(monitor_list);

    mi.cbSize = sizeof(mi);
    GetMonitorInfo(handle, &mi);

    dstr_catf(&resolution,
              "%dx%d @ %d,%d",
              mi.rcMonitor.right - mi.rcMonitor.left,
              mi.rcMonitor.bottom - mi.rcMonitor.top,
              mi.rcMonitor.left,
              mi.rcMonitor.top);

    dstr_copy(&format_string, "%s %d: %s");
    if (mi.dwFlags == MONITORINFOF_PRIMARY) {
        dstr_catf(&format_string, " (%s)", TEXT_PRIMARY_MONITOR);
    }

    dstr_catf(&monitor_desc,
              format_string.array,
              TEXT_MONITOR,
              monitor_id,
              resolution.array);

    obs_property_list_add_int(monitor_list,
                              monitor_desc.array, (int)monitor_id);

    dstr_free(&monitor_desc);
    dstr_free(&resolution);
    dstr_free(&format_string);

    return TRUE;
}
static inline void write_header(struct exception_handler_data *data)
{
	dstr_catf(&data->str, "Unhandled exception: %x\r\n"
			"Fault address: %"PRIX64" (%s)\r\n"
			"libobs version: "OBS_VERSION"\r\n"
			"Windows version: %d.%d build %d (revision %d)\r\n"
			"CPU: %s\r\n\r\n",
			data->exception->ExceptionRecord->ExceptionCode,
			data->main_trace.instruction_ptr,
			data->module_name.array,
			data->win_version.major, data->win_version.minor,
			data->win_version.build, data->win_version.revis,
			data->cpu_info.array);
}
static BOOL CALLBACK enum_all_modules(PCTSTR module_name, DWORD64 module_base,
		ULONG module_size, struct exception_handler_data *data)
{
	char name_utf8[MAX_PATH];
	os_wcs_to_utf8(module_name, 0, name_utf8, MAX_PATH);

	if (data->main_trace.instruction_ptr >= module_base &&
	    data->main_trace.instruction_ptr <  module_base + module_size) {

		dstr_copy(&data->module_name, name_utf8);
		strlwr(data->module_name.array);
	}

#ifdef _WIN64
	dstr_catf(&data->module_list, "%016"PRIX64"-%016"PRIX64" %s\r\n",
			module_base, module_base + module_size,
			name_utf8);
#else
	dstr_catf(&data->module_list, "%08"PRIX64"-%08"PRIX64" %s\r\n",
			module_base, module_base + module_size,
			name_utf8);
#endif
	return true;
}
static void add_video_encoder_params(struct ffmpeg_muxer *stream,
		struct dstr *cmd, obs_encoder_t *vencoder)
{
	obs_data_t *settings = obs_encoder_get_settings(vencoder);
	int bitrate = (int)obs_data_get_int(settings, "bitrate");
	video_t *video = obs_get_video();
	const struct video_output_info *info = video_output_get_info(video);

	obs_data_release(settings);

	dstr_catf(cmd, "%s %d %d %d %d %d ",
			"h264",
			bitrate,
			obs_output_get_width(stream->output),
			obs_output_get_height(stream->output),
			(int)info->fps_num,
			(int)info->fps_den);
}
static bool get_monitor_props(obs_property_t *monitor_list, int monitor_idx)
{
	struct dstr monitor_desc = {0};
	struct gs_monitor_info info;

	if (!gs_get_duplicator_monitor_info(monitor_idx, &info))
		return false;

	dstr_catf(&monitor_desc, "%s %d: %ldx%ld @ %ld,%ld",
			TEXT_MONITOR, monitor_idx,
			info.cx, info.cy, info.x, info.y);

	obs_property_list_add_int(monitor_list, monitor_desc.array,
			monitor_idx);

	dstr_free(&monitor_desc);

	return true;
}
static void add_audio_encoder_params(struct dstr *cmd, obs_encoder_t *aencoder)
{
	obs_data_t *settings = obs_encoder_get_settings(aencoder);
	int bitrate = (int)obs_data_get_int(settings, "bitrate");
	audio_t *audio = obs_get_audio();
	struct dstr name = {0};

	obs_data_release(settings);

	dstr_copy(&name, obs_encoder_get_name(aencoder));
	dstr_replace(&name, "\"", "\"\"");

	dstr_catf(cmd, "\"%s\" %d %d %d ",
			name.array,
			bitrate,
			(int)obs_encoder_get_sample_rate(aencoder),
			(int)audio_output_get_channels(audio));

	dstr_free(&name);
}
static inline void write_header(struct exception_handler_data *data)
{
	char date_time[80];
	time_t now = time(0);
	struct tm ts;
	ts = *localtime(&now);
	strftime(date_time, sizeof(date_time), "%Y-%m-%d, %X", &ts);

	dstr_catf(&data->str, "Unhandled exception: %x\r\n"
			"Date/Time: %s\r\n"
			"Fault address: %"PRIX64" (%s)\r\n"
			"libobs version: "OBS_VERSION"\r\n"
			"Windows version: %d.%d build %d (revision: %d; "
				"%s-bit)\r\n"
			"CPU: %s\r\n\r\n",
			data->exception->ExceptionRecord->ExceptionCode,
			date_time,
			data->main_trace.instruction_ptr,
			data->module_name.array,
			data->win_version.major, data->win_version.minor,
			data->win_version.build, data->win_version.revis,
			is_64_bit_windows() ? "64" : "32",
			data->cpu_info.array);
}
static int try_connect(struct rtmp_stream *stream)
{
	if (dstr_is_empty(&stream->path)) {
		warn("URL is empty");
		return OBS_OUTPUT_BAD_PATH;
	}

	info("Connecting to RTMP URL %s...", stream->path.array);

	memset(&stream->rtmp.Link, 0, sizeof(stream->rtmp.Link));
	if (!RTMP_SetupURL(&stream->rtmp, stream->path.array))
		return OBS_OUTPUT_BAD_PATH;

	RTMP_EnableWrite(&stream->rtmp);

	dstr_copy(&stream->encoder_name, "FMLE/3.0 (compatible; obs-studio/");

#ifdef HAVE_OBSCONFIG_H
	dstr_cat(&stream->encoder_name, OBS_VERSION);
#else
	dstr_catf(&stream->encoder_name, "%d.%d.%d",
			LIBOBS_API_MAJOR_VER,
			LIBOBS_API_MINOR_VER,
			LIBOBS_API_PATCH_VER);
#endif

	dstr_cat(&stream->encoder_name, "; FMSc/1.0)");

	set_rtmp_dstr(&stream->rtmp.Link.pubUser,   &stream->username);
	set_rtmp_dstr(&stream->rtmp.Link.pubPasswd, &stream->password);
	set_rtmp_dstr(&stream->rtmp.Link.flashVer,  &stream->encoder_name);
	stream->rtmp.Link.swfUrl = stream->rtmp.Link.tcUrl;

	RTMP_AddStream(&stream->rtmp, stream->key.array);

	for (size_t idx = 1;; idx++) {
		obs_encoder_t *encoder = obs_output_get_audio_encoder(
				stream->output, idx);
		const char *encoder_name;

		if (!encoder)
			break;

		encoder_name = obs_encoder_get_name(encoder);
		RTMP_AddStream(&stream->rtmp, encoder_name);
	}

	stream->rtmp.m_outChunkSize       = 4096;
	stream->rtmp.m_bSendChunkSizeInfo = true;
	stream->rtmp.m_bUseNagle          = true;

#ifdef _WIN32
	win32_log_interface_type(stream);
#endif

	if (!RTMP_Connect(&stream->rtmp, NULL))
		return OBS_OUTPUT_CONNECT_FAILED;
	if (!RTMP_ConnectStream(&stream->rtmp, 0))
		return OBS_OUTPUT_INVALID_STREAM;

	info("Connection to %s successful", stream->path.array);

	return init_send(stream);
}
Exemple #12
0
static inline bool ep_compile_pass_shader(struct effect_parser *ep,
		struct gs_effect_technique *tech,
		struct gs_effect_pass *pass, struct ep_pass *pass_in,
		size_t pass_idx, enum gs_shader_type type)
{
	struct dstr shader_str;
	struct dstr location;
	struct darray used_params; /* struct dstr */
	struct darray *pass_params = NULL; /* struct pass_shaderparam */
	gs_shader_t *shader = NULL;
	bool success = true;

	dstr_init(&shader_str);
	darray_init(&used_params);
	dstr_init(&location);

	dstr_copy(&location, ep->cfp.lex.file);
	if (type == GS_SHADER_VERTEX)
		dstr_cat(&location, " (Vertex ");
	else if (type == GS_SHADER_PIXEL)
		dstr_cat(&location, " (Pixel ");
	/*else if (type == SHADER_GEOMETRY)
		dstr_cat(&location, " (Geometry ");*/

	assert(pass_idx <= UINT_MAX);
	dstr_catf(&location, "shader, technique %s, pass %u)", tech->name,
			(unsigned)pass_idx);

	if (type == GS_SHADER_VERTEX) {
		ep_makeshaderstring(ep, &shader_str,
				&pass_in->vertex_program.da, &used_params);

		pass->vertshader = gs_vertexshader_create(shader_str.array,
				location.array, NULL);

		shader = pass->vertshader;
		pass_params = &pass->vertshader_params.da;
	} else if (type == GS_SHADER_PIXEL) {
		ep_makeshaderstring(ep, &shader_str,
				&pass_in->fragment_program.da, &used_params);

		pass->pixelshader = gs_pixelshader_create(shader_str.array,
				location.array, NULL);

		shader = pass->pixelshader;
		pass_params = &pass->pixelshader_params.da;
	}

#if 0
	blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++");
	blog(LOG_DEBUG, "  %s", location.array);
	blog(LOG_DEBUG, "-----------------------------------");
	blog(LOG_DEBUG, "%s", shader_str.array);
	blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++");
#endif

	if (shader)
		success = ep_compile_pass_shaderparams(ep, pass_params,
				&used_params, shader);
	else
		success = false;

	dstr_free(&location);
	dstr_array_free(used_params.array, used_params.num);
	darray_free(&used_params);
	dstr_free(&shader_str);

	return success;
}
static inline bool walk_stack(struct exception_handler_data *data,
		HANDLE thread, struct stack_trace *trace)
{
	struct module_info module_info = {0};
	DWORD64 func_offset;
	char sym_name[256];
	char *p;

	bool success = data->stack_walk64(trace->image_type,
			data->process, thread, &trace->frame, &trace->context,
			NULL, data->sym_function_table_access64,
			data->sym_get_module_base64, NULL);
	if (!success)
		return false;

	module_info.addr = trace->frame.AddrPC.Offset;
	get_module_name(data, &module_info);

	if (!!module_info.name_utf8[0]) {
		p = strrchr(module_info.name_utf8, '\\');
		p = p ? (p + 1) : module_info.name_utf8;
	} else {
		strcpy(module_info.name_utf8, "<unknown>");
		p = module_info.name_utf8;
	}

	success = !!data->sym_from_addr(data->process,
			trace->frame.AddrPC.Offset, &func_offset,
			data->sym_info);

	if (success)
		os_wcs_to_utf8(data->sym_info->Name, 0, sym_name, 256);

#ifdef _WIN64
#define SUCCESS_FORMAT \
	"%016I64X %016I64X %016I64X %016I64X " \
	"%016I64X %016I64X %s!%s+0x%I64x\r\n"
#define FAIL_FORMAT \
	"%016I64X %016I64X %016I64X %016I64X " \
	"%016I64X %016I64X %s!0x%I64x\r\n"
#else
#define SUCCESS_FORMAT \
	"%08.8I64X %08.8I64X %08.8I64X %08.8I64X " \
	"%08.8I64X %08.8I64X %s!%s+0x%I64x\r\n"
#define FAIL_FORMAT \
	"%08.8I64X %08.8I64X %08.8I64X %08.8I64X " \
	"%08.8I64X %08.8I64X %s!0x%I64x\r\n"

	trace->frame.AddrStack.Offset &= 0xFFFFFFFFF;
	trace->frame.AddrPC.Offset &= 0xFFFFFFFFF;
	trace->frame.Params[0] &= 0xFFFFFFFF;
	trace->frame.Params[1] &= 0xFFFFFFFF;
	trace->frame.Params[2] &= 0xFFFFFFFF;
	trace->frame.Params[3] &= 0xFFFFFFFF;
#endif

	if (success && (data->sym_info->Flags & SYMFLAG_EXPORT) == 0) {
		dstr_catf(&data->str, SUCCESS_FORMAT,
				trace->frame.AddrStack.Offset,
				trace->frame.AddrPC.Offset,
				trace->frame.Params[0],
				trace->frame.Params[1],
				trace->frame.Params[2],
				trace->frame.Params[3],
				p, sym_name, func_offset);
	} else {
		dstr_catf(&data->str, FAIL_FORMAT,
				trace->frame.AddrStack.Offset,
				trace->frame.AddrPC.Offset,
				trace->frame.Params[0],
				trace->frame.Params[1],
				trace->frame.Params[2],
				trace->frame.Params[3],
				p, trace->frame.AddrPC.Offset);
	}

	return true;
}
Exemple #14
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;
}