diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 01f37158..125a63cb 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -422,6 +422,14 @@ void FFmpegReader::Open() { } #endif // HAVE_HW_ACCEL + // Disable per-frame threading for album arts + // Using FF_THREAD_FRAME adds one frame decoding delay per thread, + // but there's only one frame in this case. + if (HasAlbumArt()) + { + pCodecCtx->thread_type &= ~FF_THREAD_FRAME; + } + // Open video codec if (avcodec_open2(pCodecCtx, pCodec, &opts) < 0) throw InvalidCodec("A video codec was found, but could not be opened.", path); @@ -628,6 +636,14 @@ void FFmpegReader::Close() { } } +bool FFmpegReader::HasAlbumArt() { + // Check if the video stream we use is an attached picture + // This won't return true if the file has a cover image as a secondary stream + // like an MKV file with an attached image file + return pFormatCtx && videoStream >= 0 && pFormatCtx->streams[videoStream] + && (pFormatCtx->streams[videoStream]->disposition & AV_DISPOSITION_ATTACHED_PIC); +} + void FFmpegReader::UpdateAudioInfo() { // Set values of FileInfo struct info.has_audio = true; @@ -1768,8 +1784,8 @@ void FFmpegReader::Seek(int64_t requested_frame) { bool seek_worked = false; int64_t seek_target = 0; - // Seek video stream (if any) - if (!seek_worked && info.has_video) { + // Seek video stream (if any), except album arts + if (!seek_worked && info.has_video && !HasAlbumArt()) { seek_target = ConvertFrameToVideoPTS(requested_frame - buffer_amount); if (av_seek_frame(pFormatCtx, info.video_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) { fprintf(stderr, "%s: error while seeking video stream\n", pFormatCtx->AV_FILENAME); @@ -2100,14 +2116,12 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) { // 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_frames[requested_frame] > 8 && !missing_video_frames.count(requested_frame) && !processing_audio_frames.count(requested_frame) && processed_audio_frames.count(requested_frame) && - last_frame && last_video_frame && last_video_frame->has_image_data && aCodecId == AV_CODEC_ID_MP3 && (vCodecId == AV_CODEC_ID_MJPEGB || vCodecId == AV_CODEC_ID_MJPEG)) { + last_video_frame && last_video_frame->has_image_data && HasAlbumArt()) { missing_video_frames.insert(std::pair(requested_frame, last_video_frame->number)); missing_video_frames_source.insert(std::pair(last_video_frame->number, requested_frame)); missing_frames.Add(last_video_frame); diff --git a/src/FFmpegReader.h b/src/FFmpegReader.h index 35e11a42..e4718ea8 100644 --- a/src/FFmpegReader.h +++ b/src/FFmpegReader.h @@ -195,6 +195,9 @@ namespace openshot { /// Get the PTS for the current video packet int64_t GetVideoPTS(); + /// Check if there's an album art + bool HasAlbumArt(); + /// Remove partial frames due to seek bool IsPartialFrame(int64_t requested_frame);