Merge commit 'e839de0f851535b5e19256b52f9865f0cb768a7c'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Nov 2014 13:09:35 +0000 (14:09 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Nov 2014 13:09:53 +0000 (14:09 +0100)
* commit 'e839de0f851535b5e19256b52f9865f0cb768a7c':
  oggenc: accept only STREAMINFO extradata

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

diff --combined libavformat/oggenc.c
@@@ -2,20 -2,20 +2,20 @@@
   * Ogg muxer
   * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -77,8 -77,6 +77,8 @@@ typedef struct 
  #define PARAM AV_OPT_FLAG_ENCODING_PARAM
  
  static const AVOption options[] = {
 +    { "oggpagesize", "Set preferred Ogg page size.",
 +      offsetof(OGGContext, pref_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, MAX_PAGE_SIZE, AV_OPT_FLAG_ENCODING_PARAM},
      { "pagesize", "preferred page size in bytes (deprecated)",
          OFFSET(pref_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_PAGE_SIZE, PARAM },
      { "page_duration", "preferred page duration, in microseconds",
@@@ -86,9 -84,9 +86,9 @@@
      { NULL },
  };
  
 -#define OGG_CLASS(flavor)\
 +#define OGG_CLASS(flavor, name)\
  static const AVClass flavor ## _muxer_class = {\
 -    .class_name = #flavor " muxer",\
 +    .class_name = #name " muxer",\
      .item_name  = av_default_item_name,\
      .option     = options,\
      .version    = LIBAVUTIL_VERSION_INT,\
@@@ -141,11 -139,6 +141,11 @@@ static int ogg_write_page(AVFormatConte
      return 0;
  }
  
 +static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule)
 +{
 +    return oggstream->kfgshift && !(granule & ((1<<oggstream->kfgshift)-1));
 +}
 +
  static int64_t ogg_granule_to_timestamp(OGGStreamContext *oggstream, int64_t granule)
  {
      if (oggstream->kfgshift)
@@@ -216,14 -209,9 +216,14 @@@ static int ogg_buffer_data(AVFormatCont
      int i, segments, len, flush = 0;
  
      // Handles VFR by flushing page because this frame needs to have a timestamp
 +    // For theora, keyframes also need to have a timestamp to correctly mark
 +    // them as such, otherwise seeking will not work correctly at the very
 +    // least with old libogg versions.
 +    // Do not try to flush header packets though, that will create broken files.
      if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header &&
 -        ogg_granule_to_timestamp(oggstream, granule) >
 -        ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1) {
 +        (ogg_granule_to_timestamp(oggstream, granule) >
 +         ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1 ||
 +         ogg_key_granule(oggstream, granule))) {
          if (oggstream->page.granule != -1)
              ogg_buffer_page(s, oggstream);
          flush = 1;
  static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact,
                                          int *header_len, AVDictionary **m, int framing_bit)
  {
 -    const char *vendor = bitexact ? "Libav" : LIBAVFORMAT_IDENT;
 +    const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
      int size;
      uint8_t *p, *p0;
  
@@@ -307,12 -295,10 +307,10 @@@ static int ogg_build_flac_headers(AVCod
                                    OGGStreamContext *oggstream, int bitexact,
                                    AVDictionary **m)
  {
-     enum FLACExtradataFormat format;
-     uint8_t *streaminfo;
      uint8_t *p;
  
-     if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo))
-         return -1;
+     if (avctx->extradata_size < FLAC_STREAMINFO_SIZE)
+         return AVERROR(EINVAL);
  
      // first packet: STREAMINFO
      oggstream->header_len[0] = 51;
      bytestream_put_buffer(&p, "fLaC", 4);
      bytestream_put_byte(&p, 0x00); // streaminfo
      bytestream_put_be24(&p, 34);
-     bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE);
+     bytestream_put_buffer(&p, avctx->extradata, FLAC_STREAMINFO_SIZE);
  
      // second packet: VorbisComment
      p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0);
@@@ -424,7 -410,7 +422,7 @@@ static void ogg_write_pages(AVFormatCon
  static int ogg_write_header(AVFormatContext *s)
  {
      OGGContext *ogg = s->priv_data;
 -    OGGStreamContext *oggstream;
 +    OGGStreamContext *oggstream = NULL;
      int i, j;
  
      if (ogg->pref_size)
          AVStream *st = s->streams[i];
          unsigned serial_num = i;
  
 -        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 +        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
              if (st->codec->codec_id == AV_CODEC_ID_OPUS)
                  /* Opus requires a fixed 48kHz clock */
                  avpriv_set_pts_info(st, 64, 1, 48000);
              else
                  avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
 +        }
  
          if (st->codec->codec_id != AV_CODEC_ID_VORBIS &&
              st->codec->codec_id != AV_CODEC_ID_THEORA &&
              return -1;
          }
          oggstream = av_mallocz(sizeof(*oggstream));
 +        if (!oggstream)
 +            return AVERROR(ENOMEM);
 +
          oggstream->page.stream_index = i;
  
          if (!(s->flags & AVFMT_FLAG_BITEXACT))
              } while (j < i);
          oggstream->serial_num = serial_num;
  
 +        av_dict_copy(&st->metadata, s->metadata, AV_DICT_DONT_OVERWRITE);
 +
          st->priv_data = oggstream;
          if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
              int err = ogg_build_flac_headers(st->codec, oggstream,
                                               s->flags & AVFMT_FLAG_BITEXACT,
 -                                             &s->metadata);
 +                                             &st->metadata);
              if (err) {
                  av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
                  av_freep(&st->priv_data);
          } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
              int err = ogg_build_speex_headers(st->codec, oggstream,
                                                s->flags & AVFMT_FLAG_BITEXACT,
 -                                              &s->metadata);
 +                                              &st->metadata);
              if (err) {
                  av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
                  av_freep(&st->priv_data);
          } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
              int err = ogg_build_opus_headers(st->codec, oggstream,
                                               s->flags & AVFMT_FLAG_BITEXACT,
 -                                             &s->metadata);
 +                                             &st->metadata);
              if (err) {
                  av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
                  av_freep(&st->priv_data);
              }
  
              p = ogg_write_vorbiscomment(7, s->flags & AVFMT_FLAG_BITEXACT,
 -                                        &oggstream->header_len[1], &s->metadata,
 +                                        &oggstream->header_len[1], &st->metadata,
                                          framing_bit);
              oggstream->header[1] = p;
              if (!p)
@@@ -640,7 -620,7 +638,7 @@@ static int ogg_write_trailer(AVFormatCo
          if (st->codec->codec_id == AV_CODEC_ID_FLAC ||
              st->codec->codec_id == AV_CODEC_ID_SPEEX ||
              st->codec->codec_id == AV_CODEC_ID_OPUS) {
 -            av_free(oggstream->header[0]);
 +            av_freep(&oggstream->header[0]);
          }
          av_freep(&oggstream->header[1]);
          av_freep(&st->priv_data);
  }
  
  #if CONFIG_OGG_MUXER
 -OGG_CLASS(ogg)
 +OGG_CLASS(ogg, Ogg)
  AVOutputFormat ff_ogg_muxer = {
      .name              = "ogg",
      .long_name         = NULL_IF_CONFIG_SMALL("Ogg"),
      .mime_type         = "application/ogg",
 -    .extensions        = "ogg,ogv",
 +    .extensions        = "ogg,ogv"
 +#if !CONFIG_SPX_MUXER
 +                         ",spx"
 +#endif
 +#if !CONFIG_OPUS_MUXER
 +                         ",opus"
 +#endif
 +                         ,
      .priv_data_size    = sizeof(OGGContext),
      .audio_codec       = CONFIG_LIBVORBIS_ENCODER ?
                           AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC,
  #endif
  
  #if CONFIG_OGA_MUXER
 -OGG_CLASS(oga)
 +OGG_CLASS(oga, Ogg audio)
  AVOutputFormat ff_oga_muxer = {
      .name              = "oga",
      .long_name         = NULL_IF_CONFIG_SMALL("Ogg Audio"),
  #endif
  
  #if CONFIG_SPX_MUXER
 -OGG_CLASS(spx)
 +OGG_CLASS(spx, Ogg Speex)
  AVOutputFormat ff_spx_muxer = {
      .name              = "spx",
      .long_name         = NULL_IF_CONFIG_SMALL("Ogg Speex"),
  #endif
  
  #if CONFIG_OPUS_MUXER
 -OGG_CLASS(opus)
 +OGG_CLASS(opus, Ogg Opus)
  AVOutputFormat ff_opus_muxer = {
      .name              = "opus",
      .long_name         = NULL_IF_CONFIG_SMALL("Ogg Opus"),