Skip to content

Commit

Permalink
Merge pull request #4 from phial3/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
phial3 authored Jan 31, 2025
2 parents 0ed93de + adcc17d commit dc97ba5
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 40 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 3.0.1

- Fix compilation with `serialize` feature and newest `bitflags` crate

## Version 3.0.0

- [Breaking] remove support for < ffmpeg 4.2
Expand Down
51 changes: 27 additions & 24 deletions Cargo.lock.MSRV

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ffmpeg-the-third"
version = "3.0.0+ffmpeg-7.1"
version = "3.0.1+ffmpeg-7.1"
edition = "2021"

authors = ["meh. <[email protected]>", "Zhiming Wang <[email protected]>"]
Expand All @@ -20,14 +20,14 @@ rust-version = "1.82.0"

[dependencies]
libc = "0.2"
bitflags = "2.7"
bitflags = "2.8"

[dependencies.image]
version = "0.25"
optional = true

[dependencies.ffmpeg-sys-third]
version = "3.0.0"
version = "3.0.1"
default-features = false
path = "ffmpeg-sys-third"

Expand All @@ -47,7 +47,7 @@ default = [
"non-exhaustive-enums",
]

serialize = ["serde"]
serialize = ["serde", "bitflags/serde"]
static = ["ffmpeg-sys-third/static"]

# mark enums in generated bindings as #[non_exhaustive]
Expand Down
4 changes: 3 additions & 1 deletion examples/transcode-x264.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ impl Transcoder {
let codec = encoder::find(codec::Id::H264);
let mut ost = octx.add_stream(codec)?;

let mut encoder = codec::context::Context::new(codec).encoder().video()?;
let mut encoder = codec::context::Context::new_with_codec(codec.unwrap())
.encoder()
.video()?;
ost.set_parameters_into(&encoder);
encoder.set_height(decoder.height());
encoder.set_width(decoder.width());
Expand Down
133 changes: 133 additions & 0 deletions examples/video-resize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
extern crate ffmpeg_the_third as ffmpeg;

use ffmpeg::{codec, format, frame, media, picture, software};
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
ffmpeg::init()?;

let width = 1920;
let height = 1080;
let input_file = env::args().nth(1).expect("missing input file");
let output_file = env::args().nth(2).expect("missing output file");

// 打开输入/输出文件
let mut input_context = format::input(&input_file)?;
let mut output_context = format::output(&output_file)?;

// 获取视频流信息
let input_stream = input_context
.streams()
.best(media::Type::Video)
.ok_or("no video stream found")?;
let input_stream_index = input_stream.index();
let input_codec_context = codec::context::Context::from_parameters(input_stream.parameters())?;

// 创建解码器
let mut decoder = input_codec_context.decoder().video().unwrap();

// 使用标准的帧率值(如 25fps)
let frame_rate = ffmpeg::Rational::new(25, 1);
// 使用标准的时基值(如 1/90000)
let time_base = ffmpeg::Rational::new(1, 90000);
println!("frame rate: {:?}, time base: {:?}", frame_rate, time_base);

// 创建和配置编码器
let codec = codec::encoder::find(codec::Id::H264);
let mut encoder = codec::context::Context::new_with_codec(codec.unwrap())
.encoder()
.video()?;

// 设置编码器参数
encoder.set_height(height);
encoder.set_width(width);
encoder.set_aspect_ratio(decoder.aspect_ratio());
encoder.set_format(decoder.format());
encoder.set_frame_rate(Some(frame_rate));
encoder.set_time_base(time_base);
encoder.set_max_b_frames(0);
encoder.set_gop(12);
// 设置一些H.264特定的参数
encoder.set_bit_rate(2_000_000);

let mut encoder = encoder.open_as(codec)?;

// 创建输出流
let mut output_stream = output_context.add_stream(codec)?;
output_stream.set_parameters_into(&encoder);
output_context.write_header()?;

// 创建缩放器
let mut scaler = software::scaling::Context::get(
decoder.format(),
decoder.width(),
decoder.height(),
encoder.format(),
encoder.width(),
encoder.height(),
software::scaling::Flags::BILINEAR,
)?;

// 创建帧缓冲
let mut decoded_frame = frame::Video::empty();
let mut scaled_frame = frame::Video::empty();
let mut frame_count: i64 = 0;

println!("video resize start...");

// 计算每帧的时间增量(以时基为单位)
// 90000/25 = 3600,每帧增加3600个时基单位
let time_increment = 90000_i64 / 25;

// 处理视频帧
for (stream, packet) in input_context.packets().filter_map(Result::ok) {
if stream.index() == input_stream_index {
decoder.send_packet(&packet)?;

while decoder.receive_frame(&mut decoded_frame).is_ok() {
// 缩放
scaler.run(&decoded_frame, &mut scaled_frame)?;

// 计算正确的时间戳 (pts)
let pts = frame_count * time_increment;
scaled_frame.set_pts(Some(pts));
scaled_frame.set_kind(picture::Type::None);

// println!("send frame to encoder, pts: {}, time: {:.3}s", pts, pts as f64 / 90000.0);
encoder.send_frame(&scaled_frame)?;

// 获取编码后的数据包
let mut encoded_packet = codec::packet::Packet::empty();
while encoder.receive_packet(&mut encoded_packet).is_ok() {
encoded_packet.set_stream(0);
encoded_packet.set_pts(Some(pts));
encoded_packet.set_dts(Some(pts));
// 写入数据包
encoded_packet.write_interleaved(&mut output_context)?;
}

frame_count += 1;
}
}
}

// 刷新编码器
encoder.send_eof()?;
let mut packet = codec::packet::Packet::empty();
while encoder.receive_packet(&mut packet).is_ok() {
let pts = frame_count * time_increment;
packet.set_stream(0);
packet.set_pts(Some(pts));
packet.set_dts(Some(pts));
packet.write_interleaved(&mut output_context)?;
frame_count += 1;
}

// 写入文件尾部
output_context.write_trailer()?;

println!("video resize complete: {}", output_file);
println!("total frames processed: {}", frame_count);

Ok(())
}
2 changes: 1 addition & 1 deletion ffmpeg-sys-third/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ffmpeg-sys-third"
version = "3.0.0+ffmpeg-7.1"
version = "3.0.1+ffmpeg-7.1"
links = "ffmpeg"
edition = "2021"

Expand Down
22 changes: 14 additions & 8 deletions src/codec/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,26 @@ impl Context {
}

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

pub fn new_with_codec(codec: Codec) -> Self {
unsafe {
Context {
ptr: avcodec_alloc_context3(codec.as_ptr()),
owner: None,
}
}
}

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

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

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

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

ctx
Expand Down
Loading

0 comments on commit dc97ba5

Please sign in to comment.