-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
segfault when transcoding and frame sizes match exactly #71
Comments
Interesting. I'm not sure if it's a bug in our crate or if the bug is somewhere in the FFmpeg. In any case, if discarding empty frames by the encoder helps, it's probably worth implementing. Though I'm also not sure if encoding empty frames may be intentional in some cases. Could you post here a code example that can be used to reproduce the bug? I can help with debugging. |
#[test]
fn empty_frames() {
// load sample mp3
let input_path = concat!(env!("CARGO_MANIFEST_DIR"), "/resources/test/broken.mp3");
let input_file = File::open(input_path).unwrap();
// output to a vec
let output = Vec::new();
// wrap input and output in io
let input = IO::from_seekable_read_stream(input_file);
let output = IO::from_write_stream(output);
// create demuxer
let mut demuxer = Demuxer::builder()
.build(input)
.unwrap()
.find_stream_info(None)
.map_err(|_| "could not find stream info")
.unwrap();
// find audio stream
let (input_stream_index, _, input_codec_parameters) = demuxer
.streams()
.iter()
.enumerate()
.map(|(stream_index, stream)| {
(
stream_index,
stream,
stream.codec_parameters().into_audio_codec_parameters(),
)
})
.find(|(_, _, params)| params.is_some())
.map(|(stream_index, stream, params)| (stream_index, stream, params.unwrap()))
.expect("should find audio stream");
// create output/muxer
let channel_layout = ChannelLayout::from_channels(2).unwrap();
let sample_format = SampleFormat::from_str("fltp").unwrap();
let output_format = OutputFormat::find_by_name("mp3").unwrap();
let output_codec_parameters = AudioCodecParameters::builder("mp3")
.unwrap()
.channel_layout(&channel_layout)
.sample_format(sample_format)
.sample_rate(44100)
.build();
let mut muxer = Muxer::builder();
let output_stream_index = muxer
.add_stream(&CodecParameters::from(output_codec_parameters.clone()))
.unwrap();
let mut muxer = muxer.build(output, output_format).unwrap();
// create transcoder
let mut transcoder =
AudioTranscoder::builder(input_codec_parameters, output_codec_parameters)
.unwrap()
.build()
.unwrap();
// do transcode
while let Some(packet) = demuxer.take().unwrap() {
if packet.stream_index() != input_stream_index {
continue;
}
transcoder.push(packet).unwrap();
while let Some(packet) = transcoder.take().unwrap() {
let packet = packet.with_stream_index(output_stream_index);
muxer.push(packet).unwrap();
}
}
println!("flushing transcoder");
transcoder.flush().unwrap();
// drain any remaining packets
while let Some(packet) = transcoder.take().unwrap() {
let packet = packet.with_stream_index(output_stream_index);
muxer.push(packet).unwrap()
}
println!("flushing muxer");
muxer.flush().unwrap();
println!("closing muxer");
muxer.close().unwrap();
} zip file containing the mp3: this fails with a segfault, unless I skip the empty frames |
In a slightly degenerate case, I'm transcoding a 44.1khz stereo mp3 to a 44.1khz stereo mp3.
When flushing we pass in a null frame to
swr_convert_frame
in resampler.c:256This then ends up returning a frame with nb_samples of 0, because everything matched up exactly (I think)
This 'empty' frame gets send along to
avcodec_send_frame
, which then segfaults :/I think a potential fix is to only push non-empty frames to the Encoder, but curious for ideas on other fixes
e.g. in mod.rs making this change fixes the segfault
I'm not entirely sure of exactly where the segfault happens - I need to figure out a local build of ffmpeg with debug symbols
The text was updated successfully, but these errors were encountered: