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

Expose frame rate of streams #35

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
15 changes: 13 additions & 2 deletions src/codec/audio/resampler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Audio resampler.

use std::{
convert::TryInto,
os::raw::{c_int, c_void},
ptr,
};
Expand Down Expand Up @@ -211,7 +212,12 @@ impl AudioResampler {
));
}

let frame = frame.with_time_base(TimeBase::new(1, self.source_sample_rate));
let frame = frame.with_time_base(TimeBase::new(
1,
self.source_sample_rate
.try_into()
.map_err(|e| CodecError::error(e))?,
));

unsafe {
match ffw_audio_resampler_push_frame(self.ptr, frame.as_ptr()) {
Expand Down Expand Up @@ -250,7 +256,12 @@ impl AudioResampler {
pub fn take(&mut self) -> Result<Option<AudioFrame>, Error> {
let mut fptr = ptr::null_mut();

let tb = TimeBase::new(1, self.target_sample_rate);
let tb = TimeBase::new(
1,
self.target_sample_rate
.try_into()
.map_err(|e| Error::new(e))?,
);

unsafe {
match ffw_audio_resampler_take_frame(self.ptr, &mut fptr) {
Expand Down
17 changes: 15 additions & 2 deletions src/codec/audio/transcoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! audio decoder/resampler/encoder into a single pipeline.

use std::collections::VecDeque;
use std::convert::TryInto;

use crate::Error;

Expand Down Expand Up @@ -67,12 +68,24 @@ impl AudioTranscoderBuilder {
pub fn build(self) -> Result<AudioTranscoder, Error> {
let decoder = self
.decoder_builder
.time_base(TimeBase::new(1, self.input.sample_rate()))
.time_base(TimeBase::new(
1,
self.input
.sample_rate()
.try_into()
.map_err(|e| Error::new(e))?,
))
.build()?;

let encoder = self
.encoder_builder
.time_base(TimeBase::new(1, self.output.sample_rate()))
.time_base(TimeBase::new(
1,
self.output
.sample_rate()
.try_into()
.map_err(|e| Error::new(e))?,
))
.build()?;

let resampler = AudioResampler::builder()
Expand Down
2 changes: 1 addition & 1 deletion src/codec/bsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int ffw_bsf_set_output_codec_parameters(AVBSFContext* context, const AVCodecPara
return avcodec_parameters_copy(context->par_out, params);
}

int ffw_bsf_init(AVBSFContext* context, uint32_t itb_num, uint32_t itb_den, uint32_t otb_num, uint32_t otb_den) {
int ffw_bsf_init(AVBSFContext* context, int itb_num, int itb_den, int otb_num, int otb_den) {
context->time_base_in.num = itb_num;
context->time_base_in.den = itb_den;
context->time_base_out.num = otb_num;
Expand Down
8 changes: 4 additions & 4 deletions src/codec/bsf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ extern "C" {
fn ffw_bsf_set_output_codec_parameters(context: *mut c_void, params: *const c_void) -> c_int;
fn ffw_bsf_init(
context: *mut c_void,
itb_num: u32,
itb_den: u32,
otb_num: u32,
otb_den: u32,
itb_num: c_int,
itb_den: c_int,
otb_num: c_int,
otb_den: c_int,
) -> c_int;
fn ffw_bsf_push(context: *mut c_void, packet: *mut c_void) -> c_int;
fn ffw_bsf_flush(context: *mut c_void) -> c_int;
Expand Down
4 changes: 2 additions & 2 deletions src/format/demuxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int ffw_demuxer_set_option(Demuxer* demuxer, const char* key, const char* value)
int ffw_demuxer_find_stream_info(Demuxer* demuxer, int64_t max_analyze_duration);
unsigned ffw_demuxer_get_nb_streams(const Demuxer* demuxer);
AVStream* ffw_demuxer_get_stream(Demuxer* demuxer, unsigned stream_index);
int ffw_demuxer_read_frame(Demuxer* demuxer, AVPacket** packet, uint32_t* tb_num, uint32_t* tb_den);
int ffw_demuxer_read_frame(Demuxer* demuxer, AVPacket** packet, int* tb_num, int* tb_den);
int ffw_demuxer_seek(Demuxer* demuxer, int64_t timestamp, int seek_by, int seek_target);
void ffw_demuxer_free(Demuxer* demuxer);

Expand Down Expand Up @@ -133,7 +133,7 @@ AVStream* ffw_demuxer_get_stream(Demuxer* demuxer, unsigned stream_index) {
return demuxer->fc->streams[stream_index];
}

int ffw_demuxer_read_frame(Demuxer* demuxer, AVPacket** packet, uint32_t* tb_num, uint32_t* tb_den) {
int ffw_demuxer_read_frame(Demuxer* demuxer, AVPacket** packet, int* tb_num, int* tb_den) {
AVStream* stream;
AVPacket* res;
int ret;
Expand Down
4 changes: 2 additions & 2 deletions src/format/demuxer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ extern "C" {
fn ffw_demuxer_read_frame(
demuxer: *mut c_void,
packet: *mut *mut c_void,
tb_num: *mut u32,
tb_den: *mut u32,
tb_num: *mut c_int,
tb_den: *mut c_int,
) -> c_int;
fn ffw_demuxer_seek(
demuxer: *mut c_void,
Expand Down
10 changes: 5 additions & 5 deletions src/format/muxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ int ffw_muxer_get_option(Muxer*, const char*, uint8_t**);
int ffw_muxer_set_initial_option(Muxer*, const char*, const char*);
int ffw_muxer_set_option(Muxer*, const char*, const char*);
int ffw_muxer_set_metadata(Muxer*, const char*, const char*);
int ffw_muxer_write_frame(Muxer*, AVPacket*, uint32_t, uint32_t);
int ffw_muxer_interleaved_write_frame(Muxer*, AVPacket*, uint32_t, uint32_t);
int ffw_muxer_write_frame(Muxer*, AVPacket*, int, int);
int ffw_muxer_interleaved_write_frame(Muxer*, AVPacket*, int, int);
int ffw_muxer_free(Muxer*);

Muxer* ffw_muxer_new() {
Expand Down Expand Up @@ -120,7 +120,7 @@ int ffw_muxer_set_metadata(Muxer* muxer, const char* key, const char* value) {
return av_dict_set(&muxer->fc->metadata, key, value, 0);
}

static int ffw_rescale_packet_timestamps(Muxer* muxer, AVPacket* packet, uint32_t src_tb_num, uint32_t src_tb_den) {
static int ffw_rescale_packet_timestamps(Muxer* muxer, AVPacket* packet, int src_tb_num, int src_tb_den) {
AVStream* stream;
AVRational src_tb;

Expand All @@ -146,7 +146,7 @@ static int ffw_rescale_packet_timestamps(Muxer* muxer, AVPacket* packet, uint32_
return 0;
}

int ffw_muxer_write_frame(Muxer* muxer, AVPacket* packet, uint32_t tb_num, uint32_t tb_den) {
int ffw_muxer_write_frame(Muxer* muxer, AVPacket* packet, int tb_num, int tb_den) {
int ret = ffw_rescale_packet_timestamps(muxer, packet, tb_num, tb_den);

if (ret < 0) {
Expand All @@ -156,7 +156,7 @@ int ffw_muxer_write_frame(Muxer* muxer, AVPacket* packet, uint32_t tb_num, uint3
return av_write_frame(muxer->fc, packet);
}

int ffw_muxer_interleaved_write_frame(Muxer* muxer, AVPacket* packet, uint32_t tb_num, uint32_t tb_den) {
int ffw_muxer_interleaved_write_frame(Muxer* muxer, AVPacket* packet, int tb_num, int tb_den) {
int ret = ffw_rescale_packet_timestamps(muxer, packet, tb_num, tb_den);

if (ret < 0) {
Expand Down
8 changes: 4 additions & 4 deletions src/format/muxer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ extern "C" {
fn ffw_muxer_write_frame(
muxer: *mut c_void,
packet: *mut c_void,
tb_num: u32,
tb_den: u32,
tb_num: c_int,
tb_den: c_int,
) -> c_int;
fn ffw_muxer_interleaved_write_frame(
muxer: *mut c_void,
packet: *mut c_void,
tb_num: u32,
tb_den: u32,
tb_num: c_int,
tb_den: c_int,
) -> c_int;
fn ffw_muxer_free(muxer: *mut c_void) -> c_int;
}
Expand Down
14 changes: 12 additions & 2 deletions src/format/stream.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
#include <libavformat/avformat.h>

void ffw_stream_get_time_base(const AVStream* stream, uint32_t* num, uint32_t* den);
void ffw_stream_get_time_base(const AVStream* stream, int* num, int* den);
int64_t ffw_stream_get_start_time(const AVStream* stream);
int64_t ffw_stream_get_duration(const AVStream* stream);
int64_t ffw_stream_get_nb_frames(const AVStream* stream);
AVCodecParameters* ffw_stream_get_codec_parameters(const AVStream* stream);
int ffw_stream_set_metadata(AVStream* stream, const char* key, const char* value);

void ffw_stream_get_time_base(const AVStream* stream, uint32_t* num, uint32_t* den) {
void ffw_stream_get_time_base(const AVStream* stream, int* num, int* den) {
*num = stream->time_base.num;
*den = stream->time_base.den;
}

void ffw_stream_get_r_frame_rate(const AVStream* stream, int* num, int* den) {
*num = stream->r_frame_rate.num;
*den = stream->r_frame_rate.den;
}

void ffw_stream_get_avg_frame_rate(const AVStream* stream, int* num, int* den) {
*num = stream->avg_frame_rate.num;
*den = stream->avg_frame_rate.den;
}

int64_t ffw_stream_get_start_time(const AVStream* stream) {
return stream->start_time;
}
Expand Down
37 changes: 34 additions & 3 deletions src/format/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ use std::{
use crate::{
codec::CodecParameters,
time::{TimeBase, Timestamp},
Rational,
};

extern "C" {
fn ffw_stream_get_time_base(stream: *const c_void, num: *mut u32, den: *mut u32);
fn ffw_stream_get_time_base(stream: *const c_void, num: *mut c_int, den: *mut c_int);
fn ffw_stream_get_r_frame_rate(stream: *const c_void, num: *mut c_int, den: *mut c_int);
fn ffw_stream_get_avg_frame_rate(stream: *const c_void, num: *mut c_int, den: *mut c_int);
fn ffw_stream_get_start_time(stream: *const c_void) -> i64;
fn ffw_stream_get_duration(stream: *const c_void) -> i64;
fn ffw_stream_get_nb_frames(stream: *const c_void) -> i64;
Expand All @@ -32,8 +35,8 @@ pub struct Stream {
impl Stream {
/// Create a new stream from its raw representation.
pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void) -> Self {
let mut num = 0_u32;
let mut den = 0_u32;
let mut num = 0;
let mut den = 0;

ffw_stream_get_time_base(ptr, &mut num, &mut den);

Expand All @@ -48,6 +51,34 @@ impl Stream {
self.time_base
}

/// Get real base framerate of the stream.
pub fn r_frame_rate(&self) -> Rational {
let mut num = 0;
let mut den = 0;

unsafe {
ffw_stream_get_r_frame_rate(self.ptr, &mut num, &mut den);
}

Rational::new(num, den)
}

/// Get average stream frame rate.
pub fn avg_frame_rate(&self) -> Option<Rational> {
let mut num = 0;
let mut den = 0;

unsafe {
ffw_stream_get_avg_frame_rate(self.ptr, &mut num, &mut den);
}

if num != 0 && den != 0 {
Some(Rational::new(num, den))
} else {
None
}
}

/// Get the pts of the first frame of the stream in presentation order.
pub fn start_time(&self) -> Timestamp {
let pts = unsafe { ffw_stream_get_start_time(self.ptr) as _ };
Expand Down
33 changes: 32 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod time;

use std::{
ffi::CStr,
fmt::{self, Display, Formatter},
fmt::{self, Debug, Display, Formatter},
io,
os::raw::{c_char, c_int},
sync::RwLock,
Expand Down Expand Up @@ -158,3 +158,34 @@ impl Display for Error {
}

impl std::error::Error for Error {}

/// A rational number with numerator num and denominator den (num/den).
#[derive(Copy, Clone)]
pub struct Rational {
num: i32,
den: i32,
}

impl Rational {
/// Create a rational number with a given numerator and
/// denominator.
pub const fn new(num: i32, den: i32) -> Self {
Self { num, den }
}

/// Get the numerator.
pub fn num(&self) -> i32 {
self.num
}

/// Get the denominator.
pub fn den(&self) -> i32 {
self.den
}
}

impl Debug for Rational {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{}/{}", self.num(), self.den())
}
}
2 changes: 1 addition & 1 deletion src/time.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <libavutil/avutil.h>
#include <libavutil/mathematics.h>

int64_t ffw_rescale_q(int64_t n, uint32_t aq_num, uint32_t aq_den, uint32_t bq_num, uint32_t bq_den) {
int64_t ffw_rescale_q(int64_t n, int aq_num, int aq_den, int bq_num, int bq_den) {
int64_t a = aq_num * (int64_t)bq_den;
int64_t b = bq_num * (int64_t)aq_den;

Expand Down
Loading