diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-source.c b/plugins/obs-ffmpeg/obs-ffmpeg-source.c index 96a030246..a74562688 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-source.c +++ b/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;