From a662abcfd7106f06c010f50baf30fcb1021390db Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 3 Jul 2012 02:42:47 -0500 Subject: [PATCH] Fixed many bugs, including an audio crackle between packets, and fixed many multi-threading issues. --- include/Cache.h | 3 ++ src/FFmpegReader.cpp | 69 +++++++++++++++++++++++++++++--------------- src/Frame.cpp | 10 ++----- src/Main.cpp | 6 ++-- 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/include/Cache.h b/include/Cache.h index 5e158a70..05e89d89 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -65,6 +65,9 @@ namespace openshot { /// Count the frames in the queue int Count(); + /// Set maximum frames to a different amount + void SetMaxFrames(int max_frames) { max_frames = max_frames; }; + }; } diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index e9b08cbc..e7409e19 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -4,7 +4,7 @@ using namespace openshot; FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, InvalidCodec) : last_video_frame(0), last_audio_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), - audio_pts_offset(99999), video_pts_offset(99999), working_cache(50), path(path), + audio_pts_offset(99999), video_pts_offset(99999), working_cache(150), final_cache(150), path(path), is_video_seek(true), check_interlace(false), check_fps(false), init_settings(false), enable_seek(true) { // , resampleCtx(NULL) @@ -15,7 +15,7 @@ FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, Inval if (info.has_video) CheckFPS(); - // Get Frame 1 (to determine the offset between the PTS and the Frame Number) + // Get 1st frame GetFrame(1); } @@ -218,6 +218,10 @@ void FFmpegReader::UpdateVideoInfo() info.duration = pStream->duration * info.video_timebase.ToDouble(); info.video_length = round(info.duration * info.fps.ToDouble()); + // Override an invalid framerate + if (info.fps.ToFloat() > 120.0f) + info.has_video = false; + } Frame FFmpegReader::GetFrame(int requested_frame) @@ -322,34 +326,36 @@ Frame FFmpegReader::ReadStream(int requested_frame) // Determine related video frame and starting sample # from audio PTS audio_packet_location location = GetAudioPTSLocation(packet->pts); - cout << "ProcessAudioPacket: frame:" << location.frame << ", sample start: " << location.sample_start << endl; + cout << "Audio Location: frame: " << location.frame << ", start: " << location.sample_start << endl; // Process Audio Packet ProcessAudioPacket(requested_frame, location.frame, location.sample_start); } // Check if working frames are 'finished' - if (!is_seeking) - #pragma omp critical (openshot_cache) - CheckWorkingFrames(false); - - // Check if requested 'final' frame is available + bool is_cache_found = false; #pragma omp critical (openshot_cache) - bool is_cache_found = final_cache.Exists(requested_frame); + { + if (!is_seeking) + CheckWorkingFrames(false); - if (final_cache.Exists(requested_frame)) + // Check if requested 'final' frame is available + is_cache_found = final_cache.Exists(requested_frame); + } + + // Break once the frame is found + if (is_cache_found) break; } // end while } // end omp master + + // Be sure all threads are finished + #pragma omp barrier + } // end omp parallel - // Delete packet - //av_free_packet(&packet); - - // Free the YUV frame - //av_free(pFrame); // End of stream? Mark the any other working frames as 'finished' if (end_of_stream) @@ -362,7 +368,6 @@ Frame FFmpegReader::ReadStream(int requested_frame) else // Return blank frame return CreateFrame(requested_frame); - } // Get the next packet (if any) @@ -503,7 +508,6 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame) // Convert the image into RGB (for ImageMagick++) if (img_convert_ctx == NULL) { - cout << "init img_convert_ctx" << endl; img_convert_ctx = sws_getContext(width, height, pix_fmt, width, height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); if (img_convert_ctx == NULL) { @@ -662,7 +666,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int // Loop through samples, and add them to the correct frames int start = starting_sample; int remaining_samples = channel_buffer_size; - float *iterate_channel_buffer = channel_buffer + 1; // pointer to channel buffer (increment position by 1) + float *iterate_channel_buffer = channel_buffer; // pointer to channel buffer while (remaining_samples > 0) { // Get Samples per frame (for this frame number) @@ -978,6 +982,13 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream) Frame f = working_cache.GetSmallestFrame(); bool is_ready = f.IsReady(info.has_video, info.has_audio); + if (f.number == 300) + { + cout << "CheckWorkingFrames: frame: " << f.number << endl; + cout << "f.IsReady(): " << f.IsReady(info.has_video, info.has_audio) << endl; + cout << "f.IsAudioReady(): " << f.IsAudioReady(info.has_audio) << endl; + } + // Check if working frame is final if (is_ready || end_of_stream) { @@ -1005,6 +1016,9 @@ void FFmpegReader::CheckFPS() int forth_second_counter = 0; int fifth_second_counter = 0; + int iterations = 0; + int threshold = 500; + // Loop through the stream while (true) { @@ -1045,15 +1059,22 @@ void FFmpegReader::CheckFPS() else // Too far break; + + // Remove pFrame + frames.erase(packet->pts); } } - } -// cout << "FIRST SECOND: " << first_second_counter << endl; -// cout << "SECOND SECOND: " << second_second_counter << endl; -// cout << "THIRD SECOND: " << third_second_counter << endl; -// cout << "FORTH SECOND: " << forth_second_counter << endl; -// cout << "FIFTH SECOND: " << fifth_second_counter << endl; + // remove packet + packets.erase(packet->pts); + + // Increment counters + iterations++; + + // Give up (if threshold exceeded) + if (iterations > threshold) + return; + } // Double check that all counters have greater than zero (or give up) if (second_second_counter == 0 || third_second_counter == 0 || forth_second_counter == 0 || fifth_second_counter == 0) diff --git a/src/Frame.cpp b/src/Frame.cpp index c0e1bb07..227bef53 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -354,23 +354,19 @@ bool Frame::IsAudioReady(bool has_audio) { if (has_audio) { + if (number == 300) + cout << "IsAudioReady channels: " << channels_complete.size() << endl; + // Do all channels have audio loaded? if (channels_complete.size() == channels) - { - // yes, all audio is loaded return true; - } else - { // still waiting on some channel to be loaded return false; - } } else - { // No audio needed for this frame return true; - } } // Gets whether the frame has completed loading it's image and audio data diff --git a/src/Main.cpp b/src/Main.cpp index 838af86e..594ee8e6 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -16,10 +16,10 @@ int main() // openshot::FFmpegReader r("/home/jonathan/Apps/libopenshot/src/examples/test.mp4"); // openshot::FFmpegReader r("/home/jonathan/Apps/libopenshot/src/examples/test1.mp4"); - // openshot::FFmpegReader r("/home/jonathan/Apps/libopenshot/src/examples/piano.wav"); + openshot::FFmpegReader r("/home/jonathan/Apps/libopenshot/src/examples/piano.wav"); // openshot::FFmpegReader r("/home/jonathan/Videos/sintel-1024-stereo.mp4"); // openshot::FFmpegReader r("/home/jonathan/Videos/00001.mts"); - openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4"); + // openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4"); // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/piano.wav"); // openshot::FFmpegReader r("/home/jonathan/Music/Army of Lovers/Crucified/Army of Lovers - Crucified [Single Version].mp3"); // openshot::FFmpegReader r("/home/jonathan/Documents/OpenShot Art/test.jpeg"); @@ -29,7 +29,7 @@ int main() // Display debug info r.DisplayInfo(); - for (int frame = 300; frame <= 500; frame++) + for (int frame = 1; frame <= 500; frame++) { Frame f = r.GetFrame(frame); f.Play();