diff --git a/examples/dump-frames.rs b/examples/dump-frames.rs index c76f2220..2dfa9330 100644 --- a/examples/dump-frames.rs +++ b/examples/dump-frames.rs @@ -18,7 +18,18 @@ fn main() -> Result<(), ffmpeg::Error> { .ok_or(ffmpeg::Error::StreamNotFound)?; let video_stream_index = input.index(); - let context_decoder = ffmpeg::codec::context::Context::from_parameters(input.parameters())?; + let mut context_decoder = + ffmpeg::codec::context::Context::from_parameters(input.parameters())?; + + if let Ok(parallelism) = std::thread::available_parallelism() { + context_decoder.set_threading(ffmpeg::threading::Config { + kind: ffmpeg::threading::Type::Frame, + count: parallelism.get(), + #[cfg(not(feature = "ffmpeg_6_0"))] + safe: false, + }); + } + let mut decoder = context_decoder.decoder().video()?; let mut scaler = Context::get( diff --git a/examples/transcode-audio.rs b/examples/transcode-audio.rs index ed31842a..9e8a9ca7 100644 --- a/examples/transcode-audio.rs +++ b/examples/transcode-audio.rs @@ -3,6 +3,7 @@ extern crate ffmpeg_the_third as ffmpeg; use std::env; use std::path::Path; +use crate::ffmpeg::codec::Parameters; use crate::ffmpeg::{codec, filter, format, frame, media}; use crate::ffmpeg::{rescale, Rescale}; @@ -69,10 +70,10 @@ struct Transcoder { out_time_base: ffmpeg::Rational, } -fn transcoder>( +fn transcoder + ?Sized>( ictx: &mut format::context::Input, octx: &mut format::context::Output, - path: P, + path: &P, filter_spec: &str, ) -> Result { let input = ictx @@ -135,7 +136,7 @@ fn transcoder>( output.set_time_base((1, decoder.rate() as i32)); let encoder = encoder.open_as(codec)?; - output.copy_parameters_from_context(&encoder); + output.set_parameters(Parameters::from(&encoder)); let filter = filter(filter_spec, &decoder, &encoder)?; diff --git a/examples/transcode-x264.rs b/examples/transcode-x264.rs index 39855d1c..e5998994 100644 --- a/examples/transcode-x264.rs +++ b/examples/transcode-x264.rs @@ -22,7 +22,8 @@ use std::env; use std::time::Instant; use crate::ffmpeg::{ - codec, decoder, encoder, format, frame, log, media, picture, Dictionary, Packet, Rational, + codec, codec::Parameters, decoder, encoder, format, frame, log, media, picture, Dictionary, + Packet, Rational, }; const DEFAULT_X264_OPTS: &str = "preset=medium"; @@ -30,7 +31,8 @@ const DEFAULT_X264_OPTS: &str = "preset=medium"; struct Transcoder { ost_index: usize, decoder: decoder::Video, - encoder: encoder::video::Video, + input_time_base: Rational, + encoder: encoder::Video, logging_enabled: bool, frame_count: usize, last_log_frame_count: usize, @@ -50,33 +52,34 @@ impl Transcoder { let decoder = ffmpeg::codec::context::Context::from_parameters(ist.parameters())? .decoder() .video()?; - let mut ost = octx.add_stream(encoder::find(codec::Id::H264))?; - let mut encoder = codec::context::Context::from_parameters(ost.parameters())? + + let codec = encoder::find(codec::Id::H264); + let mut ost = octx.add_stream(codec)?; + + let mut encoder = codec::context::Context::new_with_codec(codec.unwrap()) .encoder() .video()?; + ost.set_parameters(Parameters::from(&encoder)); encoder.set_height(decoder.height()); encoder.set_width(decoder.width()); encoder.set_aspect_ratio(decoder.aspect_ratio()); encoder.set_format(decoder.format()); encoder.set_frame_rate(decoder.frame_rate()); - encoder.set_time_base(decoder.frame_rate().unwrap().invert()); + encoder.set_time_base(ist.time_base()); + if global_header { encoder.set_flags(codec::Flags::GLOBAL_HEADER); } - encoder + let opened_encoder = encoder .open_with(x264_opts) - .expect("error opening libx264 encoder with supplied settings"); - encoder = codec::context::Context::from_parameters(ost.parameters())? - .encoder() - .video()?; - ost.copy_parameters_from_context(&encoder); + .expect("error opening x264 with supplied settings"); + ost.set_parameters(Parameters::from(&opened_encoder)); Ok(Self { ost_index, decoder, - encoder: codec::context::Context::from_parameters(ost.parameters())? - .encoder() - .video()?, + input_time_base: ist.time_base(), + encoder: opened_encoder, logging_enabled: enable_logging, frame_count: 0, last_log_frame_count: 0, @@ -103,7 +106,7 @@ impl Transcoder { self.frame_count += 1; let timestamp = frame.timestamp(); self.log_progress(f64::from( - Rational(timestamp.unwrap_or(0) as i32, 1) * self.decoder.time_base(), + Rational(timestamp.unwrap_or(0) as i32, 1) * self.input_time_base, )); frame.set_pts(timestamp); frame.set_kind(picture::Type::None); @@ -128,7 +131,7 @@ impl Transcoder { let mut encoded = Packet::empty(); while self.encoder.receive_packet(&mut encoded).is_ok() { encoded.set_stream(self.ost_index); - encoded.rescale_ts(self.decoder.time_base(), ost_time_base); + encoded.rescale_ts(self.input_time_base, ost_time_base); encoded.write_interleaved(octx).unwrap(); } } @@ -247,7 +250,11 @@ fn main() { let ost_time_base = ost_time_bases[ost_index as usize]; match transcoders.get_mut(&ist_index) { Some(transcoder) => { - packet.rescale_ts(stream.time_base(), transcoder.decoder.time_base()); + // FIXME: why? + // Timestamps are unset in a packet for stream 0. + // This is deprecated and will stop working in the future. + // Fix your code to set the timestamps properly + // packet.rescale_ts(stream.time_base(), transcoder.decoder.time_base()); transcoder.send_packet_to_decoder(&packet); transcoder.receive_and_process_decoded_frames(&mut octx, ost_time_base); } diff --git a/src/codec/context.rs b/src/codec/context.rs index 332e340c..b03ed9d8 100644 --- a/src/codec/context.rs +++ b/src/codec/context.rs @@ -42,6 +42,15 @@ impl Context { } } + pub fn new_with_codec(codec: Codec) -> Self { + unsafe { + Context { + ptr: avcodec_alloc_context3(codec.as_ptr()), + owner: None, + } + } + } + pub fn from_parameters>(parameters: P) -> Result { let mut context = Self::new();