[vlc-devel] [PATCH 3/4] avformat mux: Mark keyframe blocks as such.

Rémi Denis-Courmont remi at remlab.net
Sun Aug 25 10:12:29 CEST 2013


Le vendredi 16 août 2013 16:42:39 Steinar H. Gunderson a écrit :
> Some browsers, such as Firefox, are very picky about WebM streams needing to
> start with a keyframe. To be able to handle this correctly when streaming,
> the avformat mux needs to mark keyframe-containing blocks (or clusters, in
> Matroska terminology) as such even after they have been muxed. The next
> patch in the series will make httpd actually care about this flag.
> 
> Unfortunately, as avformat does not actually propagate this status, we need
> to use some heuristics to figure out which blocks contain keyframes. The
> natural thing to do would be to say that when we write a keyframe, the
> block that comes back has to be a keyframe block, but the WebM/Matroska
> muxer thwarts this by having its own internal buffering of clusters,
> flushing the _previous_ cluster when we send it a keyframe. Thus, we need
> to explicitly send a flush (a NULL packet) before the one that comes back
> when we mux a keyframe.
> ---
>  modules/demux/avformat/mux.c |   21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/modules/demux/avformat/mux.c b/modules/demux/avformat/mux.c
> index d1277ce..ab72d03 100644
> --- a/modules/demux/avformat/mux.c
> +++ b/modules/demux/avformat/mux.c
> @@ -58,7 +58,9 @@ struct sout_mux_sys_t
>      AVFormatContext *oc;
> 
>      bool     b_write_header;
> +    bool     b_write_keyframe;
>      bool     b_error;
> +    bool     b_allow_flush;
>  };
> 
>  /**************************************************************************
> *** @@ -129,6 +131,7 @@ int OpenMux( vlc_object_t *p_this )
>      p_sys->oc->nb_streams = 0;
> 
>      p_sys->b_write_header = true;
> +    p_sys->b_write_keyframe = false;
>      p_sys->b_error = false;
> 
>      /* Fill p_mux fields */
> @@ -275,7 +278,17 @@ static int MuxBlock( sout_mux_t *p_mux, sout_input_t
> *p_input ) pkt.size = p_data->i_buffer;
>      pkt.stream_index = i_stream;
> 
> -    if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) pkt.flags |= AV_PKT_FLAG_KEY;
> +    if( p_data->i_flags & BLOCK_FLAG_TYPE_I )
> +    {
> +#ifdef AVFMT_ALLOW_FLUSH

I can't find defined this in current libav.git... If it depends on pending 
patches, it might be better to hold on.

> +        /* Make sure we don't inadvertedly mark buffered data as keyframes.
> */ +        if( p_sys->oc->oformat->flags & AVFMT_ALLOW_FLUSH )
> +            av_write_frame( p_sys->oc, NULL );
> +#endif
> +
> +        p_sys->b_write_keyframe = true;
> +        pkt.flags |= AV_PKT_FLAG_KEY;
> +    }
> 
>      if( p_data->i_pts > 0 )
>          pkt.pts = p_data->i_pts * p_stream->time_base.den /
> @@ -402,6 +415,12 @@ static int IOWrite( void *opaque, uint8_t *buf, int
> buf_size ) if( p_mux->p_sys->b_write_header )
>          p_buf->i_flags |= BLOCK_FLAG_HEADER;
> 
> +    if( p_mux->p_sys->b_write_keyframe )
> +    {
> +        p_buf->i_flags |= BLOCK_FLAG_TYPE_I;
> +        p_mux->p_sys->b_write_keyframe = false;
> +    }
> +
>      i_ret = sout_AccessOutWrite( p_mux->p_access, p_buf );
>      return i_ret ? i_ret : -1;
>  }
-- 
Rémi Denis-Courmont
http://www.remlab.net/




More information about the vlc-devel mailing list