summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/APIchanges4
-rw-r--r--libavformat/avio.h66
-rw-r--r--libavformat/aviobuf.c52
-rw-r--r--libavformat/mux.c6
-rw-r--r--libavformat/version.h2
5 files changed, 127 insertions, 3 deletions
diff --git a/doc/APIchanges b/doc/APIchanges
index eae92c52ee..8f6cdca467 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,10 @@ libavutil: 2015-08-28
API changes, most recent first:
+2016-xx-xx - xxxxxxx - lavf 57.7.0 - avio.h
+ Add AVIODataMarkerType, write_data_type, ignore_boundary_point and
+ avio_write_marker.
+
2016-xx-xx - xxxxxxx - lavu 55.12.0 - opt.h
Add av_stereo3d_type_name() and av_stereo3d_from_name().
diff --git a/libavformat/avio.h b/libavformat/avio.h
index d60a5977c6..4bd5cb134a 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -54,6 +54,42 @@ typedef struct AVIOInterruptCB {
} AVIOInterruptCB;
/**
+ * Different data types that can be returned via the AVIO
+ * write_data_type callback.
+ */
+enum AVIODataMarkerType {
+ /**
+ * Header data; this needs to be present for the stream to be decodeable.
+ */
+ AVIO_DATA_MARKER_HEADER,
+ /**
+ * A point in the output bytestream where a decoder can start decoding
+ * (i.e. a keyframe). A demuxer/decoder given the data flagged with
+ * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,
+ * should give decodeable results.
+ */
+ AVIO_DATA_MARKER_SYNC_POINT,
+ /**
+ * A point in the output bytestream where a demuxer can start parsing
+ * (for non self synchronizing bytestream formats). That is, any
+ * non-keyframe packet start point.
+ */
+ AVIO_DATA_MARKER_BOUNDARY_POINT,
+ /**
+ * This is any, unlabelled data. It can either be a muxer not marking
+ * any positions at all, it can be an actual boundary/sync point
+ * that the muxer chooses not to mark, or a later part of a packet/fragment
+ * that is cut into multiple write callbacks due to limited IO buffer size.
+ */
+ AVIO_DATA_MARKER_UNKNOWN,
+ /**
+ * Trailer data, which doesn't contain actual content, but only for
+ * finalizing the output file.
+ */
+ AVIO_DATA_MARKER_TRAILER
+};
+
+/**
* Bytestream IO Context.
* New fields can be added to the end with minor version bumps.
* Removal, reordering and changes to existing fields require a major
@@ -115,6 +151,24 @@ typedef struct AVIOContext {
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
*/
int seekable;
+
+ /**
+ * A callback that is used instead of write_packet.
+ */
+ int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
+ enum AVIODataMarkerType type, int64_t time);
+ /**
+ * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,
+ * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly
+ * small chunks of data returned from the callback).
+ */
+ int ignore_boundary_point;
+
+ /**
+ * Internal, not meant to be used from outside of AVIOContext.
+ */
+ enum AVIODataMarkerType current_type;
+ int64_t last_time;
} AVIOContext;
/**
@@ -193,6 +247,18 @@ int avio_put_str16le(AVIOContext *s, const char *str);
int avio_put_str16be(AVIOContext *s, const char *str);
/**
+ * Mark the written bytestream as a specific type.
+ *
+ * Zero-length ranges are omitted from the output.
+ *
+ * @param time the stream time the current bytestream pos corresponds to
+ * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not
+ * applicable
+ * @param type the kind of data written starting at the current pos
+ */
+void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
+
+/**
* ORing this as the "whence" parameter to a seek function causes it to
* return the filesize without seeking anywhere. Supporting this is optional.
* If it is not supported then the seek function will return <0.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 29fccbea83..706cf5dd7f 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -140,6 +140,11 @@ int ffio_init_context(AVIOContext *s,
s->read_pause = NULL;
s->read_seek = NULL;
+ s->write_data_type = NULL;
+ s->ignore_boundary_point = 0;
+ s->current_type = AVIO_DATA_MARKER_UNKNOWN;
+ s->last_time = AV_NOPTS_VALUE;
+
return 0;
}
@@ -163,13 +168,25 @@ AVIOContext *avio_alloc_context(
static void flush_buffer(AVIOContext *s)
{
if (s->buf_ptr > s->buffer) {
- if (s->write_packet && !s->error) {
- int ret = s->write_packet(s->opaque, s->buffer,
+ if (!s->error) {
+ int ret = 0;
+ if (s->write_data_type)
+ ret = s->write_data_type(s->opaque, s->buffer,
+ s->buf_ptr - s->buffer,
+ s->current_type,
+ s->last_time);
+ else if (s->write_packet)
+ ret = s->write_packet(s->opaque, s->buffer,
s->buf_ptr - s->buffer);
if (ret < 0) {
s->error = ret;
}
}
+ if (s->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
+ s->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
+ s->current_type = AVIO_DATA_MARKER_UNKNOWN;
+ }
+ s->last_time = AV_NOPTS_VALUE;
if (s->update_checksum) {
s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
s->buf_ptr - s->checksum_ptr);
@@ -402,6 +419,37 @@ void avio_wb24(AVIOContext *s, unsigned int val)
avio_w8(s, val);
}
+void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
+{
+ if (!s->write_data_type)
+ return;
+ // If ignoring boundary points, just treat it as unknown
+ if (type == AVIO_DATA_MARKER_BOUNDARY_POINT && s->ignore_boundary_point)
+ type = AVIO_DATA_MARKER_UNKNOWN;
+ // Avoid unnecessary flushes if we are already in non-header/trailer
+ // data and setting the type to unknown
+ if (type == AVIO_DATA_MARKER_UNKNOWN &&
+ (s->current_type != AVIO_DATA_MARKER_HEADER &&
+ s->current_type != AVIO_DATA_MARKER_TRAILER))
+ return;
+
+ switch (type) {
+ case AVIO_DATA_MARKER_HEADER:
+ case AVIO_DATA_MARKER_TRAILER:
+ // For header/trailer, ignore a new marker of the same type;
+ // consecutive header/trailer markers can be merged.
+ if (type == s->current_type)
+ return;
+ break;
+ }
+
+ // If we've reached here, we have a new, noteworthy marker.
+ // Flush the previous data and mark the start of the new data.
+ avio_flush(s);
+ s->current_type = type;
+ s->last_time = time;
+}
+
/* Input stream */
static void fill_buffer(AVIOContext *s)
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 0761a93b6d..49fe65cf98 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -256,11 +256,15 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
if (ret = init_muxer(s, options))
return ret;
+ if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+ avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
if (s->oformat->write_header) {
ret = s->oformat->write_header(s);
if (ret < 0)
return ret;
}
+ if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+ avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) {
if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
@@ -704,6 +708,8 @@ int av_write_trailer(AVFormatContext *s)
goto fail;
}
+ if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+ avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
if (s->oformat->write_trailer)
ret = s->oformat->write_trailer(s);
diff --git a/libavformat/version.h b/libavformat/version.h
index a50e443c76..b2a1e054bf 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFORMAT_VERSION_MAJOR 57
-#define LIBAVFORMAT_VERSION_MINOR 6
+#define LIBAVFORMAT_VERSION_MINOR 7
#define LIBAVFORMAT_VERSION_MICRO 0
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \