diff options
author | Peter Schlaile <peter@schlaile.de> | 2006-07-07 00:52:03 +0400 |
---|---|---|
committer | Peter Schlaile <peter@schlaile.de> | 2006-07-07 00:52:03 +0400 |
commit | b6b394e1850370d5a4c8d892c7aae68e8ac6d089 (patch) | |
tree | 7cc2d291f3817983b9fbda038b4e21f5aef17553 /source/blender/imbuf/intern/anim.c | |
parent | 5b7ccc4bd941e0aab3226377356eb8f11db743c6 (diff) |
== FFMPEG ==
Rewrote the video seek code again. This time it is a _lot_ simpler and a lot
better.
For those interested: instead of letting ffmpeg choose the right final
position, we let it preseek (maybe to I-frame in the rare case, that is
implemented) and then scan for the correct frame on DTS basis by hand.
We therefor only have to seek once and remove all those frame-jumping
jerkiness, people noticed in the same step.
Tested with msmpeg, hd-mpeg2 and DV.
Diffstat (limited to 'source/blender/imbuf/intern/anim.c')
-rw-r--r-- | source/blender/imbuf/intern/anim.c | 83 |
1 files changed, 20 insertions, 63 deletions
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index ed0d291fef4..a1ef735ffdb 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -90,17 +90,10 @@ #include <ffmpeg/avcodec.h> #include <ffmpeg/rational.h> -/* #define FFMPEG_SEEK_DEBUG 1 */ - #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 #else #define FFMPEG_CODEC_IS_POINTER 1 -#define FFMPEG_HAVE_SKIP_OPTS 1 -#endif - -#ifndef FF_ER_CAREFUL -#define FF_ER_CAREFUL FF_ER_CAREFULL #endif #endif @@ -563,15 +556,6 @@ static int startffmpeg(struct anim * anim) { } pCodecCtx->workaround_bugs = 1; - pCodecCtx->lowres = 0; - pCodecCtx->idct_algo= FF_IDCT_AUTO; -#ifdef FFMPEG_HAVE_SKIP_OPTS - pCodecCtx->skip_frame= AVDISCARD_DEFAULT; - pCodecCtx->skip_idct= AVDISCARD_DEFAULT; - pCodecCtx->skip_loop_filter= AVDISCARD_DEFAULT; -#endif - pCodecCtx->error_resilience= FF_ER_CAREFUL; - pCodecCtx->error_concealment= 3; if(avcodec_open(pCodecCtx, pCodec)<0) { av_close_input_file(pFormatCtx); @@ -621,7 +605,7 @@ static int startffmpeg(struct anim * anim) { } if (pCodecCtx->has_b_frames) { - anim->preseek = 18; /* FIXME: detect gopsize ... */ + anim->preseek = 25; /* FIXME: detect gopsize ... */ } else { anim->preseek = 0; } @@ -633,7 +617,7 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { ImBuf * ibuf; int frameFinished; AVPacket packet; - offset_t pos_to_match = AV_NOPTS_VALUE; + int64_t pts_to_search = 0; int pos_found = 1; if (anim == 0) return (0); @@ -668,7 +652,6 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { } if (position != anim->curposition + 1) { - int keyframe_found = 0; #ifdef FFMPEG_OLD_FRAME_RATE double frame_rate = (double) anim->pCodecCtx->frame_rate @@ -681,71 +664,45 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { double time_base = av_q2d(anim->pFormatCtx->streams[anim->videoStream] ->time_base); - long long pos = (long long) position * AV_TIME_BASE - / frame_rate; + long long pos = (long long) (position - anim->preseek) + * AV_TIME_BASE / frame_rate; long long st_time = anim->pFormatCtx ->streams[anim->videoStream]->start_time; + if (pos < 0) { + pos = 0; + } + if (st_time != AV_NOPTS_VALUE) { pos += st_time * AV_TIME_BASE * time_base; } av_seek_frame(anim->pFormatCtx, -1, - pos, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD ); - - while(av_read_frame(anim->pFormatCtx, &packet)>=0) { - if(packet.stream_index == anim->videoStream) { - pos_to_match - = url_ftell(&anim->pFormatCtx->pb); - if ((packet.flags & PKT_FLAG_KEY) != 0) { - keyframe_found = 1; - } - - av_free_packet(&packet); - break; - } - av_free_packet(&packet); - } + pos, AVSEEK_FLAG_BACKWARD); - if (!keyframe_found) { - int scan_pos = position - anim->preseek; - if (scan_pos < 0) { - scan_pos = 0; - } - - pos = (long long) scan_pos * AV_TIME_BASE / frame_rate; - if (st_time != AV_NOPTS_VALUE) { - pos += st_time * AV_TIME_BASE * time_base; - } + pts_to_search = (long long) + (((double) position) / time_base / frame_rate); + if (st_time != AV_NOPTS_VALUE) { + pts_to_search += st_time; } - av_seek_frame(anim->pFormatCtx, -1, - pos, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); - pos_found = 0; avcodec_flush_buffers(anim->pCodecCtx); } while(av_read_frame(anim->pFormatCtx, &packet)>=0) { - if (packet.stream_index == anim->videoStream - && !pos_found) { - if (url_ftell(&anim->pFormatCtx->pb) == pos_to_match) { - pos_found = 1; - if (anim->pCodecCtx->has_b_frames) { - pos_found++; - /* account for delay caused by - decoding pipeline */ - } - } - } if(packet.stream_index == anim->videoStream) { avcodec_decode_video(anim->pCodecCtx, anim->pFrame, &frameFinished, packet.data, packet.size); - if (frameFinished && pos_found == 2) { - pos_found = 1; - } else if(frameFinished && pos_found == 1) { + if (frameFinished && !pos_found) { + if (packet.dts >= pts_to_search) { + pos_found = 1; + } + } + + if(frameFinished && pos_found == 1) { unsigned char * p =(unsigned char*) ibuf->rect; unsigned char * e = p + anim->x * anim->y * 4; |