diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp
index 5f3da953..7f3cf535 100644
--- a/src/FFmpegWriter.cpp
+++ b/src/FFmpegWriter.cpp
@@ -1031,8 +1031,10 @@ 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* queued_samples = new int16_t[(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE) + FF_INPUT_BUFFER_PADDING_SIZE];
- int16_t* resampled_samples = NULL;
+ int16_t* all_queued_samples = new int16_t[(queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE) + FF_INPUT_BUFFER_PADDING_SIZE];
+ int16_t* all_resampled_samples = NULL;
+ int16_t* final_samples_planar = NULL;
+ int16_t* final_samples = NULL;
// Loop through each queued audio frame
while (!queued_audio_frames.empty())
@@ -1059,7 +1061,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
- queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
+ all_queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15));
// Deallocate float array
@@ -1089,10 +1091,9 @@ void FFmpegWriter::write_audio_packets(bool final)
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);
// Fill input frame with sample data
- avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) queued_samples,
+ avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_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.
@@ -1162,15 +1163,17 @@ void FFmpegWriter::write_audio_packets(bool final)
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];
+ all_resampled_samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
// Copy audio samples over original samples
- memcpy(resampled_samples, audio_converted->data[0], nb_samples * av_get_bytes_per_sample(output_sample_fmt) * info.channels);
+ memcpy(all_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;
// Remove converted audio
+ av_freep(&audio_frame[0]); // this deletes the all_queued_samples array
+ avcodec_free_frame(&audio_frame);
av_freep(&audio_converted[0]);
avcodec_free_frame(&audio_converted);
@@ -1192,7 +1195,7 @@ void FFmpegWriter::write_audio_packets(bool final)
// Copy frame samples into the packet samples array
if (!final)
- memcpy(samples + audio_input_position, resampled_samples + samples_position, diff * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
+ memcpy(samples + audio_input_position, all_resampled_samples + samples_position, diff * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
// Increment counters
audio_input_position += diff;
@@ -1229,13 +1232,18 @@ void FFmpegWriter::write_audio_packets(bool 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 = 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);
+
+ // Create a new array
+ final_samples_planar = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
+
+ // Copy audio into buffer for frame
+ memcpy(final_samples_planar, samples, audio_frame->nb_samples * av_get_bytes_per_sample(output_sample_fmt) * info.channels);
// Fill input frame with sample data
- avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) samples,
+ avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) final_samples_planar,
audio_frame->nb_samples * av_get_bytes_per_sample(output_sample_fmt) * info.channels, 1);
// Create output frame (and allocate arrays)
@@ -1252,18 +1260,25 @@ void FFmpegWriter::write_audio_packets(bool final)
audio_frame->nb_samples); // number of input samples to convert
// Copy audio samples over original samples
- memcpy(samples, frame_final->data[0], frame_final->nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels);
+ memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels);
- // Free AVFrames
- avcodec_free_frame(&audio_frame); // TODO: Find a way to clear the memory inside this frame (memory leak)
+ // deallocate AVFrame
+ av_freep(&audio_frame[0]); // delete final_samples_planar array
+ avcodec_free_frame(&audio_frame);
#pragma omp critical (debug_output)
AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)", "nb_samples", nb_samples, "", -1, "", -1, "", -1, "", -1, "", -1);
} else {
+ // Create a new array
+ final_samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
+
+ // Copy audio into buffer for frame
+ memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt));
+
// Fill the final_frame AVFrame with audio (non planar)
- avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) samples,
+ avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples,
audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt), 1);
}
@@ -1332,7 +1347,7 @@ void FFmpegWriter::write_audio_packets(bool final)
}
// deallocate AVFrame
- av_freep(&frame_final[0]);
+ av_freep(&frame_final[0]); // delete AVFrame internal array OR final_samples array (depending on if its planar or not planar)
avcodec_free_frame(&frame_final);
// deallocate memory for packet
@@ -1343,14 +1358,10 @@ void FFmpegWriter::write_audio_packets(bool final)
final = false;
}
- // Free AVFrames
- if (audio_frame) {
- av_freep(&audio_frame[0]);
- avcodec_free_frame(&audio_frame);
- }
- if (resampled_samples) {
- delete[] resampled_samples;
- resampled_samples = NULL;
+ // Delete arrays
+ if (all_resampled_samples) {
+ delete[] all_resampled_samples;
+ all_resampled_samples = NULL;
}
} // end task
diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp
index 58921678..3e5e8388 100644
--- a/src/FrameMapper.cpp
+++ b/src/FrameMapper.cpp
@@ -598,7 +598,6 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr frame)
AVFrame *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, 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);
@@ -655,7 +654,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr frame)
// 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)
+ avcodec_free_frame(&audio_frame);
frame_samples = NULL;
av_freep(&audio_converted[0]);
avcodec_free_frame(&audio_converted);
diff --git a/src/examples/Example.cpp b/src/examples/Example.cpp
index 084887b9..02e59e6d 100644
--- a/src/examples/Example.cpp
+++ b/src/examples/Example.cpp
@@ -84,6 +84,7 @@ int main(int argc, char* argv[])
// 147000 frames, 28100 frames
//for (int frame = 1; frame <= (r9.info.video_length - 1); frame++)
+ //for (int z = 0; z < 2; z++)
for (int frame = 1; frame <= 1000; frame++)
//int frame = 1;
//while (true)
diff --git a/tests/FrameMapper_Tests.cpp b/tests/FrameMapper_Tests.cpp
index dafccabe..e6d4f62e 100644
--- a/tests/FrameMapper_Tests.cpp
+++ b/tests/FrameMapper_Tests.cpp
@@ -176,3 +176,30 @@ TEST(FrameMapper_30_fps_to_24_fps_Pulldown_None)
CHECK_EQUAL(6, frame5.Even.Frame);
}
+TEST(FrameMapper_resample_audio_48000_to_41000)
+{
+ // Create a reader: 24 fps, 2 channels, 48000 sample rate
+ FFmpegReader r("../../src/examples/sintel_trailer-720p.mp4");
+
+ // Map to 30 fps, 3 channels surround, 44100 sample rate
+ FrameMapper map(&r, Fraction(30,1), PULLDOWN_NONE, 44100, 3, LAYOUT_SURROUND);
+ map.Open();
+
+ // Check details
+ CHECK_EQUAL(3, map.GetFrame(1)->GetAudioChannelsCount());
+ CHECK_EQUAL(1459, map.GetFrame(1)->GetAudioSamplesCount());
+ CHECK_EQUAL(1469, map.GetFrame(2)->GetAudioSamplesCount());
+ CHECK_EQUAL(1469, map.GetFrame(50)->GetAudioSamplesCount());
+
+ // Change mapping data
+ map.ChangeMapping(Fraction(25,1), PULLDOWN_NONE, 22050, 1, LAYOUT_MONO);
+
+ // Check details
+ CHECK_EQUAL(1, map.GetFrame(1)->GetAudioChannelsCount());
+ CHECK_EQUAL(871, map.GetFrame(1)->GetAudioSamplesCount());
+ CHECK_EQUAL(881, map.GetFrame(2)->GetAudioSamplesCount());
+ CHECK_EQUAL(881, map.GetFrame(50)->GetAudioSamplesCount());
+
+ // Close mapper
+ map.Close();
+}