Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #1

Merged
merged 5 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
- 'README.md'
pull_request:
branches: [ "master" ]
paths-ignore:
- 'README.md'

env:
CARGO_INCREMENTAL: 0
Expand Down Expand Up @@ -82,7 +84,7 @@ jobs:
- name: Check format
run: cargo fmt --all -- --check
- name: Lint
run: cargo clippy --all-targets $CARGO_FEATURES
run: cargo clippy --all-targets $CARGO_FEATURES -- -D warnings
- name: Build
run: cargo build --all-targets $CARGO_FEATURES
- name: Test bindings
Expand Down Expand Up @@ -120,7 +122,7 @@ jobs:
- name: Check format
run: cargo fmt --all -- --check
- name: Lint
run: cargo clippy --all-targets $CARGO_FEATURES
run: cargo clippy --all-targets $CARGO_FEATURES -- -D warnings
- name: Build
run: cargo build --all-targets $CARGO_FEATURES
- name: Test bindings
Expand Down Expand Up @@ -174,7 +176,7 @@ jobs:
- name: Check format
run: cargo fmt --all -- --check
- name: Lint
run: cargo clippy --all-targets $CARGO_FEATURES
run: cargo clippy --all-targets $CARGO_FEATURES -- -D warnings
- name: Build
run: cargo build --all-targets $CARGO_FEATURES
- name: Test bindings
Expand Down
4 changes: 2 additions & 2 deletions examples/dump-frames.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extern crate ffmpeg_the_third as ffmpeg;

use crate::ffmpeg::format::{input, Pixel};
use crate::ffmpeg::format::{self, Pixel};
use crate::ffmpeg::media::Type;
use crate::ffmpeg::software::scaling::{context::Context, flag::Flags};
use crate::ffmpeg::util::frame::video::Video;
Expand All @@ -11,7 +11,7 @@ use std::io::prelude::*;
fn main() -> Result<(), ffmpeg::Error> {
ffmpeg::init().unwrap();

if let Ok(mut ictx) = input(env::args().nth(1).expect("Cannot open file.")) {
if let Ok(mut ictx) = format::input(env::args().nth(1).expect("Cannot open file.")) {
let input = ictx
.streams()
.best(Type::Video)
Expand Down
2 changes: 1 addition & 1 deletion examples/remux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate ffmpeg_the_third as ffmpeg;

use std::env;

use crate::ffmpeg::{codec, encoder, format, log, media, Rational};
use ffmpeg::{codec, encoder, format, log, media, Rational};

fn main() {
let input_file = env::args().nth(1).expect("missing input file");
Expand Down
10 changes: 5 additions & 5 deletions examples/transcode-audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ extern crate ffmpeg_the_third as ffmpeg;
use std::env;
use std::path::Path;

use crate::ffmpeg::{codec, filter, format, frame, media};
use crate::ffmpeg::{rescale, Rescale};
use ffmpeg::{codec, filter, format, frame, media};
use ffmpeg::{rescale, Rescale};

fn filter(
spec: &str,
Expand Down Expand Up @@ -69,10 +69,10 @@ struct Transcoder {
out_time_base: ffmpeg::Rational,
}

fn transcoder<P: AsRef<Path>>(
fn transcoder<P: AsRef<Path> + ?Sized>(
ictx: &mut format::context::Input,
octx: &mut format::context::Output,
path: P,
path: &P,
filter_spec: &str,
) -> Result<Transcoder, ffmpeg::Error> {
let input = ictx
Expand Down Expand Up @@ -135,7 +135,7 @@ fn transcoder<P: AsRef<Path>>(
output.set_time_base((1, decoder.rate() as i32));

let encoder = encoder.open_as(codec)?;
output.copy_parameters_from_context(&encoder);
output.set_parameters_into(&encoder);

let filter = filter(filter_spec, &decoder, &encoder)?;

Expand Down
44 changes: 24 additions & 20 deletions examples/transcode-x264.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::collections::HashMap;
use std::env;
use std::time::Instant;

use crate::ffmpeg::{
use ffmpeg::{
codec, decoder, encoder, format, frame, log, media, picture, Dictionary, Packet, Rational,
};

Expand All @@ -30,7 +30,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,
Expand All @@ -50,33 +51,32 @@ 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())?
.encoder()
.video()?;

let codec = encoder::find(codec::Id::H264);
let mut ost = octx.add_stream(codec)?;

let mut encoder = codec::context::Context::new(codec).encoder().video()?;
ost.set_parameters_into(&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_into(&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,
Expand All @@ -103,7 +103,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);
Expand All @@ -128,7 +128,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();
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@ fn main() {
)
.expect("invalid x264 options string");

eprintln!("x264 options: {x264_opts:?}");
eprintln!("x264 options: {:?}", x264_opts);

ffmpeg::init().unwrap();
log::set_level(log::Level::Info);
Expand Down Expand Up @@ -247,7 +247,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);
}
Expand Down
9 changes: 3 additions & 6 deletions src/codec/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ pub fn list_descriptors() -> CodecDescriptorIter {
CodecDescriptorIter::new()
}

pub type Audio = Codec<AudioType>;
pub type Video = Codec<VideoType>;

#[derive(PartialEq, Eq, Copy, Clone)]
pub struct Codec<Type = UnknownType> {
ptr: NonNull<AVCodec>,
Expand Down Expand Up @@ -50,7 +47,7 @@ impl Codec<UnknownType> {

impl<T> Codec<T> {
pub fn as_ptr(&self) -> *const AVCodec {
self.ptr.as_ptr()
self.ptr.as_ptr() as *const _
}

pub fn is_encoder(&self) -> bool {
Expand Down Expand Up @@ -81,7 +78,7 @@ impl<T> Codec<T> {
self.medium() == media::Type::Video
}

pub fn video(self) -> Option<Video> {
pub fn video(self) -> Option<Codec<VideoType>> {
if self.medium() == media::Type::Video {
Some(Codec {
ptr: self.ptr,
Expand All @@ -96,7 +93,7 @@ impl<T> Codec<T> {
self.medium() == media::Type::Audio
}

pub fn audio(self) -> Option<Audio> {
pub fn audio(self) -> Option<Codec<AudioType>> {
if self.medium() == media::Type::Audio {
Some(Codec {
ptr: self.ptr,
Expand Down
13 changes: 8 additions & 5 deletions src/codec/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@ impl Context {
}

impl Context {
pub fn new() -> Self {
pub fn new(codec: Option<Codec>) -> Self {
unsafe {
Context {
ptr: avcodec_alloc_context3(ptr::null()),
ptr: match codec {
Some(c) => avcodec_alloc_context3(c.as_ptr()),
None => avcodec_alloc_context3(ptr::null()),
},
owner: None,
}
}
}

pub fn from_parameters<P: AsPtr<AVCodecParameters>>(parameters: P) -> Result<Self, Error> {
let mut context = Self::new();
let mut context = Self::new(None);

unsafe {
match avcodec_parameters_to_context(context.as_mut_ptr(), parameters.as_ptr()) {
Expand Down Expand Up @@ -128,7 +131,7 @@ impl Context {

impl Default for Context {
fn default() -> Self {
Self::new()
Self::new(None)
}
}

Expand All @@ -145,7 +148,7 @@ impl Drop for Context {
#[cfg(not(feature = "ffmpeg_5_0"))]
impl Clone for Context {
fn clone(&self) -> Self {
let mut ctx = Context::new();
let mut ctx = Context::new(None);
ctx.clone_from(self);

ctx
Expand Down
2 changes: 1 addition & 1 deletion src/codec/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::ffi::*;
use crate::Codec;

pub fn new() -> Decoder {
Context::new().decoder()
Context::new(None).decoder()
}

pub fn find(id: Id) -> Option<Codec> {
Expand Down
2 changes: 1 addition & 1 deletion src/codec/encoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::ffi::*;
use crate::Codec;

pub fn new() -> Encoder {
Context::new().encoder()
Context::new(None).encoder()
}

pub fn find(id: Id) -> Option<Codec> {
Expand Down
2 changes: 1 addition & 1 deletion src/codec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub mod capabilities;
pub use self::capabilities::Capabilities;

pub mod codec;
pub use self::codec::{Audio, Codec, Video};
pub use self::codec::Codec;

pub mod parameters;
pub use self::parameters::{Parameters, ParametersMut, ParametersRef};
Expand Down
24 changes: 12 additions & 12 deletions src/format/context/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,19 @@ impl Input {
}

pub fn seek<R: RangeBounds<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> {
unsafe {
let start = match range.start_bound().cloned() {
Bound::Included(i) => i,
Bound::Excluded(i) => i.saturating_add(1),
Bound::Unbounded => i64::MIN,
};

let end = match range.end_bound().cloned() {
Bound::Included(i) => i,
Bound::Excluded(i) => i.saturating_sub(1),
Bound::Unbounded => i64::MAX,
};
let start = match range.start_bound().cloned() {
Bound::Included(i) => i,
Bound::Excluded(i) => i.saturating_add(1),
Bound::Unbounded => i64::MIN,
};

let end = match range.end_bound().cloned() {
Bound::Included(i) => i,
Bound::Excluded(i) => i.saturating_sub(1),
Bound::Unbounded => i64::MAX,
};

unsafe {
match avformat_seek_file(self.as_mut_ptr(), -1, start, ts, end, 0) {
s if s >= 0 => Ok(()),
e => Err(Error::from(e)),
Expand Down
5 changes: 2 additions & 3 deletions src/format/context/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ impl Output {

pub fn add_stream<T, E: traits::Encoder<T>>(&mut self, codec: E) -> Result<StreamMut, Error> {
unsafe {
let codec = codec.encoder();
let codec = codec.map_or(ptr::null(), |c| c.as_ptr());
let ptr = avformat_new_stream(self.as_mut_ptr(), codec);
let codec_ptr = codec.encoder().map_or(ptr::null(), |c| c.as_ptr());
let ptr = avformat_new_stream(self.as_mut_ptr(), codec_ptr);

if ptr.is_null() {
return Err(Error::Unknown);
Expand Down
8 changes: 8 additions & 0 deletions src/format/stream/stream_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ impl<'a> StreamMut<'a> {
}
}

pub fn set_parameters_into<P: Into<codec::Parameters>>(&mut self, parameters: P) {
let parameters = parameters.into();

unsafe {
avcodec_parameters_copy((*self.as_mut_ptr()).codecpar, parameters.as_ptr());
}
}

pub fn copy_parameters_from_context(&mut self, ctx: &codec::Context) {
unsafe {
avcodec_parameters_from_context((*self.as_mut_ptr()).codecpar, ctx.as_ptr());
Expand Down
Loading