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 anyhow::{bail, Result};
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,
avformat_free_context, avformat_new_stream, avformat_write_header, avio_alloc_context,
avio_open, AVFormatContext, AVIOContext, AVPacket, AVStream, AVERROR_EOF, AVFMT_GLOBALHEADER,
AVFMT_NOFILE, AVIO_FLAG_DIRECT, AVIO_FLAG_WRITE, AV_CODEC_FLAG_GLOBAL_HEADER,
avio_close, avio_open, AVFormatContext, AVIOContext, AVPacket, AVStream, AVERROR_EOF,
AVFMT_GLOBALHEADER, AVFMT_NOFILE, AVIO_FLAG_DIRECT, AVIO_FLAG_WRITE,
AV_CODEC_FLAG_GLOBAL_HEADER,
};
use slimbox::{slimbox_unsize, SlimBox, SlimMut};
use std::collections::HashMap;
@ -111,6 +112,12 @@ pub struct MuxerBuilder {
format: Option<String>,
}
impl Default for MuxerBuilder {
fn default() -> Self {
Self::new()
}
}
impl MuxerBuilder {
pub fn new() -> Self {
Self {
@ -282,13 +289,9 @@ impl Muxer {
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<()> {
MuxerBuilder::init_ctx(
&mut self.ctx,
self.url.as_ref().map(|v| v.as_str()),
self.format.as_ref().map(|v| v.as_str()),
)
MuxerBuilder::init_ctx(&mut self.ctx, self.url.as_deref(), self.format.as_deref())
}
/// Change the muxer URL
@ -352,11 +355,32 @@ impl Muxer {
/// Close the output and write the trailer
/// [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);
bail_ffmpeg!(ret);
self.free_ctx()?;
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(())
}
}
@ -364,13 +388,7 @@ impl Muxer {
impl Drop for Muxer {
fn drop(&mut self) {
unsafe {
if !self.ctx.is_null() {
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);
}
self.free_ctx();
}
}
}
@ -426,7 +444,7 @@ mod tests {
for f_pk in encoder.encode_frame(ptr::null_mut())? {
muxer.write_packet(f_pk)?;
}
muxer.reset()?;
muxer.close()?;
Ok(())
}

View File

@ -97,7 +97,7 @@ impl Transcoder {
// flush
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())? {
self.muxer.write_packet(new_pkt)?;
av_packet_free(&mut new_pkt);
@ -155,7 +155,7 @@ impl Transcoder {
while !self.next()? {
// nothing here
}
self.muxer.reset()?;
self.muxer.close()?;
Ok(())
}
}