Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/anim_movie.c
| Show First 20 Lines • Show All 1,378 Lines • ▼ Show 20 Lines | static int ffmpeg_seek_to_key_frame(struct anim *anim, | ||||
| if (anim->cur_packet->stream_index == anim->videoStream) { | if (anim->cur_packet->stream_index == anim->videoStream) { | ||||
| av_packet_unref(anim->cur_packet); | av_packet_unref(anim->cur_packet); | ||||
| anim->cur_packet->stream_index = -1; | anim->cur_packet->stream_index = -1; | ||||
| } | } | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| static void ffmpeg_reset_decoder_and_stream_position(struct anim *anim) | |||||
| { | |||||
| avcodec_flush_buffers(anim->pCodecCtx); | |||||
| anim->cur_position = -1; | |||||
| anim->cur_frame_final = 0; | |||||
| anim->cur_pts = -1; | |||||
| anim->cur_key_frame_pts = -1; | |||||
| } | |||||
| static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc) | static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc) | ||||
| { | { | ||||
| if (anim == NULL) { | if (anim == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position); | av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position); | ||||
| Show All 18 Lines | av_log(anim->pFormatCtx, | ||||
| AV_LOG_DEBUG, | AV_LOG_DEBUG, | ||||
| "FETCH: frame repeat: pts: %" PRId64 "\n", | "FETCH: frame repeat: pts: %" PRId64 "\n", | ||||
| (int64_t)anim->cur_pts); | (int64_t)anim->cur_pts); | ||||
| IMB_refImBuf(anim->cur_frame_final); | IMB_refImBuf(anim->cur_frame_final); | ||||
| anim->cur_position = position; | anim->cur_position = position; | ||||
| return anim->cur_frame_final; | return anim->cur_frame_final; | ||||
| } | } | ||||
| if (position == anim->cur_position + 1 || ffmpeg_is_first_frame_decode(anim, position)) { | bool seek_needed = position != anim->cur_position + 1 && | ||||
| !ffmpeg_is_first_frame_decode(anim, position); | |||||
| if (!seek_needed) { | |||||
| av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n"); | av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n"); | ||||
| ffmpeg_decode_video_frame(anim); | ffmpeg_decode_video_frame(anim); | ||||
| /* Check if during sequential decoding we got requested frame. If not, frame must be discarded | |||||
| * and seek from keyframe has to be done. */ | |||||
| if (anim->cur_pts != pts_to_search) { | |||||
| ffmpeg_reset_decoder_and_stream_position(anim); | |||||
| seek_needed = true; | |||||
| } | |||||
| } | } | ||||
| else if (ffmpeg_seek_to_key_frame(anim, position, tc_index, pts_to_search) >= 0) { | |||||
| if (seek_needed && ffmpeg_seek_to_key_frame(anim, position, tc_index, pts_to_search) >= 0) { | |||||
| ffmpeg_decode_video_frame_scan(anim, pts_to_search); | ffmpeg_decode_video_frame_scan(anim, pts_to_search); | ||||
| } | } | ||||
| IMB_freeImBuf(anim->cur_frame_final); | IMB_freeImBuf(anim->cur_frame_final); | ||||
| /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash | /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash | ||||
| * when destination buffer is not properly aligned. For example, this happens | * when destination buffer is not properly aligned. For example, this happens | ||||
| * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is | * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is | ||||
| ▲ Show 20 Lines • Show All 300 Lines • Show Last 20 Lines | |||||