[FFmpeg-devel] [PATCH 4/6] lavf: add automatic bitstream filtering

Michael Niedermayer michael at niedermayer.cc
Thu Oct 8 13:13:38 CEST 2015


On Wed, Oct 07, 2015 at 09:50:05PM -0500, Rodger Combs wrote:
> This solves the problem discussed in https://ffmpeg.org/pipermail/ffmpeg-devel/2015-September/179238.html
> by allowing AVCodec::write_header to be delayed until after packets have been
> run through required bitstream filters in order to generate global extradata.
> 
> It also provides a mechanism by which a muxer can add a bitstream filter to a
> stream automatically, rather than prompting the user to do so.
> ---
>  libavformat/avformat.h | 29 +++++++++++++++++++++++++++++
>  libavformat/mux.c      | 31 ++++++++++++++++++++++++++++---
>  2 files changed, 57 insertions(+), 3 deletions(-)
> 
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 5226b0a..f3c8260 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -598,6 +598,21 @@ typedef struct AVOutputFormat {
>       */
>      int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
>      enum AVCodecID data_codec; /**< default data codec */
> +    /**
> +     * Initialize format. May allocate data here, and set any AVFormatContext or
> +     * AVStream parameters that need to be set before packets are sent.
> +     * Must not write output.
> +     *
> +     * FIXME: Data allocated here would be leaked if there's a failure before
> +     * write_header is called. Ban allocations? Add a `deinit` cleanup function?
> +     */
> +    int (*init)(struct AVFormatContext *);
> +    /**
> +     * Set up any necessary bitstream filtering and extract any extra data needed
> +     * for the global header.
> +     * Return 0 if more packets from this stream must be checked; 1 if not.
> +     */
> +    int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
>  } AVOutputFormat;
>  /**
>   * @}
> @@ -1167,6 +1182,18 @@ typedef struct AVStream {
>      AVRational display_aspect_ratio;
>  
>      struct FFFrac *priv_pts;
> +
> +    /**
> +     * bitstream filter to run on stream
> +     * - encoding: Set by muxer or user using av_add_bitstream_filter
> +     * - decoding: unused
> +     */
> +    AVBitStreamFilterContext *bsfc;
> +
> +    /**
> +     * internal check if check_bitstream should still be run on each packet
> +     */
> +    int bitstream_checked;
>  } AVStream;
>  
>  AVRational av_stream_get_r_frame_rate(const AVStream *s);
> @@ -1782,6 +1809,8 @@ typedef struct AVFormatContext {
>       * Demuxing: Set by user.
>       */
>      int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
> +
> +    int header_written;
>  } AVFormatContext;
>  
>  int av_format_get_probe_score(const AVFormatContext *s);
> diff --git a/libavformat/mux.c b/libavformat/mux.c
> index c9ef490..b5b2c8a 100644
> --- a/libavformat/mux.c
> +++ b/libavformat/mux.c
> @@ -400,7 +400,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
>           *options = tmp;
>      }
>  
> -    return 0;
> +    return s->oformat->init ? s->oformat->init(s) : 0;
>  
>  fail:
>      av_dict_free(&tmp);
> @@ -451,7 +451,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
>      if ((ret = init_muxer(s, options)) < 0)
>          return ret;
>  
> -    if (s->oformat->write_header) {
> +    if (s->oformat->write_header && !s->oformat->check_bitstream) {
>          ret = s->oformat->write_header(s);
>          if (ret >= 0 && s->pb && s->pb->error < 0)
>              ret = s->pb->error;
> @@ -459,6 +459,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
>              return ret;
>          if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
>              avio_flush(s->pb);
> +        s->header_written = 1;
>      }
>  
>      if ((ret = init_pts(s)) < 0)
> @@ -951,6 +952,18 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
>              ret = AVERROR(EINVAL);
>              goto fail;
>          }
> +
> +        if (s->oformat->check_bitstream) {
> +            if (!st->bitstream_checked) {
> +                if ((ret = s->oformat->check_bitstream(s, pkt)) < 0)
> +                    goto fail;
> +                else if (ret == 1)
> +                    st->bitstream_checked = 1;
> +            }
> +        }
> +
> +        if ((ret = av_apply_bitstream_filters(s, pkt, st->bsfc)) < 0)
> +            goto fail;
>      } else {
>          av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n");
>          flush = 1;
> @@ -967,10 +980,22 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
>          if (ret <= 0) //FIXME cleanup needed for ret<0 ?
>              return ret;
>  
> +        if (!s->header_written && s->oformat->write_header) {
> +            ret = s->oformat->write_header(s);
> +            if (ret >= 0 && s->pb && s->pb->error < 0)
> +                ret = s->pb->error;
> +            if (ret < 0)
> +                goto fail2;
> +            if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
> +                avio_flush(s->pb);
> +            s->header_written = 1;
> +        }
> +
>          ret = write_packet(s, &opkt);
>          if (ret >= 0)
>              s->streams[opkt.stream_index]->nb_frames++;
>  
> +fail2:
>          av_free_packet(&opkt);
>  
>          if (ret < 0)
> @@ -1008,7 +1033,7 @@ int av_write_trailer(AVFormatContext *s)
>      }
>  
>  fail:
> -    if (s->oformat->write_trailer)
> +    if (s->header_written && s->oformat->write_trailer)

this changes the behavior in case no packets are written
as then also no header or trailer is ever written while previously
a header and trailer was written

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

No snowflake in an avalanche ever feels responsible. -- 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/20151008/1a2772ba/attachment.sig>


More information about the ffmpeg-devel mailing list