Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 1 Mar 2012 00:13:16 +0000 (01:13 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 1 Mar 2012 02:17:11 +0000 (03:17 +0100)
* qatar/master: (58 commits)
  amrnbdec: check frame size before decoding.
  cscd: use negative error values to indicate decode_init() failures.
  h264: prevent overreads in intra PCM decoding.
  FATE: do not decode audio in the nuv test.
  dxa: set audio stream time base using the sample rate
  psx-str: do not allow seeking by bytes
  asfdec: Do not set AVCodecContext.frame_size
  vqf: set packet parameters after av_new_packet()
  mpegaudiodec: use DSPUtil.butterflies_float().
  FATE: add mp3 test for sample that exhibited false overreads
  fate: add cdxl test for bit line plane arrangement
  vmnc: return error on decode_init() failure.
  libvorbis: add/update error messages
  libvorbis: use AVFifoBuffer for output packet buffer
  libvorbis: remove unneeded e_o_s check
  libvorbis: check return values for functions that can return errors
  libvorbis: use float input instead of s16
  libvorbis: do not flush libvorbis analysis if dsp state was not initialized
  libvorbis: use VBR by default, with default quality of 3
  libvorbis: fix use of minrate/maxrate AVOptions
  ...

Conflicts:
Changelog
doc/APIchanges
libavcodec/avcodec.h
libavcodec/dpxenc.c
libavcodec/libvorbis.c
libavcodec/vmnc.c
libavformat/asfdec.c
libavformat/id3v2enc.c
libavformat/internal.h
libavformat/mp3enc.c
libavformat/utils.c
libavformat/version.h
libswscale/utils.c
tests/fate/video.mak
tests/ref/fate/nuv
tests/ref/fate/prores-alpha
tests/ref/lavf/ffm
tests/ref/vsynth1/prores
tests/ref/vsynth2/prores

Merged-by: Michael Niedermayer <michaelni@gmx.at>
59 files changed:
1  2 
Changelog
doc/APIchanges
doc/muxers.texi
libavcodec/aacdec.c
libavcodec/ac3enc.c
libavcodec/ac3enc_fixed.c
libavcodec/ac3enc_float.c
libavcodec/amrnbdec.c
libavcodec/avcodec.h
libavcodec/cscd.c
libavcodec/dpxenc.c
libavcodec/flvenc.c
libavcodec/h261enc.c
libavcodec/h263.h
libavcodec/h264_cabac.c
libavcodec/libvorbis.c
libavcodec/mpeg12enc.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegaudiodec.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/options.c
libavcodec/proresdec_lgpl.c
libavcodec/proresenc_kostya.c
libavcodec/qtrle.c
libavcodec/rpza.c
libavcodec/rv10enc.c
libavcodec/rv20enc.c
libavcodec/version.h
libavcodec/vmnc.c
libavcodec/vp5.c
libavcodec/vp6.c
libavformat/asfdec.c
libavformat/avformat.h
libavformat/dxa.c
libavformat/ffmdec.c
libavformat/ffmenc.c
libavformat/id3v2.c
libavformat/id3v2.h
libavformat/id3v2enc.c
libavformat/internal.h
libavformat/matroska.h
libavformat/mov.c
libavformat/mp3enc.c
libavformat/omadec.c
libavformat/psxstr.c
libavformat/rtpenc.c
libavformat/swfdec.c
libavformat/utils.c
libavformat/version.h
libavformat/vqf.c
libswscale/utils.c
tests/codec-regression.sh
tests/fate/video.mak
tests/ref/fate/cdxl-bitline-ham6
tests/ref/fate/nuv
tests/ref/lavf/ffm
tests/ref/vsynth1/prores_kostya
tests/ref/vsynth2/prores_kostya

diff --cc Changelog
+++ b/Changelog
@@@ -1,61 -1,39 +1,62 @@@
  Entries are sorted chronologically from oldest to youngest within each release,
  releases are sorted from youngest to oldest.
  
 -version <next>:
 -
 -- XWD encoder and decoder
 -- Support for fragmentation in the mov/mp4 muxer
 -- ISMV (Smooth Streaming) muxer
 +version next:
 +- v408 Quicktime and Microsoft AYUV Uncompressed 4:4:4:4 encoder and decoder
 +- setfield filter
  - CDXL demuxer and decoder
  - Apple ProRes encoder
 +- ffprobe -count_packets and -count_frames options
  - Sun Rasterfile Encoder
 -- remove libpostproc
+ - ID3v2 attached pictures reading and writing
  
  
 -version 0.8:
 -
 +version 0.10:
 +- Fixes: CVE-2011-3929, CVE-2011-3934, CVE-2011-3935, CVE-2011-3936,
 +         CVE-2011-3937, CVE-2011-3940, CVE-2011-3941, CVE-2011-3944,
 +         CVE-2011-3945, CVE-2011-3946, CVE-2011-3947, CVE-2011-3949,
 +         CVE-2011-3950, CVE-2011-3951, CVE-2011-3952
 +- v410 Quicktime Uncompressed 4:4:4 10-bit encoder and decoder
 +- SBaGen (SBG) binaural beats script demuxer
 +- OpenMG Audio muxer
 +- Timecode extraction in DV and MOV
 +- thumbnail video filter
 +- XML output in ffprobe
 +- asplit audio filter
 +- tinterlace video filter
 +- astreamsync audio filter
 +- amerge audio filter
 +- ISMV (Smooth Streaming) muxer
  - GSM audio parser
  - SMJPEG muxer
 -
 -
 -version 0.8_beta2:
 -
 +- XWD encoder and decoder
  - Automatic thread count based on detection number of (available) CPU cores
 -- Deprecate libpostproc. If desired, the switch --enable-postproc will
 -  enable it but it may be removed in a later Libav release.
 +- y41p Brooktree Uncompressed 4:1:1 12-bit encoder and decoder
 +- ffprobe -show_error option
 +- Avid 1:1 10-bit RGB Packer codec
 +- v308 Quicktime Uncompressed 4:4:4 encoder and decoder
 +- yuv4 libquicktime packed 4:2:0 encoder and decoder
 +- ffprobe -show_frames option
 +- silencedetect audio filter
 +- ffprobe -show_program_version, -show_library_versions, -show_versions options
  - rv34: frame-level multi-threading
  - optimized iMDCT transform on x86 using SSE for for mpegaudiodec
 +- Improved PGS subtitle decoder
 +- dumpgraph option to lavfi device
 +- r210 and r10k encoders
 +- ffwavesynth decoder
 +- aviocat tool
 +- ffeval tool
  
  
 -version 0.8_beta1:
 +version 0.9:
  
 +- openal input device added
 +- boxblur filter added
  - BWF muxer
  - Flash Screen Video 2 decoder
 -- ffplay/ffprobe/ffserver renamed to avplay/avprobe/avserver
 -- ffmpeg deprecated, added avconv, which is almost the same for now, except
 +- lavfi input device added
 +- added avconv, which is almost the same for now, except
  for a few incompatible changes in the options, which will hopefully make them
  easier to use. The changes are:
      * The options placement is now strictly enforced! While in theory the
diff --cc doc/APIchanges
@@@ -13,28 -12,10 +13,36 @@@ libavutil:   2011-04-1
  
  API changes, most recent first:
  
++<<<<<<< HEAD
 +2012-02-21 - xxxxxxx - lavc 54.4.100
 +  Add av_get_pcm_codec() function.
 +
 +2012-02-16 - xxxxxxx - libswr 0.7.100
 +  Add swr_set_matrix() function.
 +
 +2012-02-09 - xxxxxxx - lavu 51.39.100
 +  Add a new installed header libavutil/timestamp.h with timestamp
 +  utilities.
 +
 +2012-02-06 - xxxxxxx - lavu 51.38.100
 +  Add av_parse_ratio() function to parseutils.h.
 +
 +2012-02-06 - xxxxxxx - lavu 51.38.100
 +  Add AV_LOG_MAX_OFFSET macro to log.h.
 +
 +2012-02-02 - xxxxxxx - lavu 51.37.100
 +  Add public timecode helpers.
 +
 +2012-01-24 - xxxxxxx - lavfi 2.60.100
 +  Add avfilter_graph_dump.
 +
++||||||| merged common ancestors
++=======
+ 2012-xx-xx - xxxxxxx - lavf 54.2.0 - avformat.h
+   Add AVStream.attached_pic and AV_DISPOSITION_ATTACHED_PIC,
+   used for dealing with attached pictures/cover art.
++>>>>>>> qatar/master
  2012-02-25 - c9bca80 - lavu 51.24.0 - error.h
    Add AVERROR_UNKNOWN
  
diff --cc doc/muxers.texi
@@@ -367,8 -358,42 +367,42 @@@ Wrap around segment index once it reach
  @end table
  
  @example
 -avconv -i in.mkv -c copy -map 0 -f segment -list out.list out%03d.nut
 +ffmpeg -i in.mkv -c copy -map 0 -f segment -list out.list out%03d.nut
  @end example
  
 -avconv -i INPUT -id3v2_version 3 -write_id3v1 1 out.mp3
+ @section mp3
+ The MP3 muxer writes a raw MP3 stream with an ID3v2 header at the beginning and
+ optionally an ID3v1 tag at the end. ID3v2.3 and ID3v2.4 are supported, the
+ @code{id3v2_version} option controls which one is used. The legacy ID3v1 tag is
+ not written by default, but may be enabled with the @code{write_id3v1} option.
+ For seekable output the muxer also writes a Xing frame at the beginning, which
+ contains the number of frames in the file. It is useful for computing duration
+ of VBR files.
+ The muxer supports writing ID3v2 attached pictures (APIC frames). The pictures
+ are supplied to the muxer in form of a video stream with a single packet. There
+ can be any number of those streams, each will correspond to a single APIC frame.
+ The stream metadata tags @var{title} and @var{comment} map to APIC
+ @var{description} and @var{picture type} respectively. See
+ @url{http://id3.org/id3v2.4.0-frames} for allowed picture types.
+ Note that the APIC frames must be written at the beginning, so the muxer will
+ buffer the audio frames until it gets all the pictures. It is therefore advised
+ to provide the pictures as soon as possible to avoid excessive buffering.
+ Examples:
+ Write an mp3 with an ID3v2.3 header and an ID3v1 footer:
+ @example
 -avconv -i input.mp3 -i cover.png -c copy -metadata:s:v title="Album cover"
++ffmpeg -i INPUT -id3v2_version 3 -write_id3v1 1 out.mp3
+ @end example
+ Attach a picture to an mp3:
+ @example
++ffmpeg -i input.mp3 -i cover.png -c copy -metadata:s:v title="Album cover"
+ -metadata:s:v comment="Cover (Front)" out.mp3
+ @end example
  
  @c man end MUXERS
@@@ -437,24 -388,91 +388,108 @@@ static av_cold int output_configure(AAC
      return 0;
  }
  
 +static void flush(AVCodecContext *avctx)
 +{
 +    AACContext *ac= avctx->priv_data;
 +    int type, i, j;
 +
 +    for (type = 3; type >= 0; type--) {
 +        for (i = 0; i < MAX_ELEM_ID; i++) {
 +            ChannelElement *che = ac->che[type][i];
 +            if (che) {
 +                for (j = 0; j <= 1; j++) {
 +                    memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
 +                }
 +            }
 +        }
 +    }
 +}
 +
  /**
+  * Set up channel positions based on a default channel configuration
+  * as specified in table 1.17.
+  *
+  * @return  Returns error status. 0 - OK, !0 - error
+  */
+ static av_cold int set_default_channel_config(AVCodecContext *avctx,
+                                               uint8_t (*layout_map)[3],
+                                               int *tags,
+                                               int channel_config)
+ {
+     if (channel_config < 1 || channel_config > 7) {
+         av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n",
+                channel_config);
+         return -1;
+     }
+     *tags = tags_per_config[channel_config];
+     memcpy(layout_map, aac_channel_layout_map[channel_config-1], *tags * sizeof(*layout_map));
+     return 0;
+ }
+ static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
+ {
+     // For PCE based channel configurations map the channels solely based on tags.
+     if (!ac->m4ac.chan_config) {
+         return ac->tag_che_map[type][elem_id];
+     }
+     // Allow single CPE stereo files to be signalled with mono configuration.
+     if (!ac->tags_mapped && type == TYPE_CPE && ac->m4ac.chan_config == 1) {
+         uint8_t layout_map[MAX_ELEM_ID*4][3];
+         int layout_map_tags;
+         if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags,
+                                        2) < 0)
+             return NULL;
+         if (output_configure(ac, layout_map, layout_map_tags,
+                              2, OC_TRIAL_FRAME) < 0)
+             return NULL;
+         ac->m4ac.chan_config = 2;
+     }
+     // For indexed channel configurations map the channels solely based on position.
+     switch (ac->m4ac.chan_config) {
+     case 7:
+         if (ac->tags_mapped == 3 && type == TYPE_CPE) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
+         }
+     case 6:
+         /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1]
+            instead of SCE[0] CPE[0] CPE[1] LFE[0]. If we seem to have
+            encountered such a stream, transfer the LFE[0] element to the SCE[1]'s mapping */
+         if (ac->tags_mapped == tags_per_config[ac->m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
+         }
+     case 5:
+         if (ac->tags_mapped == 2 && type == TYPE_CPE) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
+         }
+     case 4:
+         if (ac->tags_mapped == 2 && ac->m4ac.chan_config == 4 && type == TYPE_SCE) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+         }
+     case 3:
+     case 2:
+         if (ac->tags_mapped == (ac->m4ac.chan_config != 2) && type == TYPE_CPE) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
+         } else if (ac->m4ac.chan_config == 2) {
+             return NULL;
+         }
+     case 1:
+         if (!ac->tags_mapped && type == TYPE_SCE) {
+             ac->tags_mapped++;
+             return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
+         }
+     default:
+         return NULL;
+     }
+ }
+ /**
   * Decode an array of 4 bit element IDs, optionally interleaved with a stereo/mono switching bit.
   *
   * @param type speaker type/position for these channels
Simple merge
Simple merge
Simple merge
@@@ -947,9 -951,12 +951,13 @@@ static int amrnb_decode_frame(AVCodecCo
      buf_out = (float *)p->avframe.data[0];
  
      p->cur_frame_mode = unpack_bitstream(p, buf, buf_size);
+     if (p->cur_frame_mode == NO_DATA) {
+         av_log(avctx, AV_LOG_ERROR, "Corrupt bitstream\n");
+         return AVERROR_INVALIDDATA;
+     }
      if (p->cur_frame_mode == MODE_DTX) {
 -        av_log_missing_feature(avctx, "dtx mode", 1);
 +        av_log_missing_feature(avctx, "dtx mode", 0);
 +        av_log(avctx, AV_LOG_INFO, "Note: libopencore_amrnb supports dtx\n");
          return -1;
      }
  
@@@ -588,13 -565,15 +586,17 @@@ typedef struct RcOverride
  #define CODEC_FLAG_INTERLACED_ME  0x20000000 ///< interlaced motion estimation
  #define CODEC_FLAG_CLOSED_GOP     0x80000000
  #define CODEC_FLAG2_FAST          0x00000001 ///< Allow non spec compliant speedup tricks.
- #define CODEC_FLAG2_STRICT_GOP    0x00000002 ///< Strictly enforce GOP size.
  #define CODEC_FLAG2_NO_OUTPUT     0x00000004 ///< Skip bitstream encoding.
  #define CODEC_FLAG2_LOCAL_HEADER  0x00000008 ///< Place global headers at every keyframe instead of in extradata.
 +#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. DEPRECATED!!!!
+ #if FF_API_MPV_GLOBAL_OPTS
+ #define CODEC_FLAG_CBP_RD         0x04000000 ///< Use rate distortion optimization for cbp.
+ #define CODEC_FLAG_QP_RD          0x08000000 ///< Use rate distortion optimization for qp selectioon.
+ #define CODEC_FLAG2_STRICT_GOP    0x00000002 ///< Strictly enforce GOP size.
  #define CODEC_FLAG2_SKIP_RD       0x00004000 ///< RD optimal MB level residual skipping
+ #endif
  #define CODEC_FLAG2_CHUNKS        0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries.
 +#define CODEC_FLAG2_SHOW_ALL      0x00400000 ///< Show all frames before the first keyframe
  
  /* Unsupported options :
   *              Syntax Arithmetic coding (SAC)
@@@ -228,10 -228,9 +228,10 @@@ static av_cold int decode_init(AVCodecC
              av_log(avctx, AV_LOG_ERROR,
                     "CamStudio codec error: invalid depth %i bpp\n",
                     avctx->bits_per_coded_sample);
-             return 1;
+             return AVERROR_INVALIDDATA;
      }
      c->bpp = avctx->bits_per_coded_sample;
 +    avcodec_get_frame_defaults(&c->pic);
      c->pic.data[0] = NULL;
      c->linelen = avctx->width * avctx->bits_per_coded_sample / 8;
      c->height = avctx->height;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -101,46 -118,18 +118,47 @@@ static av_cold int oggvorbis_init_encod
      }
  
      /* cutoff frequency */
-     if (avccontext->cutoff > 0) {
-         cfreq = avccontext->cutoff / 1000.0;
+     if (avctx->cutoff > 0) {
+         cfreq = avctx->cutoff / 1000.0;
          if ((ret = vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq)))
 -            goto error;
 +            goto error; /* should not happen */
      }
  
-     if (context->iblock) {
-         if ((ret = vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &context->iblock)))
+     /* impulse block bias */
+     if (s->iblock) {
+         if ((ret = vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &s->iblock)))
              goto error;
      }
  
-     if (avccontext->channels == 3 &&
-             avccontext->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) ||
-         avccontext->channels == 4 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_2_2 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_QUAD ||
-         avccontext->channels == 5 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_5POINT0 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_5POINT0_BACK ||
-         avccontext->channels == 6 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_5POINT1 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_5POINT1_BACK ||
-         avccontext->channels == 7 &&
-             avccontext->channel_layout != (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) ||
-         avccontext->channels == 8 &&
-             avccontext->channel_layout != AV_CH_LAYOUT_7POINT1) {
-         if (avccontext->channel_layout) {
++    if (avctx->channels == 3 &&
++            avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) ||
++        avctx->channels == 4 &&
++            avctx->channel_layout != AV_CH_LAYOUT_2_2 &&
++            avctx->channel_layout != AV_CH_LAYOUT_QUAD ||
++        avctx->channels == 5 &&
++            avctx->channel_layout != AV_CH_LAYOUT_5POINT0 &&
++            avctx->channel_layout != AV_CH_LAYOUT_5POINT0_BACK ||
++        avctx->channels == 6 &&
++            avctx->channel_layout != AV_CH_LAYOUT_5POINT1 &&
++            avctx->channel_layout != AV_CH_LAYOUT_5POINT1_BACK ||
++        avctx->channels == 7 &&
++            avctx->channel_layout != (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) ||
++        avctx->channels == 8 &&
++            avctx->channel_layout != AV_CH_LAYOUT_7POINT1) {
++        if (avctx->channel_layout) {
 +            char name[32];
-             av_get_channel_layout_string(name, sizeof(name), avccontext->channels,
-                                          avccontext->channel_layout);
-             av_log(avccontext, AV_LOG_ERROR, "%s not supported by Vorbis: "
++            av_get_channel_layout_string(name, sizeof(name), avctx->channels,
++                                         avctx->channel_layout);
++            av_log(avctx, AV_LOG_ERROR, "%s not supported by Vorbis: "
 +                                             "output stream will have incorrect "
 +                                             "channel layout.\n", name);
 +        } else {
-             av_log(avccontext, AV_LOG_WARNING, "No channel layout specified. The encoder "
++            av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The encoder "
 +                                               "will use Vorbis channel layout for "
-                                                "%d channels.\n", avccontext->channels);
++                                               "%d channels.\n", avctx->channels);
 +        }
 +    }
 +
      if ((ret = vorbis_encode_setup_init(vi)))
          goto error;
  
@@@ -245,77 -240,83 +269,83 @@@ error
      return ret;
  }
  
- static int oggvorbis_encode_frame(AVCodecContext *avccontext,
-                                   unsigned char *packets,
+ static int oggvorbis_encode_frame(AVCodecContext *avctx, unsigned char *packets,
                                    int buf_size, void *data)
  {
-     OggVorbisContext *context = avccontext->priv_data;
+     OggVorbisContext *s = avctx->priv_data;
      ogg_packet op;
-     signed short *audio = data;
-     int l;
+     float *audio = data;
+     int pkt_size, ret;
  
+     /* send samples to libvorbis */
      if (data) {
-         const int samples = avccontext->frame_size;
+         const int samples = avctx->frame_size;
          float **buffer;
-         int c, channels = context->vi.channels;
+         int c, channels = s->vi.channels;
  
-         buffer = vorbis_analysis_buffer(&context->vd, samples);
+         buffer = vorbis_analysis_buffer(&s->vd, samples);
          for (c = 0; c < channels; c++) {
+             int i;
              int co = (channels > 8) ? c :
                       ff_vorbis_encoding_channel_layout_offsets[channels - 1][c];
-             for (l = 0; l < samples; l++)
-                 buffer[c][l] = audio[l * channels + co] / 32768.f;
+             for (i = 0; i < samples; i++)
+                 buffer[c][i] = audio[i * channels + co];
+         }
+         if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) {
+             av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n");
+             return vorbis_error_to_averror(ret);
          }
-         vorbis_analysis_wrote(&context->vd, samples);
      } else {
-         if (!context->eof)
-             vorbis_analysis_wrote(&context->vd, 0);
-         context->eof = 1;
+         if (!s->eof)
+             if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) {
+                 av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n");
+                 return vorbis_error_to_averror(ret);
+             }
+         s->eof = 1;
      }
  
-     while (vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
-         vorbis_analysis(&context->vb, NULL);
-         vorbis_bitrate_addblock(&context->vb);
-         while (vorbis_bitrate_flushpacket(&context->vd, &op)) {
-             /* i'd love to say the following line is a hack, but sadly it's
-              * not, apparently the end of stream decision is in libogg. */
-             if (op.bytes == 1 && op.e_o_s)
-                 continue;
-             if (context->buffer_index + sizeof(ogg_packet) + op.bytes > BUFFER_SIZE) {
-                 av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow.\n");
-                 return AVERROR(EINVAL);
+     /* retrieve available packets from libvorbis */
+     while ((ret = vorbis_analysis_blockout(&s->vd, &s->vb)) == 1) {
+         if ((ret = vorbis_analysis(&s->vb, NULL)) < 0)
+             break;
+         if ((ret = vorbis_bitrate_addblock(&s->vb)) < 0)
+             break;
+         /* add any available packets to the output packet buffer */
+         while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) {
+             if (av_fifo_space(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) {
 -                av_log(avctx, AV_LOG_ERROR, "packet buffer is too small");
++                av_log(avctx, AV_LOG_ERROR, "packet buffer is too small\n");
+                 return AVERROR_BUG;
              }
-             memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
-             context->buffer_index += sizeof(ogg_packet);
-             memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
-             context->buffer_index += op.bytes;
- //            av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
+             av_fifo_generic_write(s->pkt_fifo, &op, sizeof(ogg_packet), NULL);
+             av_fifo_generic_write(s->pkt_fifo, op.packet, op.bytes, NULL);
+         }
+         if (ret < 0) {
+             av_log(avctx, AV_LOG_ERROR, "error getting available packets\n");
+             break;
          }
      }
+     if (ret < 0) {
+         av_log(avctx, AV_LOG_ERROR, "error getting available packets\n");
+         return vorbis_error_to_averror(ret);
+     }
  
-     l = 0;
-     if (context->buffer_index) {
-         ogg_packet *op2 = (ogg_packet *)context->buffer;
-         op2->packet = context->buffer + sizeof(ogg_packet);
-         l = op2->bytes;
-         avccontext->coded_frame->pts = ff_samples_to_time_base(avccontext,
-                                                                op2->granulepos);
-         //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate
-         if (l > buf_size) {
-             av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow.\n");
+     /* output then next packet from the output buffer, if available */
+     pkt_size = 0;
+     if (av_fifo_size(s->pkt_fifo) >= sizeof(ogg_packet)) {
+         av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL);
+         pkt_size = op.bytes;
+         // FIXME: we should use the user-supplied pts and duration
+         avctx->coded_frame->pts = ff_samples_to_time_base(avctx,
+                                                           op.granulepos);
+         if (pkt_size > buf_size) {
 -            av_log(avctx, AV_LOG_ERROR, "output buffer is too small");
++            av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
              return AVERROR(EINVAL);
          }
-         memcpy(packets, op2->packet, l);
-         context->buffer_index -= l + sizeof(ogg_packet);
-         memmove(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
- //        av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
+         av_fifo_generic_read(s->pkt_fifo, packets, pkt_size, NULL);
      }
  
-     return l;
+     return pkt_size;
  }
  
  AVCodec ff_libvorbis_encoder = {
Simple merge
Simple merge
Simple merge
  #include "parser.h"
  #include "mpeg12data.h"
  #include "rl.h"
 +#include "libavutil/timecode.h"
  
+ #include "libavutil/opt.h"
  #define FRAME_SKIPPED 100 ///< return value for header parsers if frame is not coded
  
  enum OutputFormat {
Simple merge
@@@ -103,10 -104,11 +105,12 @@@ static const AVOption options[]=
  {"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"},
  {"cgop", "closed gop", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"},
  {"fast", "allow non spec compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"},
- {"sgop", "strictly enforce gop size", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_STRICT_GOP }, INT_MIN, INT_MAX, V|E, "flags2"},
+ #if FF_API_MPV_GLOBAL_OPTS
+ {"sgop", "Deprecated, use mpegvideo private options instead", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_STRICT_GOP }, INT_MIN, INT_MAX, V|E, "flags2"},
+ #endif
  {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
  {"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"},
 +{"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"},
  {"sub_id", NULL, OFFSET(sub_id), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
  {"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.dbl = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
  {"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.dbl = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" },
  {"all"             , NULL, 0, AV_OPT_TYPE_CONST, {.dbl = AVDISCARD_ALL     }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.dbl = 1 }, 0, 4, V|E},
  {"brd_scale", "downscales frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, 10, V|E},
 -{"keyint_min", "minimum interval between IDR-frames (x264)", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.dbl = 25 }, INT_MIN, INT_MAX, V|E},
 -{"refs", "reference frames to consider for motion compensation (Snow)", OFFSET(refs), AV_OPT_TYPE_INT, {.dbl = 1 }, INT_MIN, INT_MAX, V|E},
 +{"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.dbl = 25 }, INT_MIN, INT_MAX, V|E},
 +{"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.dbl = 1 }, INT_MIN, INT_MAX, V|E},
  {"chromaoffset", "chroma qp offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
- {"skiprd", "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_SKIP_RD }, INT_MIN, INT_MAX, V|E, "flags2"},
+ #if FF_API_MPV_GLOBAL_OPTS
+ {"skiprd", "Deprecated, use mpegvideo private options instead", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_SKIP_RD }, INT_MIN, INT_MAX, V|E, "flags2"},
+ #endif
  {"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), AV_OPT_TYPE_INT, {.dbl = 6 }, 0, INT_MAX, V|E},
  {"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.dbl = 256 }, 0, INT_MAX, V|E},
  {"b_sensitivity", "adjusts sensitivity of b_frame_strategy 1", OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.dbl = 40 }, 1, INT_MAX, V|E},
Simple merge
Simple merge
@@@ -424,10 -407,9 +424,10 @@@ static av_cold int qtrle_decode_init(AV
      default:
          av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
              avctx->bits_per_coded_sample);
-         break;
+         return AVERROR_INVALIDDATA;
      }
  
 +    avcodec_get_frame_defaults(&s->frame);
      s->frame.data[0] = NULL;
  
      return 0;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -107,8 -107,10 +107,10 @@@ static int dxa_read_header(AVFormatCont
          ret = ff_get_wav_header(pb, ast->codec, fsize);
          if (ret < 0)
              return ret;
+         if (ast->codec->sample_rate > 0)
+             avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
          // find 'data' chunk
 -        while(avio_tell(pb) < c->vidpos && !pb->eof_reached){
 +        while(avio_tell(pb) < c->vidpos && !url_feof(pb)){
              tag = avio_rl32(pb);
              fsize = avio_rl32(pb);
              if(tag == MKTAG('d', 'a', 't', 'a')) break;
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -19,7 -19,8 +19,9 @@@
   */
  
  #include <stdint.h>
+ #include <string.h>
 +#include "libavutil/avstring.h"
  #include "libavutil/dict.h"
  #include "libavutil/intreadwrite.h"
  #include "avformat.h"
@@@ -97,66 -109,28 +110,68 @@@ static int id3v2_check_write_tag(ID3v2E
      return -1;
  }
  
- int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version,
-                    const char *magic)
 +static void id3v2_3_metadata_split_date(AVDictionary **pm)
 +{
 +    AVDictionaryEntry *mtag = NULL;
 +    AVDictionary *dst = NULL;
 +    const char *key, *value;
 +    char year[5] = {0}, day_month[5] = {0};
 +    int i;
 +
 +    while ((mtag = av_dict_get(*pm, "", mtag, AV_DICT_IGNORE_SUFFIX))) {
 +        key = mtag->key;
 +        if (!av_strcasecmp(key, "date")) {
 +            /* split date tag using "YYYY-MM-DD" format into year and month/day segments */
 +            value = mtag->value;
 +            i = 0;
 +            while (value[i] >= '0' && value[i] <= '9') i++;
 +            if (value[i] == '\0' || value[i] == '-') {
 +                av_strlcpy(year, value, sizeof(year));
 +                av_dict_set(&dst, "TYER", year, 0);
 +
 +                if (value[i] == '-' &&
 +                    value[i+1] >= '0' && value[i+1] <= '1' &&
 +                    value[i+2] >= '0' && value[i+2] <= '9' &&
 +                    value[i+3] == '-' &&
 +                    value[i+4] >= '0' && value[i+4] <= '3' &&
 +                    value[i+5] >= '0' && value[i+5] <= '9' &&
 +                    (value[i+6] == '\0' || value[i+6] == ' ')) {
 +                    snprintf(day_month, sizeof(day_month), "%.2s%.2s", value + i + 4, value + i + 1);
 +                    av_dict_set(&dst, "TDAT", day_month, 0);
 +                }
 +            } else
 +                av_dict_set(&dst, key, value, 0);
 +        } else
 +            av_dict_set(&dst, key, mtag->value, 0);
 +    }
 +    av_dict_free(pm);
 +    *pm = dst;
 +}
 +
+ void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
+                     const char *magic)
  {
-     int64_t size_pos, cur_pos;
-     AVDictionaryEntry *t = NULL;
+     id3->version = id3v2_version;
  
-     int totlen = 0, enc = id3v2_version == 3 ? ID3v2_ENCODING_UTF16BOM :
-                                                ID3v2_ENCODING_UTF8;
-     avio_wb32(s->pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version));
-     avio_w8(s->pb, 0);
-     avio_w8(s->pb, 0); /* flags */
+     avio_wb32(pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version));
+     avio_w8(pb, 0);
+     avio_w8(pb, 0); /* flags */
  
      /* reserve space for size */
-     size_pos = avio_tell(s->pb);
-     avio_wb32(s->pb, 0);
+     id3->size_pos = avio_tell(pb);
+     avio_wb32(pb, 0);
+ }
+ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
+ {
+     AVDictionaryEntry *t = NULL;
+     int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
+                                   ID3v2_ENCODING_UTF8;
  
      ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL);
-     if (id3v2_version == 3)
 -    if (id3->version == 4)
++    if (id3->version == 3)
 +        id3v2_3_metadata_split_date(&s->metadata);
-     else if (id3v2_version == 4)
++    else if (id3->version == 4)
          ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
  
      while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
@@@ -37,6 -37,13 +37,11 @@@ typedef struct AVCodecTag 
      unsigned int tag;
  } AVCodecTag;
  
 -void ff_dynarray_add(intptr_t **tab_ptr, int *nb_ptr, intptr_t elem);
 -
+ typedef struct CodecMime{
+     char str[32];
+     enum CodecID id;
+ } CodecMime;
  #ifdef __GNUC__
  #define dynarray_add(tab, nb_ptr, elem)\
  do {\
Simple merge
Simple merge
@@@ -79,93 -74,36 +79,52 @@@ static int id3v1_create_tag(AVFormatCon
      return count;
  }
  
 +#define VBR_NUM_BAGS 400
 +#define VBR_TOC_SIZE 100
 +
  typedef struct MP3Context {
      const AVClass *class;
+     ID3v2EncContext id3;
      int id3v2_version;
      int write_id3v1;
 -    int64_t nb_frames_offset;
 +    int64_t frames_offset;
 +    int32_t frames;
 +    int32_t size;
 +    uint32_t want;
 +    uint32_t seen;
 +    uint32_t pos;
 +    uint64_t bag[VBR_NUM_BAGS];
- } MP3Context;
- static int mp2_write_trailer(struct AVFormatContext *s)
- {
-     uint8_t buf[ID3v1_TAG_SIZE];
-     MP3Context *mp3 = s->priv_data;
-     /* write the id3v1 tag */
-     if (mp3 && mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) {
-         avio_write(s->pb, buf, ID3v1_TAG_SIZE);
-     }
  
-     /* write number of frames */
-     if (mp3 && mp3->frames_offset) {
-         avio_seek(s->pb, mp3->frames_offset, SEEK_SET);
-         avio_wb32(s->pb, s->streams[0]->nb_frames);
-         avio_seek(s->pb, 0, SEEK_END);
-     }
-     avio_flush(s->pb);
-     return 0;
- }
- #if CONFIG_MP2_MUXER
- AVOutputFormat ff_mp2_muxer = {
-     .name              = "mp2",
-     .long_name         = NULL_IF_CONFIG_SMALL("MPEG audio layer 2"),
-     .mime_type         = "audio/x-mpeg",
-     .extensions        = "mp2,m2a",
-     .audio_codec       = CODEC_ID_MP2,
-     .video_codec       = CODEC_ID_NONE,
-     .write_packet      = ff_raw_write_packet,
-     .write_trailer     = mp2_write_trailer,
-     .flags             = AVFMT_NOTIMESTAMPS,
- };
- #endif
- #if CONFIG_MP3_MUXER
- static const AVOption options[] = {
-     { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.",
-       offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.dbl = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM},
-     { "write_id3v1", "Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software.",
-       offsetof(MP3Context, write_id3v1), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
-     { NULL },
- };
+     /* index of the audio stream */
+     int audio_stream_idx;
+     /* number of attached pictures we still need to write */
+     int pics_to_write;
  
- static const AVClass mp3_muxer_class = {
-     .class_name     = "MP3 muxer",
-     .item_name      = av_default_item_name,
-     .option         = options,
-     .version        = LIBAVUTIL_VERSION_INT,
- };
+     /* audio packets are queued here until we get all the attached pictures */
+     AVPacketList *queue, *queue_end;
+ } MP3Context;
  
 -/* insert a dummy frame containing number of frames */
 -static void mp3_write_xing(AVFormatContext *s)
 +static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
 +
 +/*
 + * Write an empty XING header and initialize respective data.
 + */
 +static int mp3_write_xing(AVFormatContext *s)
  {
-     AVCodecContext   *codec = s->streams[0]->codec;
      MP3Context       *mp3 = s->priv_data;
 -    int       bitrate_idx = 1;    // 32 kbps
 -    int64_t   xing_offset = (codec->channels == 2) ? 32 : 17;
 -    int32_t        header;
 -    MPADecodeHeader  mpah;
 -    int srate_idx, i, channels;
+     AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
 +    int              bitrate_idx;
 +    int              best_bitrate_idx = -1;
 +    int              best_bitrate_error= INT_MAX;
 +    int64_t          xing_offset;
 +    int32_t          header, mask;
 +    MPADecodeHeader  c;
 +    int              srate_idx, i, channels;
 +    int              needed;
  
 -        return;
+     if (!s->pb->seekable)
++        return 0;
      for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++)
          if (avpriv_mpa_freq_tab[i] == codec->sample_rate) {
              srate_idx = i;
      /* dummy MPEG audio header */
      header  =  0xff                                  << 24; // sync
      header |= (0x7 << 5 | 0x3 << 3 | 0x1 << 1 | 0x1) << 16; // sync/mpeg-1/layer 3/no crc*/
 -    header |= (bitrate_idx << 4 | srate_idx << 2)    <<  8;
 +    header |= (srate_idx << 2) <<  8;
      header |= channels << 6;
 -    avio_wb32(s->pb, header);
  
 -    avpriv_mpegaudio_decode_header(&mpah, header);
 +    for (bitrate_idx=1; bitrate_idx<15; bitrate_idx++) {
 +        int error;
 +        avpriv_mpegaudio_decode_header(&c, header | (bitrate_idx << (4+8)));
 +        error= FFABS(c.bit_rate - codec->bit_rate);
 +        if(error < best_bitrate_error){
 +            best_bitrate_error= error;
 +            best_bitrate_idx  = bitrate_idx;
 +        }
 +    }
 +    av_assert0(best_bitrate_idx >= 0);
 +
 +    for (bitrate_idx= best_bitrate_idx;; bitrate_idx++) {
 +        if (15 == bitrate_idx)
 +            return -1;
 +        mask = bitrate_idx << (4+8);
 +        header |= mask;
 +        avpriv_mpegaudio_decode_header(&c, header);
 +        xing_offset=xing_offtbl[c.lsf == 1][c.nb_channels == 1];
 +        needed = 4              // header
 +               + xing_offset
 +               + 4              // xing tag
 +               + 4              // frames/size/toc flags
 +               + 4              // frames
 +               + 4              // size
 +               + VBR_TOC_SIZE;  // toc
 +
 +        if (needed <= c.frame_size)
 +            break;
 +        header &= ~mask;
 +    }
  
 +    avio_wb32(s->pb, header);
      ffio_fill(s->pb, 0, xing_offset);
 -    ffio_wfourcc(s->pb, "Xing");
 -    avio_wb32(s->pb, 0x1);    // only number of frames
 -    mp3->nb_frames_offset = avio_tell(s->pb);
 -    avio_wb32(s->pb, 0);
 +    avio_wb32(s->pb, MKBETAG('X', 'i', 'n', 'g'));
 +    avio_wb32(s->pb, 0x01 | 0x02 | 0x04);  // frames/size/toc
 +
 +    mp3->frames_offset = avio_tell(s->pb);
 +    mp3->size = c.frame_size;
 +    mp3->want=1;
 +    mp3->seen=0;
 +    mp3->pos=0;
 +
 +    avio_wb32(s->pb, 0);  // frames
 +    avio_wb32(s->pb, 0);  // size
 +
 +    // toc
 +    for (i = 0; i < VBR_TOC_SIZE; ++i)
 +        avio_w8(s->pb, (uint8_t)(255 * i / VBR_TOC_SIZE));
 +
 +    ffio_fill(s->pb, 0, c.frame_size - needed);
 +    avio_flush(s->pb);
 +
 +    return 0;
 +}
 +
 +/*
 + * Add a frame to XING data.
 + * Following lame's "VbrTag.c".
 + */
 +static void mp3_xing_add_frame(AVFormatContext *s, AVPacket *pkt)
 +{
 +    MP3Context  *mp3 = s->priv_data;
 +    int i;
 +
 +    ++mp3->frames;
 +    mp3->size += pkt->size;
 +
 +    if (mp3->want == ++mp3->seen) {
 +        mp3->bag[mp3->pos] = mp3->size;
 +
 +        if (VBR_NUM_BAGS == ++mp3->pos) {
 +            /* shrink table to half size by throwing away each second bag. */
 +            for (i = 1; i < VBR_NUM_BAGS; i += 2)
 +                mp3->bag[i >> 1] = mp3->bag[i];
 +
 +            /* double wanted amount per bag. */
 +            mp3->want <<= 1;
 +            /* adjust current position to half of table size. */
 +            mp3->pos >>= 1;
 +        }
 +
 +        mp3->seen = 0;
 +    }
 +}
 +
 +static void mp3_fix_xing(AVFormatContext *s)
 +{
 +    MP3Context  *mp3 = s->priv_data;
 +    int i;
 +
 +    avio_flush(s->pb);
 +    avio_seek(s->pb, mp3->frames_offset, SEEK_SET);
 +    avio_wb32(s->pb, mp3->frames);
 +    avio_wb32(s->pb, mp3->size);
 +
 +    avio_w8(s->pb, 0);  // first toc entry has to be zero.
  
 -    mpah.frame_size -= 4 + xing_offset + 4 + 4 + 4;
 -    ffio_fill(s->pb, 0, mpah.frame_size);
 +    for (i = 1; i < VBR_TOC_SIZE; ++i) {
 +        int j = i * mp3->pos / VBR_TOC_SIZE;
 +        int seek_point = 256LL * mp3->bag[j] / mp3->size;
 +        avio_w8(s->pb, FFMIN(seek_point, 255));
 +    }
 +
 +    avio_flush(s->pb);
 +    avio_seek(s->pb, 0, SEEK_END);
 +}
 +
- /**
-  * Write an ID3v2 header at beginning of stream
-  */
- static int mp3_write_header(struct AVFormatContext *s)
- {
-     MP3Context  *mp3 = s->priv_data;
-     int ret;
-     ret = ff_id3v2_write(s, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC);
-     if (ret < 0)
-         return ret;
-     if (s->pb->seekable)
-         mp3_write_xing(s);
-     return 0;
- }
- static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
++static int mp3_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
 +{
 +    if (! pkt || ! pkt->data || pkt->size < 4)
 +        return ff_raw_write_packet(s, pkt);
 +    else {
 +        MP3Context  *mp3 = s->priv_data;
 +#ifdef FILTER_VBR_HEADERS
 +        MPADecodeHeader c;
 +        int base;
 +
 +        ff_mpegaudio_decode_header(&c, AV_RB32(pkt->data));
 +
 +        /* filter out XING and INFO headers. */
 +        base = 4 + xing_offtbl[c.lsf == 1][c.nb_channels == 1];
 +
 +        if (base + 4 <= pkt->size) {
 +            uint32_t v = AV_RB32(pkt->data + base);
 +
 +            if (MKBETAG('X','i','n','g') == v || MKBETAG('I','n','f','o') == v)
 +                return 0;
 +        }
 +
 +        /* filter out VBRI headers. */
 +        base = 4 + 32;
 +
 +        if (base + 4 <= pkt->size && MKBETAG('V','B','R','I') == AV_RB32(pkt->data + base))
 +            return 0;
 +#endif
 +
 +        if (mp3->frames_offset)
 +            mp3_xing_add_frame(s, pkt);
 +
 +        return ff_raw_write_packet(s, pkt);
 +    }
  }
  
 -        if (write && (ret = ff_raw_write_packet(s, &pktl->pkt)) < 0)
+ static int mp3_queue_flush(AVFormatContext *s)
+ {
+     MP3Context *mp3 = s->priv_data;
+     AVPacketList *pktl;
+     int ret = 0, write = 1;
+     ff_id3v2_finish(&mp3->id3, s->pb);
+     mp3_write_xing(s);
+     while ((pktl = mp3->queue)) {
 -static int mp3_write_trailer(struct AVFormatContext *s)
++        if (write && (ret = mp3_write_packet_internal(s, &pktl->pkt)) < 0)
+             write = 0;
+         av_free_packet(&pktl->pkt);
+         mp3->queue = pktl->next;
+         av_freep(&pktl);
+     }
+     mp3->queue_end = NULL;
+     return ret;
+ }
 -    if (mp3 && mp3->nb_frames_offset) {
 -        avio_seek(s->pb, mp3->nb_frames_offset, SEEK_SET);
++static int mp2_write_trailer(struct AVFormatContext *s)
+ {
+     uint8_t buf[ID3v1_TAG_SIZE];
+     MP3Context *mp3 = s->priv_data;
+     if (mp3 && mp3->pics_to_write) {
+         av_log(s, AV_LOG_WARNING, "No packets were sent for some of the "
+                "attached pictures.\n");
+         mp3_queue_flush(s);
+     }
+     /* write the id3v1 tag */
+     if (mp3 && mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) {
+         avio_write(s->pb, buf, ID3v1_TAG_SIZE);
+     }
+     /* write number of frames */
 -    .write_trailer     = mp3_write_trailer,
++    if (mp3 && mp3->frames_offset) {
++        avio_seek(s->pb, mp3->frames_offset, SEEK_SET);
+         avio_wb32(s->pb, s->streams[mp3->audio_stream_idx]->nb_frames);
+         avio_seek(s->pb, 0, SEEK_END);
+     }
+     avio_flush(s->pb);
+     return 0;
+ }
+ #if CONFIG_MP2_MUXER
+ AVOutputFormat ff_mp2_muxer = {
+     .name              = "mp2",
+     .long_name         = NULL_IF_CONFIG_SMALL("MPEG audio layer 2"),
+     .mime_type         = "audio/x-mpeg",
+     .extensions        = "mp2,m2a",
+     .audio_codec       = CODEC_ID_MP2,
+     .video_codec       = CODEC_ID_NONE,
+     .write_packet      = ff_raw_write_packet,
 -            return ff_raw_write_packet(s, pkt);
++    .write_trailer     = mp2_write_trailer,
++    .flags             = AVFMT_NOTIMESTAMPS,
+ };
+ #endif
+ #if CONFIG_MP3_MUXER
+ static const AVOption options[] = {
+     { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.",
+       offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.dbl = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM},
+     { "write_id3v1", "Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software.",
+       offsetof(MP3Context, write_id3v1), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
+     { NULL },
+ };
+ static const AVClass mp3_muxer_class = {
+     .class_name     = "MP3 muxer",
+     .item_name      = av_default_item_name,
+     .option         = options,
+     .version        = LIBAVUTIL_VERSION_INT,
+ };
+ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
+ {
+     MP3Context *mp3 = s->priv_data;
+     if (pkt->stream_index == mp3->audio_stream_idx) {
+         if (mp3->pics_to_write) {
+             /* buffer audio packets until we get all the pictures */
+             AVPacketList *pktl = av_mallocz(sizeof(*pktl));
+             if (!pktl)
+                 return AVERROR(ENOMEM);
+             pktl->pkt     = *pkt;
+             pkt->destruct = NULL;
+             if (mp3->queue_end)
+                 mp3->queue_end->next = pktl;
+             else
+                 mp3->queue = pktl;
+             mp3->queue_end = pktl;
+         } else
++            return mp3_write_packet_internal(s, pkt);
+     } else {
+         int ret;
+         /* warn only once for each stream */
+         if (s->streams[pkt->stream_index]->nb_frames == 1) {
+             av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
+                    " ignoring.\n", pkt->stream_index);
+         }
+         if (!mp3->pics_to_write || s->streams[pkt->stream_index]->nb_frames >= 1)
+             return 0;
+         if ((ret = ff_id3v2_write_apic(s, &mp3->id3, pkt)) < 0)
+             return ret;
+         mp3->pics_to_write--;
+         /* flush the buffered audio packets */
+         if (!mp3->pics_to_write &&
+             (ret = mp3_queue_flush(s)) < 0)
+             return ret;
+     }
+     return 0;
+ }
+ /**
+  * Write an ID3v2 header at beginning of stream
+  */
+ static int mp3_write_header(struct AVFormatContext *s)
+ {
+     MP3Context  *mp3 = s->priv_data;
+     int ret, i;
+     /* check the streams -- we want exactly one audio and arbitrary number of
+      * video (attached pictures) */
+     mp3->audio_stream_idx = -1;
+     for (i = 0; i < s->nb_streams; i++) {
+         AVStream *st = s->streams[i];
+         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+             if (mp3->audio_stream_idx >= 0 || st->codec->codec_id != CODEC_ID_MP3) {
+                 av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one MP3 "
+                        "audio stream is required.\n");
+                 return AVERROR(EINVAL);
+             }
+             mp3->audio_stream_idx = i;
+         } else if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO) {
+             av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in MP3.\n");
+             return AVERROR(EINVAL);
+         }
+     }
+     if (mp3->audio_stream_idx < 0) {
+         av_log(s, AV_LOG_ERROR, "No audio stream present.\n");
+         return AVERROR(EINVAL);
+     }
+     mp3->pics_to_write = s->nb_streams - 1;
+     ff_id3v2_start(&mp3->id3, s->pb, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC);
+     ret = ff_id3v2_write_metadata(s, &mp3->id3);
+     if (ret < 0)
+         return ret;
+     if (!mp3->pics_to_write) {
+         ff_id3v2_finish(&mp3->id3, s->pb);
+         mp3_write_xing(s);
+     }
+     return 0;
+ }
 +static int mp3_write_trailer(AVFormatContext *s)
 +{
 +    MP3Context  *mp3 = s->priv_data;
 +    int ret=mp2_write_trailer(s);
 +
 +    if (ret < 0)
 +        return ret;
 +
 +    if (mp3->frames_offset)
 +        mp3_fix_xing(s);
 +
 +    return 0;
 +}
 +
  AVOutputFormat ff_mp3_muxer = {
      .name              = "mp3",
      .long_name         = NULL_IF_CONFIG_SMALL("MPEG audio layer 3"),
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -592,13 -563,26 +610,26 @@@ int avformat_open_input(AVFormatContex
  
      /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
      if (s->pb)
-         ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC);
+         ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
  
 -    if (s->iformat->read_header)
 +    if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
          if ((ret = s->iformat->read_header(s)) < 0)
              goto fail;
  
 -    if (s->pb && !s->data_offset)
+     if (id3v2_extra_meta &&
+         (ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
+         goto fail;
+     ff_id3v2_free_extra_meta(&id3v2_extra_meta);
+     /* queue attached pictures */
+     for (i = 0; i < s->nb_streams; i++)
+         if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
+             AVPacket copy = s->streams[i]->attached_pic;
+             copy.destruct = NULL;
+             add_to_pktbuf(&s->raw_packet_buffer, &copy, &s->raw_packet_buffer_end);
+         }
 +    if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset)
          s->data_offset = avio_tell(s->pb);
  
      s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
@@@ -2722,14 -2562,16 +2737,16 @@@ void avformat_free_context(AVFormatCont
              av_parser_close(st->parser);
              av_free_packet(&st->cur_pkt);
          }
+         if (st->attached_pic.data)
+             av_free_packet(&st->attached_pic);
          av_dict_free(&st->metadata);
 -        av_free(st->index_entries);
 -        av_free(st->codec->extradata);
 -        av_free(st->codec->subtitle_header);
 -        av_free(st->codec);
 -        av_free(st->priv_data);
 -        av_free(st->info);
 -        av_free(st);
 +        av_freep(&st->index_entries);
 +        av_freep(&st->codec->extradata);
 +        av_freep(&st->codec->subtitle_header);
 +        av_freep(&st->codec);
 +        av_freep(&st->priv_data);
 +        av_freep(&st->info);
 +        av_freep(&st);
      }
      for(i=s->nb_programs-1; i>=0; i--) {
          av_dict_free(&s->programs[i]->metadata);
@@@ -30,8 -30,8 +30,8 @@@
  #include "libavutil/avutil.h"
  
  #define LIBAVFORMAT_VERSION_MAJOR 54
- #define LIBAVFORMAT_VERSION_MINOR  1
+ #define LIBAVFORMAT_VERSION_MINOR  2
 -#define LIBAVFORMAT_VERSION_MICRO  0
 +#define LIBAVFORMAT_VERSION_MICRO 100
  
  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                 LIBAVFORMAT_VERSION_MINOR, \
Simple merge
Simple merge
Simple merge
@@@ -124,52 -124,53 +124,52 @@@ fate-iff-fibonacci: CMD = md5 -i $(SAMP
  FATE_IFF += fate-iff-ilbm
  fate-iff-ilbm: CMD = framecrc -i $(SAMPLES)/iff/lms-matriks.ilbm -pix_fmt rgb24
  
 -FATE_TESTS += $(FATE_IFF)
 +FATE_VIDEO += $(FATE_IFF)
  fate-iff: $(FATE_IFF)
  
 -FATE_TESTS += fate-kmvc
 +FATE_VIDEO += fate-kmvc
  fate-kmvc: CMD = framecrc -i $(SAMPLES)/KMVC/LOGO1.AVI -an -t 3 -pix_fmt rgb24
  
 -FATE_TESTS += fate-mimic
 +FATE_VIDEO += fate-mimic
  fate-mimic: CMD = framecrc -idct simple -i $(SAMPLES)/mimic/mimic2-womanloveffmpeg.cam
  
 -FATE_TESTS += fate-mjpegb
 +FATE_VIDEO += fate-mjpegb
  fate-mjpegb: CMD = framecrc -idct simple -flags +bitexact -i $(SAMPLES)/mjpegb/mjpegb_part.mov -an
  
 -FATE_TESTS += fate-motionpixels
 +FATE_VIDEO += fate-motionpixels
  fate-motionpixels: CMD = framecrc -i $(SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -vframes 111
  
 -FATE_TESTS += fate-mpeg2-field-enc
 +FATE_VIDEO += fate-mpeg2-field-enc
  fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -dct fastint -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -an
  
 -# FIXME dropped frames in this test because of coarse timebase
 -FATE_TESTS += fate-nuv
 +FATE_VIDEO += fate-nuv
- fate-nuv: CMD = framecrc -idct simple -i $(SAMPLES)/nuv/Today.nuv
+ fate-nuv: CMD = framecrc -idct simple -i $(SAMPLES)/nuv/Today.nuv -an
  
 -FATE_TESTS += fate-qpeg
 +FATE_VIDEO += fate-qpeg
  fate-qpeg: CMD = framecrc -i $(SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24
  
 -FATE_TESTS += fate-r210
 +FATE_VIDEO += fate-r210
  fate-r210: CMD = framecrc -i $(SAMPLES)/r210/r210.avi -pix_fmt rgb48le
  
 -FATE_TESTS += fate-rl2
 +FATE_VIDEO += fate-rl2
  fate-rl2: CMD = framecrc -i $(SAMPLES)/rl2/Z4915300.RL2 -pix_fmt rgb24 -an
  
 -FATE_TESTS += fate-smacker
 +FATE_VIDEO += fate-smacker
  fate-smacker: CMD = framecrc -i $(SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24
  
 -FATE_TESTS += fate-smc
 +FATE_VIDEO += fate-smc
  fate-smc: CMD = framecrc -i $(SAMPLES)/smc/cass_schi.qt -pix_fmt rgb24
  
 -FATE_TESTS += fate-sp5x
 +FATE_VIDEO += fate-sp5x
  fate-sp5x: CMD = framecrc -idct simple -i $(SAMPLES)/sp5x/sp5x_problem.avi
  
 -FATE_TESTS += fate-sub-srt
 +FATE_VIDEO += fate-sub-srt
  fate-sub-srt: CMD = md5 -i $(SAMPLES)/sub/SubRip_capability_tester.srt -f ass
  
 -FATE_TESTS += fate-tiertex-seq
 +FATE_VIDEO += fate-tiertex-seq
  fate-tiertex-seq: CMD = framecrc -i $(SAMPLES)/tiertex-seq/Gameover.seq -pix_fmt rgb24
  
 -FATE_TESTS += fate-tmv
 +FATE_VIDEO += fate-tmv
  fate-tmv: CMD = framecrc -i $(SAMPLES)/tmv/pop-partial.tmv -pix_fmt rgb24
  
  FATE_TXD += fate-txd-16bpp
index 0000000,e4071a9..8060f06
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,11 +1,11 @@@
 -#tb 0: 1/11025
 -0,          0,          0,        0,    63180, 0xcda82c16
 -0,        220,        220,        0,    63180, 0xa6097bf9
 -0,        440,        440,        0,    63180, 0x4c2fb091
 -0,        660,        660,        0,    63180, 0xc597db00
 -0,        880,        880,        0,    63180, 0xfa581ccd
 -0,       1100,       1100,        0,    63180, 0x3e51498f
 -0,       1320,       1320,        0,    63180, 0xe3495396
 -0,       1540,       1540,        0,    63180, 0x425f5f02
 -0,       1760,       1760,        0,    63180, 0x6077465f
 -0,       1980,       1980,        0,    63180, 0x923ba29c
++#tb 0: 12/601
++0,          0,          0,        1,    63180, 0xcda82c16
++0,          1,          1,        1,    63180, 0xa6097bf9
++0,          2,          2,        1,    63180, 0x4c2fb091
++0,          3,          3,        1,    63180, 0xc597db00
++0,          4,          4,        1,    63180, 0xfa581ccd
++0,          5,          5,        1,    63180, 0x3e51498f
++0,          6,          6,        1,    63180, 0xe3495396
++0,          7,          7,        1,    63180, 0x425f5f02
++0,          8,          8,        1,    63180, 0x6077465f
++0,          9,          9,        1,    63180, 0x923ba29c
@@@ -1,29 -1,10 +1,10 @@@
 -#tb 0: 1/1000
 -0,        118,        118,        0,   460800, 0x54aedafe
 -0,        152,        152,        0,   460800, 0xb7aa8b56
 -0,        177,        177,        0,   460800, 0x283ea3b5
 -0,        202,        202,        0,   460800, 0x283ea3b5
 -0,        235,        235,        0,   460800, 0x10e577de
 -0,        269,        269,        0,   460800, 0x4e091ee2
 -0,        302,        302,        0,   460800, 0x2ea88828
 -0,        335,        335,        0,   460800, 0x4b7f4df0
 -0,        369,        369,        0,   460800, 0xb30eb322
 +#tb 0: 100/2997
- #tb 1: 1/44100
- 1,          0,          0,     1024,     4096, 0x00000000
- 1,       1024,       1024,     1024,     4096, 0x4dfae7a6
- 1,       2048,       2048,     1024,     4096, 0x3fd9f5c6
- 1,       3072,       3072,     1024,     4096, 0x7b86e310
- 1,       4096,       4096,     1024,     4096, 0x611cece5
- 1,       5120,       5120,     1024,     4096, 0xb7d8e872
 +0,          4,          4,        1,   460800, 0x54aedafe
- 1,       6144,       6144,     1024,     4096, 0x072ef72b
- 1,       7168,       7168,     1024,     4096, 0xb3560144
 +0,          5,          5,        1,   460800, 0xb7aa8b56
- 1,       8192,       8192,     1024,     4096, 0x0a3d119e
 +0,          6,          6,        1,   460800, 0x283ea3b5
- 1,       9216,       9216,     1024,     4096, 0xbe391aa4
- 1,      10240,      10240,     1024,     4096, 0x28f7c6e5
 +0,          7,          7,        1,   460800, 0x283ea3b5
- 1,      11264,      11264,     1024,     4096, 0xca9d9df2
 +0,          8,          8,        1,   460800, 0x10e577de
- 1,      12288,      12288,     1024,     4096, 0x5c6b95a9
 +0,          9,          9,        1,   460800, 0x4e091ee2
- 1,      13312,      13312,     1024,     4096, 0x0bdfc0bf
- 1,      14336,      14336,     1024,     4096, 0xd95a9277
 +0,         10,         10,        1,   460800, 0x2ea88828
- 1,      15360,      15360,     1024,     4096, 0xae2bef2c
 +0,         11,         11,        1,   460800, 0x4b7f4df0
- 1,      16384,      16384,     1024,     4096, 0xbf031e83
- 1,      17408,      17408,     1024,     4096, 0x4c83e2d1
 +0,         12,         12,        1,   460800, 0xa57f20d0
@@@ -1,3 -1,3 +1,3 @@@
- 4ef091d638bb20b8eaef5b3a0d6f97b7 *./tests/data/lavf/lavf.ffm
 -8a95fa3db8e6082ed24e963e40ec1526 *./tests/data/lavf/lavf.ffm
++8ce2ea9a73a1187647df7bf3c8e1b8fd *./tests/data/lavf/lavf.ffm
  376832 ./tests/data/lavf/lavf.ffm
 -./tests/data/lavf/lavf.ffm CRC=0x88f58ba1
 +./tests/data/lavf/lavf.ffm CRC=0xf361ed74
index 870e284,0000000..032cda2
mode 100644,000000..100644
--- /dev/null
@@@ -1,4 -1,0 +1,4 @@@
- 40e7637e04991dbe9a23fe109f95bfc8 *./tests/data/vsynth1/prores_kostya.mov
++f8fe98b7f9bb66857c81dbca409a9037 *./tests/data/vsynth1/prores_kostya.mov
 +3858901 ./tests/data/vsynth1/prores_kostya.mov
 +0a4153637d0cc0a88a8bcbf04cfaf8c6 *./tests/data/prores_kostya.vsynth1.out.yuv
 +stddev:    3.17 PSNR: 38.09 MAXDIFF:   39 bytes:  7603200/  7603200
index 2b99c75,0000000..efdcd8f
mode 100644,000000..100644
--- /dev/null
@@@ -1,4 -1,0 +1,4 @@@
- ed8b8a94da049518af8f95c5da736e57 *./tests/data/vsynth2/prores_kostya.mov
++26adb18726c08dde23bc4bee2eb591e2 *./tests/data/vsynth2/prores_kostya.mov
 +3884586 ./tests/data/vsynth2/prores_kostya.mov
 +ca2f6c1162635dedfa468c90f1fdc0ef *./tests/data/prores_kostya.vsynth2.out.yuv
 +stddev:    0.92 PSNR: 48.77 MAXDIFF:   10 bytes:  7603200/  7603200