[FFmpeg-devel] [PATCH 1/4] lavf: add write_uncoded_frame() API.

Michael Niedermayer michaelni at gmx.at
Thu Jan 2 01:31:02 CET 2014


On Wed, Jan 01, 2014 at 01:27:05PM +0100, Nicolas George wrote:
> 
> Signed-off-by: Nicolas George <george at nsup.org>
> ---
>  libavformat/avformat.h |   44 ++++++++++++++++++++++++++++++++++++++++++++
>  libavformat/mux.c      |   43 ++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 86 insertions(+), 1 deletion(-)
> 
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 6d719d7..9b25bff 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -453,6 +453,14 @@ typedef struct AVOutputFormat {
>  
>      void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
>                                   int64_t *dts, int64_t *wall);
> +
> +    /**
> +     * Write an uncoded AVFrame
> +     *
> +     * See av_write_uncoded_frame() for details.
> +     */
> +    int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
> +                               AVFrame *frame, unsigned flags);
>  } AVOutputFormat;
>  /**
>   * @}
> @@ -1908,6 +1916,42 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
>  int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
>  
>  /**
> + * Write a uncoded frame to an output media file
> + *
> + * If the muxer supports it, this function allows to write an AVFrame
> + * structure directly, without encoding it into a packet.
> + * It is mostly useful for devices and similar special muxers that use raw
> + * video or PCM data and will not serialize it into a byte stream.
> + *
> + * To test whether it is possible to use it with a given muxer and stream,
> + * use the AV_WRITE_UNCODED_FRAME_QUERY flag with frame = NULL.
> + *
> + * The caller keeps ownership of the frame and is responsible for freeing
> + * it.
> + *
> + * @return  >=0 for success, a negative code on error
> + */
> +int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
> +                           AVFrame *frame, unsigned flags);
> +
> +enum AVWriteUncodedFrameFlags {
> +
> +    /**
> +     * Query whether the feature is possible on this stream.
> +     * The frame argument is ignored.
> +     */
> +    AV_WRITE_UNCODED_FRAME_QUERY           = 0x0001,
> +

> +    /**
> +     * Do not queue packets for interleaving.
> +     * If this flag is set, the application is responsible for interleaving.
> +     */
> +    AV_WRITE_UNCODED_FRAME_NO_INTERLEAVE   = 0x0002,

whats the use-case of this ?
its not trivial for an application to interleave packets correctly
for each muxer and could lead to broken files when it is done wrong


> +
> +};
> +
> +
> +/**
>   * Write the stream trailer to an output media file and free the
>   * file private data.
>   *
> diff --git a/libavformat/mux.c b/libavformat/mux.c
> index f01b82b..0ea7dfc 100644
> --- a/libavformat/mux.c
> +++ b/libavformat/mux.c
> @@ -414,6 +414,8 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
>      return 0;
>  }
>  
> +#define AV_PKT_FLAG_UNCODED_FRAME 0x2000
> +
>  //FIXME merge with compute_pkt_fields
>  static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
>  {
> @@ -536,7 +538,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
>      }
>  
>      did_split = av_packet_split_side_data(pkt);
> -    ret = s->oformat->write_packet(s, pkt);
> +    if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {

> +        av_assert0(pkt->size == sizeof(AVFrame));

this looks very hackish


> +        ret = s->oformat->write_uncoded_frame(s, pkt->stream_index,
> +                                              (AVFrame *)pkt->data, 0);
> +    } else {
> +        ret = s->oformat->write_packet(s, pkt);
> +    }
>  
>      if (s->flush_packets && s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
>          avio_flush(s->pb);
> @@ -871,3 +879,36 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
>                                            dst->streams[dst_stream]->time_base);
>      return av_write_frame(dst, &local_pkt);
>  }
> +
> +int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
> +                           AVFrame *frame, unsigned flags)
> +{
> +    AVPacket pkt, *pktp;
> +
> +    av_assert0(s->oformat);
> +    if (!s->oformat->write_uncoded_frame)
> +        return AVERROR(ENOSYS);

> +    if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
> +        return s->oformat->write_uncoded_frame(s, stream_index, NULL, flags);

maybe PCM/RAWVIDEO could be assert0() here


> +
> +    if (!frame) {
> +        pktp = NULL;
> +    } else {
> +        pktp = &pkt;
> +        av_init_packet(&pkt);
> +        pkt.data = (void *)frame;

> +        /* Note: using sizeof(AVFrame) from outside lavu is unsafe in
> +           geneal, but it is only being used internally to this file as a
> +           consistency check. */
> +        pkt.size         = sizeof(*frame);

if its just a random number that doesnt represent the size then it
could as well be 0, that also would ensure that any use of it would
be detected
sizeof(AVFrame) works almost so its unlikely to be detected if some
code does a memcpy of it but that then can fail mysteriously with
shared libs and some being upgraded


> +        pkt.pts          = frame->pts != AV_NOPTS_VALUE ? frame->pts : frame->pkt_pts;
> +        pkt.dts          = frame->pkt_dts;
> +        pkt.duration     = av_frame_get_pkt_duration(frame);
> +        pkt.stream_index = stream_index;
> +        pkt.flags |= AV_PKT_FLAG_UNCODED_FRAME;
> +    }
> +
> +    return (flags & AV_WRITE_UNCODED_FRAME_NO_INTERLEAVE) ?
> +           av_write_frame(s, pktp) :
> +           av_interleaved_write_frame(s, pktp);
> +}
> -- 
> 1.7.10.4
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The worst form of inequality is to try to make unequal things equal.
-- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140102/20d70ba8/attachment.asc>


More information about the ffmpeg-devel mailing list