Changed the method of determining if a frame is completed or not.

This commit is contained in:
Jonathan Thomas
2012-07-06 02:34:18 -05:00
parent c7b9795c2a
commit 457df5b2ff
5 changed files with 75 additions and 117 deletions

View File

@@ -73,6 +73,8 @@ namespace openshot
Cache working_cache;
map<AVPacket*, AVPacket*> packets;
map<AVFrame*, AVFrame*> frames;
map<int, int> processing_video_frames;
map<int, int> processing_audio_frames;
bool is_seeking;
int seeking_pts;
@@ -118,6 +120,12 @@ namespace openshot
/// Get the next packet (if any)
int GetNextPacket();
/// Get the smallest video frame that is still being processed
int GetSmallestVideoFrame();
/// Get the smallest audio frame that is still being processed
int GetSmallestAudioFrame();
/// Calculate the # of samples per video frame (for a specific frame number)
int GetSamplesPerFrame(int frame_number);

View File

@@ -113,18 +113,6 @@ namespace openshot
/// Play audio samples for this frame
void Play();
/// Set if the audio has been completely loaded into a channel (for this frame)
void SetAudioComplete(int channel);
/// Set if the image has been completely loaded into the frame
void SetImageComplete();
/// Gets whether the frame has completely loaded all it's audio data (for each channel)
bool IsAudioReady(bool has_audio);
/// Gets whether the frame has completely loaded it's image and audio data
bool IsReady(bool has_video, bool has_audio);
};
}

View File

@@ -516,6 +516,10 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame)
AVPacket *my_packet = packets[packet];
AVFrame *my_frame = frames[pFrame];
// Add video frame to list of processing video frames
#pragma omp critical (processing_list)
processing_video_frames[current_frame] = current_frame;
#pragma omp task firstprivate(current_frame, my_last_video_frame, my_cache, my_packet, my_frame, height, width, video_length, pix_fmt)
{
// Create variables for a RGB Frame (since most videos are not in RGB, we must convert it)
@@ -566,7 +570,6 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame)
f.AddImage(width, height, "RGB", Magick::CharPixel, buffer);
// Update working cache
f.SetImageComplete();
my_cache->Add(f.number, f);
// Update shared variable (last video frame processed)
@@ -585,6 +588,10 @@ void FFmpegReader::ProcessVideoPacket(int requested_frame)
RemoveAVPacket(my_packet);
}
// Remove video frame from list of processing video frames
#pragma omp critical (processing_list)
processing_video_frames.erase(current_frame);
} // end omp task
@@ -728,6 +735,10 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
// Get Samples per frame (for this frame number)
int samples_per_frame = GetSamplesPerFrame(starting_frame_number);
// Add video frame to list of processing video frames
#pragma omp critical (processing_list)
processing_audio_frames[starting_frame_number] = starting_frame_number;
#pragma omp critical (openshot_cache)
{
// Create or get frame object
@@ -744,26 +755,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
// Decrement remaining samples
remaining_samples -= samples;
// DEBUG CODE
if (f.number == 3)
{
cout << "Frame 3: AddAudio (start: " << start << ", samples: " << samples << ", channel: " << channel_filter << ")" << endl;
cout << "remaining_samples: " << remaining_samples << endl;
cout << "samples_per_frame: " << samples_per_frame << endl;
cout << "start + samples: : " << start + samples << endl;
cout << "packet.pts: " << pts << endl;
}
// Update working cache (if audio is completed for this frame + channel)
if (remaining_samples > 0 || start + samples >= samples_per_frame)
{
if (f.number == 3)
cout << "SET AUDIO COMPLETE - Channel: " << channel_filter << endl;
// If more samples remain, this frame must all it's audio data now
f.SetAudioComplete(channel_filter);
}
// Add or update cache
my_cache->Add(f.number, f);
@@ -797,6 +788,14 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
if (*my_last_audio_frame < (starting_frame_number - 1))
*my_last_audio_frame = (starting_frame_number - 1);
}
// Add video frame to list of processing video frames
#pragma omp critical (processing_list)
{
// Update all frames as completed
for (int f = target_frame; f < starting_frame_number; f++)
processing_audio_frames.erase(f);
}
}
}
@@ -1038,11 +1037,20 @@ Frame FFmpegReader::CreateFrame(int requested_frame)
// Check the working queue, and move finished frames to the finished queue
void FFmpegReader::CheckWorkingFrames(bool end_of_stream)
{
// Adjust for video only, or audio only
if (!info.has_video)
last_video_frame = last_audio_frame;
if (!info.has_audio)
last_audio_frame = last_video_frame;
// Get the smallest processing video and audio frame numbers
int smallest_video_frame = 1;
int smallest_audio_frame = 1;
#pragma omp critical (processing_list)
{
smallest_video_frame = GetSmallestVideoFrame() - 8; // requires that at least 8 frames bigger have already been processed
smallest_audio_frame = GetSmallestAudioFrame() - 8; // requires that at least 8 frames bigger have already been processed
// Adjust for video only, or audio only
if (!info.has_video)
smallest_video_frame = smallest_audio_frame;
if (!info.has_audio)
smallest_audio_frame = smallest_video_frame;
}
// Loop through all working queue frames
while (true)
@@ -1053,17 +1061,10 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream)
// Get the front frame of working cache
Frame f = working_cache.GetSmallestFrame();
bool is_ready = f.IsReady(info.has_video, info.has_audio);
// Check if working frame is final
if (is_ready || end_of_stream)
if ((!end_of_stream && f.number < smallest_video_frame && f.number < smallest_audio_frame) || end_of_stream)
{
// DEBUG
if (f.number == 3)
{
cout << "Moving frame 3 to FINAL CACHE" << endl;
}
// Move frame to final cache
final_cache.Add(f.number, f);
@@ -1230,4 +1231,36 @@ void FFmpegReader::RemoveAVPacket(AVPacket* remove_packet)
}
}
/// Get the smallest video frame that is still being processed
int FFmpegReader::GetSmallestVideoFrame()
{
// Loop through frame numbers
map<int, int>::iterator itr;
int smallest_frame = -1;
for(itr = processing_video_frames.begin(); itr != processing_video_frames.end(); ++itr)
{
if (itr->first < smallest_frame || smallest_frame == -1)
smallest_frame = itr->first;
}
// Return frame number
return smallest_frame;
}
/// Get the smallest audio frame that is still being processed
int FFmpegReader::GetSmallestAudioFrame()
{
// Loop through frame numbers
map<int, int>::iterator itr;
int smallest_frame = -1;
for(itr = processing_audio_frames.begin(); itr != processing_audio_frames.end(); ++itr)
{
if (itr->first < smallest_frame || smallest_frame == -1)
smallest_frame = itr->first;
}
// Return frame number
return smallest_frame;
}

View File

@@ -336,76 +336,6 @@ void Frame::AddAudio(int destChannel, int destStartSample, const float* source,
audio->addFrom(destChannel, destStartSample, source, numSamples, gainToApplyToSource);
}
// Set if the audio has been completed loaded into the frame
void Frame::SetAudioComplete(int channel)
{
// Add channel as completed
channels_complete[channel] = true;
}
// Set if the image has been completed loaded into the frame
void Frame::SetImageComplete()
{
image_complete = true;
}
// Gets whether the frame has completely loaded all it's audio data (for each channel)
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)
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
bool Frame::IsReady(bool has_video, bool has_audio)
{
if (has_video && has_audio)
{
// Does the frame have both audio and image data?
if (image_complete && IsAudioReady(has_audio))
return true;
else
return false;
}
else if (has_video)
{
// Does the frame have image data?
if (image_complete)
return true;
else
return false;
}
else if (has_audio)
{
// Does the frame have audio data?
if (IsAudioReady(has_audio))
return true;
else
return false;
}
else
{
// Invalid
return false;
}
}
// Play audio samples for this frame
void Frame::Play()
{

View File

@@ -13,7 +13,6 @@ void FrameReady(int number)
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");