fix: muxer cleanup

This commit is contained in:
kieran 2024-11-29 23:31:42 +00:00
parent 464ec32898
commit b1f054d7d1
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
2 changed files with 40 additions and 22 deletions

View File

@ -1,11 +1,12 @@
use crate::{bail_ffmpeg, cstr, set_opts, Encoder, AVIO_BUFFER_SIZE}; use crate::{bail_ffmpeg, cstr, set_opts, Encoder, AVIO_BUFFER_SIZE};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use ffmpeg_sys_the_third::{ use ffmpeg_sys_the_third::{
av_free, av_interleaved_write_frame, av_mallocz, av_packet_rescale_ts, av_write_trailer, av_interleaved_write_frame, av_mallocz, av_packet_rescale_ts, av_write_trailer,
avcodec_parameters_copy, avcodec_parameters_from_context, avformat_alloc_output_context2, avcodec_parameters_copy, avcodec_parameters_from_context, avformat_alloc_output_context2,
avformat_free_context, avformat_new_stream, avformat_write_header, avio_alloc_context, avformat_free_context, avformat_new_stream, avformat_write_header, avio_alloc_context,
avio_open, AVFormatContext, AVIOContext, AVPacket, AVStream, AVERROR_EOF, AVFMT_GLOBALHEADER, avio_close, avio_open, AVFormatContext, AVIOContext, AVPacket, AVStream, AVERROR_EOF,
AVFMT_NOFILE, AVIO_FLAG_DIRECT, AVIO_FLAG_WRITE, AV_CODEC_FLAG_GLOBAL_HEADER, AVFMT_GLOBALHEADER, AVFMT_NOFILE, AVIO_FLAG_DIRECT, AVIO_FLAG_WRITE,
AV_CODEC_FLAG_GLOBAL_HEADER,
}; };
use slimbox::{slimbox_unsize, SlimBox, SlimMut}; use slimbox::{slimbox_unsize, SlimBox, SlimMut};
use std::collections::HashMap; use std::collections::HashMap;
@ -111,6 +112,12 @@ pub struct MuxerBuilder {
format: Option<String>, format: Option<String>,
} }
impl Default for MuxerBuilder {
fn default() -> Self {
Self::new()
}
}
impl MuxerBuilder { impl MuxerBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -282,13 +289,9 @@ impl Muxer {
MuxerBuilder::add_copy_stream(self.ctx, in_stream) MuxerBuilder::add_copy_stream(self.ctx, in_stream)
} }
/// Initialize the context, usually after it was closed with [Muxer::reset] /// Initialize the context, usually after it was closed with [Muxer::close]
pub unsafe fn init(&mut self) -> Result<()> { pub unsafe fn init(&mut self) -> Result<()> {
MuxerBuilder::init_ctx( MuxerBuilder::init_ctx(&mut self.ctx, self.url.as_deref(), self.format.as_deref())
&mut self.ctx,
self.url.as_ref().map(|v| v.as_str()),
self.format.as_ref().map(|v| v.as_str()),
)
} }
/// Change the muxer URL /// Change the muxer URL
@ -352,11 +355,32 @@ impl Muxer {
/// Close the output and write the trailer /// Close the output and write the trailer
/// [Muxer::init] can be used to re-init the muxer /// [Muxer::init] can be used to re-init the muxer
pub unsafe fn reset(&mut self) -> Result<()> { pub unsafe fn close(&mut self) -> Result<()> {
let ret = av_write_trailer(self.ctx); let ret = av_write_trailer(self.ctx);
bail_ffmpeg!(ret); bail_ffmpeg!(ret);
avformat_free_context(self.ctx); self.free_ctx()?;
self.ctx = ptr::null_mut(); Ok(())
}
unsafe fn free_ctx(&mut self) -> Result<()> {
if !self.ctx.is_null() {
match self.output {
MuxerOutput::Url(_) => {
if !(*self.ctx).pb.is_null() {
let ret = avio_close((*self.ctx).pb);
bail_ffmpeg!(ret);
}
}
MuxerOutput::WriterSeeker(_) => {
drop(SlimBox::<dyn WriteSeek>::from_raw((*(*self.ctx).pb).opaque));
}
MuxerOutput::Writer(_) => {
drop(SlimBox::<dyn Write>::from_raw((*(*self.ctx).pb).opaque));
}
}
avformat_free_context(self.ctx);
self.ctx = ptr::null_mut();
}
Ok(()) Ok(())
} }
} }
@ -364,13 +388,7 @@ impl Muxer {
impl Drop for Muxer { impl Drop for Muxer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if !self.ctx.is_null() { self.free_ctx();
if let MuxerOutput::Writer(_) = self.output {
av_free((*(*self.ctx).pb).buffer as *mut _);
drop(SlimBox::<dyn Read>::from_raw((*(*self.ctx).pb).opaque));
}
avformat_free_context(self.ctx);
}
} }
} }
} }
@ -426,7 +444,7 @@ mod tests {
for f_pk in encoder.encode_frame(ptr::null_mut())? { for f_pk in encoder.encode_frame(ptr::null_mut())? {
muxer.write_packet(f_pk)?; muxer.write_packet(f_pk)?;
} }
muxer.reset()?; muxer.close()?;
Ok(()) Ok(())
} }

View File

@ -97,7 +97,7 @@ impl Transcoder {
// flush // flush
if pkt.is_null() { if pkt.is_null() {
for (_, enc) in &mut self.encoders { for enc in self.encoders.values_mut() {
for mut new_pkt in enc.encode_frame(ptr::null_mut())? { for mut new_pkt in enc.encode_frame(ptr::null_mut())? {
self.muxer.write_packet(new_pkt)?; self.muxer.write_packet(new_pkt)?;
av_packet_free(&mut new_pkt); av_packet_free(&mut new_pkt);
@ -155,7 +155,7 @@ impl Transcoder {
while !self.next()? { while !self.next()? {
// nothing here // nothing here
} }
self.muxer.reset()?; self.muxer.close()?;
Ok(()) Ok(())
} }
} }