--- libavformat/flvdec.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-)
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 2bf1e05..b4fb4e2 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,11 @@ #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 +67,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 +105,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 +117,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 +330,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 +339,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 +397,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 +454,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 +669,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 +689,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.6.4 (Apple Git-63) _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel