You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Fixed some big memory leaks with audio samples and ffmpeg (pprof ./openshot-example "/tmp/openshot-example.30691._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv
This commit is contained in:
@@ -995,7 +995,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
|
||||
|
||||
// Convert audio samples
|
||||
nb_samples = avresample_convert(avr, // audio resample context
|
||||
audio_converted->data, // output data pointers
|
||||
audio_converted->data, // output data pointers
|
||||
audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
|
||||
audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
|
||||
audio_frame->data, // input data pointers
|
||||
|
||||
@@ -1031,7 +1031,8 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
|
||||
|
||||
// Create a new array (to hold all S16 audio samples, for the current queued frames
|
||||
int16_t* frame_samples = new int16_t[(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE) + FF_INPUT_BUFFER_PADDING_SIZE];
|
||||
int16_t* queued_samples = new int16_t[(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE) + FF_INPUT_BUFFER_PADDING_SIZE];
|
||||
int16_t* resampled_samples = NULL;
|
||||
|
||||
// Loop through each queued audio frame
|
||||
while (!queued_audio_frames.empty())
|
||||
@@ -1058,7 +1059,7 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
// Translate audio sample values back to 16 bit integers
|
||||
for (int s = 0; s < total_frame_samples; s++, frame_position++)
|
||||
// Translate sample value and copy into buffer
|
||||
frame_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
|
||||
queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
|
||||
|
||||
|
||||
// Deallocate float array
|
||||
@@ -1082,15 +1083,16 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
// Keep track of the original sample format
|
||||
AVSampleFormat output_sample_fmt = audio_codec->sample_fmt;
|
||||
|
||||
AVFrame *audio_frame = NULL;
|
||||
if (!final) {
|
||||
// Create input frame (and allocate arrays)
|
||||
AVFrame *audio_frame = avcodec_alloc_frame();
|
||||
audio_frame = avcodec_alloc_frame();
|
||||
avcodec_get_frame_defaults(audio_frame);
|
||||
audio_frame->nb_samples = total_frame_samples / channels_in_frame;
|
||||
av_samples_alloc(audio_frame->data, audio_frame->linesize, channels_in_frame, total_frame_samples / channels_in_frame, AV_SAMPLE_FMT_S16, 0);
|
||||
//av_samples_alloc(audio_frame->data, audio_frame->linesize, channels_in_frame, total_frame_samples / channels_in_frame, AV_SAMPLE_FMT_S16, 0);
|
||||
|
||||
// Fill input frame with sample data
|
||||
avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples,
|
||||
avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) queued_samples,
|
||||
audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame, 1);
|
||||
|
||||
// Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
|
||||
@@ -1159,19 +1161,21 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
|
||||
audio_frame->nb_samples); // number of input samples to convert
|
||||
|
||||
// Create a new array (to hold all resampled S16 audio samples)
|
||||
resampled_samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
|
||||
|
||||
// Copy audio samples over original samples
|
||||
memcpy(frame_samples, audio_converted->data[0], nb_samples * av_get_bytes_per_sample(output_sample_fmt) * info.channels);
|
||||
memcpy(resampled_samples, audio_converted->data[0], nb_samples * av_get_bytes_per_sample(output_sample_fmt) * info.channels);
|
||||
|
||||
// Update remaining samples (since we just resampled the audio, and things might have changed)
|
||||
remaining_frame_samples = nb_samples * (float(av_get_bytes_per_sample(output_sample_fmt)) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)) * info.channels;
|
||||
|
||||
#pragma omp critical (debug_output)
|
||||
AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)", "nb_samples", nb_samples, "remaining_frame_samples", remaining_frame_samples, "", -1, "", -1, "", -1, "", -1);
|
||||
|
||||
// Free AVFrames
|
||||
avcodec_free_frame(&audio_frame); // TODO: Find a way to clear the memory inside this frame (memory leak)
|
||||
// Remove converted audio
|
||||
av_freep(&audio_converted[0]);
|
||||
avcodec_free_frame(&audio_converted);
|
||||
|
||||
#pragma omp critical (debug_output)
|
||||
AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)", "nb_samples", nb_samples, "remaining_frame_samples", remaining_frame_samples, "", -1, "", -1, "", -1, "", -1);
|
||||
}
|
||||
|
||||
// Loop until no more samples
|
||||
@@ -1188,7 +1192,7 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
|
||||
// Copy frame samples into the packet samples array
|
||||
if (!final)
|
||||
memcpy(samples + audio_input_position, frame_samples + samples_position, diff * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
|
||||
memcpy(samples + audio_input_position, resampled_samples + samples_position, diff * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
|
||||
|
||||
// Increment counters
|
||||
audio_input_position += diff;
|
||||
@@ -1228,7 +1232,7 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
AVFrame *audio_frame = avcodec_alloc_frame();
|
||||
avcodec_get_frame_defaults(audio_frame);
|
||||
audio_frame->nb_samples = audio_input_position / info.channels;
|
||||
av_samples_alloc(audio_frame->data, audio_frame->linesize, info.channels, audio_input_position / info.channels, output_sample_fmt, 0);
|
||||
//av_samples_alloc(audio_frame->data, audio_frame->linesize, info.channels, audio_input_position / info.channels, output_sample_fmt, 0);
|
||||
|
||||
// Fill input frame with sample data
|
||||
avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) samples,
|
||||
@@ -1339,8 +1343,15 @@ void FFmpegWriter::write_audio_packets(bool final)
|
||||
final = false;
|
||||
}
|
||||
|
||||
// Delete arrays
|
||||
delete[] frame_samples;
|
||||
// Free AVFrames
|
||||
if (audio_frame) {
|
||||
av_freep(&audio_frame[0]);
|
||||
avcodec_free_frame(&audio_frame);
|
||||
}
|
||||
if (resampled_samples) {
|
||||
delete[] resampled_samples;
|
||||
resampled_samples = NULL;
|
||||
}
|
||||
|
||||
} // end task
|
||||
}
|
||||
|
||||
@@ -548,6 +548,13 @@ void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldow
|
||||
info.sample_rate = target_sample_rate;
|
||||
info.channels = target_channels;
|
||||
info.channel_layout = target_channel_layout;
|
||||
|
||||
// Deallocate resample buffer
|
||||
if (avr) {
|
||||
avresample_close(avr);
|
||||
avresample_free(&avr);
|
||||
avr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Resample audio and map channels (if needed)
|
||||
@@ -563,23 +570,21 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
int samples_in_frame = frame->GetAudioSamplesCount();
|
||||
ChannelLayout channel_layout_in_frame = frame->ChannelsLayout();
|
||||
|
||||
// Create a new array (to hold all S16 audio samples, for the current queued frames
|
||||
int16_t* frame_samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
|
||||
|
||||
// Get audio sample array
|
||||
float* frame_samples_float = NULL;
|
||||
// Get samples interleaved together (c1 c2 c1 c2 c1 c2)
|
||||
frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
|
||||
|
||||
|
||||
// Calculate total samples
|
||||
total_frame_samples = samples_in_frame * channels_in_frame;
|
||||
|
||||
// Create a new array (to hold all S16 audio samples for the current queued frames)
|
||||
int16_t* frame_samples = new int16_t[total_frame_samples];
|
||||
|
||||
// Translate audio sample values back to 16 bit integers
|
||||
for (int s = 0; s < total_frame_samples; s++)
|
||||
// Translate sample value and copy into buffer
|
||||
frame_samples[s] = int(frame_samples_float[s] * (1 << 15));
|
||||
//frame_samples[s] = s * 3;
|
||||
|
||||
// Deallocate float array
|
||||
delete[] frame_samples_float;
|
||||
@@ -593,8 +598,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
AVFrame *audio_frame = avcodec_alloc_frame();
|
||||
avcodec_get_frame_defaults(audio_frame);
|
||||
audio_frame->nb_samples = total_frame_samples / channels_in_frame;
|
||||
//audio_frame->sample_rate = frame->SampleRate();
|
||||
av_samples_alloc(audio_frame->data, audio_frame->linesize, channels_in_frame, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
|
||||
//av_samples_alloc(audio_frame->data, audio_frame->linesize, channels_in_frame, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
|
||||
|
||||
int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples,
|
||||
audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame, 1);
|
||||
@@ -614,7 +618,6 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
AVFrame *audio_converted = avcodec_alloc_frame();
|
||||
avcodec_get_frame_defaults(audio_converted);
|
||||
audio_converted->nb_samples = audio_frame->nb_samples;
|
||||
//audio_converted->sample_rate = info.sample_rate;
|
||||
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
|
||||
|
||||
#pragma omp critical (debug_output)
|
||||
@@ -644,12 +647,16 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
|
||||
audio_frame->nb_samples); // number of input samples to convert
|
||||
|
||||
// Create a new array (to hold all resampled S16 audio samples)
|
||||
int16_t* resampled_samples = new int16_t[nb_samples * info.channels];
|
||||
|
||||
// Copy audio samples over original samples
|
||||
memcpy(frame_samples, audio_converted->data[0], nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels);
|
||||
memcpy(resampled_samples, audio_converted->data[0], nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels);
|
||||
|
||||
// Free frames
|
||||
av_freep(&audio_frame[0]);
|
||||
avcodec_free_frame(&audio_frame); // TODO: Find a way to clear the memory inside this frame (memory leak)
|
||||
frame_samples = NULL;
|
||||
av_freep(&audio_converted[0]);
|
||||
avcodec_free_frame(&audio_converted);
|
||||
|
||||
@@ -680,7 +687,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
if (channel_filter == channel)
|
||||
{
|
||||
// Add sample (convert from (-32768 to 32768) to (-1.0 to 1.0))
|
||||
channel_buffer[position] = frame_samples[sample] * (1.0f / (1 << 15));
|
||||
channel_buffer[position] = resampled_samples[sample] * (1.0f / (1 << 15));
|
||||
|
||||
// Increment audio position
|
||||
position++;
|
||||
@@ -707,5 +714,6 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
|
||||
channel_buffer = NULL;
|
||||
|
||||
// Delete arrays
|
||||
delete[] frame_samples;
|
||||
delete[] resampled_samples;
|
||||
resampled_samples = NULL;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ int main(int argc, char* argv[])
|
||||
//r9.GetFrame(frame_number)->DisplayWaveform();
|
||||
//f->DisplayWaveform();
|
||||
//f->AddColor(r9.info.width, r9.info.height, "blue");
|
||||
//w9.WriteFrame(f);
|
||||
w9.WriteFrame(f);
|
||||
|
||||
//frame++;
|
||||
}
|
||||
@@ -112,6 +112,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Close timeline
|
||||
r9.Close();
|
||||
map.Close();
|
||||
/* ---------------- */
|
||||
cout << "happy ending" << endl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user