diff --git a/include/Cache.h b/include/Cache.h index 682c6dd1..5e158a70 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -56,6 +56,9 @@ namespace openshot { /// Clear the cache of all frames void Clear(); + /// Display a list of cached frame numbers + void Display(); + /// Display the list of cache and clear the cache (mainly for debugging reasons) void DisplayAndClear(); diff --git a/include/Frame.h b/include/Frame.h index 8fb4115f..ed168fd7 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -38,7 +38,8 @@ namespace openshot int sample_rate; public: - int number; ///< This is the frame number (starting at 1) + int number; ///< This is the frame number (starting at 1) + bool processing; ///< This flag is used to determine if a frame is still being processed /// Constructor - blank frame (300x200 blank image, 48kHz audio silence) Frame(); diff --git a/src/Cache.cpp b/src/Cache.cpp index c1ceae4e..d63d18a5 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -129,6 +129,21 @@ void Cache::CleanUp() } } + +// Display a list of cached frame numbers +void Cache::Display() +{ + cout << "----- Cache List (" << frames.size() << ") ------" << endl; + deque::iterator itr; + + int i = 1; + for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr) + { + cout << " " << i << ") --- Frame " << *itr << endl; + i++; + } +} + // Display the list of cache and clear the cache (mainly for debugging reasons) void Cache::DisplayAndClear() { diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 3bf19180..8e22547b 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -344,9 +344,6 @@ Frame FFmpegReader::ReadStream(int requested_frame) } // end omp master } // end omp parallel - // Set flag to not get the next packet (since we already got it) - //needs_packet = false; - // Delete packet //av_free_packet(&packet); @@ -438,21 +435,26 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame) { // Calculate current frame # int current_frame = ConvertVideoPTStoFrame(GetVideoPTS()); - last_video_frame = current_frame; // Are we close enough to decode the frame? if ((current_frame) < (requested_frame - 20)) + { + // Update last processed video frame + last_video_frame = current_frame; + // Skip to next frame without decoding or caching return; + } - // Copy some things local + // Init some things local (for OpenMP) PixelFormat pix_fmt = pCodecCtx->pix_fmt; int height = info.height; int width = info.width; long int video_length = info.video_length; Cache *my_cache = &working_cache; + int *my_last_video_frame = &last_video_frame; - #pragma omp task firstprivate(current_frame, my_cache, height, width, video_length, pix_fmt) + #pragma omp task firstprivate(current_frame, my_last_video_frame, my_cache, height, width, video_length, pix_fmt) { // Get a copy of the AVPicture AVPicture copyFrame; @@ -501,14 +503,16 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame) // Create or get frame object Frame f = CreateFrame(current_frame); - cout << "Create OMP Frame: " << f.number << endl; - // Add Image data to frame f.AddImage(width, height, "RGB", Magick::CharPixel, buffer); // Update working cache + f.processing = false; my_cache->Add(f.number, f); - my_cache->GetFrame(f.number).Display(); + + // Update shared variable (last video frame processed) + if (*my_last_video_frame < current_frame) + *my_last_video_frame = current_frame; } // Free the RGB image @@ -651,6 +655,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int f.AddAudio(channel_filter, start, iterate_channel_buffer, samples, 1.0f); // Update working cache + f.processing = false; working_cache.Add(f.number, f); // Decrement remaining samples @@ -891,8 +896,13 @@ Frame FFmpegReader::CreateFrame(int requested_frame) { // Check working cache if (working_cache.Exists(requested_frame)) + { // Return existing frame - return working_cache.GetFrame(requested_frame); + Frame output = working_cache.GetFrame(requested_frame); + output.processing = true; + + return output; + } else { // Get Samples per frame @@ -902,6 +912,7 @@ Frame FFmpegReader::CreateFrame(int requested_frame) Frame f(requested_frame, info.width, info.height, "#000000", samples_per_frame, info.channels); f.SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den); f.SetSampleRate(info.sample_rate); + f.processing = true; working_cache.Add(requested_frame, f); // Return new frame @@ -927,6 +938,11 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream) // Get the front frame of working cache Frame f = working_cache.GetSmallestFrame(); + bool is_processing = f.processing; + + // Skip processing frames + if (is_processing) + break; // Check if working frame is final if ((!end_of_stream && f.number <= last_video_frame && f.number < last_audio_frame) || end_of_stream) diff --git a/src/Frame.cpp b/src/Frame.cpp index 089ca5b7..46344257 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -15,6 +15,7 @@ Frame::Frame() : number(1), image(0), audio(0), pixel_ratio(1,1), sample_rate(48 // Init the image magic and audio buffer image = new Magick::Image(Magick::Geometry(300,200), Magick::Color("red")); audio = new juce::AudioSampleBuffer(2,1600); + processing = false; // initialize the audio samples to zero (silence) audio->clear(); @@ -27,6 +28,7 @@ Frame::Frame(int number, int width, int height, string color) // Init the image magic and audio buffer image = new Magick::Image(Magick::Geometry(width, height), Magick::Color(color)); audio = new juce::AudioSampleBuffer(2,1600); + processing = false; // initialize the audio samples to zero (silence) audio->clear(); @@ -39,6 +41,7 @@ Frame::Frame(int number, int width, int height, const string map, const Magick:: // Init the image magic and audio buffer image = new Magick::Image(width, height, map, type, pixels); audio = new juce::AudioSampleBuffer(2,1600); + processing = false; // initialize the audio samples to zero (silence) audio->clear(); @@ -51,6 +54,7 @@ Frame::Frame(int number, int samples, int channels) : // Init the image magic and audio buffer image = new Magick::Image(Magick::Geometry(300, 200), Magick::Color("white")); audio = new juce::AudioSampleBuffer(channels, samples); + processing = false; // initialize the audio samples to zero (silence) audio->clear(); @@ -63,6 +67,7 @@ Frame::Frame(int number, int width, int height, string color, int samples, int c // Init the image magic and audio buffer image = new Magick::Image(Magick::Geometry(width, height), Magick::Color(color)); audio = new juce::AudioSampleBuffer(channels, samples); + processing = false; // initialize the audio samples to zero (silence) audio->clear();