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

Rafaël Carré funman at videolan.org
Tue Sep 3 14:09:53 CEST 2013


Hello Steinar,

Le 16/08/2013 16:42, 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;

This one is unused, I guess it should be removed.

>  };
>  
>  /*****************************************************************************
> @@ -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
> +        /* 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;
>  }

Looks good, thanks



More information about the vlc-devel mailing list