diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp
index 1c80bb84..dae538f2 100644
--- a/src/FFmpegReader.cpp
+++ b/src/FFmpegReader.cpp
@@ -872,8 +872,6 @@ std::shared_ptr FFmpegReader::GetFrame(int64_t requested_frame)
#pragma omp critical (ReadStream)
{
// Check the cache a 2nd time (due to a potential previous lock)
- if (has_missing_frames)
- CheckMissingFrame(requested_frame);
frame = final_cache.GetFrame(requested_frame);
if (frame) {
// Debug output
@@ -1048,9 +1046,6 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame)
// Check if working frames are 'finished'
if (!is_seeking) {
- // Check for any missing frames
- CheckMissingFrame(requested_frame);
-
// Check for final frames
CheckWorkingFrames(false, requested_frame);
}
@@ -2091,7 +2086,7 @@ AudioLocation FFmpegReader::GetAudioPTSLocation(int64_t pts)
for (int64_t audio_frame = previous_packet_location.frame; audio_frame < location.frame; audio_frame++) {
if (!missing_audio_frames.count(audio_frame)) {
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAudioPTSLocation (tracking missing frame)", "missing_audio_frame", audio_frame, "previous_audio_frame", previous_packet_location.frame, "new location frame", location.frame, "", -1, "", -1, "", -1);
- missing_audio_frames.insert(pair(previous_packet_location.frame - 1, audio_frame));
+ missing_audio_frames.insert(pair(audio_frame, previous_packet_location.frame - 1));
}
}
}
@@ -2166,13 +2161,25 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame)
map::iterator itr;
bool found_missing_frame = false;
- // Check if requested frame is a missing frame
- if (missing_video_frames.count(requested_frame) || missing_audio_frames.count(requested_frame)) {
- int64_t missing_source_frame = -1;
- if (missing_video_frames.count(requested_frame))
- missing_source_frame = missing_video_frames.find(requested_frame)->second;
- else if (missing_audio_frames.count(requested_frame))
- missing_source_frame = missing_audio_frames.find(requested_frame)->second;
+ // Special MP3 Handling (ignore more than 1 video frame)
+ if (info.has_audio and info.has_video) {
+ AVCodecID aCodecId = AV_FIND_DECODER_CODEC_ID(aStream);
+ AVCodecID vCodecId = AV_FIND_DECODER_CODEC_ID(pStream);
+ // If MP3 with single video frame, handle this special case by copying the previously
+ // decoded image to the new frame. Otherwise, it will spend a huge amount of
+ // CPU time looking for missing images for all the audio-only frames.
+ if (checked_count > 8 && !missing_video_frames.count(requested_frame) &&
+ !processing_audio_frames.count(requested_frame) && processed_audio_frames.count(requested_frame) &&
+ last_frame && last_video_frame->has_image_data && aCodecId == AV_CODEC_ID_MP3 && (vCodecId == AV_CODEC_ID_MJPEGB || vCodecId == AV_CODEC_ID_MJPEG)) {
+ missing_video_frames.insert(pair(requested_frame, last_video_frame->number));
+ missing_video_frames_source.insert(pair(last_video_frame->number, requested_frame));
+ missing_frames.Add(last_video_frame);
+ }
+ }
+
+ // Check if requested video frame is a missing
+ if (missing_video_frames.count(requested_frame)) {
+ int64_t missing_source_frame = missing_video_frames.find(requested_frame)->second;
// Increment missing source frame check count (or init to 1)
if (checked_frames.count(missing_source_frame) == 0)
@@ -2205,21 +2212,26 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame)
std::shared_ptr parent_image = parent_frame->GetImage();
if (parent_image) {
missing_frame->AddImage(std::shared_ptr(new QImage(*parent_image)));
-
processed_video_frames[missing_frame->number] = missing_frame->number;
- processed_audio_frames[missing_frame->number] = missing_frame->number;
-
- // Move frame to final cache
- final_cache.Add(missing_frame);
-
- // Remove frame from working cache
- working_cache.Remove(missing_frame->number);
-
- // Update last_frame processed
- last_frame = missing_frame->number;
}
}
+ }
+ // Check if requested audio frame is a missing
+ if (missing_audio_frames.count(requested_frame)) {
+
+ // Create blank missing frame
+ std::shared_ptr missing_frame = CreateFrame(requested_frame);
+
+ // Get Samples per frame (for this frame number)
+ int samples_per_frame = Frame::GetSamplesPerFrame(missing_frame->number, info.fps, info.sample_rate, info.channels);
+
+ // Debug output
+ ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame (Add Silence for Missing Audio Frame)", "requested_frame", requested_frame, "missing_frame->number", missing_frame->number, "samples_per_frame", samples_per_frame, "", -1, "", -1, "", -1);
+
+ // Add this frame to the processed map (since it's already done)
+ missing_frame->AddAudioSilence(samples_per_frame);
+ processed_audio_frames[missing_frame->number] = missing_frame->number;
}
return found_missing_frame;
@@ -2232,6 +2244,9 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
bool checked_count_tripped = false;
int max_checked_count = 80;
+ // Check if requested frame is 'missing'
+ CheckMissingFrame(requested_frame);
+
while (true)
{
// Get the front frame of working cache