diff options
author | Peter Schlaile <peter@schlaile.de> | 2011-11-20 20:08:56 +0400 |
---|---|---|
committer | Peter Schlaile <peter@schlaile.de> | 2011-11-20 20:08:56 +0400 |
commit | af66321f3b7c1b84fada90fa0ab6f6e0774f4163 (patch) | |
tree | 1d5b065e3f913d3386a7268b8bc07e07ba5d2a56 /source/blender/imbuf | |
parent | 778cd80eb8497c7c2e10385ea9274254ae9494cb (diff) |
== Sequencer / FFMPEG ==
This fixed two issues:
* RAW DV-seeking has to be done using DTS. Sounds silly, but ffmpeg
tracks internal state in RAW DV format decoder and runs mad, if
we seek by byte. Don't know, why I haven't noticed that, when I
added it.
* real fix(tm) for #29295
problem was: we did AVFrame read ahead, and the pattern
read_frame -> decode -> read_frame -> do color conversion of first frame
works everywhere but RAW RGB-files which do some pointer shuffling
within ffmpeg to save a memcpy...
I removed read ahead completely, since it didn't work like originally
intented. Might come back later, but the original purpose (making
resyncing easier if we are completely lost in stream) it never
fullfilled.
Diffstat (limited to 'source/blender/imbuf')
-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; } |