Browse Source

Merge pull request #989 from derrod/stinger-frames

Add option to use frame instead of timestamp for stinger transition
Jim 8 years ago
parent
commit
3cf12feb1e

+ 39 - 0
plugins/obs-ffmpeg/obs-ffmpeg-source.c

@@ -365,6 +365,43 @@ static void get_duration(void *data, calldata_t *cd)
 	calldata_set_int(cd, "duration", dur * 1000);
 }
 
+static void get_nb_frames(void *data, calldata_t *cd)
+{
+	struct ffmpeg_source *s = data;
+	int64_t frames = 0;
+
+	if (!s->media.fmt) {
+		calldata_set_int(cd, "num_frames", frames);
+		return;
+	}
+
+	int video_stream_index = av_find_best_stream(s->media.fmt,
+			AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
+
+	if (video_stream_index < 0) {
+		FF_BLOG(LOG_WARNING, "Getting number of frames failed: No "
+				"video stream in media file!");
+		calldata_set_int(cd, "num_frames", frames);
+		return;
+	}
+
+	AVStream *stream = s->media.fmt->streams[video_stream_index];
+
+	if (stream->nb_frames > 0) {
+		frames = stream->nb_frames;
+	} else {
+		FF_BLOG(LOG_DEBUG, "nb_frames not set, estimating using frame "
+				"rate and duration");
+		AVRational avg_frame_rate = stream->avg_frame_rate;
+		frames = (int64_t)ceil((double)s->media.fmt->duration /
+				(double)AV_TIME_BASE *
+				(double)avg_frame_rate.num /
+				(double)avg_frame_rate.den);
+	}
+
+	calldata_set_int(cd, "num_frames", frames);
+}
+
 static void *ffmpeg_source_create(obs_data_t *settings, obs_source_t *source)
 {
 	UNUSED_PARAMETER(settings);
@@ -381,6 +418,8 @@ static void *ffmpeg_source_create(obs_data_t *settings, obs_source_t *source)
 	proc_handler_add(ph, "void restart()", restart_proc, s);
 	proc_handler_add(ph, "void get_duration(out int duration)",
 			get_duration, s);
+	proc_handler_add(ph, "void get_nb_frames(out int num_frames)",
+			get_nb_frames, s);
 
 	ffmpeg_source_update(s, settings);
 	return s;

+ 4 - 1
plugins/obs-transitions/data/locale/en-US.ini

@@ -12,7 +12,10 @@ Direction.Down="Down"
 SwipeIn="Swipe In"
 Color="Color"
 VideoFile="Video File"
-TransitionPoint="Transition Point (milliseconds)"
+TransitionPoint="Transition Point"
+TransitionPointType="Transition Point Type"
+TransitionPointTypeFrame="Frame"
+TransitionPointTypeTime="Time (milliseconds)"
 SwitchPoint="Peak Color Point (percentage)"
 LumaWipeTransition="Luma Wipe"
 LumaWipe.Image="Image"

+ 33 - 6
plugins/obs-transitions/transition-stinger.c

@@ -1,16 +1,22 @@
 #include <obs-module.h>
 
+#define TIMING_TIME  0
+#define TIMING_FRAME 1
+
 struct stinger_info {
 	obs_source_t *source;
 
 	obs_source_t *media_source;
 
 	uint64_t duration_ns;
+	uint64_t duration_frames;
 	uint64_t transition_point_ns;
+	uint64_t transition_point_frame;
 	float transition_point;
 	float transition_a_mul;
 	float transition_b_mul;
 	bool transitioning;
+	bool transition_point_is_frame;
 };
 
 static const char *stinger_get_name(void *type_data)
@@ -32,9 +38,15 @@ static void stinger_update(void *data, obs_data_t *settings)
 			media_settings);
 	obs_data_release(media_settings);
 
-	int64_t point_ms = obs_data_get_int(settings, "transition_point");
+	int64_t point = obs_data_get_int(settings, "transition_point");
+
+	s->transition_point_is_frame =
+			obs_data_get_int(settings, "tp_type") == TIMING_FRAME;
 
-	s->transition_point_ns = (uint64_t)(point_ms * 1000000LL);
+	if (s->transition_point_is_frame)
+		s->transition_point_frame = (uint64_t)point;
+	else
+		s->transition_point_ns = (uint64_t)(point * 1000000LL);
 }
 
 static void *stinger_create(obs_data_t *settings, obs_source_t *source)
@@ -165,12 +177,19 @@ static void stinger_transition_start(void *data)
 		}
 
 		proc_handler_call(ph, "get_duration", &cd);
-
+		proc_handler_call(ph, "get_nb_frames", &cd);
 		s->duration_ns = (uint64_t)calldata_int(&cd, "duration");
+		s->duration_frames = (uint64_t)calldata_int(&cd, "num_frames");
+
+		if (s->transition_point_is_frame)
+			s->transition_point = (float)(
+				(long double)s->transition_point_frame /
+				(long double)s->duration_frames);
+		else
+			s->transition_point = (float)(
+				(long double)s->transition_point_ns /
+				(long double)s->duration_ns);
 
-		s->transition_point = (float)(
-			(long double)s->transition_point_ns /
-			(long double)s->duration_ns);
 		if (s->transition_point > 1.0f)
 			s->transition_point = 1.0f;
 		else if (s->transition_point < 0.001f)
@@ -229,6 +248,14 @@ static obs_properties_t *stinger_properties(void *data)
 			obs_module_text("VideoFile"),
 			OBS_PATH_FILE,
 			FILE_FILTER, NULL);
+	obs_property_t *list = obs_properties_add_list(ppts, "tp_type",
+			obs_module_text("TransitionPointType"),
+			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
+	obs_property_list_add_int(list,
+			obs_module_text("TransitionPointTypeTime"), TIMING_TIME);
+	obs_property_list_add_int(list,
+			obs_module_text("TransitionPointTypeFrame"), TIMING_FRAME);
+
 	obs_properties_add_int(ppts, "transition_point",
 			obs_module_text("TransitionPoint"),
 			0, 120000, 1);