2016-07-20 21:46 GMT+08:00 XinZheng Zhang <zhangxzh...@gmail.com>: > There has an error when seeking in a flv file, which key frames was > sorted before video frame. > This ensures that all the key frames was cached, and add to > corresponding stream when it was created. > > On Wed, Jul 20, 2016 at 9:30 PM, zhangxinzheng <zhangxzh...@gmail.com> > wrote: > > From: Xinzheng Zhang <zhangxzh...@gmail.com> > > > > --- > > libavformat/flvdec.c | 52 > +++++++++++++++++++++++++++++++++++++++++++++------- > > 1 file changed, 45 insertions(+), 7 deletions(-) > > > > diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c > > index 2bf1e05..8a73b68 100644 > > --- a/libavformat/flvdec.c > > +++ b/libavformat/flvdec.c > > @@ -30,6 +30,7 @@ > > #include "libavutil/opt.h" > > #include "libavutil/intfloat.h" > > #include "libavutil/mathematics.h" > > +#include "libavutil/mem.h" > > #include "libavcodec/bytestream.h" > > #include "libavcodec/mpeg4audio.h" > > #include "avformat.h" > > @@ -41,6 +42,12 @@ > > > > #define RESYNC_BUFFER_SIZE (1<<20) > > > > + > > +typedef struct FLVKeyFrame { > > + int64_t pos; > > + int64_t timestamp; > > +} FLVKeyFrame; > > + > > typedef struct FLVContext { > > const AVClass *class; ///< Class for private options. > > int trust_metadata; ///< configure streams according onMetaData > > @@ -61,6 +68,10 @@ typedef struct FLVContext { > > > > int broken_sizes; > > int sum_flv_tag_size; > > + > > + int head_flags; //r8 > > + FLVKeyFrame *keyframes; > > + int keyframe_count; > > } FLVContext; > > > > static int probe(AVProbeData *p, int live) > > @@ -95,6 +106,9 @@ static int live_flv_probe(AVProbeData *p) > > static AVStream *create_stream(AVFormatContext *s, int codec_type) > > { > > AVStream *st = avformat_new_stream(s, NULL); > > + FLVContext *flv = s->priv_data; > > + int flags = flv->head_flags; > > + int i = 0; > > if (!st) > > return NULL; > > st->codecpar->codec_type = codec_type; > > @@ -104,6 +118,17 @@ static AVStream *create_stream(AVFormatContext *s, > int codec_type) > > s->ctx_flags &= ~AVFMTCTX_NOHEADER; > > > > avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ > > + if ((!(flags & FLV_HEADER_FLAG_HASVIDEO) && codec_type == > AVMEDIA_TYPE_AUDIO) || > > + (codec_type == AVMEDIA_TYPE_VIDEO) > > + ) { > > + for (; i < flv->keyframe_count; i++) { > > + FLVKeyFrame *keyframe = &flv->keyframes[i]; > > + av_add_index_entry(st, keyframe->pos, keyframe->timestamp, > > + 0, 0, AVINDEX_KEYFRAME); > > + } > > + flv->keyframe_count = 0; > > + av_freep(&flv->keyframes); > > + } > > return st; > > } > > > > @@ -306,7 +331,7 @@ static int amf_get_string(AVIOContext *ioc, char > *buffer, int buffsize) > > } > > > > static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, > > - AVStream *vstream, int64_t max_pos) > > + AVStream *vstream, AVStream *astream, > int64_t max_pos) > > { > > FLVContext *flv = s->priv_data; > > unsigned int timeslen = 0, fileposlen = 0, i; > > @@ -315,8 +340,12 @@ static int parse_keyframes_index(AVFormatContext > *s, AVIOContext *ioc, > > int64_t *filepositions = NULL; > > int ret = AVERROR(ENOSYS); > > int64_t initial_pos = avio_tell(ioc); > > + int head_flags = flv->head_flags; > > + AVStream *kf_stream = vstream; > > + if (!kf_stream && astream && (!(head_flags & > FLV_HEADER_FLAG_HASVIDEO) && (head_flags & FLV_HEADER_FLAG_HASAUDIO))) > > + kf_stream = astream; > > > > - if (vstream->nb_index_entries>0) { > > + if (kf_stream && kf_stream->nb_index_entries > 0) { > > av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n"); > > return 0; > > } > > @@ -369,8 +398,16 @@ static int parse_keyframes_index(AVFormatContext > *s, AVIOContext *ioc, > > > > if (timeslen == fileposlen && fileposlen>1 && max_pos <= > filepositions[0]) { > > for (i = 0; i < fileposlen; i++) { > > - av_add_index_entry(vstream, filepositions[i], times[i] * > 1000, > > - 0, 0, AVINDEX_KEYFRAME); > > + if (kf_stream) { > > + av_add_index_entry(kf_stream, filepositions[i], > times[i] * 1000, > > + 0, 0, AVINDEX_KEYFRAME); > > + } else { > > + FLVKeyFrame frame = {0}; > > + frame.pos = filepositions[i]; > > + frame.timestamp = times[i] * 1000; > > + av_dynarray2_add((void **)&flv->keyframes, > &flv->keyframe_count,sizeof(FLVKeyFrame), (const uint8_t *)&frame); > > + } > > + > > if (i < 2) { > > flv->validate_index[i].pos = filepositions[i]; > > flv->validate_index[i].dts = times[i] * 1000; > > @@ -418,10 +455,10 @@ static int amf_parse_object(AVFormatContext *s, > AVStream *astream, > > } > > break; > > case AMF_DATA_TYPE_OBJECT: > > - if ((vstream || astream) && key && > > + if (key && > > ioc->seekable && > > !strcmp(KEYFRAMES_TAG, key) && depth == 1) > > - if (parse_keyframes_index(s, ioc, vstream ? vstream : > astream, > > + if (parse_keyframes_index(s, ioc, vstream, astream, > > max_pos) < 0) > > av_log(s, AV_LOG_ERROR, "Keyframe index parsing > failed\n"); > > > > @@ -633,7 +670,7 @@ static int flv_read_header(AVFormatContext *s) > > int offset; > > > > avio_skip(s->pb, 4); > > - avio_r8(s->pb); // flags > > + flv->head_flags = avio_r8(s->pb); // flags > > > > s->ctx_flags |= AVFMTCTX_NOHEADER; > > > > @@ -653,6 +690,7 @@ static int flv_read_close(AVFormatContext *s) > > FLVContext *flv = s->priv_data; > > for (i=0; i<FLV_STREAM_TYPE_NB; i++) > > av_freep(&flv->new_extradata[i]); > > + av_freep(&flv->keyframes); > > return 0; > > } > > > > -- > > 2.5.4 (Apple Git-61) > > >
Where is the original mail? _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel