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

Nicolas George george at nsup.org
Mon Jan 13 10:23:43 CET 2014


Signed-off-by: Nicolas George <george at nsup.org>
---
 libavformat/avformat.h | 46 +++++++++++++++++++++++++++++++++++
 libavformat/internal.h | 14 +++++++++++
 libavformat/mux.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 124 insertions(+), 1 deletion(-)


Split the API into av_write_uncoded_frame() /
av_interleaved_write_uncoded_frame() / av_write_uncoded_frame_query().
The QUERY flag stays for internal use in the muxers callback.

Also use a more robust magic number as the packet size.


diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 6d719d7..4c03985 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,44 @@ 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.
+ *
+ * The frame must be correctly interleaved according to the container
+ * specification; if not, then av_interleaved_write_frame() must be used.
+ *
+ * See av_interleaved_write_frame() for details.
+ */
+int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
+                           AVFrame *frame);
+
+/**
+ * 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 av_write_uncoded_frame_query().
+ *
+ * The caller keeps ownership of the frame and is responsible for freeing
+ * it.
+ *
+ * @return  >=0 for success, a negative code on error
+ */
+int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
+                                       AVFrame *frame);
+
+/**
+ * Test whether a muxer supports uncoded frame.
+ *
+ * @return  >=0 if an uncoded frame can be written to that muxer and stream,
+ *          <0 if not
+ */
+int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
+
+/**
  * Write the stream trailer to an output media file and free the
  * file private data.
  *
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 1560e9f..7a17a3d 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -390,4 +390,18 @@ int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts);
 
 void ff_rfps_calculate(AVFormatContext *ic);
 
+/**
+ * Flags for AVFormatContext.write_uncoded_frame()
+ */
+enum AVWriteUncodedFrameFlags {
+
+    /**
+     * Query whether the feature is possible on this stream.
+     * The frame argument is ignored.
+     */
+    AV_WRITE_UNCODED_FRAME_QUERY           = 0x0001,
+
+};
+
+
 #endif /* AVFORMAT_INTERNAL_H */
diff --git a/libavformat/mux.c b/libavformat/mux.c
index bd50191..f6c2a0a 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -414,6 +414,15 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
     return 0;
 }
 
+#define AV_PKT_FLAG_UNCODED_FRAME 0x2000
+
+/* Note: using sizeof(AVFrame) from outside lavu is unsafe in general, but
+   it is only being used internally to this file as a consistency check.
+   The value is chosen to be very unlikely to appear on its own and to cause
+   immediate failure if used anywhere as a real size. */
+#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame))
+
+
 //FIXME merge with compute_pkt_fields
 static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 {
@@ -536,7 +545,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 == UNCODED_FRAME_PACKET_SIZE);
+        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 +886,51 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
                                           dst->streams[dst_stream]->time_base);
     return av_write_frame(dst, &local_pkt);
 }
+
+static int av_write_uncoded_frame_internal(AVFormatContext *s, int stream_index,
+                                           AVFrame *frame, int interleaved)
+{
+    AVPacket pkt, *pktp;
+
+    av_assert0(s->oformat);
+    if (!s->oformat->write_uncoded_frame)
+        return AVERROR(ENOSYS);
+
+    if (!frame) {
+        pktp = NULL;
+    } else {
+        pktp = &pkt;
+        av_init_packet(&pkt);
+        pkt.data = (void *)frame;
+        pkt.size         = UNCODED_FRAME_PACKET_SIZE;
+        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 interleaved ? av_interleaved_write_frame(s, pktp) :
+                         av_write_frame(s, pktp);
+}
+
+int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
+                           AVFrame *frame)
+{
+    return av_write_uncoded_frame_internal(s, stream_index, frame, 0);
+}
+
+int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
+                                       AVFrame *frame)
+{
+    return av_write_uncoded_frame_internal(s, stream_index, frame, 1);
+}
+
+int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index)
+{
+    av_assert0(s->oformat);
+    if (!s->oformat->write_uncoded_frame)
+        return AVERROR(ENOSYS);
+    return s->oformat->write_uncoded_frame(s, stream_index, NULL,
+                                           AV_WRITE_UNCODED_FRAME_QUERY);
+}
-- 
1.8.5.2



More information about the ffmpeg-devel mailing list