From 5b36faa08d0d6ec8543877186521e1912ca2bbbd Mon Sep 17 00:00:00 2001 From: Arrizal Amin Date: Sat, 3 Aug 2024 13:45:06 +0700 Subject: [PATCH] add frame-specific seek method --- src/decode.rs | 18 ++++++++++++++++-- src/io.rs | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/decode.rs b/src/decode.rs index 52b135f..4fe51c2 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -224,7 +224,19 @@ impl Decoder { /// See [`Reader::seek`](crate::io::Reader::seek) for more information. #[inline] pub fn seek(&mut self, timestamp_milliseconds: i64) -> Result<()> { - self.reader.seek(timestamp_milliseconds) + self.reader + .seek(timestamp_milliseconds) + .inspect(|_| self.decoder.decoder.flush()) + } + + /// Seek to specific frame in reader. + /// + /// See [`Reader::seek_to_frame`](crate::io::Reader::seek_to_frame) for more information. + #[inline] + pub fn seek_to_frame(&mut self, frame_number: i64) -> Result<()> { + self.reader + .seek_to_frame(frame_number) + .inspect(|_| self.decoder.decoder.flush()) } /// Seek to start of reader. @@ -232,7 +244,9 @@ impl Decoder { /// See [`Reader::seek_to_start`](crate::io::Reader::seek_to_start) for more information. #[inline] pub fn seek_to_start(&mut self) -> Result<()> { - self.reader.seek_to_start() + self.reader + .seek_to_start() + .inspect(|_| self.decoder.decoder.flush()) } /// Split the decoder into a decoder (of type [`DecoderSplit`]) and a [`Reader`]. diff --git a/src/io.rs b/src/io.rs index fc0a47e..0c730a0 100644 --- a/src/io.rs +++ b/src/io.rs @@ -5,6 +5,7 @@ use ffmpeg::ffi::AV_TIME_BASE_Q; use ffmpeg::format::context::{Input as AvInput, Output as AvOutput}; use ffmpeg::media::Type as AvMediaType; use ffmpeg::Error as AvError; +use ffmpeg_next::ffi::av_seek_frame; use crate::error::Error; use crate::ffi; @@ -157,6 +158,20 @@ impl Reader { .map_err(Error::BackendError) } + /// Seek to a specific frame in the video stream. + /// + /// # Arguments + /// + /// * `frame_number` - The frame number to seek to. + pub fn seek_to_frame(&mut self, frame_number: i64) -> Result<()> { + unsafe { + match av_seek_frame(self.input.as_mut_ptr(), -1, frame_number, 0) { + 0 => Ok(()), + e => Err(Error::BackendError(AvError::from(e))), + } + } + } + /// Seek to start of reader. This function performs best effort seeking to the start of the /// file. pub fn seek_to_start(&mut self) -> Result<()> {