[FFmpeg-devel] [PATCH] avformat/fivdec: cached keyframes before video or audio stream was created

Michael Niedermayer michael at niedermayer.cc
Mon Jul 25 11:41:22 EEST 2016


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

It also may be needed to keep 2 sets that is one per stream
and the arrays should be freed after their use


> +
>  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

thanks

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

It is dangerous to be right in matters on which the established authorities
are wrong. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160725/244c8bab/attachment.sig>


More information about the ffmpeg-devel mailing list