diff options
-rw-r--r-- | source/blender/imbuf/intern/IMB_anim.h | 2 | ||||
-rw-r--r-- | source/blender/imbuf/intern/anim_movie.c | 109 |
2 files changed, 46 insertions, 65 deletions
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 5a410a6a583..b627baf99bd 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -173,6 +173,7 @@ struct anim { AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; + int pFrameComplete; AVFrame *pFrameRGB; AVFrame *pFrameDeinterlaced; struct SwsContext *img_convert_ctx; @@ -181,7 +182,6 @@ struct anim { struct ImBuf * last_frame; int64_t last_pts; int64_t next_pts; - int64_t next_undecoded_pts; AVPacket next_packet; #endif diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index db27c1cee63..642b84f4897 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -504,7 +504,6 @@ static int startffmpeg(struct anim * anim) { anim->last_frame = 0; anim->last_pts = -1; anim->next_pts = -1; - anim->next_undecoded_pts = -1; anim->next_packet.stream_index = -1; anim->pFormatCtx = pFormatCtx; @@ -513,6 +512,7 @@ static int startffmpeg(struct anim * anim) { anim->videoStream = videoStream; anim->pFrame = avcodec_alloc_frame(); + anim->pFrameComplete = FALSE; anim->pFrameDeinterlaced = avcodec_alloc_frame(); anim->pFrameRGB = avcodec_alloc_frame(); @@ -602,6 +602,10 @@ static void ffmpeg_postprocess(struct anim * anim) ibuf->profile = IB_PROFILE_SRGB; + if (!anim->pFrameComplete) { + return; + } + /* This means the data wasnt read properly, this check stops crashing */ if (input->data[0]==0 && input->data[1]==0 @@ -611,6 +615,12 @@ static void ffmpeg_postprocess(struct anim * anim) return; } + av_log(anim->pFormatCtx, AV_LOG_DEBUG, + " POSTPROC: anim->pFrame planes: %p %p %p %p\n", + input->data[0], input->data[1], input->data[2], + input->data[3]); + + if (anim->ib_flags & IB_animdeinterlace) { if (avpicture_deinterlace( (AVPicture*) @@ -715,42 +725,15 @@ static void ffmpeg_postprocess(struct anim * anim) } } -/* decode one video frame and load the next packet into anim->packet, - so that we can obtain next_pts and next undecoded pts */ +/* decode one video frame also considering the packet read into next_packet */ static int ffmpeg_decode_video_frame(struct anim * anim) { - int frameFinished = 0; int rval = 0; av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n"); - anim->next_undecoded_pts = -1; - if (anim->next_packet.stream_index == anim->videoStream) { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - " DECODE: cached next packet\n"); - - avcodec_decode_video2(anim->pCodecCtx, - anim->pFrame, &frameFinished, - &anim->next_packet); - - if (frameFinished) { - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - " FRAME DONE: " - "next_pts=%lld pkt_pts=%lld\n", - (anim->pFrame->pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pts, - (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pkt_pts); - anim->next_pts = - av_get_pts_from_frame(anim->pFormatCtx, - anim->pFrame); - - ffmpeg_postprocess(anim); - } - av_free_packet(&anim->next_packet); anim->next_packet.stream_index = -1; } @@ -771,21 +754,14 @@ static int ffmpeg_decode_video_frame(struct anim * anim) (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? " KEY" : ""); if (anim->next_packet.stream_index == anim->videoStream) { - if (frameFinished) { - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - " FRAME finished, we leave\n"); - anim->next_undecoded_pts - = anim->next_packet.dts; - break; - } + anim->pFrameComplete = 0; avcodec_decode_video2( anim->pCodecCtx, - anim->pFrame, &frameFinished, + anim->pFrame, &anim->pFrameComplete, &anim->next_packet); - if (frameFinished) { + if (anim->pFrameComplete) { anim->next_pts = av_get_pts_from_frame( anim->pFormatCtx, anim->pFrame); @@ -799,15 +775,16 @@ static int ffmpeg_decode_video_frame(struct anim * anim) == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pkt_pts, (long long int)anim->next_pts); - - ffmpeg_postprocess(anim); } + break; } av_free_packet(&anim->next_packet); anim->next_packet.stream_index = -1; } if (rval < 0) { + anim->next_packet.stream_index = -1; + av_log(anim->pFormatCtx, AV_LOG_ERROR, " DECODE READ FAILED: av_read_frame() " "returned error: %d\n", rval); @@ -875,7 +852,7 @@ static int match_format(const char *name, AVFormatContext * pFormatCtx) static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx) { - static const char * byte_seek_list [] = { "dv", "mpegts", 0 }; + static const char * byte_seek_list [] = { "mpegts", 0 }; const char ** p; if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) { @@ -928,7 +905,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, tc_index, new_frame_index); } else { pts_to_search = (long long) - floor(((double) position) / pts_time_base / frame_rate + 0.5); + floor(((double) position) + / pts_time_base / frame_rate + 0.5); if (st_time != AV_NOPTS_VALUE) { pts_to_search += st_time / pts_time_base @@ -939,36 +917,23 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: looking for PTS=%lld " "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", - (long long int)pts_to_search, pts_time_base, frame_rate, st_time); + (long long int)pts_to_search,pts_time_base, frame_rate, st_time); if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search){ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: frame repeat: last: %lld next: %lld\n", - (long long int)anim->last_pts, (long long int)anim->next_pts); + (long long int)anim->last_pts, + (long long int)anim->next_pts); IMB_refImBuf(anim->last_frame); anim->curposition = position; return anim->last_frame; } - IMB_freeImBuf(anim->last_frame); - anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); - - if (anim->next_pts <= pts_to_search && - anim->next_undecoded_pts > pts_to_search) { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: no seek necessary: " - "next: %lld next undecoded: %lld\n", - (long long int)anim->next_pts, - (long long int)anim->next_undecoded_pts); - - /* we are already done :) */ - - } else if (position > anim->curposition + 1 - && anim->preseek - && !tc_index - && position - (anim->curposition + 1) < anim->preseek) { - + if (position > anim->curposition + 1 + && anim->preseek + && !tc_index + && position - (anim->curposition + 1) < anim->preseek) { av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: within preseek interval (no index)\n"); @@ -1017,6 +982,11 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, } else { pos = (long long) (position - anim->preseek) * AV_TIME_BASE / frame_rate; + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, + "NO INDEX seek pos = %lld, st_time = %lld\n", + pos, (st_time != AV_NOPTS_VALUE) ? st_time : 0); + if (pos < 0) { pos = 0; } @@ -1025,6 +995,9 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, pos += st_time; } + av_log(anim->pFormatCtx, AV_LOG_DEBUG, + "NO INDEX final seek pos = %lld\n", pos); + ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD); } @@ -1054,8 +1027,16 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, } else if (position == 0 && anim->curposition == -1) { /* first frame without seeking special case... */ ffmpeg_decode_video_frame(anim); + } else { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, + "FETCH: no seek necessary, just continue...\n"); } + IMB_freeImBuf(anim->last_frame); + anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); + + ffmpeg_postprocess(anim); + anim->last_pts = anim->next_pts; ffmpeg_decode_video_frame(anim); @@ -1063,7 +1044,7 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position, anim->curposition = position; IMB_refImBuf(anim->last_frame); - + return anim->last_frame; } |