Browse Source

obs-ffmpeg: Add speed percentage option

(Note: This commit also modifies the deps/media-playback module.)

Allows modifying the speed of local file playback.

Closes jp9000/obs-studio#1091
Exeldro 7 years ago
parent
commit
277b664001

+ 9 - 0
deps/media-playback/media-playback/decode.c

@@ -338,6 +338,15 @@ bool mp_decode_next(struct mp_decode *d)
 					d->stream->time_base,
 					(AVRational){1, 1000000000});
 
+		if (d->m->speed != 100) {
+			d->frame_pts = av_rescale_q(d->frame_pts,
+					(AVRational){1, d->m->speed},
+					(AVRational){1, 100});
+			duration = av_rescale_q(duration,
+					(AVRational){1, d->m->speed},
+					(AVRational){1, 100});
+		}
+
 		d->last_duration = duration;
 		d->next_pts = d->frame_pts + duration;
 	}

+ 5 - 1
deps/media-playback/media-playback/media.c

@@ -271,7 +271,7 @@ static void mp_media_next_audio(mp_media_t *m)
 	for (size_t i = 0; i < MAX_AV_PLANES; i++)
 		audio.data[i] = f->data[i];
 
-	audio.samples_per_sec = f->sample_rate;
+	audio.samples_per_sec = f->sample_rate * m->speed / 100;
 	audio.speakers = convert_speaker_layout(f->channels);
 	audio.format = convert_sample_format(f->format);
 	audio.frames = f->nb_samples;
@@ -687,8 +687,12 @@ bool mp_media_init(mp_media_t *media, const struct mp_media_info *info)
 	media->v_preload_cb = info->v_preload_cb;
 	media->force_range = info->force_range;
 	media->buffering = info->buffering;
+	media->speed = info->speed;
 	media->is_local_file = info->is_local_file;
 
+	if (!info->is_local_file || media->speed < 1 || media->speed > 200)
+		media->speed = 100;
+
 	static bool initialized = false;
 	if (!initialized) {
 		av_register_all();

+ 2 - 0
deps/media-playback/media-playback/media.h

@@ -54,6 +54,7 @@ struct mp_media {
 	char *path;
 	char *format_name;
 	int buffering;
+	int speed;
 
 	enum AVPixelFormat scale_format;
 	struct SwsContext *swscale;
@@ -107,6 +108,7 @@ struct mp_media_info {
 	const char *path;
 	const char *format;
 	int buffering;
+	int speed;
 	enum video_range_type force_range;
 	bool hardware_decoding;
 	bool is_local_file;

+ 1 - 0
plugins/obs-ffmpeg/data/locale/en-US.ini

@@ -36,6 +36,7 @@ ColorRange.Auto="Auto"
 ColorRange.Partial="Partial"
 ColorRange.Full="Full"
 RestartMedia="Restart Media"
+SpeedPercentage="Speed (perecent)"
 Seekable="Seekable"
 
 MediaFileFilter.AllMediaFiles="All Media Files"

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

@@ -49,6 +49,7 @@ struct ffmpeg_source {
 	char *input;
 	char *input_format;
 	int buffering_mb;
+	int speed_percent;
 	bool is_looping;
 	bool is_local_file;
 	bool is_hw_decoding;
@@ -72,12 +73,14 @@ static bool is_local_file_modified(obs_properties_t *props,
 	obs_property_t *buffering = obs_properties_get(props, "buffering_mb");
 	obs_property_t *close = obs_properties_get(props, "close_when_inactive");
 	obs_property_t *seekable = obs_properties_get(props, "seekable");
+	obs_property_t *speed = obs_properties_get(props, "speed_percent");
 	obs_property_set_visible(input, !enabled);
 	obs_property_set_visible(input_format, !enabled);
 	obs_property_set_visible(buffering, !enabled);
 	obs_property_set_visible(close, enabled);
 	obs_property_set_visible(local_file, enabled);
 	obs_property_set_visible(looping, enabled);
+	obs_property_set_visible(speed, enabled);
 	obs_property_set_visible(seekable, !enabled);
 
 	return true;
@@ -93,6 +96,7 @@ static void ffmpeg_source_defaults(obs_data_t *settings)
 	obs_data_set_default_bool(settings, "hw_decode", true);
 #endif
 	obs_data_set_default_int(settings, "buffering_mb", 2);
+	obs_data_set_default_int(settings, "speed_percent", 100);
 }
 
 static const char *media_filter =
@@ -171,6 +175,9 @@ static obs_properties_t *ffmpeg_source_getproperties(void *data)
 	obs_property_set_long_description(prop,
 			obs_module_text("CloseFileWhenInactive.ToolTip"));
 
+	obs_properties_add_int_slider(props, "speed_percent",
+			obs_module_text("SpeedPercentage"), 1, 200, 1);
+
 	prop = obs_properties_add_list(props, "color_range",
 			obs_module_text("ColorRange"), OBS_COMBO_TYPE_LIST,
 			OBS_COMBO_FORMAT_INT);
@@ -193,6 +200,7 @@ static void dump_source_info(struct ffmpeg_source *s, const char *input,
 			"settings:\n"
 			"\tinput:                   %s\n"
 			"\tinput_format:            %s\n"
+			"\tspeed:                   %d\n"
 			"\tis_looping:              %s\n"
 			"\tis_hw_decoding:          %s\n"
 			"\tis_clear_on_media_end:   %s\n"
@@ -200,6 +208,7 @@ static void dump_source_info(struct ffmpeg_source *s, const char *input,
 			"\tclose_when_inactive:     %s",
 			input ? input : "(null)",
 			input_format ? input_format : "(null)",
+			s->speed_percent,
 			s->is_looping ? "yes" : "no",
 			s->is_hw_decoding ? "yes" : "no",
 			s->is_clear_on_media_end ? "yes" : "no",
@@ -251,6 +260,7 @@ static void ffmpeg_source_open(struct ffmpeg_source *s)
 			.path = s->input,
 			.format = s->input_format,
 			.buffering = s->buffering_mb * 1024 * 1024,
+			.speed = s->speed_percent,
 			.force_range = s->range,
 			.hardware_decoding = s->is_hw_decoding,
 			.is_local_file = s->is_local_file || s->seekable
@@ -328,9 +338,13 @@ static void ffmpeg_source_update(void *data, obs_data_t *settings)
 	s->range = (enum video_range_type)obs_data_get_int(settings,
 			"color_range");
 	s->buffering_mb = (int)obs_data_get_int(settings, "buffering_mb");
+	s->speed_percent = (int)obs_data_get_int(settings, "speed_percent");
 	s->is_local_file = is_local_file;
 	s->seekable = obs_data_get_bool(settings, "seekable");
 
+	if (s->speed_percent < 1 || s->speed_percent > 200)
+		s->speed_percent = 100;
+
 	if (s->media_valid) {
 		mp_media_free(&s->media);
 		s->media_valid = false;