Fixed a big audio bug, where varying timestamp values on low precision audio timebases (i.e. 1/1000) would leave small gaps in the audio wave. Also, fixed a few issues related to sample_rate getting lost between the reader and clip and timeline objects.

This commit is contained in:
Jonathan Thomas
2012-11-20 16:22:50 -06:00
parent 7e51c204f9
commit 495ca9dc9e
9 changed files with 35 additions and 58 deletions

View File

@@ -86,9 +86,6 @@ namespace openshot {
/// Adjust frame number minimum value
int adjust_frame_number_minimum(int frame_number);
/// Apply basic image processing (scale, rotate, move, etc...)
void apply_basic_image_processing(tr1::shared_ptr<Frame> frame, int frame_number);
/// Get file extension
string get_file_extension(string path);

View File

@@ -69,12 +69,6 @@ namespace openshot
bool check_interlace;
bool check_fps;
// DEBUG STUFF
int counter;
int previous_audio_pts;
int total_samples;
audio_packet_location previous_packet_location;
int num_of_rescalers;
int rescaler_position;
vector<SwsContext*> image_rescalers;
@@ -86,6 +80,7 @@ namespace openshot
map<AVPicture*, AVPicture*> frames;
map<int, int> processing_video_frames;
map<int, int> processing_audio_frames;
audio_packet_location previous_packet_location;
bool is_seeking;
int seeking_pts;

View File

@@ -191,9 +191,6 @@ tr1::shared_ptr<Frame> Clip::GetFrame(int requested_frame) throw(ReaderClosed)
// Get time mapped frame number (used to increase speed, change direction, etc...)
tr1::shared_ptr<Frame> new_frame = get_time_mapped_frame(frame, requested_frame);
// Apply basic image processing (scale, rotation, etc...)
//apply_basic_image_processing(new_frame, new_frame_number);
// Return processed 'frame'
return new_frame;
}
@@ -450,19 +447,6 @@ tr1::shared_ptr<Frame> Clip::get_time_mapped_frame(tr1::shared_ptr<Frame> frame,
return new_frame;
}
// Apply basic image processing (scale, rotate, move, etc...)
void Clip::apply_basic_image_processing(tr1::shared_ptr<Frame> frame, int frame_number)
{
// Get values
float rotation_value = rotation.GetValue(frame_number);
//float scale_x_value = scale_x.GetValue(frame_number);
//float scale_y_value = scale_y.GetValue(frame_number);
// rotate frame
if (rotation_value != 0)
frame->Rotate(rotation_value);
}
// Adjust frame number minimum value
int Clip::adjust_frame_number_minimum(int frame_number)
{

View File

@@ -6,7 +6,7 @@ FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, Inval
: last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0),
audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false),
check_fps(false), enable_seek(true), rescaler_position(0), num_of_rescalers(32), is_open(false),
seek_audio_frame_found(-1), seek_video_frame_found(-1), resampleCtx(NULL), counter(0), previous_audio_pts(0), total_samples(0) {
seek_audio_frame_found(-1), seek_video_frame_found(-1), resampleCtx(NULL) {
// Init FileInfo struct (clear all values)
InitFileInfo();
@@ -718,12 +718,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
// Allocate audio buffer
int16_t *audio_buf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
//if (packet->pts == 4378 || packet->pts == 4402)
// cout << "ProcessAudioPacket: pts: " << packet->pts << ", my_packet->size: " << my_packet->size << endl;
// DEBUG COUNTER
counter++;
int packet_samples = 0;
while (my_packet->size > 0) {
// re-initialize buffer size (it gets changed in the avcodec_decode_audio2 method call)
@@ -745,7 +739,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
}
// Estimate the # of samples and the end of this packet's location (to prevent GAPS for the next timestamp)
int pts_remaining_samples = packet_samples / info.channels;
int pts_remaining_samples = round(packet_samples / info.channels);
while (pts_remaining_samples)
{
// Get Samples per frame (for this frame number)
@@ -770,18 +764,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
}
// DEBUG
total_samples += packet_samples;
cout << "packet: " << counter << ", PTS: " << packet->pts << ", PTS Diff: " << (packet->pts - previous_audio_pts) << ", samples: " << packet_samples << ", total: " << total_samples << endl;
previous_audio_pts = packet->pts;
// if (packet->pts >= 4378 && packet->pts <= 4500)
// {
// cout << "ProcessAudioPacket: pts: " << packet->pts << ", packet_samples: " << packet_samples << endl;
// cout << "first samples for pts: " << packet->pts << ", " << audio_buf[0] << ", " << audio_buf[1] << ", " << audio_buf[2] << ", " << audio_buf[3] << ", " << audio_buf[4] << ", " << audio_buf[5] << endl;
// cout << "last samples for pts: " << packet->pts << ", " << audio_buf[2045] << ", " << audio_buf[2046] << ", " << audio_buf[2047] << ", " << audio_buf[2048] << ", " << audio_buf[2049] << ", " << audio_buf[2050] << endl;
// }
#pragma omp critical (packet_cache)
{
// Remove packet
@@ -789,8 +771,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
RemoveAVPacket(my_packet);
}
#pragma omp task firstprivate(requested_frame, target_frame, my_cache, starting_sample, audio_buf)
{
@@ -835,7 +815,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
{
// Array of floats (to hold samples for each channel)
starting_frame_number = target_frame;
int channel_buffer_size = (packet_samples / info.channels) + 1;
int channel_buffer_size = round(packet_samples / info.channels);
float *channel_buffer = new float[channel_buffer_size];
// Init buffer array
@@ -1136,11 +1116,20 @@ audio_packet_location FFmpegReader::GetAudioPTSLocation(int pts)
int diff_previous_packet = abs(location.sample_start - previous_packet_location.sample_start);
if (location.frame == previous_packet_location.frame && diff_previous_packet >= 0 && diff_previous_packet <= 100)
{
if (location.frame >= 175 && location.frame < 220)
cout << "GAP DETECTED!!! Changing frame " << location.frame << ", sample start: " << location.sample_start << " to " << previous_packet_location.sample_start + 1 << endl;
int orig_frame = location.frame;
int orig_start = location.sample_start;
// Update sample start, to prevent gaps in audio
location.sample_start = previous_packet_location.sample_start + 1;
if (previous_packet_location.sample_start + 1 <= samples_per_frame)
location.sample_start = previous_packet_location.sample_start + 1;
else
{
// set to next frame (since we exceeded the # of samples on a frame)
location.sample_start = 0;
location.frame++;
}
//cout << "GAP DETECTED!!! Changing frame " << orig_frame << ":" << orig_start << " to frame " << location.frame << ":" << location.sample_start << endl;
}
// Set previous location

View File

@@ -526,9 +526,6 @@ void Frame::AddImage(tr1::shared_ptr<Magick::Image> new_image, float alpha)
// Add audio samples to a specific channel
void Frame::AddAudio(int destChannel, int destStartSample, const float* source, int numSamples, float gainToApplyToSource = 1.0f)
{
if (number >= 181 && number < 220)
cout << "AddAudio for frame: " << number << ", destChannel: " << destChannel << ", destStartSample: " << destStartSample << ", numSamples: " << numSamples << ", ending sample: " << (destStartSample + numSamples) << endl;
// Extend audio buffer (if needed)
if (destStartSample + numSamples > audio->getNumSamples())
audio->setSize(audio->getNumChannels(), destStartSample + numSamples, true, true, false);

View File

@@ -26,6 +26,10 @@ FrameMapper::FrameMapper(FileReaderBase *reader, Framerate target, Pulldown_Meth
info.video_timebase.num = target.GetFraction().den;
info.video_timebase.den = target.GetFraction().num;
info.video_length = round(info.duration * info.fps.ToDouble());
info.sample_rate = reader->info.sample_rate;
info.channels = reader->info.channels;
info.width = reader->info.width;
info.height = reader->info.height;
// Used to toggle odd / even fields
field_toggle = true;
@@ -252,6 +256,7 @@ tr1::shared_ptr<Frame> FrameMapper::GetFrame(int requested_frame) throw(ReaderCl
// Create a new frame
tr1::shared_ptr<Frame> frame(new Frame(requested_frame, 1, 1, "#000000", samples_in_frame, info.channels));
frame->SetSampleRate(info.sample_rate);
// Copy the image from the odd field (TODO: make this copy each field from the correct frames)
frame->AddImage(reader->GetFrame(mapped.Odd.Frame)->GetImage(), true);

View File

@@ -81,6 +81,7 @@ tr1::shared_ptr<Frame> ImageReader::GetFrame(int requested_frame) throw(ReaderCl
{
// Create or get frame object
tr1::shared_ptr<Frame> image_frame(new Frame(requested_frame, image->size().width(), image->size().height(), "#000000", 0, 2));
image_frame->SetSampleRate(44100);
// Add Image data to frame
tr1::shared_ptr<Magick::Image> copy_image(new Magick::Image(*image.get()));

View File

@@ -54,7 +54,7 @@ int main()
// Create timeline
Timeline t(620, 348, Framerate(24,1), 44100, 2);
Timeline t(624, 348, Framerate(24,1), 44100, 2);
// Add some clips
//Clip c1(new FFmpegReader("/home/jonathan/Apps/videcho_site/media/user_files/videos/bd0bf442-3221-11e2-8bf6-001fd00ee3aa.webm"));
@@ -173,7 +173,7 @@ int main()
// Set options
//w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000, false);
w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000, false);
w.SetVideoOptions(true, "libvpx", Fraction(24, 1), 620, 348, Fraction(1,1), false, false, 2000000);
w.SetVideoOptions(true, "libvpx", Fraction(24, 1), 624, 348, Fraction(1,1), false, false, 2000000);
// Prepare Streams
w.PrepareStreams();
@@ -184,7 +184,7 @@ int main()
// Output stream info
w.OutputStreamInfo();
for (int frame = 1; frame <= 300; frame++)
for (int frame = 1; frame <= 600; frame++)
{
tr1::shared_ptr<Frame> f = t.GetFrame(frame);
if (f)

View File

@@ -14,6 +14,15 @@ Timeline::Timeline(int width, int height, Framerate fps, int sample_rate, int ch
// Init cache
int64 bytes = height * width * 4 + (44100 * 2 * 4);
final_cache = Cache(20 * bytes); // 20 frames, 4 colors of chars, 2 audio channels of 4 byte floats
// Init FileInfo struct (clear all values)
InitFileInfo();
info.width = width;
info.height = height;
info.fps = fps.GetFraction();
info.sample_rate = sample_rate;
info.channels = channels;
info.video_timebase = fps.GetFraction().Reciprocal();
}
// Add an openshot::Clip to the timeline
@@ -49,7 +58,6 @@ void Timeline::add_layer(tr1::shared_ptr<Frame> new_frame, Clip* source_clip, in
source_frame = tr1::shared_ptr<Frame>(source_clip->GetFrame(clip_frame_number));
tr1::shared_ptr<Magick::Image> source_image = source_frame->GetImage();
// Get some basic image properties
int source_width = source_image->columns();
int source_height = source_image->rows();
@@ -273,6 +281,7 @@ tr1::shared_ptr<Frame> Timeline::GetFrame(int requested_frame) throw(ReaderClose
{
// Create blank frame (which will become the requested frame)
tr1::shared_ptr<Frame> new_frame(tr1::shared_ptr<Frame>(new Frame(frame_number, width, height, "#000000", GetSamplesPerFrame(frame_number), channels)));
new_frame->SetSampleRate(info.sample_rate);
// Calculate time of frame
float requested_time = calculate_time(frame_number, fps);