Skip to content

Commit

Permalink
Fix crashes and failures on decoding some types of album art images
Browse files Browse the repository at this point in the history
  • Loading branch information
PhysSong committed May 29, 2020
1 parent 10ed4ba commit d338e0b
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
3 changes: 3 additions & 0 deletions include/FFmpegReader.h
Expand Up @@ -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);

Expand Down
21 changes: 16 additions & 5 deletions src/FFmpegReader.cpp
Expand Up @@ -435,6 +435,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);
Expand Down Expand Up @@ -641,6 +649,11 @@ void FFmpegReader::Close() {
}
}

bool FFmpegReader::HasAlbumArt() {
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;
Expand Down Expand Up @@ -1779,8 +1792,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);
Expand Down Expand Up @@ -2089,14 +2102,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<int64_t, int64_t>(requested_frame, last_video_frame->number));
missing_video_frames_source.insert(std::pair<int64_t, int64_t>(last_video_frame->number, requested_frame));
missing_frames.Add(last_video_frame);
Expand Down

0 comments on commit d338e0b

Please sign in to comment.