@@ -472,8 +472,6 @@ std::shared_ptr<Frame> FFmpegReader::GetFrame(int64_t requested_frame)
472472 #pragma omp critical (ReadStream)
473473 {
474474 // Check the cache a 2nd time (due to a potential previous lock)
475- if (has_missing_frames)
476- CheckMissingFrame (requested_frame);
477475 frame = final_cache.GetFrame (requested_frame);
478476 if (frame) {
479477 // Debug output
@@ -648,9 +646,6 @@ std::shared_ptr<Frame> FFmpegReader::ReadStream(int64_t requested_frame)
648646
649647 // Check if working frames are 'finished'
650648 if (!is_seeking) {
651- // Check for any missing frames
652- CheckMissingFrame (requested_frame);
653-
654649 // Check for final frames
655650 CheckWorkingFrames (false , requested_frame);
656651 }
@@ -1651,7 +1646,7 @@ AudioLocation FFmpegReader::GetAudioPTSLocation(int64_t pts)
16511646 for (int64_t audio_frame = previous_packet_location.frame ; audio_frame < location.frame ; audio_frame++) {
16521647 if (!missing_audio_frames.count (audio_frame)) {
16531648 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 );
1654- missing_audio_frames.insert (pair<int64_t , int64_t >(previous_packet_location.frame - 1 , audio_frame ));
1649+ missing_audio_frames.insert (pair<int64_t , int64_t >(audio_frame, previous_packet_location.frame - 1 ));
16551650 }
16561651 }
16571652 }
@@ -1726,13 +1721,25 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame)
17261721 map<int64_t , int64_t >::iterator itr;
17271722 bool found_missing_frame = false ;
17281723
1729- // Check if requested frame is a missing frame
1730- if (missing_video_frames.count (requested_frame) || missing_audio_frames.count (requested_frame)) {
1731- int64_t missing_source_frame = -1 ;
1732- if (missing_video_frames.count (requested_frame))
1733- missing_source_frame = missing_video_frames.find (requested_frame)->second ;
1734- else if (missing_audio_frames.count (requested_frame))
1735- missing_source_frame = missing_audio_frames.find (requested_frame)->second ;
1724+ // Special MP3 Handling (ignore more than 1 video frame)
1725+ if (info.has_audio and info.has_video ) {
1726+ AVCodecID aCodecId = AV_FIND_DECODER_CODEC_ID (aStream);
1727+ AVCodecID vCodecId = AV_FIND_DECODER_CODEC_ID (pStream);
1728+ // If MP3 with single video frame, handle this special case by copying the previously
1729+ // decoded image to the new frame. Otherwise, it will spend a huge amount of
1730+ // CPU time looking for missing images for all the audio-only frames.
1731+ if (checked_count > 8 && !missing_video_frames.count (requested_frame) &&
1732+ !processing_audio_frames.count (requested_frame) && processed_audio_frames.count (requested_frame) &&
1733+ last_frame && last_video_frame->has_image_data && aCodecId == AV_CODEC_ID_MP3 && (vCodecId == AV_CODEC_ID_MJPEGB || vCodecId == AV_CODEC_ID_MJPEG)) {
1734+ missing_video_frames.insert (pair<int64_t , int64_t >(requested_frame, last_video_frame->number ));
1735+ missing_video_frames_source.insert (pair<int64_t , int64_t >(last_video_frame->number , requested_frame));
1736+ missing_frames.Add (last_video_frame);
1737+ }
1738+ }
1739+
1740+ // Check if requested video frame is a missing
1741+ if (missing_video_frames.count (requested_frame)) {
1742+ int64_t missing_source_frame = missing_video_frames.find (requested_frame)->second ;
17361743
17371744 // Increment missing source frame check count (or init to 1)
17381745 if (checked_frames.count (missing_source_frame) == 0 )
@@ -1765,21 +1772,26 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame)
17651772 std::shared_ptr<QImage> parent_image = parent_frame->GetImage ();
17661773 if (parent_image) {
17671774 missing_frame->AddImage (std::shared_ptr<QImage>(new QImage (*parent_image)));
1768-
17691775 processed_video_frames[missing_frame->number ] = missing_frame->number ;
1770- processed_audio_frames[missing_frame->number ] = missing_frame->number ;
1776+ }
1777+ }
1778+ }
17711779
1772- // Move frame to final cache
1773- final_cache. Add (missing_frame);
1780+ // Check if requested audio frame is a missing
1781+ if (missing_audio_frames. count (requested_frame)) {
17741782
1775- // Remove frame from working cache
1776- working_cache. Remove (missing_frame-> number );
1783+ // Create blank missing frame
1784+ std::shared_ptr<Frame> missing_frame = CreateFrame (requested_frame );
17771785
1778- // Update last_frame processed
1779- last_frame = missing_frame->number ;
1780- }
1781- }
1786+ // Get Samples per frame (for this frame number)
1787+ int samples_per_frame = Frame::GetSamplesPerFrame (missing_frame->number , info.fps , info.sample_rate , info.channels );
1788+
1789+ // Debug output
1790+ 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 );
17821791
1792+ // Add this frame to the processed map (since it's already done)
1793+ missing_frame->AddAudioSilence (samples_per_frame);
1794+ processed_audio_frames[missing_frame->number ] = missing_frame->number ;
17831795 }
17841796
17851797 return found_missing_frame;
@@ -1792,6 +1804,9 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
17921804 bool checked_count_tripped = false ;
17931805 int max_checked_count = 80 ;
17941806
1807+ // Check if requested frame is 'missing'
1808+ CheckMissingFrame (requested_frame);
1809+
17951810 while (true )
17961811 {
17971812 // Get the front frame of working cache
0 commit comments