[FFmpeg-devel] [PATCH] avformat/fivdec: cached keyframes before video or audio stream was created
XinZheng Zhang
zhangxzheng at gmail.com
Mon Jul 25 12:34:58 EEST 2016
On Mon, Jul 25, 2016 at 4:41 PM, Michael Niedermayer
<michael at niedermayer.cc> wrote:
> On Thu, Jul 21, 2016 at 10:36:20AM +0800, Xinzheng Zhang wrote:
>> ---
>> 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;
>
> instead of adding a 3rd array the local arrays from parse_keyframes_index()
> could be moved into the context. That would reduce the memory needed
>
ok
> It also may be needed to keep 2 sets that is one per stream
> and the arrays should be freed after their use
>
>
Is that mean we need to call av_add_index_entry() for both stream?
>> +
>> 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,
>
> maybe the filepositions/times -> av_add_index_entry() code can be
> split out of parse_keyframes_index() in a seperate patch
>
> that way parse_keyframes_index() would always do the same and not
> depend on a stream while the 2nd part would be called once a
> strea and index is available
>
ok
> thanks
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> It is dangerous to be right in matters on which the established authorities
> are wrong. -- Voltaire
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
More information about the ffmpeg-devel
mailing list