Made Keyframe objects thread safe, by generating the values as Points are added, and the Timeline's Open and Close logic was made thread safe, so a reader is not closed while it's still being accessed on another thread. Also removed some unneeded code and comments.

This commit is contained in:
Jonathan Thomas
2012-12-03 22:55:46 -06:00
parent a8fa5a91d2
commit 0d82a4e716
9 changed files with 51 additions and 32 deletions

View File

@@ -48,7 +48,6 @@ namespace openshot
int channels; ///< The number of audio channels used in the audio stream
int audio_stream_index; ///< The index of the audio stream
Fraction audio_timebase; ///< The audio timebase determines how long each audio packet should be played
bool visualize; ///< Replace the video stream with a waveform visualization of the audio samples
};
/**

View File

@@ -47,6 +47,7 @@ namespace openshot {
int sample_rate; ///<Sample rate of timeline
int channels; ///<Channels in timeline
list<Clip*> clips; ///<List of clips on this timeline
list<Clip*> closing_clips; ///<List of clips that need to be closed
map<Clip*, Clip*> open_clips; ///<List of 'opened' clips on this timeline
Cache final_cache; ///<Final cache of timeline frames
@@ -65,6 +66,9 @@ namespace openshot {
/// Update the list of 'opened' clips
void update_open_clips(Clip *clip, bool is_open);
/// Update the list of 'closed' clips
void update_closed_clips();
public:
/// Default Constructor for the timeline (which sets the canvas width and height and FPS)

View File

@@ -56,8 +56,6 @@ void Clip::init_settings()
// Default pointers
file_reader = NULL;
resampler = NULL;
cout << "INIT CLIP SETTINGS!!!!" << endl;
}
// Default Constructor for a clip

View File

@@ -199,9 +199,6 @@ void FFmpegReader::UpdateAudioInfo()
info.audio_timebase.num = aStream->time_base.num;
info.audio_timebase.den = aStream->time_base.den;
cout << "aStream->time_base: " << aStream->time_base.num << "/" << aStream->time_base.den << endl;
cout << "aCodecCtx->time_base: " << aCodecCtx->time_base.num << "/" << aCodecCtx->time_base.den << endl;
// Get timebase of audio stream (if valid)
if (aStream->duration > 0.0f)
info.duration = aStream->duration * info.audio_timebase.ToDouble();

View File

@@ -28,7 +28,6 @@ void FileWriterBase::InitFileInfo()
info.channels = 0;
info.audio_stream_index = -1;
info.audio_timebase = Fraction();
info.visualize = false;
}
// Display file information
@@ -66,7 +65,6 @@ void FileWriterBase::DisplayInfo() {
cout << "--> # of Channels: " << info.channels << endl;
cout << "--> Audio Stream Index: " << info.audio_stream_index << endl;
cout << "--> Audio Timebase: " << info.audio_timebase.ToDouble() << " (" << info.audio_timebase.num << "/" << info.audio_timebase.den << ")" << endl;
cout << "--> Visualize Waveform: " << info.visualize << endl;
cout << "----------------------------" << endl;
}

View File

@@ -302,7 +302,6 @@ float* Frame::GetInterleavedAudioSamples(int new_sample_rate, AudioResampler* re
for (int channel = 0; channel < num_of_channels; channel++)
{
// Add sample to output array
//cout << position << ", " << channel << ", " << sample << endl;
output[position] = buffer->getSampleData(channel)[sample];
// increment position
@@ -528,11 +527,6 @@ void Frame::AddImage(tr1::shared_ptr<Magick::Image> new_image, float alpha)
// Add audio samples to a specific channel
void Frame::AddAudio(bool replaceSamples, int destChannel, int destStartSample, const float* source, int numSamples, float gainToApplyToSource = 1.0f)
{
// DEBUG CODE (FOR AUDIO ISSUES)
//cout << "AddAudio: Frame: " << number << ", replaceSamples: " << replaceSamples << ", destChannel: " << destChannel << ", destStartSample: " << destStartSample << ", numSamples: " << numSamples << ", gain: " << gainToApplyToSource << ", end: " << (destStartSample + numSamples) << endl;
//cout << " " << source[0] << "," << source[1] << "," << source[2] << " ... " << "," << source[numSamples-2] << "," << source[numSamples-1] << "," << source[numSamples] << "," << source[numSamples+1] << endl;
// Extend audio buffer (if needed)
if (destStartSample + numSamples > audio->getNumSamples())
audio->setSize(audio->getNumChannels(), destStartSample + numSamples, true, true, false);

View File

@@ -62,6 +62,10 @@ void Keyframe::AddPoint(Point p) {
// Set Handles (used for smooth curves).
SetHandles(p);
// Check if it needs to be processed
if (needs_update)
Process();
}
// Add a new point on the key-frame, with some defaults set (BEZIER, AUTO Handles, etc...)

View File

@@ -61,10 +61,10 @@ int main()
// Add some clips
//Clip c1(new FFmpegReader("/home/jonathan/Apps/videcho_site/media/user_files/videos/bd0bf442-3221-11e2-8bf6-001fd00ee3aa.webm"));
//Clip c1(new FFmpegReader("/home/jonathan/Videos/Movie Music/02 - Shattered [Turn The Car Around] (Album Version).mp3"));
FFmpegReader r1("../../src/examples/piano.wav");
Clip c1(new FFmpegReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"));
Clip c2(new ImageReader("/home/jonathan/Desktop/logo.png"));
Clip c3(new FFmpegReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"));
FFmpegReader r1("/home/jonathan/Videos/sintel-1024-stereo.mp4");
Clip c1(new FFmpegReader("/home/jonathan/Videos/sintel-1024-stereo.mp4"));
Clip c2(new ImageReader("/home/jonathan/Desktop/Logo.png"));
Clip c3(new FFmpegReader("/home/jonathan/Videos/sintel-1024-stereo.mp4"));
//Clip c3(new FFmpegReader("/home/jonathan/Videos/Movie Music/01 Whip It.mp3"));
c1.Position(0.0);
c1.gravity = GRAVITY_CENTER;
@@ -181,10 +181,10 @@ int main()
// Add clips
t.AddClip(&c1);
//t.AddClip(&c2);
t.AddClip(&c2);
//t.AddClip(&c3);
r1.Open();
//r1.Open();
// Create a writer
FFmpegWriter w("/home/jonathan/output.webm");
@@ -192,8 +192,8 @@ int main()
// Set options
//w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000, false);
w.SetAudioOptions(true, "libvorbis", 48000, 2, 128000);
w.SetVideoOptions(true, "libvpx", Fraction(24,1), 624, 348, Fraction(1,1), false, false, 2000000);
w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000);
w.SetVideoOptions(true, "libvpx", Fraction(25,1), 624, 348, Fraction(1,1), false, false, 2000000);
// Prepare Streams
w.PrepareStreams();
@@ -204,13 +204,13 @@ int main()
// Output stream info
w.OutputStreamInfo();
for (int frame = 1; frame <= 100; frame++)
for (int frame = 100; frame <= 200; frame++)
{
tr1::shared_ptr<Frame> f = r1.GetFrame(frame);
tr1::shared_ptr<Frame> f = t.GetFrame(frame);
if (f)
{
//if (frame >= 13)
//f->DisplayWaveform();
//f->Display();
// Write frame
cout << "queue frame " << frame << " (" << f->number << ", " << f << ")" << endl;

View File

@@ -231,11 +231,8 @@ void Timeline::update_open_clips(Clip *clip, bool is_open)
if (clip_found && !is_open)
{
// Remove clip from 'opened' list, because it's closed now
open_clips.erase(clip);
// Close the clip's reader
clip->Close();
// Mark clip "to be removed"
closing_clips.push_back(clip);
}
else if (!clip_found && is_open)
{
@@ -247,6 +244,27 @@ void Timeline::update_open_clips(Clip *clip, bool is_open)
}
}
// Update the list of 'closed' clips
void Timeline::update_closed_clips()
{
// Close all "to be closed" clips
list<Clip*>::iterator clip_itr;
for (clip_itr=closing_clips.begin(); clip_itr != closing_clips.end(); ++clip_itr)
{
// Get clip object from the iterator
Clip *clip = (*clip_itr);
// Close the clip's reader
clip->Close();
// Remove clip from 'opened' list, because it's closed now
open_clips.erase(clip);
}
// Clear list
closing_clips.clear();
}
// Sort clips by position on the timeline
void Timeline::SortClips()
{
@@ -267,6 +285,9 @@ void Timeline::Close()
// Open or Close this clip, based on if it's intersecting or not
update_open_clips(clip, false);
}
// Actually close the clips
update_closed_clips();
}
// Open the reader (and start consuming resources)
@@ -319,7 +340,7 @@ tr1::shared_ptr<Frame> Timeline::GetFrame(int requested_frame) throw(ReaderClose
// Loop through all requested frames
for (int frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++)
{
#pragma xxx omp task firstprivate(frame_number)
#pragma omp task firstprivate(frame_number)
{
// 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)));
@@ -339,7 +360,7 @@ tr1::shared_ptr<Frame> Timeline::GetFrame(int requested_frame) throw(ReaderClose
float clip_duration = clip->End() - clip->Start();
bool does_clip_intersect = (clip->Position() <= requested_time && clip->Position() + clip_duration >= requested_time);
// Open or Close this clip, based on if it's intersecting or not
// Open (or schedule for closing) this clip, based on if it's intersecting or not
#pragma omp critical (reader_lock)
update_open_clips(clip, does_clip_intersect);
@@ -374,6 +395,10 @@ tr1::shared_ptr<Frame> Timeline::GetFrame(int requested_frame) throw(ReaderClose
} // end omp task
} // end frame loop
// Actually close all clips no longer needed
#pragma omp critical (reader_lock)
update_closed_clips();
} // end omp single
} // end omp parallel