Merge commit 'f1f6156b3fc9eb77b439d031ba18974d80b8341e'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 1 Jul 2014 17:58:57 +0000 (19:58 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 1 Jul 2014 17:58:57 +0000 (19:58 +0200)
* commit 'f1f6156b3fc9eb77b439d031ba18974d80b8341e':
  matroska: K&R formatting cosmetics

Conflicts:
libavformat/matroskaenc.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/matroskaenc.c

@@@ -129,27 -117,23 +129,26 @@@ typedef struct MatroskaMuxContext 
   * offset, 4 bytes for target EBML ID */
  #define MAX_SEEKENTRY_SIZE 21
  
 -/** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2
 +/** per-cuepoint-track - 5 1-byte EBML IDs, 5 1-byte EBML sizes, 4
   * 8-byte uint max */
 -#define MAX_CUETRACKPOS_SIZE 22
 +#define MAX_CUETRACKPOS_SIZE 42
  
  /** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */
- #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks
+ #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE * num_tracks
  
 +/** Seek preroll value for opus */
 +#define OPUS_SEEK_PREROLL 80000000
 +
  static int ebml_id_size(unsigned int id)
  {
-     return (av_log2(id+1)-1)/7+1;
+     return (av_log2(id + 1) - 1) / 7 + 1;
  }
  
  static void put_ebml_id(AVIOContext *pb, unsigned int id)
  {
      int i = ebml_id_size(id);
      while (i--)
-         avio_w8(pb, (uint8_t)(id >> (i*8)));
 -        avio_w8(pb, id >> (i * 8));
++        avio_w8(pb, (uint8_t)(id >> (i * 8)));
  }
  
  /**
@@@ -185,18 -171,18 +185,18 @@@ static void put_ebml_num(AVIOContext *p
      int i, needed_bytes = ebml_num_size(num);
  
      // sizes larger than this are currently undefined in EBML
-     av_assert0(num < (1ULL<<56)-1);
 -    assert(num < (1ULL << 56) - 1);
++    av_assert0(num < (1ULL << 56) - 1);
  
      if (bytes == 0)
          // don't care how many bytes are used, so use the min
          bytes = needed_bytes;
      // the bytes needed to write the given size would exceed the bytes
      // that we need to use, so write unknown size. This shouldn't happen.
 -    assert(bytes >= needed_bytes);
 +    av_assert0(bytes >= needed_bytes);
  
-     num |= 1ULL << bytes*7;
+     num |= 1ULL << bytes * 7;
      for (i = bytes - 1; i >= 0; i--)
-         avio_w8(pb, (uint8_t)(num >> i*8));
 -        avio_w8(pb, num >> i * 8);
++        avio_w8(pb, (uint8_t)(num >> i * 8));
  }
  
  static void put_ebml_uint(AVIOContext *pb, unsigned int elementid, uint64_t val)
      put_ebml_id(pb, elementid);
      put_ebml_num(pb, bytes, 0);
      for (i = bytes - 1; i >= 0; i--)
-         avio_w8(pb, (uint8_t)(val >> i*8));
 -        avio_w8(pb, val >> i * 8);
++        avio_w8(pb, (uint8_t)(val >> i * 8));
 +}
 +
 +static void put_ebml_sint(AVIOContext *pb, unsigned int elementid, int64_t val)
 +{
 +    int i, bytes = 1;
 +    uint64_t tmp = 2*(val < 0 ? val^-1 : val);
 +
 +    while (tmp>>=8) bytes++;
 +
 +    put_ebml_id(pb, elementid);
 +    put_ebml_num(pb, bytes, 0);
 +    for (i = bytes - 1; i >= 0; i--)
-         avio_w8(pb, (uint8_t)(val >> i*8));
++        avio_w8(pb, (uint8_t)(val >> i * 8));
  }
  
  static void put_ebml_float(AVIOContext *pb, unsigned int elementid, double val)
@@@ -261,13 -236,15 +263,14 @@@ static void put_ebml_void(AVIOContext *
      // size we need to reserve so 2 cases, we use 8 bytes to store the
      // size if possible, 1 byte otherwise
      if (size < 10)
-         put_ebml_num(pb, size-1, 0);
+         put_ebml_num(pb, size - 1, 0);
      else
-         put_ebml_num(pb, size-9, 8);
+         put_ebml_num(pb, size - 9, 8);
 -    while (avio_tell(pb) < currentpos + size)
 -        avio_w8(pb, 0);
 +    ffio_fill(pb, 0, currentpos + size - avio_tell(pb));
  }
  
- static ebml_master start_ebml_master(AVIOContext *pb, unsigned int elementid, uint64_t expectedsize)
+ static ebml_master start_ebml_master(AVIOContext *pb, unsigned int elementid,
+                                      uint64_t expectedsize)
  {
      int bytes = expectedsize ? ebml_num_size(expectedsize) : 8;
      put_ebml_id(pb, elementid);
@@@ -595,45 -569,27 +606,45 @@@ static int mkv_write_codecprivate(AVFor
                  ret = AVERROR_INVALIDDATA;
              } else
                  avio_write(dyn_cp, codec->extradata + 12,
-                                    codec->extradata_size - 12);
+                            codec->extradata_size - 12);
 -        } else if (codec->extradata_size)
 +        } else if (codec->codec_id == AV_CODEC_ID_PRORES &&
 +                   ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == AV_CODEC_ID_PRORES) {
 +            avio_wl32(dyn_cp, codec->codec_tag);
-         }
-         else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA)
++        } else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA)
              avio_write(dyn_cp, codec->extradata, codec->extradata_size);
      } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
          if (qt_id) {
              if (!codec->codec_tag)
-                 codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id);
+                 codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags,
+                                                     codec->codec_id);
 -            if (codec->extradata_size)
 +            if (codec->extradata_size) {
 +                if (   ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == codec->codec_id
-                     && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata+4)) != codec->codec_id
++                    && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata + 4)) != codec->codec_id
 +                ) {
 +                    int i;
 +                    avio_wb32(dyn_cp, 0x5a + codec->extradata_size);
 +                    avio_wl32(dyn_cp, codec->codec_tag);
-                     for(i=0; i<0x5a-8; i++)
++                    for(i = 0; i < 0x5a - 8; i++)
 +                        avio_w8(dyn_cp, 0);
 +                }
                  avio_write(dyn_cp, codec->extradata, codec->extradata_size);
 +            }
          } else {
 +            if (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id))
 +                av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n",
 +                       avcodec_get_name(codec->codec_id));
 +
              if (!codec->codec_tag)
-                 codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id);
+                 codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags,
+                                                     codec->codec_id);
              if (!codec->codec_tag) {
 -                av_log(s, AV_LOG_ERROR, "No bmp codec ID found.\n");
 -                ret = -1;
 +                av_log(s, AV_LOG_ERROR, "No bmp codec tag found for codec %s\n",
 +                       avcodec_get_name(codec->codec_id));
 +                ret = AVERROR(EINVAL);
              }
  
 -            ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0);
 +            ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0, 0);
          }
      } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
          unsigned int tag;
          tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id);
@@@ -660,10 -616,11 +672,11 @@@ static int mkv_write_tracks(AVFormatCon
      MatroskaMuxContext *mkv = s->priv_data;
      AVIOContext *pb = s->pb;
      ebml_master tracks;
 -    int i, j, ret;
 +    int i, j, ret, default_stream_exists = 0;
  
      ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, avio_tell(pb));
-     if (ret < 0) return ret;
+     if (ret < 0)
+         return ret;
  
      tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0);
      for (i = 0; i < s->nb_streams; i++) {
          }
  
          switch (codec->codec_type) {
-             case AVMEDIA_TYPE_VIDEO:
-                 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
-                 if(   st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0
-                    && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base))
-                     put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9 / av_q2d(st->avg_frame_rate));
-                 else
-                     put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9);
-                 if (!native_id &&
-                       ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) &&
-                     (!ff_codec_get_tag(ff_codec_bmp_tags,   codec->codec_id)
-                      || codec->codec_id == AV_CODEC_ID_SVQ1
-                      || codec->codec_id == AV_CODEC_ID_SVQ3
-                      || codec->codec_id == AV_CODEC_ID_CINEPAK))
-                     qt_id = 1;
-                 if (qt_id)
-                     put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
-                 else if (!native_id) {
-                     // if there is no mkv-specific codec ID, use VFW mode
-                     put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
-                     mkv->tracks[i].write_dts = 1;
-                 }
+         case AVMEDIA_TYPE_VIDEO:
+             put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
 -            if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0)
++
++            if(   st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0
++               && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base))
+                 put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9 / av_q2d(st->avg_frame_rate));
++            else
++                put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9);
+             if (!native_id &&
+                 ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) &&
+                 (!ff_codec_get_tag(ff_codec_bmp_tags,   codec->codec_id) ||
+                  codec->codec_id == AV_CODEC_ID_SVQ1 ||
+                  codec->codec_id == AV_CODEC_ID_SVQ3 ||
+                  codec->codec_id == AV_CODEC_ID_CINEPAK))
+                 qt_id = 1;
+             if (qt_id)
+                 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
+             else if (!native_id) {
+                 // if there is no mkv-specific codec ID, use VFW mode
+                 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
+                 mkv->tracks[i].write_dts = 1;
+             }
  
-                 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
-                 // XXX: interlace flag?
-                 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
-                 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
-                 if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
-                     (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
-                     // save stereo mode flag
-                     uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;
-                     for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++)
-                         if (!strcmp(tag->value, ff_matroska_video_stereo_mode[j])){
-                             st_mode = j;
-                             break;
-                         }
-                     if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11)
-                         || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) {
-                         av_log(s, AV_LOG_ERROR,
-                                "The specified stereo mode is not valid.\n");
-                         return AVERROR(EINVAL);
-                     } else
-                         put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode);
-                     switch (st_mode) {
-                     case 1:
-                     case 8:
-                     case 9:
-                     case 11:
-                         display_width_div = 2;
-                         break;
-                     case 2:
-                     case 3:
-                     case 6:
-                     case 7:
-                         display_height_div = 2;
+             subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
+             // XXX: interlace flag?
+             put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
+             put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
 -            if ((tag = av_dict_get(s->metadata, "stereo_mode", NULL, 0))) {
 -                uint8_t stereo_fmt = atoi(tag->value);
 -                int valid_fmt = 0;
 -
 -                switch (mkv->mode) {
 -                case MODE_WEBM:
 -                    if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM ||
 -                        stereo_fmt == MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT)
 -                        valid_fmt = 1;
++
++            if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
++                (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
++                // save stereo mode flag
++                uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;
++
++                for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++)
++                    if (!strcmp(tag->value, ff_matroska_video_stereo_mode[j])){
++                        st_mode = j;
 +                        break;
 +                    }
-                 }
 +
-                 if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||
-                     (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) ||
-                     (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) {
-                     put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1);
++                if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11)
++                    || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) {
++                    av_log(s, AV_LOG_ERROR,
++                           "The specified stereo mode is not valid.\n");
++                    return AVERROR(EINVAL);
++                } else
++                    put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode);
++
++                switch (st_mode) {
++                case 1:
++                case 8:
++                case 9:
++                case 11:
++                    display_width_div = 2;
+                     break;
 -                case MODE_MATROSKAv2:
 -                    if (stereo_fmt <= MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL)
 -                        valid_fmt = 1;
++                case 2:
++                case 3:
++                case 6:
++                case 7:
++                    display_height_div = 2;
+                     break;
                  }
++            }
  
-                 if (st->sample_aspect_ratio.num) {
-                     int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
-                     if (d_width > INT_MAX) {
-                         av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
-                         return AVERROR(EINVAL);
-                     }
-                     put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div);
-                     put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
-                 } else if (display_width_div != 1 || display_height_div != 1) {
-                     put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div);
-                     put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
-                 }
 -                if (valid_fmt)
 -                    put_ebml_uint (pb, MATROSKA_ID_VIDEOSTEREOMODE, stereo_fmt);
++            if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||
++                (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) ||
++                (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) {
++                put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1);
+             }
 +
-                 if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
-                     uint32_t color_space = av_le2ne32(codec->codec_tag);
-                     put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space));
-                 }
-                 end_ebml_master(pb, subinfo);
-                 break;
-             case AVMEDIA_TYPE_AUDIO:
-                 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
-                 if (!native_id)
-                     // no mkv-specific ID, use ACM mode
-                     put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
-                 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
-                 put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , codec->channels);
-                 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
-                 if (output_sample_rate)
-                     put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
-                 if (bit_depth)
-                     put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
-                 end_ebml_master(pb, subinfo);
-                 break;
-             case AVMEDIA_TYPE_SUBTITLE:
-                 if (!native_id) {
-                     av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id);
-                     return AVERROR(ENOSYS);
+             if (st->sample_aspect_ratio.num) {
 -                int d_width = codec->width*av_q2d(st->sample_aspect_ratio);
 -                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width);
 -                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height);
 -                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3);
++                int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
++                if (d_width > INT_MAX) {
++                    av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
++                    return AVERROR(EINVAL);
 +                }
++                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div);
++                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
++            } else if (display_width_div != 1 || display_height_div != 1) {
++                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div);
++                put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
++            }
 +
-                 if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT)
-                     native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
++            if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
++                uint32_t color_space = av_le2ne32(codec->codec_tag);
++                put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space));
+             }
+             end_ebml_master(pb, subinfo);
+             break;
+         case AVMEDIA_TYPE_AUDIO:
+             put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
+             if (!native_id)
+                 // no mkv-specific ID, use ACM mode
+                 put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
+             subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
+             put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , codec->channels);
+             put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
+             if (output_sample_rate)
+                 put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
+             if (bit_depth)
+                 put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
+             end_ebml_master(pb, subinfo);
+             break;
+         case AVMEDIA_TYPE_SUBTITLE:
 -            put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE);
+             if (!native_id) {
+                 av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id);
+                 return AVERROR(ENOSYS);
+             }
 +
-                 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);
-                 break;
-             default:
-                 av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n");
-                 return AVERROR(EINVAL);
++            if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT)
++                native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
++
++            put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);
+             break;
+         default:
+             av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n");
 -            break;
++            return AVERROR(EINVAL);
 +        }
 +
 +        if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) {
 +            ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id);
-             if (ret < 0) return ret;
++            if (ret < 0)
++                return ret;
          }
 -        ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id);
 -        if (ret < 0)
 -            return ret;
  
          end_ebml_master(pb, track);
      }
@@@ -1151,38 -995,14 +1165,40 @@@ static int mkv_write_header(AVFormatCon
      AVIOContext *pb = s->pb;
      ebml_master ebml_header, segment_info;
      AVDictionaryEntry *tag;
 -    int ret, i;
 +    int ret, i, version = 2;
  
-     if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM;
-     else                                   mkv->mode = MODE_MATROSKAv2;
+     if (!strcmp(s->oformat->name, "webm"))
+         mkv->mode = MODE_WEBM;
+     else
+         mkv->mode = MODE_MATROSKAv2;
  
 -    mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks));
 +    if (s->avoid_negative_ts < 0)
 +        s->avoid_negative_ts = 1;
 +
 +    if (mkv->mode != MODE_WEBM ||
 +        av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||
 +        av_dict_get(s->metadata, "alpha_mode", NULL, 0))
 +        version = 4;
 +
 +    for (i = 0; i < s->nb_streams; i++) {
 +        if (s->streams[i]->codec->codec_id == AV_CODEC_ID_ATRAC3 ||
 +            s->streams[i]->codec->codec_id == AV_CODEC_ID_COOK ||
 +            s->streams[i]->codec->codec_id == AV_CODEC_ID_RA_288 ||
 +            s->streams[i]->codec->codec_id == AV_CODEC_ID_SIPR ||
 +            s->streams[i]->codec->codec_id == AV_CODEC_ID_RV10 ||
 +            s->streams[i]->codec->codec_id == AV_CODEC_ID_RV20) {
 +            av_log(s, AV_LOG_ERROR,
 +                   "The Matroska muxer does not yet support muxing %s\n",
 +                   avcodec_get_name(s->streams[i]->codec->codec_id));
 +            return AVERROR_PATCHWELCOME;
 +        }
 +        if (s->streams[i]->codec->codec_id == AV_CODEC_ID_OPUS ||
 +            av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||
 +            av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))
 +            version = 4;
 +    }
 +
 +    mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
      if (!mkv->tracks)
          return AVERROR(ENOMEM);
  
      end_ebml_master(pb, segment_info);
  
      ret = mkv_write_tracks(s);
-     if (ret < 0) return ret;
+     if (ret < 0)
+         return ret;
  
 +    for (i = 0; i < s->nb_chapters; i++)
 +        mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id);
 +
      if (mkv->mode != MODE_WEBM) {
          ret = mkv_write_chapters(s);
-         if (ret < 0) return ret;
+         if (ret < 0)
+             return ret;
  
          ret = mkv_write_tags(s);
-         if (ret < 0) return ret;
+         if (ret < 0)
+             return ret;
  
          ret = mkv_write_attachments(s);
-         if (ret < 0) return ret;
+         if (ret < 0)
+             return ret;
      }
  
      if (!s->pb->seekable)
@@@ -1321,47 -1129,47 +1341,51 @@@ static int ass_get_duration(const uint8
      if (sscanf(p, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d",
                 &sh, &sm, &ss, &sc, &eh, &em, &es, &ec) != 8)
          return 0;
-     start = 3600000LL*sh + 60000LL*sm + 1000LL*ss + 10LL*sc;
-     end   = 3600000LL*eh + 60000LL*em + 1000LL*es + 10LL*ec;
 -    start = 3600000 * sh + 60000 * sm + 1000 * ss + 10 * sc;
 -    end   = 3600000 * eh + 60000 * em + 1000 * es + 10 * ec;
++    start = 3600000LL * sh + 60000LL * sm + 1000LL * ss + 10LL * sc;
++    end   = 3600000LL * eh + 60000LL * em + 1000LL * es + 10LL * ec;
      return end - start;
  }
  
 -static int mkv_write_ass_blocks(AVFormatContext *s, AVIOContext *pb,
 -                                AVPacket *pkt)
 +#if FF_API_ASS_SSA
 +/* Writes the contents of pkt to a block, using the data starting at *datap.
 + * If pkt corresponds to more than one block, this writes the contents of the first block
 + * (starting from *datap) and updates *datap so it points to the beginning of the data
 + * corresponding to the next block.
 + */
- static int mkv_write_ass_block(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt, uint8_t **datap)
++static int mkv_write_ass_block(AVFormatContext *s, AVIOContext *pb,
++                               AVPacket *pkt, uint8_t **datap)
  {
      MatroskaMuxContext *mkv = s->priv_data;
 -    int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size;
 -    uint8_t *start, *end, *data = pkt->data;
 +    int i, layer = 0, size, line_size, data_size = pkt->size - (*datap - pkt->data);
 +    uint8_t *start, *end, *data = *datap;
      ebml_master blockgroup;
      char buffer[2048];
  
 -    while (data_size) {
          int duration = ass_get_duration(data);
-         end = memchr(data, '\n', data_size);
-         size = line_size = end ? end-data+1 : data_size;
-         size -= end ? (end[-1]=='\r')+1 : 0;
-         start = data;
-         for (i=0; i<3; i++, start++)
-             if (!(start = memchr(start, ',', size-(start-data))))
 -        max_duration = FFMAX(duration, max_duration);
+         end          = memchr(data, '\n', data_size);
+         size         = line_size = end ? end - data + 1 : data_size;
+         size        -= end ? (end[-1] == '\r') + 1 : 0;
+         start        = data;
+         for (i = 0; i < 3; i++, start++)
+             if (!(start = memchr(start, ',', size - (start - data))))
 -                return max_duration;
 +                return duration;
          size -= start - data;
          sscanf(data, "Dialogue: %d,", &layer);
-         i = snprintf(buffer, sizeof(buffer), "%"PRId64",%d,",
+         i = snprintf(buffer, sizeof(buffer), "%" PRId64 ",%d,",
                       s->streams[pkt->stream_index]->nb_frames, layer);
-         size = FFMIN(i+size, sizeof(buffer));
-         memcpy(buffer+i, start, size-i);
+         size = FFMIN(i + size, sizeof(buffer));
+         memcpy(buffer + i, start, size - i);
  
-         av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
+         av_log(s, AV_LOG_DEBUG,
+                "Writing block at offset %" PRIu64 ", size %d, "
                 "pts %" PRId64 ", duration %d\n",
                 avio_tell(pb), size, pkt->pts, duration);
-         blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size));
+         blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP,
+                                        mkv_blockgroup_size(size));
          put_ebml_id(pb, MATROSKA_ID_BLOCK);
-         put_ebml_num(pb, size+4, 0);
-         avio_w8(pb, 0x80 | (pkt->stream_index + 1));     // this assumes stream_index is less than 126
+         put_ebml_num(pb, size + 4, 0);
+         // this assumes stream_index is less than 126
+         avio_w8(pb, 0x80 | (pkt->stream_index + 1));
          avio_wb16(pb, pkt->pts - mkv->cluster_pts);
          avio_w8(pb, 0);
          avio_write(pb, buffer, size);
@@@ -1465,34 -1271,10 +1489,34 @@@ static void mkv_write_block(AVFormatCon
          offset = 8;
      }
  
 +    side_data = av_packet_get_side_data(pkt,
 +                                        AV_PKT_DATA_SKIP_SAMPLES,
 +                                        &side_data_size);
 +
 +    if (side_data && side_data_size >= 10) {
 +        discard_padding = av_rescale_q(AV_RL32(side_data + 4),
 +                                       (AVRational){1, codec->sample_rate},
 +                                       (AVRational){1, 1000000000});
 +    }
 +
 +    side_data = av_packet_get_side_data(pkt,
 +                                        AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
 +                                        &side_data_size);
 +    if (side_data) {
 +        additional_id = AV_RB64(side_data);
 +        side_data += 8;
 +        side_data_size -= 8;
 +    }
 +
 +    if ((side_data_size && additional_id == 1) || discard_padding) {
 +        block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0);
 +        blockid = MATROSKA_ID_BLOCK;
 +    }
 +
      put_ebml_id(pb, blockid);
-     put_ebml_num(pb, size+4, 0);
+     put_ebml_num(pb, size + 4, 0);
      // this assumes stream_index is less than 126
 -    avio_w8(pb, 0x80 | (pkt->stream_index + 1));
 +    avio_w8(pb, 0x80 | (mkv->is_dash ? mkv->dash_track_number : (pkt->stream_index + 1)));
      avio_wb16(pb, ts - mkv->cluster_pts);
      avio_w8(pb, flags);
      avio_write(pb, data + offset, size);
@@@ -1527,12 -1291,17 +1551,17 @@@ static int srt_get_duration(uint8_t **b
          if (sscanf(*buf, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d",
                     &s_hour, &s_min, &s_sec, &s_hsec,
                     &e_hour, &e_min, &e_sec, &e_hsec) == 8) {
-             s_min  +=   60*s_hour;      e_min  +=   60*e_hour;
-             s_sec  +=   60*s_min;       e_sec  +=   60*e_min;
-             s_hsec += 1000*s_sec;       e_hsec += 1000*e_sec;
+             s_min += 60 * s_hour;
+             e_min += 60 * e_hour;
+             s_sec += 60 * s_min;
+             e_sec  += 60 * e_min;
+             s_hsec += 1000 * s_sec;
+             e_hsec += 1000 * e_sec;
              duration = e_hsec - s_hsec;
          }
 -        *buf += strcspn(*buf, "\n") + 1;
 +        *buf += ff_subtitles_next_line(*buf);
      }
      return duration;
  }
@@@ -1553,44 -1323,6 +1583,44 @@@ static int mkv_write_srt_blocks(AVForma
      return duration;
  }
  
-     put_ebml_num(pb, size+4, 0);
 +static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
 +{
 +    MatroskaMuxContext *mkv = s->priv_data;
 +    ebml_master blockgroup;
 +    int id_size, settings_size, size;
 +    uint8_t *id, *settings;
 +    int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
 +    const int flags = 0;
 +
 +    id_size = 0;
 +    id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER,
 +                                 &id_size);
 +
 +    settings_size = 0;
 +    settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS,
 +                                       &settings_size);
 +
 +    size = id_size + 1 + settings_size + 1 + pkt->size;
 +
 +    av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
 +           "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n",
 +           avio_tell(pb), size, pkt->pts, pkt->dts, pkt->duration, flags);
 +
 +    blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size));
 +
 +    put_ebml_id(pb, MATROSKA_ID_BLOCK);
++    put_ebml_num(pb, size + 4, 0);
 +    avio_w8(pb, 0x80 | (pkt->stream_index + 1));     // this assumes stream_index is less than 126
 +    avio_wb16(pb, ts - mkv->cluster_pts);
 +    avio_w8(pb, flags);
 +    avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size, id, settings_size, settings, pkt->size, pkt->data);
 +
 +    put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, pkt->duration);
 +    end_ebml_master(pb, blockgroup);
 +
 +    return pkt->duration;
 +}
 +
  static void mkv_flush_dynbuf(AVFormatContext *s)
  {
      MatroskaMuxContext *mkv = s->priv_data;
      mkv->dyn_bc = NULL;
  }
  
 -static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
 +static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_cue)
  {
      MatroskaMuxContext *mkv = s->priv_data;
-     AVIOContext *pb = s->pb;
-     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
-     int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
-     int duration = pkt->duration;
+     AVIOContext *pb         = s->pb;
+     AVCodecContext *codec   = s->streams[pkt->stream_index]->codec;
+     int keyframe            = !!(pkt->flags & AV_PKT_FLAG_KEY);
+     int duration            = pkt->duration;
      int ret;
      int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
 +    int64_t relative_packet_pos;
 +    uint8_t *data_offset = pkt->data;
 +    int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1;
  
      if (ts == AV_NOPTS_VALUE) {
          av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
          pb = mkv->dyn_bc;
      }
  
 -    if (!mkv->cluster_pos) {
 +    if (mkv->cluster_pos == -1) {
          mkv->cluster_pos = avio_tell(s->pb);
-         mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
+         mkv->cluster     = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
          put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
          mkv->cluster_pts = FFMAX(0, ts);
      }
  
 +    relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos;
 +
      if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
          mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
 +        if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue) {
 +            ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1);
 +            if (ret < 0) return ret;
 +        }
 +#if FF_API_ASS_SSA
      } else if (codec->codec_id == AV_CODEC_ID_SSA) {
 -        duration = mkv_write_ass_blocks(s, pb, pkt);
 -    } else if (codec->codec_id == AV_CODEC_ID_SRT) {
 +        while (data_offset < pkt->data + pkt->size) {
 +            duration = mkv_write_ass_block(s, pb, pkt, &data_offset);
 +            ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, duration);
 +            if (ret < 0) return ret;
 +            relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos;
 +        }
 +#endif
 +    } else {
 +    if (codec->codec_id == AV_CODEC_ID_SRT) {
          duration = mkv_write_srt_blocks(s, pb, pkt);
 +    } else if (codec->codec_id == AV_CODEC_ID_WEBVTT) {
 +        duration = mkv_write_vtt_blocks(s, pb, pkt);
      } else {
-         ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size));
+         ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP,
+                                                    mkv_blockgroup_size(pkt->size));
 -        duration = pkt->convergence_duration;
 +        /* For backward compatibility, prefer convergence_duration. */
 +        if (pkt->convergence_duration > 0) {
 +            duration = pkt->convergence_duration;
 +        }
          mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 0);
          put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration);
          end_ebml_master(pb, blockgroup);
      }
  
-     ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, duration);
-     if (ret < 0) return ret;
 -    if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) {
 -        ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts,
 -                               mkv->cluster_pos);
 -        if (ret < 0)
 -            return ret;
++    ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts,
++                           mkv->cluster_pos, relative_packet_pos, duration);
++    if (ret < 0)
++        return ret;
      }
  
      mkv->duration = FFMAX(mkv->duration, ts + duration);
@@@ -1710,31 -1419,17 +1743,32 @@@ static int mkv_write_packet(AVFormatCon
          cluster_size = avio_tell(pb);
      }
  
 -    if (mkv->cluster_pos &&
 -        (cluster_size > mkv->cluster_size_limit ||
 -         cluster_time > mkv->cluster_time_limit ||
 -         (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&
 -          cluster_size > 4 * 1024))) {
 +    if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) {
 +        // WebM DASH specification states that the first block of every cluster
 +        // has to be a key frame. So for DASH video, we only create a cluster
 +        // on seeing key frames.
 +        start_new_cluster = keyframe;
 +    } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO &&
 +               cluster_time > mkv->cluster_time_limit) {
 +        // For DASH audio, we create a Cluster based on cluster_time_limit
 +        start_new_cluster = 1;
 +    } else if (!mkv->is_dash &&
 +               (cluster_size > mkv->cluster_size_limit ||
 +                cluster_time > mkv->cluster_time_limit ||
 +                (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&
 +                 cluster_size > 4 * 1024))) {
 +        start_new_cluster = 1;
 +    } else {
 +        start_new_cluster = 0;
 +    }
 +
 +    if (mkv->cluster_pos != -1 && start_new_cluster) {
-         av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
-                " bytes, pts %" PRIu64 "dts %" PRIu64 "\n",
+         av_log(s, AV_LOG_DEBUG,
+                "Starting new cluster at offset %" PRIu64 " bytes, "
+                "pts %" PRIu64 "dts %" PRIu64 "\n",
                 avio_tell(pb), pkt->pts, pkt->dts);
          end_ebml_master(pb, mkv->cluster);
 -        mkv->cluster_pos = 0;
 +        mkv->cluster_pos = -1;
          if (mkv->dyn_bc)
              mkv_flush_dynbuf(s);
          avio_flush(s->pb);
  
      // check if we have an audio packet cached
      if (mkv->cur_audio_pkt.size > 0) {
 -        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
 +        // for DASH audio, a CuePoint has to be added when there is a new cluster.
 +        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt,
 +                                        mkv->is_dash ? start_new_cluster : 0);
          av_free_packet(&mkv->cur_audio_pkt);
          if (ret < 0) {
-             av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
+             av_log(s, AV_LOG_ERROR,
+                    "Could not write cached audio packet ret:%d\n", ret);
              return ret;
          }
      }
@@@ -1778,11 -1469,12 +1813,12 @@@ static int mkv_write_flush_packet(AVFor
      else
          pb = mkv->dyn_bc;
      if (!pkt) {
 -        if (mkv->cluster_pos) {
 +        if (mkv->cluster_pos != -1) {
-             av_log(s, AV_LOG_DEBUG, "Flushing cluster at offset %" PRIu64
-                    " bytes\n", avio_tell(pb));
+             av_log(s, AV_LOG_DEBUG,
+                    "Flushing cluster at offset %" PRIu64 " bytes\n",
+                    avio_tell(pb));
              end_ebml_master(pb, mkv->cluster);
 -            mkv->cluster_pos = 0;
 +            mkv->cluster_pos = -1;
              if (mkv->dyn_bc)
                  mkv_flush_dynbuf(s);
              avio_flush(s->pb);
@@@ -1801,10 -1493,11 +1837,11 @@@ static int mkv_write_trailer(AVFormatCo
  
      // check if we have an audio packet cached
      if (mkv->cur_audio_pkt.size > 0) {
 -        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
 +        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt, 0);
          av_free_packet(&mkv->cur_audio_pkt);
          if (ret < 0) {
-             av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
+             av_log(s, AV_LOG_ERROR,
+                    "Could not write cached audio packet ret:%d\n", ret);
              return ret;
          }
      }
                  currentpos = avio_tell(pb);
                  avio_seek(pb, mkv->cues_pos, SEEK_SET);
  
-                 cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams);
 -                cuespos  = mkv_write_cues(pb, mkv->cues, s->nb_streams);
++                cuespos  = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams);
                  cues_end = avio_tell(pb);
                  if (cues_end > cuespos + mkv->reserve_cues_space) {
-                     av_log(s, AV_LOG_ERROR, "Insufficient space reserved for cues: %d "
-                            "(needed: %"PRId64").\n", mkv->reserve_cues_space,
-                            cues_end - cuespos);
+                     av_log(s, AV_LOG_ERROR,
+                            "Insufficient space reserved for cues: %d "
+                            "(needed: %" PRId64 ").\n",
+                            mkv->reserve_cues_space, cues_end - cuespos);
                      return AVERROR(EINVAL);
                  }
  
  
                  avio_seek(pb, currentpos, SEEK_SET);
              } else {
 -                cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
 +                cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams);
              }
  
-             ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos);
-             if (ret < 0) return ret;
+             ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES,
+                                          cuespos);
+             if (ret < 0)
+                 return ret;
          }
  
          mkv_write_seekhead(pb, mkv->main_seekhead);