lumen_ffmpeg/encode/
output.rs1use std::ptr;
2
3use crate::ffi::{self, sys};
4use crate::{FfmpegError, Result};
5
6pub struct OutputContext {
7 path: String,
8 pub(crate) ptr: *mut sys::AVFormatContext,
9 opened_io: bool,
10}
11
12unsafe impl Send for OutputContext {}
13
14impl OutputContext {
15 pub fn create(path: impl Into<String>) -> Result<Self> {
16 ffi::init();
17 let path = path.into();
18 let c_path = ffi::cstring("avformat_alloc_output_context2", &path)?;
19 let mut ptr: *mut sys::AVFormatContext = ptr::null_mut();
20 unsafe {
21 ffi::check(
22 sys::avformat_alloc_output_context2(
23 &mut ptr,
24 ptr::null_mut(),
25 ptr::null(),
26 c_path.as_ptr(),
27 ),
28 "avformat_alloc_output_context2",
29 )
30 .map_err(|error| error.with_path(path.clone()))?;
31 }
32 if ptr.is_null() {
33 return Err(FfmpegError::new(
34 "avformat_alloc_output_context2",
35 "failed to allocate output context",
36 )
37 .with_path(path));
38 }
39 Ok(Self {
40 path,
41 ptr,
42 opened_io: false,
43 })
44 }
45
46 pub fn path(&self) -> &str {
47 &self.path
48 }
49
50 pub(crate) fn write_header(&mut self) -> Result<()> {
51 self.open_io()?;
52 unsafe {
53 ffi::check(
54 sys::avformat_write_header(self.ptr, ptr::null_mut()),
55 "avformat_write_header",
56 )
57 .map_err(|error| error.with_path(self.path.clone()))
58 }
59 }
60
61 pub(crate) fn write_trailer(&mut self) -> Result<()> {
62 unsafe {
63 ffi::check(sys::av_write_trailer(self.ptr), "av_write_trailer")
64 .map_err(|error| error.with_path(self.path.clone()))
65 }
66 }
67
68 fn open_io(&mut self) -> Result<()> {
69 unsafe {
70 if ((*(*self.ptr).oformat).flags & sys::AVFMT_NOFILE) == 0 {
71 let c_path = ffi::cstring("avio_open", &self.path)?;
72 ffi::check(
73 sys::avio_open(&mut (*self.ptr).pb, c_path.as_ptr(), sys::AVIO_FLAG_WRITE),
74 "avio_open",
75 )
76 .map_err(|error| error.with_path(self.path.clone()))?;
77 self.opened_io = true;
78 }
79 }
80 Ok(())
81 }
82}
83
84impl Drop for OutputContext {
85 fn drop(&mut self) {
86 unsafe {
87 if self.opened_io && !(*self.ptr).pb.is_null() {
88 sys::avio_closep(&mut (*self.ptr).pb);
89 }
90 sys::avformat_free_context(self.ptr);
91 }
92 }
93}