[FFmpeg-cvslog] Merge commit 'db7968bff4851c2be79b15b2cb2ae747424d2fca'

Matthieu Bouron git at videolan.org
Thu Jun 23 17:40:50 CEST 2016


ffmpeg | branch: master | Matthieu Bouron <matthieu.bouron at stupeflix.com> | Thu Jun 23 15:27:00 2016 +0200| [5d75e4667742c851e21dcd6ce70154834fb7d22b] | committer: Matthieu Bouron

Merge commit 'db7968bff4851c2be79b15b2cb2ae747424d2fca'

* commit 'db7968bff4851c2be79b15b2cb2ae747424d2fca':
  avio: Allow custom IO users to get labels for the output bytestream

Merged-by: Matthieu Bouron <matthieu.bouron at stupeflix.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=5d75e4667742c851e21dcd6ce70154834fb7d22b
---

 doc/APIchanges        |    4 +++
 libavformat/avio.h    |   66 +++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/aviobuf.c |   52 ++++++++++++++++++++++++++++++++++++--
 libavformat/mux.c     |    9 ++++++-
 libavformat/version.h |    2 +-
 5 files changed, 129 insertions(+), 4 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 5c7d21a..9ca71b7 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,10 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-xx-xx - xxxxxxx / db7968b - lavf 57.40.100 / 57.7.0 - avio.h
+  Add AVIODataMarkerType, write_data_type, ignore_boundary_point and
+  avio_write_marker.
+
 2016-xx-xx - xxxxxxx / 0c4468d - lavu 55.26.100 / 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 5e86f7e..b1ce1d1 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -97,6 +97,42 @@ typedef struct AVIODirContext {
 } AVIODirContext;
 
 /**
+ * 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
@@ -259,6 +295,24 @@ typedef struct AVIOContext {
      * ',' separated list of disallowed protocols.
      */
     const char *protocol_blacklist;
+
+    /**
+     * 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;
 
 /**
@@ -412,6 +466,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 f02ae21..95793c9 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -115,6 +115,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;
 }
 
@@ -137,12 +142,24 @@ AVIOContext *avio_alloc_context(
 
 static void writeout(AVIOContext *s, const uint8_t *data, int len)
 {
-    if (s->write_packet && !s->error) {
-        int ret = s->write_packet(s->opaque, (uint8_t *)data, len);
+    if (!s->error) {
+        int ret = 0;
+        if (s->write_data_type)
+            ret = s->write_data_type(s->opaque, (uint8_t *)data,
+                                     len,
+                                     s->current_type,
+                                     s->last_time);
+        else if (s->write_packet)
+            ret = s->write_packet(s->opaque, (uint8_t *)data, len);
         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;
     s->writeout_count ++;
     s->pos += len;
 }
@@ -450,6 +467,37 @@ void avio_wb24(AVIOContext *s, unsigned int val)
     avio_w8(s, (uint8_t)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 76db607..8488043 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -475,6 +475,8 @@ static int init_pts(AVFormatContext *s)
 
 static int write_header_internal(AVFormatContext *s)
 {
+    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) {
         int ret = s->oformat->write_header(s);
         if (ret >= 0 && s->pb && s->pb->error < 0)
@@ -486,6 +488,8 @@ static int write_header_internal(AVFormatContext *s)
             avio_flush(s->pb);
     }
     s->internal->header_written = 1;
+    if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+        avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
     return 0;
 }
 
@@ -1164,12 +1168,15 @@ int av_write_trailer(AVFormatContext *s)
     }
 
 fail:
-    if (s->internal->header_written && s->oformat->write_trailer)
+    if (s->internal->header_written && s->oformat->write_trailer) {
+        if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
         if (ret >= 0) {
         ret = s->oformat->write_trailer(s);
         } else {
             s->oformat->write_trailer(s);
         }
+    }
 
     if (s->oformat->deinit)
         s->oformat->deinit(s);
diff --git a/libavformat/version.h b/libavformat/version.h
index 0293b48..543afbb 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you belive might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  39
+#define LIBAVFORMAT_VERSION_MINOR  40
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \


======================================================================

diff --cc doc/APIchanges
index 5c7d21a,8f6cdca..9ca71b7
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@@ -15,17 -13,20 +15,21 @@@ libavutil:     2015-08-2
  
  API changes, most recent first:
  
 -2016-xx-xx - xxxxxxx - lavf 57.7.0 - avio.h
++2016-xx-xx - xxxxxxx / db7968b - lavf 57.40.100 / 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
 +2016-xx-xx - xxxxxxx / 0c4468d - lavu 55.26.100 / 55.12.0 - opt.h
    Add av_stereo3d_type_name() and av_stereo3d_from_name().
  
 -2016-xx-xx - xxxxxxx - lavu 55.11.0 - hwcontext_dxva2.h
 +2016-06-22 - xxxxxxx - lavu 55.25.100 - hwcontext_dxva2.h
    Add new installed header with DXVA2-specific hwcontext definitions.
  
 -2016-xx-xx - xxxxxxx - lavu 55.10.0 - opt.h
 -  Add av_opt_copy().
 +2016-04-27 - fb91871 - lavu 55.23.100 - log.h
 +  Add a new function av_log_format_line2() which returns number of bytes
 +  written to the target buffer.
  
 -2016-xx-xx - xxxxxxx - lavc 57.16.0 - avcodec.h
 +2016-04-21 - 7fc329e - lavc 57.37.100 - avcodec.h
    Add a new audio/video encoding and decoding API with decoupled input
    and output -- avcodec_send_packet(), avcodec_receive_frame(),
    avcodec_send_frame() and avcodec_receive_packet().
diff --cc libavformat/avio.h
index 5e86f7e,4bd5cb1..b1ce1d1
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@@ -53,50 -54,42 +53,86 @@@ typedef struct AVIOInterruptCB 
  } AVIOInterruptCB;
  
  /**
 + * Directory entry types.
 + */
 +enum AVIODirEntryType {
 +    AVIO_ENTRY_UNKNOWN,
 +    AVIO_ENTRY_BLOCK_DEVICE,
 +    AVIO_ENTRY_CHARACTER_DEVICE,
 +    AVIO_ENTRY_DIRECTORY,
 +    AVIO_ENTRY_NAMED_PIPE,
 +    AVIO_ENTRY_SYMBOLIC_LINK,
 +    AVIO_ENTRY_SOCKET,
 +    AVIO_ENTRY_FILE,
 +    AVIO_ENTRY_SERVER,
 +    AVIO_ENTRY_SHARE,
 +    AVIO_ENTRY_WORKGROUP,
 +};
 +
 +/**
 + * Describes single entry of the directory.
 + *
 + * Only name and type fields are guaranteed be set.
 + * Rest of fields are protocol or/and platform dependent and might be unknown.
 + */
 +typedef struct AVIODirEntry {
 +    char *name;                           /**< Filename */
 +    int type;                             /**< Type of the entry */
 +    int utf8;                             /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
 +                                               Name can be encoded with UTF-8 even though 0 is set. */
 +    int64_t size;                         /**< File size in bytes, -1 if unknown. */
 +    int64_t modification_timestamp;       /**< Time of last modification in microseconds since unix
 +                                               epoch, -1 if unknown. */
 +    int64_t access_timestamp;             /**< Time of last access in microseconds since unix epoch,
 +                                               -1 if unknown. */
 +    int64_t status_change_timestamp;      /**< Time of last status change in microseconds since unix
 +                                               epoch, -1 if unknown. */
 +    int64_t user_id;                      /**< User ID of owner, -1 if unknown. */
 +    int64_t group_id;                     /**< Group ID of owner, -1 if unknown. */
 +    int64_t filemode;                     /**< Unix file mode, -1 if unknown. */
 +} AVIODirEntry;
 +
 +typedef struct AVIODirContext {
 +    struct URLContext *url_context;
 +} AVIODirContext;
 +
 +/**
+  * 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
@@@ -207,58 -153,22 +243,76 @@@ typedef struct AVIOContext 
      int seekable;
  
      /**
 +     * max filesize, used to limit allocations
 +     * This field is internal to libavformat and access from outside is not allowed.
 +     */
 +    int64_t maxsize;
 +
 +    /**
 +     * avio_read and avio_write should if possible be satisfied directly
 +     * instead of going through a buffer, and avio_seek will always
 +     * call the underlying seek function directly.
 +     */
 +    int direct;
 +
 +    /**
 +     * Bytes read statistic
 +     * This field is internal to libavformat and access from outside is not allowed.
 +     */
 +    int64_t bytes_read;
 +
 +    /**
 +     * seek statistic
 +     * This field is internal to libavformat and access from outside is not allowed.
 +     */
 +    int seek_count;
 +
 +    /**
 +     * writeout statistic
 +     * This field is internal to libavformat and access from outside is not allowed.
 +     */
 +    int writeout_count;
 +
 +    /**
 +     * Original buffer size
 +     * used internally after probing and ensure seekback to reset the buffer size
 +     * This field is internal to libavformat and access from outside is not allowed.
 +     */
 +    int orig_buffer_size;
 +
 +    /**
 +     * Threshold to favor readahead over seek.
 +     * This is current internal only, do not use from outside.
 +     */
 +    int short_seek_threshold;
 +
 +    /**
 +     * ',' separated list of allowed protocols.
 +     */
 +    const char *protocol_whitelist;
 +
 +    /**
 +     * ',' separated list of disallowed protocols.
 +     */
 +    const char *protocol_blacklist;
++
++    /**
+      * 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;
  
  /**
diff --cc libavformat/aviobuf.c
index f02ae21,706cf5d..95793c9
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@@ -135,22 -165,28 +140,34 @@@ AVIOContext *avio_alloc_context
      return s;
  }
  
 -static void flush_buffer(AVIOContext *s)
 +static void writeout(AVIOContext *s, const uint8_t *data, int len)
  {
-     if (s->write_packet && !s->error) {
-         int ret = s->write_packet(s->opaque, (uint8_t *)data, len);
 -    if (s->buf_ptr > 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->error) {
++        int ret = 0;
++        if (s->write_data_type)
++            ret = s->write_data_type(s->opaque, (uint8_t *)data,
++                                     len,
++                                     s->current_type,
++                                     s->last_time);
++        else if (s->write_packet)
++            ret = s->write_packet(s->opaque, (uint8_t *)data, len);
 +        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->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;
 +    s->writeout_count ++;
 +    s->pos += len;
 +}
 +
 +static void flush_buffer(AVIOContext *s)
 +{
 +    if (s->write_flag && s->buf_ptr > s->buffer) {
 +        writeout(s, s->buffer, s->buf_ptr - s->buffer);
          if (s->update_checksum) {
              s->checksum     = s->update_checksum(s->checksum, s->checksum_ptr,
                                                   s->buf_ptr - s->checksum_ptr);
@@@ -446,10 -415,41 +463,41 @@@ void avio_wl24(AVIOContext *s, unsigne
  
  void avio_wb24(AVIOContext *s, unsigned int val)
  {
 -    avio_wb16(s, val >> 8);
 -    avio_w8(s, val);
 +    avio_wb16(s, (int)val >> 8);
 +    avio_w8(s, (uint8_t)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 --cc libavformat/mux.c
index 76db607,49fe65c..8488043
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@@ -436,77 -249,24 +436,81 @@@ fail
      return ret;
  }
  
 -int avformat_write_header(AVFormatContext *s, AVDictionary **options)
 +static int init_pts(AVFormatContext *s)
  {
 -    int ret = 0;
 +    int i;
 +    AVStream *st;
  
 -    if (ret = init_muxer(s, options))
 -        return ret;
 +    /* init PTS generation */
 +    for (i = 0; i < s->nb_streams; i++) {
 +        int64_t den = AV_NOPTS_VALUE;
 +        st = s->streams[i];
 +
 +        switch (st->codecpar->codec_type) {
 +        case AVMEDIA_TYPE_AUDIO:
 +            den = (int64_t)st->time_base.num * st->codecpar->sample_rate;
 +            break;
 +        case AVMEDIA_TYPE_VIDEO:
 +            den = (int64_t)st->time_base.num * st->time_base.den;
 +            break;
 +        default:
 +            break;
 +        }
 +
 +        if (!st->priv_pts)
 +            st->priv_pts = av_mallocz(sizeof(*st->priv_pts));
 +        if (!st->priv_pts)
 +            return AVERROR(ENOMEM);
 +
 +        if (den != AV_NOPTS_VALUE) {
 +            if (den <= 0)
 +                return AVERROR_INVALIDDATA;
  
 +            frac_init(st->priv_pts, 0, 0, den);
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static int write_header_internal(AVFormatContext *s)
 +{
+     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);
 +        int ret = s->oformat->write_header(s);
 +        if (ret >= 0 && s->pb && s->pb->error < 0)
 +            ret = s->pb->error;
 +        s->internal->write_header_ret = ret;
          if (ret < 0)
              return ret;
 +        if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
 +            avio_flush(s->pb);
      }
 +    s->internal->header_written = 1;
+     if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+         avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
 +    return 0;
 +}
 +
 +int avformat_write_header(AVFormatContext *s, AVDictionary **options)
 +{
 +    int ret = 0;
 +
 +    if ((ret = init_muxer(s, options)) < 0)
 +        return ret;
 +
 +    if (!s->oformat->check_bitstream) {
 +        ret = write_header_internal(s);
 +        if (ret < 0)
 +            goto fail;
 +    }
  
 -    if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) {
 +    if ((ret = init_pts(s)) < 0)
 +        goto fail;
 +
 +    if (s->avoid_negative_ts < 0) {
 +        av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
          if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
              s->avoid_negative_ts = 0;
          } else
@@@ -1153,31 -706,17 +1157,34 @@@ int av_write_trailer(AVFormatContext *s
  
          if (ret < 0)
              goto fail;
 +        if(s->pb && s->pb->error)
 +            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)
 +    if (!s->internal->header_written) {
 +        ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
 +        if (ret < 0)
 +            goto fail;
 +    }
 +
 +fail:
-     if (s->internal->header_written && s->oformat->write_trailer)
++    if (s->internal->header_written && s->oformat->write_trailer) {
++        if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
++            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
 +        if (ret >= 0) {
          ret = s->oformat->write_trailer(s);
 +        } else {
 +            s->oformat->write_trailer(s);
 +        }
++    }
  
 -    if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
 -        avio_flush(s->pb);
 +    if (s->oformat->deinit)
 +        s->oformat->deinit(s);
  
 -fail:
 +    if (s->pb)
 +       avio_flush(s->pb);
 +    if (ret == 0)
 +       ret = s->pb ? s->pb->error : 0;
      for (i = 0; i < s->nb_streams; i++) {
          av_freep(&s->streams[i]->priv_data);
          av_freep(&s->streams[i]->index_entries);
diff --cc libavformat/version.h
index 0293b48,b2a1e05..543afbb
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@@ -29,11 -29,9 +29,11 @@@
  
  #include "libavutil/version.h"
  
 -#define LIBAVFORMAT_VERSION_MAJOR 57
 -#define LIBAVFORMAT_VERSION_MINOR  7
 -#define LIBAVFORMAT_VERSION_MICRO  0
 +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 +// Also please add any ticket numbers that you belive might be affected here
 +#define LIBAVFORMAT_VERSION_MAJOR  57
- #define LIBAVFORMAT_VERSION_MINOR  39
++#define LIBAVFORMAT_VERSION_MINOR  40
 +#define LIBAVFORMAT_VERSION_MICRO 100
  
  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                 LIBAVFORMAT_VERSION_MINOR, \



More information about the ffmpeg-cvslog mailing list