Skip to content

Commit dc97ba5

Browse files
authored
Merge pull request #4 from phial3/develop
Develop
2 parents 0ed93de + adcc17d commit dc97ba5

File tree

9 files changed

+188
-40
lines changed

9 files changed

+188
-40
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Version 3.0.1
2+
3+
- Fix compilation with `serialize` feature and newest `bitflags` crate
4+
15
## Version 3.0.0
26

37
- [Breaking] remove support for < ffmpeg 4.2

Cargo.lock.MSRV

Lines changed: 27 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ffmpeg-the-third"
3-
version = "3.0.0+ffmpeg-7.1"
3+
version = "3.0.1+ffmpeg-7.1"
44
edition = "2021"
55

66
authors = ["meh. <meh@schizofreni.co>", "Zhiming Wang <i@zhimingwang.org>"]
@@ -20,14 +20,14 @@ rust-version = "1.82.0"
2020

2121
[dependencies]
2222
libc = "0.2"
23-
bitflags = "2.7"
23+
bitflags = "2.8"
2424

2525
[dependencies.image]
2626
version = "0.25"
2727
optional = true
2828

2929
[dependencies.ffmpeg-sys-third]
30-
version = "3.0.0"
30+
version = "3.0.1"
3131
default-features = false
3232
path = "ffmpeg-sys-third"
3333

@@ -47,7 +47,7 @@ default = [
4747
"non-exhaustive-enums",
4848
]
4949

50-
serialize = ["serde"]
50+
serialize = ["serde", "bitflags/serde"]
5151
static = ["ffmpeg-sys-third/static"]
5252

5353
# mark enums in generated bindings as #[non_exhaustive]

examples/transcode-x264.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ impl Transcoder {
5555
let codec = encoder::find(codec::Id::H264);
5656
let mut ost = octx.add_stream(codec)?;
5757

58-
let mut encoder = codec::context::Context::new(codec).encoder().video()?;
58+
let mut encoder = codec::context::Context::new_with_codec(codec.unwrap())
59+
.encoder()
60+
.video()?;
5961
ost.set_parameters_into(&encoder);
6062
encoder.set_height(decoder.height());
6163
encoder.set_width(decoder.width());

examples/video-resize.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
extern crate ffmpeg_the_third as ffmpeg;
2+
3+
use ffmpeg::{codec, format, frame, media, picture, software};
4+
use std::env;
5+
6+
fn main() -> Result<(), Box<dyn std::error::Error>> {
7+
ffmpeg::init()?;
8+
9+
let width = 1920;
10+
let height = 1080;
11+
let input_file = env::args().nth(1).expect("missing input file");
12+
let output_file = env::args().nth(2).expect("missing output file");
13+
14+
// 打开输入/输出文件
15+
let mut input_context = format::input(&input_file)?;
16+
let mut output_context = format::output(&output_file)?;
17+
18+
// 获取视频流信息
19+
let input_stream = input_context
20+
.streams()
21+
.best(media::Type::Video)
22+
.ok_or("no video stream found")?;
23+
let input_stream_index = input_stream.index();
24+
let input_codec_context = codec::context::Context::from_parameters(input_stream.parameters())?;
25+
26+
// 创建解码器
27+
let mut decoder = input_codec_context.decoder().video().unwrap();
28+
29+
// 使用标准的帧率值(如 25fps)
30+
let frame_rate = ffmpeg::Rational::new(25, 1);
31+
// 使用标准的时基值(如 1/90000)
32+
let time_base = ffmpeg::Rational::new(1, 90000);
33+
println!("frame rate: {:?}, time base: {:?}", frame_rate, time_base);
34+
35+
// 创建和配置编码器
36+
let codec = codec::encoder::find(codec::Id::H264);
37+
let mut encoder = codec::context::Context::new_with_codec(codec.unwrap())
38+
.encoder()
39+
.video()?;
40+
41+
// 设置编码器参数
42+
encoder.set_height(height);
43+
encoder.set_width(width);
44+
encoder.set_aspect_ratio(decoder.aspect_ratio());
45+
encoder.set_format(decoder.format());
46+
encoder.set_frame_rate(Some(frame_rate));
47+
encoder.set_time_base(time_base);
48+
encoder.set_max_b_frames(0);
49+
encoder.set_gop(12);
50+
// 设置一些H.264特定的参数
51+
encoder.set_bit_rate(2_000_000);
52+
53+
let mut encoder = encoder.open_as(codec)?;
54+
55+
// 创建输出流
56+
let mut output_stream = output_context.add_stream(codec)?;
57+
output_stream.set_parameters_into(&encoder);
58+
output_context.write_header()?;
59+
60+
// 创建缩放器
61+
let mut scaler = software::scaling::Context::get(
62+
decoder.format(),
63+
decoder.width(),
64+
decoder.height(),
65+
encoder.format(),
66+
encoder.width(),
67+
encoder.height(),
68+
software::scaling::Flags::BILINEAR,
69+
)?;
70+
71+
// 创建帧缓冲
72+
let mut decoded_frame = frame::Video::empty();
73+
let mut scaled_frame = frame::Video::empty();
74+
let mut frame_count: i64 = 0;
75+
76+
println!("video resize start...");
77+
78+
// 计算每帧的时间增量(以时基为单位)
79+
// 90000/25 = 3600,每帧增加3600个时基单位
80+
let time_increment = 90000_i64 / 25;
81+
82+
// 处理视频帧
83+
for (stream, packet) in input_context.packets().filter_map(Result::ok) {
84+
if stream.index() == input_stream_index {
85+
decoder.send_packet(&packet)?;
86+
87+
while decoder.receive_frame(&mut decoded_frame).is_ok() {
88+
// 缩放
89+
scaler.run(&decoded_frame, &mut scaled_frame)?;
90+
91+
// 计算正确的时间戳 (pts)
92+
let pts = frame_count * time_increment;
93+
scaled_frame.set_pts(Some(pts));
94+
scaled_frame.set_kind(picture::Type::None);
95+
96+
// println!("send frame to encoder, pts: {}, time: {:.3}s", pts, pts as f64 / 90000.0);
97+
encoder.send_frame(&scaled_frame)?;
98+
99+
// 获取编码后的数据包
100+
let mut encoded_packet = codec::packet::Packet::empty();
101+
while encoder.receive_packet(&mut encoded_packet).is_ok() {
102+
encoded_packet.set_stream(0);
103+
encoded_packet.set_pts(Some(pts));
104+
encoded_packet.set_dts(Some(pts));
105+
// 写入数据包
106+
encoded_packet.write_interleaved(&mut output_context)?;
107+
}
108+
109+
frame_count += 1;
110+
}
111+
}
112+
}
113+
114+
// 刷新编码器
115+
encoder.send_eof()?;
116+
let mut packet = codec::packet::Packet::empty();
117+
while encoder.receive_packet(&mut packet).is_ok() {
118+
let pts = frame_count * time_increment;
119+
packet.set_stream(0);
120+
packet.set_pts(Some(pts));
121+
packet.set_dts(Some(pts));
122+
packet.write_interleaved(&mut output_context)?;
123+
frame_count += 1;
124+
}
125+
126+
// 写入文件尾部
127+
output_context.write_trailer()?;
128+
129+
println!("video resize complete: {}", output_file);
130+
println!("total frames processed: {}", frame_count);
131+
132+
Ok(())
133+
}

ffmpeg-sys-third/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ffmpeg-sys-third"
3-
version = "3.0.0+ffmpeg-7.1"
3+
version = "3.0.1+ffmpeg-7.1"
44
links = "ffmpeg"
55
edition = "2021"
66

src/codec/context.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,26 @@ impl Context {
3333
}
3434

3535
impl Context {
36-
pub fn new(codec: Option<Codec>) -> Self {
36+
pub fn new() -> Self {
3737
unsafe {
3838
Context {
39-
ptr: match codec {
40-
Some(c) => avcodec_alloc_context3(c.as_ptr()),
41-
None => avcodec_alloc_context3(ptr::null()),
42-
},
39+
ptr: avcodec_alloc_context3(ptr::null()),
40+
owner: None,
41+
}
42+
}
43+
}
44+
45+
pub fn new_with_codec(codec: Codec) -> Self {
46+
unsafe {
47+
Context {
48+
ptr: avcodec_alloc_context3(codec.as_ptr()),
4349
owner: None,
4450
}
4551
}
4652
}
4753

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

5157
unsafe {
5258
match avcodec_parameters_to_context(context.as_mut_ptr(), parameters.as_ptr()) {
@@ -131,7 +137,7 @@ impl Context {
131137

132138
impl Default for Context {
133139
fn default() -> Self {
134-
Self::new(None)
140+
Self::new()
135141
}
136142
}
137143

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

154160
ctx

0 commit comments

Comments
 (0)