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},
index 882503a,0000000..e358d7f
mode 100644,000000..100644
--- /dev/null
@@@ -1,654 -1,0 +1,673 @@@
-                                const int16_t *qmat)
 +/*
 + * Apple ProRes compatible decoder
 + *
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + *
 + * This file is part of Libav.
 + *
 + * Libav 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,
 + * 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
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * This is a decoder for Apple ProRes 422 SD/HQ/LT/Proxy and ProRes 4444.
 + * It is used for storing and editing high definition video data in Apple's Final Cut Pro.
 + *
 + * @see http://wiki.multimedia.cx/index.php?title=Apple_ProRes
 + */
 +
 +#define LONG_BITSTREAM_READER // some ProRes vlc codes require up to 28 bits to be read at once
 +
 +#include <stdint.h>
 +
 +#include "libavutil/intmath.h"
 +#include "avcodec.h"
 +#include "proresdata.h"
 +#include "proresdsp.h"
 +#include "get_bits.h"
 +
 +typedef struct {
 +    const uint8_t *index;            ///< pointers to the data of this slice
 +    int slice_num;
 +    int x_pos, y_pos;
 +    int slice_width;
 +    int prev_slice_sf;               ///< scalefactor of the previous decoded slice
 +    DECLARE_ALIGNED(16, DCTELEM, blocks)[8 * 4 * 64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64];
 +    DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64];
 +} ProresThreadData;
 +
 +typedef struct {
 +    ProresDSPContext dsp;
 +    AVFrame    picture;
 +    ScanTable  scantable;
 +    int        scantable_type;           ///< -1 = uninitialized, 0 = progressive, 1/2 = interlaced
 +
 +    int        frame_type;               ///< 0 = progressive, 1 = top-field first, 2 = bottom-field first
 +    int        pic_format;               ///< 2 = 422, 3 = 444
 +    uint8_t    qmat_luma[64];            ///< dequantization matrix for luma
 +    uint8_t    qmat_chroma[64];          ///< dequantization matrix for chroma
 +    int        qmat_changed;             ///< 1 - global quantization matrices changed
 +    int        total_slices;            ///< total number of slices in a picture
 +    ProresThreadData *slice_data;
 +    int        pic_num;
 +    int        chroma_factor;
 +    int        mb_chroma_factor;
 +    int        num_chroma_blocks;       ///< number of chrominance blocks in a macroblock
 +    int        num_x_slices;
 +    int        num_y_slices;
 +    int        slice_width_factor;
 +    int        slice_height_factor;
 +    int        num_x_mbs;
 +    int        num_y_mbs;
 +    int        alpha_info;
 +} ProresContext;
 +
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    ctx->total_slices     = 0;
 +    ctx->slice_data       = NULL;
 +
 +    avctx->bits_per_raw_sample = PRORES_BITS_PER_SAMPLE;
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +
 +    avctx->coded_frame = &ctx->picture;
 +    avcodec_get_frame_defaults(&ctx->picture);
 +    ctx->picture.type      = AV_PICTURE_TYPE_I;
 +    ctx->picture.key_frame = 1;
 +
 +    ctx->scantable_type = -1;   // set scantable type to uninitialized
 +    memset(ctx->qmat_luma, 4, 64);
 +    memset(ctx->qmat_chroma, 4, 64);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, version, width, height, flags;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "frame data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    if (version >= 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported header version: %d\n", version);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "picture dimension changed: old: %d x %d, new: %d x %d\n",
 +               avctx->width, avctx->height, width, height);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +    if (ctx->frame_type > 2) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported frame type: %d\n", ctx->frame_type);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->chroma_factor     = (buf[12] >> 6) & 3;
 +    ctx->mb_chroma_factor  = ctx->chroma_factor + 2;
 +    ctx->num_chroma_blocks = (1 << ctx->chroma_factor) >> 1;
 +    switch (ctx->chroma_factor) {
 +    case 2:
 +        avctx->pix_fmt = PIX_FMT_YUV422P10;
 +        break;
 +    case 3:
 +        avctx->pix_fmt = PIX_FMT_YUV444P10;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported picture format: %d\n", ctx->pic_format);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->scantable_type != ctx->frame_type) {
 +        if (!ctx->frame_type)
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_progressive_scan);
 +        else
 +            ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable,
 +                              ff_prores_interlaced_scan);
 +        ctx->scantable_type = ctx->frame_type;
 +    }
 +
 +    if (ctx->frame_type) {      /* if interlaced */
 +        ctx->picture.interlaced_frame = 1;
 +        ctx->picture.top_field_first  = ctx->frame_type & 1;
 +    }
 +
++    avctx->color_primaries = buf[14];
++    avctx->color_trc       = buf[15];
++    avctx->colorspace      = buf[16];
++
 +    ctx->alpha_info = buf[17] & 0xf;
 +    if (ctx->alpha_info)
 +        av_log_missing_feature(avctx, "alpha channel", 0);
 +
 +    ctx->qmat_changed = 0;
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    if (flags & 2) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        if (memcmp(ctx->qmat_luma, ptr, 64)) {
 +            memcpy(ctx->qmat_luma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    if (flags & 1) {
 +        if (ptr - buf > hdr_size - 64) {
 +            av_log(avctx, AV_LOG_ERROR, "header data too small\n");
 +            return -1;
 +        }
 +        if (memcmp(ctx->qmat_chroma, ptr, 64)) {
 +            memcpy(ctx->qmat_chroma, ptr, 64);
 +            ctx->qmat_changed = 1;
 +        }
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +        ctx->qmat_changed = 1;
 +    }
 +
 +    return hdr_size;
 +}
 +
 +
 +static int decode_picture_header(ProresContext *ctx, const uint8_t *buf,
 +                                 const int data_size, AVCodecContext *avctx)
 +{
 +    int   i, hdr_size, pic_data_size, num_slices;
 +    int   slice_width_factor, slice_height_factor;
 +    int   remainder, num_x_slices;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = data_size > 0 ? buf[0] >> 3 : 0;
 +    if (hdr_size < 8 || hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture header too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "picture data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    slice_width_factor  = buf[7] >> 4;
 +    slice_height_factor = buf[7] & 0xF;
 +    if (slice_width_factor > 3 || slice_height_factor) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "unsupported slice dimension: %d x %d\n",
 +               1 << slice_width_factor, 1 << slice_height_factor);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ctx->slice_width_factor  = slice_width_factor;
 +    ctx->slice_height_factor = slice_height_factor;
 +
 +    ctx->num_x_mbs = (avctx->width + 15) >> 4;
 +    ctx->num_y_mbs = (avctx->height +
 +                      (1 << (4 + ctx->picture.interlaced_frame)) - 1) >>
 +                     (4 + ctx->picture.interlaced_frame);
 +
 +    remainder    = ctx->num_x_mbs & ((1 << slice_width_factor) - 1);
 +    num_x_slices = (ctx->num_x_mbs >> slice_width_factor) + (remainder & 1) +
 +                   ((remainder >> 1) & 1) + ((remainder >> 2) & 1);
 +
 +    num_slices = num_x_slices * ctx->num_y_mbs;
 +    if (num_slices != AV_RB16(buf + 5)) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid number of slices\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (ctx->total_slices != num_slices) {
 +        av_freep(&ctx->slice_data);
 +        ctx->slice_data = av_malloc((num_slices + 1) * sizeof(ctx->slice_data[0]));
 +        if (!ctx->slice_data)
 +            return AVERROR(ENOMEM);
 +        ctx->total_slices = num_slices;
 +    }
 +
 +    if (hdr_size + num_slices * 2 > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "slice table too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice table allowing quick access to the slice data */
 +    index_ptr = buf + hdr_size;
 +    data_ptr = index_ptr + num_slices * 2;
 +
 +    for (i = 0; i < num_slices; i++) {
 +        ctx->slice_data[i].index = data_ptr;
 +        ctx->slice_data[i].prev_slice_sf = 0;
 +        data_ptr += AV_RB16(index_ptr + i * 2);
 +    }
 +    ctx->slice_data[i].index = data_ptr;
 +    ctx->slice_data[i].prev_slice_sf = 0;
 +
 +    if (data_ptr > buf + data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "out of slice data\n");
 +        return -1;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +
 +/**
 + * Read an unsigned rice/exp golomb codeword.
 + */
 +static inline int decode_vlc_codeword(GetBitContext *gb, unsigned codebook)
 +{
 +    unsigned int rice_order, exp_order, switch_bits;
 +    unsigned int buf, code;
 +    int log, prefix_len, len;
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);
 +    buf = GET_CACHE(re, gb);
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  = codebook >> 5;        /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    log = 31 - av_log2(buf); /* count prefix bits (zeroes) */
 +
 +    if (log < switch_bits) { /* ok, we got a rice code */
 +        if (!rice_order) {
 +            /* shortcut for faster decoding of rice codes without remainder */
 +            code = log;
 +            LAST_SKIP_BITS(re, gb, log + 1);
 +        } else {
 +            prefix_len = log + 1;
 +            code = (log << rice_order) + NEG_USR32(buf << prefix_len, rice_order);
 +            LAST_SKIP_BITS(re, gb, prefix_len + rice_order);
 +        }
 +    } else { /* otherwise we got a exp golomb code */
 +        len  = (log << 1) - switch_bits + exp_order + 1;
 +        code = NEG_USR32(buf, len) - (1 << exp_order) + (switch_bits << rice_order);
 +        LAST_SKIP_BITS(re, gb, len);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +
 +    return code;
 +}
 +
 +#define LSB2SIGN(x) (-((x) & 1))
 +#define TOSIGNED(x) (((x) >> 1) ^ LSB2SIGN(x))
 +
 +/**
 + * Decode DC coefficients for all blocks in a slice.
 + */
 +static inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,
 +                                    int nblocks)
 +{
 +    DCTELEM prev_dc;
 +    int     i, sign;
 +    int16_t delta;
 +    unsigned int code;
 +
 +    code   = decode_vlc_codeword(gb, FIRST_DC_CB);
 +    out[0] = prev_dc = TOSIGNED(code);
 +
 +    out   += 64; /* move to the DC coeff of the next block */
 +    delta  = 3;
 +
 +    for (i = 1; i < nblocks; i++, out += 64) {
 +        code = decode_vlc_codeword(gb, ff_prores_dc_codebook[FFMIN(FFABS(delta), 3)]);
 +
 +        sign     = -(((delta >> 15) & 1) ^ (code & 1));
 +        delta    = (((code + 1) >> 1) ^ sign) - sign;
 +        prev_dc += delta;
 +        out[0]   = prev_dc;
 +    }
 +}
 +
 +
 +/**
 + * Decode AC coefficients for all blocks in a slice.
 + */
 +static inline void decode_ac_coeffs(GetBitContext *gb, DCTELEM *out,
 +                                    int blocks_per_slice,
 +                                    int plane_size_factor,
 +                                    const uint8_t *scan)
 +{
 +    int pos, block_mask, run, level, sign, run_cb_index, lev_cb_index;
 +    int max_coeffs, bits_left;
 +
 +    /* set initial prediction values */
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = blocks_per_slice - 1; pos < max_coeffs;) {
 +        run_cb_index = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +        lev_cb_index = ff_prores_lev_to_cb_index[FFMIN(level, 9)];
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        run = decode_vlc_codeword(gb, ff_prores_ac_codebook[run_cb_index]);
 +
 +        bits_left = get_bits_left(gb);
 +        if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left)))
 +            return;
 +
 +        level = decode_vlc_codeword(gb, ff_prores_ac_codebook[lev_cb_index]) + 1;
 +
 +        pos += run + 1;
 +        if (pos >= max_coeffs)
 +            break;
 +
 +        sign = get_sbits(gb, 1);
 +        out[((pos & block_mask) << 6) + scan[pos >> plane_size_factor]] =
 +            (level ^ sign) - sign;
 +    }
 +}
 +
 +
 +/**
 + * Decode a slice plane (luma or chroma).
 + */
 +static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
 +                               const uint8_t *buf,
 +                               int data_size, uint16_t *out_ptr,
 +                               int linesize, int mbs_per_slice,
 +                               int blocks_per_mb, int plane_size_factor,
-     for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
-         ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
-         block_ptr += 64;
-         if (blocks_per_mb > 2) {
-             ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
++                               const int16_t *qmat, int is_chroma)
 +{
 +    GetBitContext gb;
 +    DCTELEM *block_ptr;
 +    int mb_num, blocks_per_slice;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    memset(td->blocks, 0, 8 * 4 * 64 * sizeof(*td->blocks));
 +
 +    init_get_bits(&gb, buf, data_size << 3);
 +
 +    decode_dc_coeffs(&gb, td->blocks, blocks_per_slice);
 +
 +    decode_ac_coeffs(&gb, td->blocks, blocks_per_slice,
 +                     plane_size_factor, ctx->scantable.permutated);
 +
 +    /* inverse quantization, inverse transform and output */
 +    block_ptr = td->blocks;
 +
-         ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
-         block_ptr += 64;
-         if (blocks_per_mb > 2) {
-             ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
++    if (!is_chroma) {
++        for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
++            ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
++            block_ptr += 64;
++            if (blocks_per_mb > 2) {
++                ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
++                block_ptr += 64;
++            }
++            ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
 +            block_ptr += 64;
++            if (blocks_per_mb > 2) {
++                ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
++                block_ptr += 64;
++            }
 +        }
-                        td->qmat_luma_scaled);
++    } else {
++        for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) {
++            ctx->dsp.idct_put(out_ptr,                    linesize, block_ptr, qmat);
++            block_ptr += 64;
++            ctx->dsp.idct_put(out_ptr + linesize * 4,     linesize, block_ptr, qmat);
 +            block_ptr += 64;
++            if (blocks_per_mb > 2) {
++                ctx->dsp.idct_put(out_ptr + 8,            linesize, block_ptr, qmat);
++                block_ptr += 64;
++                ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat);
++                block_ptr += 64;
++            }
 +        }
 +    }
 +}
 +
 +
 +static int decode_slice(AVCodecContext *avctx, void *tdata)
 +{
 +    ProresThreadData *td = tdata;
 +    ProresContext *ctx = avctx->priv_data;
 +    int mb_x_pos  = td->x_pos;
 +    int mb_y_pos  = td->y_pos;
 +    int pic_num   = ctx->pic_num;
 +    int slice_num = td->slice_num;
 +    int mbs_per_slice = td->slice_width;
 +    const uint8_t *buf;
 +    uint8_t *y_data, *u_data, *v_data;
 +    AVFrame *pic = avctx->coded_frame;
 +    int i, sf, slice_width_factor;
 +    int slice_data_size, hdr_size, y_data_size, u_data_size, v_data_size;
 +    int y_linesize, u_linesize, v_linesize;
 +
 +    buf             = ctx->slice_data[slice_num].index;
 +    slice_data_size = ctx->slice_data[slice_num + 1].index - buf;
 +
 +    slice_width_factor = av_log2(mbs_per_slice);
 +
 +    y_data     = pic->data[0];
 +    u_data     = pic->data[1];
 +    v_data     = pic->data[2];
 +    y_linesize = pic->linesize[0];
 +    u_linesize = pic->linesize[1];
 +    v_linesize = pic->linesize[2];
 +
 +    if (pic->interlaced_frame) {
 +        if (!(pic_num ^ pic->top_field_first)) {
 +            y_data += y_linesize;
 +            u_data += u_linesize;
 +            v_data += v_linesize;
 +        }
 +        y_linesize <<= 1;
 +        u_linesize <<= 1;
 +        v_linesize <<= 1;
 +    }
 +
 +    if (slice_data_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "slice data too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    /* parse slice header */
 +    hdr_size    = buf[0] >> 3;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = hdr_size > 7 ? AV_RB16(buf + 6) :
 +        slice_data_size - y_data_size - u_data_size - hdr_size;
 +
 +    if (hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size ||
 +        v_data_size < 0 || hdr_size < 6) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid data size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    sf = av_clip(buf[1], 1, 224);
 +    sf = sf > 128 ? (sf - 96) << 2 : sf;
 +
 +    /* scale quantization matrixes according with slice's scale factor */
 +    /* TODO: this can be SIMD-optimized a lot */
 +    if (ctx->qmat_changed || sf != td->prev_slice_sf) {
 +        td->prev_slice_sf = sf;
 +        for (i = 0; i < 64; i++) {
 +            td->qmat_luma_scaled[ctx->dsp.idct_permutation[i]]   = ctx->qmat_luma[i]   * sf;
 +            td->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf;
 +        }
 +    }
 +
 +    /* decode luma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size, y_data_size,
 +                       (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize +
 +                                    (mb_x_pos << 5)), y_linesize,
 +                       mbs_per_slice, 4, slice_width_factor + 2,
-                        td->qmat_chroma_scaled);
++                       td->qmat_luma_scaled, 0);
 +
 +    /* decode U chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size,
 +                       (uint16_t*) (u_data + (mb_y_pos << 4) * u_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       u_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
-                        td->qmat_chroma_scaled);
++                       td->qmat_chroma_scaled, 1);
 +
 +    /* decode V chroma plane */
 +    decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size,
 +                       v_data_size,
 +                       (uint16_t*) (v_data + (mb_y_pos << 4) * v_linesize +
 +                                    (mb_x_pos << ctx->mb_chroma_factor)),
 +                       v_linesize, mbs_per_slice, ctx->num_chroma_blocks,
 +                       slice_width_factor + ctx->chroma_factor - 1,
++                       td->qmat_chroma_scaled, 1);
 +
 +    return 0;
 +}
 +
 +
 +static int decode_picture(ProresContext *ctx, int pic_num,
 +                          AVCodecContext *avctx)
 +{
 +    int slice_num, slice_width, x_pos, y_pos;
 +
 +    slice_num = 0;
 +
 +    ctx->pic_num = pic_num;
 +    for (y_pos = 0; y_pos < ctx->num_y_mbs; y_pos++) {
 +        slice_width = 1 << ctx->slice_width_factor;
 +
 +        for (x_pos = 0; x_pos < ctx->num_x_mbs && slice_width;
 +             x_pos += slice_width) {
 +            while (ctx->num_x_mbs - x_pos < slice_width)
 +                slice_width >>= 1;
 +
 +            ctx->slice_data[slice_num].slice_num   = slice_num;
 +            ctx->slice_data[slice_num].x_pos       = x_pos;
 +            ctx->slice_data[slice_num].y_pos       = y_pos;
 +            ctx->slice_data[slice_num].slice_width = slice_width;
 +
 +            slice_num++;
 +        }
 +    }
 +
 +    return avctx->execute(avctx, decode_slice,
 +                          ctx->slice_data, NULL, slice_num,
 +                          sizeof(ctx->slice_data[0]));
 +}
 +
 +
 +#define MOVE_DATA_PTR(nbytes) buf += (nbytes); buf_size -= (nbytes)
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    AVFrame *picture   = avctx->coded_frame;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size       = avpkt->size;
 +    int frame_hdr_size, pic_num, pic_data_size;
 +
 +    /* check frame atom container */
 +    if (buf_size < 28 || buf_size < AV_RB32(buf) ||
 +        AV_RB32(buf + 4) != FRAME_ID) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    MOVE_DATA_PTR(8);
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return AVERROR_INVALIDDATA;
 +
 +    MOVE_DATA_PTR(frame_hdr_size);
 +
 +    if (picture->data[0])
 +        avctx->release_buffer(avctx, picture);
 +
 +    picture->reference = 0;
 +    if (avctx->get_buffer(avctx, picture) < 0)
 +        return -1;
 +
 +    for (pic_num = 0; ctx->picture.interlaced_frame - pic_num + 1; pic_num++) {
 +        pic_data_size = decode_picture_header(ctx, buf, buf_size, avctx);
 +        if (pic_data_size < 0)
 +            return AVERROR_INVALIDDATA;
 +
 +        if (decode_picture(ctx, pic_num, avctx))
 +            return -1;
 +
 +        MOVE_DATA_PTR(pic_data_size);
 +    }
 +
 +    *data_size       = sizeof(AVPicture);
 +    *(AVFrame*) data = *avctx->coded_frame;
 +
 +    return avpkt->size;
 +}
 +
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    if (ctx->picture.data[0])
 +        avctx->release_buffer(avctx, &ctx->picture);
 +
 +    av_freep(&ctx->slice_data);
 +
 +    return 0;
 +}
 +
 +
 +AVCodec ff_prores_lgpl_decoder = {
 +    .name           = "prores_lgpl",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)")
 +};
index 375dc52,0000000..7920d65
mode 100644,000000..100644
--- /dev/null
@@@ -1,890 -1,0 +1,903 @@@
-                            int mbs_per_slice, int blocks_per_mb)
 +/*
 + * Apple ProRes encoder
 + *
 + * Copyright (c) 2012 Konstantin Shishkov
 + *
 + * This file is part of Libav.
 + *
 + * Libav 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,
 + * 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
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "put_bits.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "proresdsp.h"
 +#include "proresdata.h"
 +
 +#define CFACTOR_Y422 2
 +#define CFACTOR_Y444 3
 +
 +#define MAX_MBS_PER_SLICE 8
 +
 +#define MAX_PLANES 3 // should be increased to 4 when there's PIX_FMT_YUV444AP10
 +
 +enum {
 +    PRORES_PROFILE_PROXY = 0,
 +    PRORES_PROFILE_LT,
 +    PRORES_PROFILE_STANDARD,
 +    PRORES_PROFILE_HQ,
 +};
 +
 +#define NUM_MB_LIMITS 4
 +static const int prores_mb_limits[NUM_MB_LIMITS] = {
 +    1620, // up to 720x576
 +    2700, // up to 960x720
 +    6075, // up to 1440x1080
 +    9216, // up to 2048x1152
 +};
 +
 +static const struct prores_profile {
 +    const char *full_name;
 +    uint32_t    tag;
 +    int         min_quant;
 +    int         max_quant;
 +    int         br_tab[NUM_MB_LIMITS];
 +    uint8_t     quant[64];
 +} prores_profile_info[4] = {
 +    {
 +        .full_name = "proxy",
 +        .tag       = MKTAG('a', 'p', 'c', 'o'),
 +        .min_quant = 4,
 +        .max_quant = 8,
 +        .br_tab    = { 300, 242, 220, 194 },
 +        .quant     = {
 +             4,  7,  9, 11, 13, 14, 15, 63,
 +             7,  7, 11, 12, 14, 15, 63, 63,
 +             9, 11, 13, 14, 15, 63, 63, 63,
 +            11, 11, 13, 14, 63, 63, 63, 63,
 +            11, 13, 14, 63, 63, 63, 63, 63,
 +            13, 14, 63, 63, 63, 63, 63, 63,
 +            13, 63, 63, 63, 63, 63, 63, 63,
 +            63, 63, 63, 63, 63, 63, 63, 63,
 +        },
 +    },
 +    {
 +        .full_name = "LT",
 +        .tag       = MKTAG('a', 'p', 'c', 's'),
 +        .min_quant = 1,
 +        .max_quant = 9,
 +        .br_tab    = { 720, 560, 490, 440 },
 +        .quant     = {
 +             4,  5,  6,  7,  9, 11, 13, 15,
 +             5,  5,  7,  8, 11, 13, 15, 17,
 +             6,  7,  9, 11, 13, 15, 15, 17,
 +             7,  7,  9, 11, 13, 15, 17, 19,
 +             7,  9, 11, 13, 14, 16, 19, 23,
 +             9, 11, 13, 14, 16, 19, 23, 29,
 +             9, 11, 13, 15, 17, 21, 28, 35,
 +            11, 13, 16, 17, 21, 28, 35, 41,
 +        },
 +    },
 +    {
 +        .full_name = "standard",
 +        .tag       = MKTAG('a', 'p', 'c', 'n'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1050, 808, 710, 632 },
 +        .quant     = {
 +             4,  4,  5,  5,  6,  7,  7,  9,
 +             4,  4,  5,  6,  7,  7,  9,  9,
 +             5,  5,  6,  7,  7,  9,  9, 10,
 +             5,  5,  6,  7,  7,  9,  9, 10,
 +             5,  6,  7,  7,  8,  9, 10, 12,
 +             6,  7,  7,  8,  9, 10, 12, 15,
 +             6,  7,  7,  9, 10, 11, 14, 17,
 +             7,  7,  9, 10, 11, 14, 17, 21,
 +        },
 +    },
 +    {
 +        .full_name = "high quality",
 +        .tag       = MKTAG('a', 'p', 'c', 'h'),
 +        .min_quant = 1,
 +        .max_quant = 6,
 +        .br_tab    = { 1566, 1216, 1070, 950 },
 +        .quant     = {
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  4,
 +             4,  4,  4,  4,  4,  4,  4,  5,
 +             4,  4,  4,  4,  4,  4,  5,  5,
 +             4,  4,  4,  4,  4,  5,  5,  6,
 +             4,  4,  4,  4,  5,  5,  6,  7,
 +             4,  4,  4,  4,  5,  6,  7,  7,
 +        },
 +    }
 +// for 4444 profile bitrate numbers are { 2350, 1828, 1600, 1425 }
 +};
 +
 +#define TRELLIS_WIDTH 16
 +#define SCORE_LIMIT   INT_MAX / 2
 +
 +struct TrellisNode {
 +    int prev_node;
 +    int quant;
 +    int bits;
 +    int score;
 +};
 +
 +#define MAX_STORED_Q 16
 +
 +typedef struct ProresContext {
 +    AVClass *class;
 +    DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE];
 +    DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16];
 +    int16_t quants[MAX_STORED_Q][64];
 +    int16_t custom_q[64];
 +
 +    ProresDSPContext dsp;
 +    ScanTable  scantable;
 +
 +    int mb_width, mb_height;
 +    int mbs_per_slice;
 +    int num_chroma_blocks, chroma_factor;
 +    int slices_width;
 +    int num_slices;
 +    int num_planes;
 +    int bits_per_mb;
 +
 +    int frame_size;
 +
 +    int profile;
 +    const struct prores_profile *profile_info;
 +
 +    struct TrellisNode *nodes;
 +    int *slice_q;
 +} ProresContext;
 +
 +static void get_slice_data(ProresContext *ctx, const uint16_t *src,
 +                           int linesize, int x, int y, int w, int h,
 +                           DCTELEM *blocks,
-             const int estride = 16 / sizeof(*ctx->emu_buf);
++                           int mbs_per_slice, int blocks_per_mb, int is_chroma)
 +{
 +    const uint16_t *esrc;
 +    const int mb_width = 4 * blocks_per_mb;
 +    int elinesize;
 +    int i, j, k;
 +
 +    for (i = 0; i < mbs_per_slice; i++, src += mb_width) {
 +        if (x >= w) {
 +            memset(blocks, 0, 64 * (mbs_per_slice - i) * blocks_per_mb
 +                              * sizeof(*blocks));
 +            return;
 +        }
 +        if (x + mb_width <= w && y + 16 <= h) {
 +            esrc      = src;
 +            elinesize = linesize;
 +        } else {
 +            int bw, bh, pix;
-             elinesize = 16;
 +
 +            esrc      = ctx->emu_buf;
-                 memcpy(ctx->emu_buf + j * estride, src + j * linesize,
++            elinesize = 16 * sizeof(*ctx->emu_buf);
 +
 +            bw = FFMIN(w - x, mb_width);
 +            bh = FFMIN(h - y, 16);
 +
 +            for (j = 0; j < bh; j++) {
-                 pix = ctx->emu_buf[j * estride + bw - 1];
++                memcpy(ctx->emu_buf + j * 16,
++                       (const uint8_t*)src + j * linesize,
 +                       bw * sizeof(*src));
-                     ctx->emu_buf[j * estride + k] = pix;
++                pix = ctx->emu_buf[j * 16 + bw - 1];
 +                for (k = bw; k < mb_width; k++)
-                 memcpy(ctx->emu_buf + j * estride,
-                        ctx->emu_buf + (bh - 1) * estride,
++                    ctx->emu_buf[j * 16 + k] = pix;
 +            }
 +            for (; j < 16; j++)
-         ctx->dsp.fdct(esrc, elinesize, blocks);
-         blocks += 64;
-         if (blocks_per_mb > 2) {
-             ctx->dsp.fdct(src + 8, linesize, blocks);
++                memcpy(ctx->emu_buf + j * 16,
++                       ctx->emu_buf + (bh - 1) * 16,
 +                       mb_width * sizeof(*ctx->emu_buf));
 +        }
-         }
-         ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
-         blocks += 64;
-         if (blocks_per_mb > 2) {
-             ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
++        if (!is_chroma) {
++            ctx->dsp.fdct(esrc, elinesize, blocks);
 +            blocks += 64;
-                        mbs_per_slice, num_cblocks);
++            if (blocks_per_mb > 2) {
++                ctx->dsp.fdct(src + 8, linesize, blocks);
++                blocks += 64;
++            }
++            ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
 +            blocks += 64;
++            if (blocks_per_mb > 2) {
++                ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
++                blocks += 64;
++            }
++        } else {
++            ctx->dsp.fdct(esrc, elinesize, blocks);
++            blocks += 64;
++            ctx->dsp.fdct(src + linesize * 4, linesize, blocks);
++            blocks += 64;
++            if (blocks_per_mb > 2) {
++                ctx->dsp.fdct(src + 8, linesize, blocks);
++                blocks += 64;
++                ctx->dsp.fdct(src + linesize * 4 + 8, linesize, blocks);
++                blocks += 64;
++            }
 +        }
 +
 +        x += mb_width;
 +    }
 +}
 +
 +/**
 + * Write an unsigned rice/exp golomb codeword.
 + */
 +static inline void encode_vlc_codeword(PutBitContext *pb, unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        put_bits(pb, exponent - exp_order + switch_bits, 0);
 +        put_bits(pb, 1, 1);
 +        put_bits(pb, exponent, val);
 +    } else {
 +        exponent = val >> rice_order;
 +
 +        if (exponent)
 +            put_bits(pb, exponent, 0);
 +        put_bits(pb, 1, 1);
 +        if (rice_order)
 +            put_sbits(pb, rice_order, val);
 +    }
 +}
 +
 +#define GET_SIGN(x)  ((x) >> 31)
 +#define MAKE_CODE(x) (((x) << 1) ^ GET_SIGN(x))
 +
 +static void encode_dcs(PutBitContext *pb, DCTELEM *blocks,
 +                       int blocks_per_slice, int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +
 +    prev_dc = (blocks[0] - 0x4000) / scale;
 +    encode_vlc_codeword(pb, FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        encode_vlc_codeword(pb, ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +}
 +
 +static void encode_acs(PutBitContext *pb, DCTELEM *blocks,
 +                       int blocks_per_slice,
 +                       int plane_size_factor,
 +                       const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level = blocks[idx] / qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[run_cb], run);
 +                encode_vlc_codeword(pb, ff_prores_ac_codebook[lev_cb],
 +                                    abs_level - 1);
 +                put_sbits(pb, 1, GET_SIGN(level));
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +}
 +
 +static int encode_slice_plane(ProresContext *ctx, PutBitContext *pb,
 +                              const uint16_t *src, int linesize,
 +                              int mbs_per_slice, DCTELEM *blocks,
 +                              int blocks_per_mb, int plane_size_factor,
 +                              const int16_t *qmat)
 +{
 +    int blocks_per_slice, saved_pos;
 +
 +    saved_pos = put_bits_count(pb);
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    encode_dcs(pb, blocks, blocks_per_slice, qmat[0]);
 +    encode_acs(pb, blocks, blocks_per_slice, plane_size_factor,
 +               ctx->scantable.permutated, qmat);
 +    flush_put_bits(pb);
 +
 +    return (put_bits_count(pb) - saved_pos) >> 3;
 +}
 +
 +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
 +                        PutBitContext *pb,
 +                        int sizes[4], int x, int y, int quant,
 +                        int mbs_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, xp, yp;
 +    int total_size = 0;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks, pwidth;
 +    int plane_factor, is_chroma;
 +    uint16_t *qmat;
 +
 +    if (quant < MAX_STORED_Q) {
 +        qmat = ctx->quants[quant];
 +    } else {
 +        qmat = ctx->custom_q;
 +        for (i = 0; i < 64; i++)
 +            qmat[i] = ctx->profile_info->quant[i] * quant;
 +    }
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma    = (i == 1 || i == 2);
 +        plane_factor = slice_width_factor + 2;
 +        if (is_chroma)
 +            plane_factor += ctx->chroma_factor - 3;
 +        if (!is_chroma || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp          = x << 4;
 +            yp          = y << 4;
 +            num_cblocks = 4;
 +            pwidth      = avctx->width;
 +        } else {
 +            xp          = x << 3;
 +            yp          = y << 4;
 +            num_cblocks = 2;
 +            pwidth      = avctx->width >> 1;
 +        }
 +        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, pic->linesize[i], xp, yp,
 +                       pwidth, avctx->height, ctx->blocks[0],
-                        mbs_per_slice, num_cblocks[i]);
++                       mbs_per_slice, num_cblocks, is_chroma);
 +        sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i],
 +                                      mbs_per_slice, ctx->blocks[0],
 +                                      num_cblocks, plane_factor,
 +                                      qmat);
 +        total_size += sizes[i];
 +    }
 +    return total_size;
 +}
 +
 +static inline int estimate_vlc(unsigned codebook, int val)
 +{
 +    unsigned int rice_order, exp_order, switch_bits, switch_val;
 +    int exponent;
 +
 +    /* number of prefix bits to switch between Rice and expGolomb */
 +    switch_bits = (codebook & 3) + 1;
 +    rice_order  =  codebook >> 5;       /* rice code order */
 +    exp_order   = (codebook >> 2) & 7;  /* exp golomb code order */
 +
 +    switch_val  = switch_bits << rice_order;
 +
 +    if (val >= switch_val) {
 +        val -= switch_val - (1 << exp_order);
 +        exponent = av_log2(val);
 +
 +        return exponent * 2 - exp_order + switch_bits + 1;
 +    } else {
 +        return (val >> rice_order) + rice_order + 1;
 +    }
 +}
 +
 +static int estimate_dcs(int *error, DCTELEM *blocks, int blocks_per_slice,
 +                        int scale)
 +{
 +    int i;
 +    int codebook = 3, code, dc, prev_dc, delta, sign, new_sign;
 +    int bits;
 +
 +    prev_dc  = (blocks[0] - 0x4000) / scale;
 +    bits     = estimate_vlc(FIRST_DC_CB, MAKE_CODE(prev_dc));
 +    sign     = 0;
 +    codebook = 3;
 +    blocks  += 64;
 +    *error  += FFABS(blocks[0] - 0x4000) % scale;
 +
 +    for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
 +        dc       = (blocks[0] - 0x4000) / scale;
 +        *error  += FFABS(blocks[0] - 0x4000) % scale;
 +        delta    = dc - prev_dc;
 +        new_sign = GET_SIGN(delta);
 +        delta    = (delta ^ sign) - sign;
 +        code     = MAKE_CODE(delta);
 +        bits    += estimate_vlc(ff_prores_dc_codebook[codebook], code);
 +        codebook = (code + (code & 1)) >> 1;
 +        codebook = FFMIN(codebook, 3);
 +        sign     = new_sign;
 +        prev_dc  = dc;
 +    }
 +
 +    return bits;
 +}
 +
 +static int estimate_acs(int *error, DCTELEM *blocks, int blocks_per_slice,
 +                        int plane_size_factor,
 +                        const uint8_t *scan, const int16_t *qmat)
 +{
 +    int idx, i;
 +    int run, level, run_cb, lev_cb;
 +    int max_coeffs, abs_level;
 +    int bits = 0;
 +
 +    max_coeffs = blocks_per_slice << 6;
 +    run_cb     = ff_prores_run_to_cb_index[4];
 +    lev_cb     = ff_prores_lev_to_cb_index[2];
 +    run        = 0;
 +
 +    for (i = 1; i < 64; i++) {
 +        for (idx = scan[i]; idx < max_coeffs; idx += 64) {
 +            level   = blocks[idx] / qmat[scan[i]];
 +            *error += FFABS(blocks[idx]) % qmat[scan[i]];
 +            if (level) {
 +                abs_level = FFABS(level);
 +                bits += estimate_vlc(ff_prores_ac_codebook[run_cb], run);
 +                bits += estimate_vlc(ff_prores_ac_codebook[lev_cb],
 +                                     abs_level - 1) + 1;
 +
 +                run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)];
 +                lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)];
 +                run    = 0;
 +            } else {
 +                run++;
 +            }
 +        }
 +    }
 +
 +    return bits;
 +}
 +
 +static int estimate_slice_plane(ProresContext *ctx, int *error, int plane,
 +                                const uint16_t *src, int linesize,
 +                                int mbs_per_slice,
 +                                int blocks_per_mb, int plane_size_factor,
 +                                const int16_t *qmat)
 +{
 +    int blocks_per_slice;
 +    int bits;
 +
 +    blocks_per_slice = mbs_per_slice * blocks_per_mb;
 +
 +    bits  = estimate_dcs(error, ctx->blocks[plane], blocks_per_slice, qmat[0]);
 +    bits += estimate_acs(error, ctx->blocks[plane], blocks_per_slice,
 +                         plane_size_factor, ctx->scantable.permutated, qmat);
 +
 +    return FFALIGN(bits, 8);
 +}
 +
 +static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,
 +                            int trellis_node, int x, int y, int mbs_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, q, pq, xp, yp;
 +    const uint16_t *src;
 +    int slice_width_factor = av_log2(mbs_per_slice);
 +    int num_cblocks[MAX_PLANES], pwidth;
 +    int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES];
 +    const int min_quant = ctx->profile_info->min_quant;
 +    const int max_quant = ctx->profile_info->max_quant;
 +    int error, bits, bits_limit;
 +    int mbs, prev, cur, new_score;
 +    int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH];
 +    int overquant;
 +    uint16_t *qmat;
 +
 +    mbs = x + mbs_per_slice;
 +
 +    for (i = 0; i < ctx->num_planes; i++) {
 +        is_chroma[i]    = (i == 1 || i == 2);
 +        plane_factor[i] = slice_width_factor + 2;
 +        if (is_chroma[i])
 +            plane_factor[i] += ctx->chroma_factor - 3;
 +        if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) {
 +            xp             = x << 4;
 +            yp             = y << 4;
 +            num_cblocks[i] = 4;
 +            pwidth         = avctx->width;
 +        } else {
 +            xp             = x << 3;
 +            yp             = y << 4;
 +            num_cblocks[i] = 2;
 +            pwidth         = avctx->width >> 1;
 +        }
 +        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;
 +
 +        get_slice_data(ctx, src, pic->linesize[i], xp, yp,
 +                       pwidth, avctx->height, ctx->blocks[i],
-     bytestream_put_byte  (&buf, 0);             // primaries
-     bytestream_put_byte  (&buf, 0);             // transfer function
-     bytestream_put_byte  (&buf, 6);             // colour matrix - ITU-R BT.601-4
++                       mbs_per_slice, num_cblocks[i], is_chroma[i]);
 +    }
 +
 +    for (q = min_quant; q < max_quant + 2; q++) {
 +        ctx->nodes[trellis_node + q].prev_node = -1;
 +        ctx->nodes[trellis_node + q].quant     = q;
 +    }
 +
 +    // todo: maybe perform coarser quantising to fit into frame size when needed
 +    for (q = min_quant; q <= max_quant; q++) {
 +        bits  = 0;
 +        error = 0;
 +        for (i = 0; i < ctx->num_planes; i++) {
 +            bits += estimate_slice_plane(ctx, &error, i,
 +                                         src, pic->linesize[i],
 +                                         mbs_per_slice,
 +                                         num_cblocks[i], plane_factor[i],
 +                                         ctx->quants[q]);
 +        }
 +        if (bits > 65000 * 8) {
 +            error = SCORE_LIMIT;
 +            break;
 +        }
 +        slice_bits[q]  = bits;
 +        slice_score[q] = error;
 +    }
 +    if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) {
 +        slice_bits[max_quant + 1]  = slice_bits[max_quant];
 +        slice_score[max_quant + 1] = slice_score[max_quant] + 1;
 +        overquant = max_quant;
 +    } else {
 +        for (q = max_quant + 1; q < 128; q++) {
 +            bits  = 0;
 +            error = 0;
 +            if (q < MAX_STORED_Q) {
 +                qmat = ctx->quants[q];
 +            } else {
 +                qmat = ctx->custom_q;
 +                for (i = 0; i < 64; i++)
 +                    qmat[i] = ctx->profile_info->quant[i] * q;
 +            }
 +            for (i = 0; i < ctx->num_planes; i++) {
 +                bits += estimate_slice_plane(ctx, &error, i,
 +                                             src, pic->linesize[i],
 +                                             mbs_per_slice,
 +                                             num_cblocks[i], plane_factor[i],
 +                                             qmat);
 +            }
 +            if (bits <= ctx->bits_per_mb * mbs_per_slice)
 +                break;
 +        }
 +
 +        slice_bits[max_quant + 1]  = bits;
 +        slice_score[max_quant + 1] = error;
 +        overquant = q;
 +    }
 +    ctx->nodes[trellis_node + max_quant + 1].quant = overquant;
 +
 +    bits_limit = mbs * ctx->bits_per_mb;
 +    for (pq = min_quant; pq < max_quant + 2; pq++) {
 +        prev = trellis_node - TRELLIS_WIDTH + pq;
 +
 +        for (q = min_quant; q < max_quant + 2; q++) {
 +            cur = trellis_node + q;
 +
 +            bits  = ctx->nodes[prev].bits + slice_bits[q];
 +            error = slice_score[q];
 +            if (bits > bits_limit)
 +                error = SCORE_LIMIT;
 +
 +            if (ctx->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT)
 +                new_score = ctx->nodes[prev].score + error;
 +            else
 +                new_score = SCORE_LIMIT;
 +            if (ctx->nodes[cur].prev_node == -1 ||
 +                ctx->nodes[cur].score >= new_score) {
 +
 +                ctx->nodes[cur].bits      = bits;
 +                ctx->nodes[cur].score     = new_score;
 +                ctx->nodes[cur].prev_node = prev;
 +            }
 +        }
 +    }
 +
 +    error = ctx->nodes[trellis_node + min_quant].score;
 +    pq    = trellis_node + min_quant;
 +    for (q = min_quant + 1; q < max_quant + 2; q++) {
 +        if (ctx->nodes[trellis_node + q].score <= error) {
 +            error = ctx->nodes[trellis_node + q].score;
 +            pq    = trellis_node + q;
 +        }
 +    }
 +
 +    return pq;
 +}
 +
 +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                        const AVFrame *pic, int *got_packet)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t *orig_buf, *buf, *slice_hdr, *slice_sizes, *tmp;
 +    uint8_t *picture_size_pos;
 +    PutBitContext pb;
 +    int x, y, i, mb, q = 0;
 +    int sizes[4] = { 0 };
 +    int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
 +    int frame_size, picture_size, slice_size;
 +    int mbs_per_slice = ctx->mbs_per_slice;
 +    int pkt_size, ret;
 +
 +    *avctx->coded_frame           = *pic;
 +    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 +    avctx->coded_frame->key_frame = 1;
 +
 +    pkt_size = ctx->frame_size + FF_MIN_BUFFER_SIZE;
 +
 +    if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
 +        return ret;
 +    }
 +
 +    orig_buf = pkt->data;
 +
 +    // frame atom
 +    orig_buf += 4;                              // frame size
 +    bytestream_put_be32  (&orig_buf, FRAME_ID); // frame container ID
 +    buf = orig_buf;
 +
 +    // frame header
 +    tmp = buf;
 +    buf += 2;                                   // frame header size will be stored here
 +    bytestream_put_be16  (&buf, 0);             // version 1
 +    bytestream_put_buffer(&buf, "Lavc", 4);     // creator
 +    bytestream_put_be16  (&buf, avctx->width);
 +    bytestream_put_be16  (&buf, avctx->height);
 +    bytestream_put_byte  (&buf, ctx->chroma_factor << 6); // frame flags
 +    bytestream_put_byte  (&buf, 0);             // reserved
++    bytestream_put_byte  (&buf, avctx->color_primaries);
++    bytestream_put_byte  (&buf, avctx->color_trc);
++    bytestream_put_byte  (&buf, avctx->colorspace);
 +    bytestream_put_byte  (&buf, 0x40);          // source format and alpha information
 +    bytestream_put_byte  (&buf, 0);             // reserved
 +    bytestream_put_byte  (&buf, 0x03);          // matrix flags - both matrices are present
 +    // luma quantisation matrix
 +    for (i = 0; i < 64; i++)
 +        bytestream_put_byte(&buf, ctx->profile_info->quant[i]);
 +    // chroma quantisation matrix
 +    for (i = 0; i < 64; i++)
 +        bytestream_put_byte(&buf, ctx->profile_info->quant[i]);
 +    bytestream_put_be16  (&tmp, buf - orig_buf); // write back frame header size
 +
 +    // picture header
 +    picture_size_pos = buf + 1;
 +    bytestream_put_byte  (&buf, 0x40);          // picture header size (in bits)
 +    buf += 4;                                   // picture data size will be stored here
 +    bytestream_put_be16  (&buf, ctx->num_slices); // total number of slices
 +    bytestream_put_byte  (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
 +
 +    // seek table - will be filled during slice encoding
 +    slice_sizes = buf;
 +    buf += ctx->num_slices * 2;
 +
 +    // slices
 +    for (y = 0; y < ctx->mb_height; y++) {
 +        mbs_per_slice = ctx->mbs_per_slice;
 +        for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +            while (ctx->mb_width - x < mbs_per_slice)
 +                mbs_per_slice >>= 1;
 +            q = find_slice_quant(avctx, pic, (mb + 1) * TRELLIS_WIDTH, x, y,
 +                                 mbs_per_slice);
 +        }
 +
 +        for (x = ctx->slices_width - 1; x >= 0; x--) {
 +            ctx->slice_q[x] = ctx->nodes[q].quant;
 +            q = ctx->nodes[q].prev_node;
 +        }
 +
 +        mbs_per_slice = ctx->mbs_per_slice;
 +        for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
 +            q = ctx->slice_q[mb];
 +
 +            while (ctx->mb_width - x < mbs_per_slice)
 +                mbs_per_slice >>= 1;
 +
 +            bytestream_put_byte(&buf, slice_hdr_size << 3);
 +            slice_hdr = buf;
 +            buf += slice_hdr_size - 1;
 +            init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8);
 +            encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice);
 +
 +            bytestream_put_byte(&slice_hdr, q);
 +            slice_size = slice_hdr_size + sizes[ctx->num_planes - 1];
 +            for (i = 0; i < ctx->num_planes - 1; i++) {
 +                bytestream_put_be16(&slice_hdr, sizes[i]);
 +                slice_size += sizes[i];
 +            }
 +            bytestream_put_be16(&slice_sizes, slice_size);
 +            buf += slice_size - slice_hdr_size;
 +        }
 +    }
 +
 +    orig_buf -= 8;
 +    frame_size = buf - orig_buf;
 +    picture_size = buf - picture_size_pos - 6;
 +    bytestream_put_be32(&orig_buf, frame_size);
 +    bytestream_put_be32(&picture_size_pos, picture_size);
 +
 +    pkt->size   = frame_size;
 +    pkt->flags |= AV_PKT_FLAG_KEY;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    if (avctx->coded_frame->data[0])
 +        avctx->release_buffer(avctx, avctx->coded_frame);
 +
 +    av_freep(&avctx->coded_frame);
 +
 +    av_freep(&ctx->nodes);
 +    av_freep(&ctx->slice_q);
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int mps;
 +    int i, j;
 +    int min_quant, max_quant;
 +
 +    avctx->bits_per_raw_sample = 10;
 +    avctx->coded_frame = avcodec_alloc_frame();
 +    if (!avctx->coded_frame)
 +        return AVERROR(ENOMEM);
 +
 +    ff_proresdsp_init(&ctx->dsp, avctx);
 +    ff_init_scantable(ctx->dsp.dct_permutation, &ctx->scantable,
 +                      ff_prores_progressive_scan);
 +
 +    mps = ctx->mbs_per_slice;
 +    if (mps & (mps - 1)) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "there should be an integer power of two MBs per slice\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    ctx->chroma_factor = avctx->pix_fmt == PIX_FMT_YUV422P10
 +                         ? CFACTOR_Y422
 +                         : CFACTOR_Y444;
 +    ctx->profile_info  = prores_profile_info + ctx->profile;
 +    ctx->num_planes    = 3;
 +
 +    ctx->mb_width      = FFALIGN(avctx->width,  16) >> 4;
 +    ctx->mb_height     = FFALIGN(avctx->height, 16) >> 4;
 +    ctx->slices_width  = ctx->mb_width / mps;
 +    ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps);
 +    ctx->num_slices    = ctx->mb_height * ctx->slices_width;
 +
 +    for (i = 0; i < NUM_MB_LIMITS - 1; i++)
 +        if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height)
 +            break;
 +    ctx->bits_per_mb   = ctx->profile_info->br_tab[i];
 +
 +    ctx->frame_size = ctx->num_slices * (2 + 2 * ctx->num_planes
 +                                         + (2 * mps * ctx->bits_per_mb) / 8)
 +                      + 200;
 +
 +    min_quant = ctx->profile_info->min_quant;
 +    max_quant = ctx->profile_info->max_quant;
 +    for (i = min_quant; i < MAX_STORED_Q; i++) {
 +        for (j = 0; j < 64; j++)
 +            ctx->quants[i][j] = ctx->profile_info->quant[j] * i;
 +    }
 +
 +    avctx->codec_tag   = ctx->profile_info->tag;
 +
 +    av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n",
 +           ctx->profile, ctx->num_slices, ctx->bits_per_mb);
 +    av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n",
 +           ctx->frame_size);
 +
 +    ctx->nodes = av_malloc((ctx->slices_width + 1) * TRELLIS_WIDTH
 +                           * sizeof(*ctx->nodes));
 +    if (!ctx->nodes) {
 +        encode_close(avctx);
 +        return AVERROR(ENOMEM);
 +    }
 +    for (i = min_quant; i < max_quant + 2; i++) {
 +        ctx->nodes[i].prev_node = -1;
 +        ctx->nodes[i].bits      = 0;
 +        ctx->nodes[i].score     = 0;
 +    }
 +
 +    ctx->slice_q = av_malloc(ctx->slices_width * sizeof(*ctx->slice_q));
 +    if (!ctx->slice_q) {
 +        encode_close(avctx);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(ProresContext, x)
 +#define VE     AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +
 +static const AVOption options[] = {
 +    { "mbs_per_slice", "macroblocks per slice", OFFSET(mbs_per_slice),
 +        AV_OPT_TYPE_INT, { 8 }, 1, MAX_MBS_PER_SLICE, VE },
 +    { "profile",       NULL, OFFSET(profile), AV_OPT_TYPE_INT,
 +        { PRORES_PROFILE_STANDARD },
 +        PRORES_PROFILE_PROXY, PRORES_PROFILE_HQ, VE, "profile" },
 +    { "proxy",         NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_PROXY },
 +        0, 0, VE, "profile" },
 +    { "lt",            NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_LT },
 +        0, 0, VE, "profile" },
 +    { "standard",      NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_STANDARD },
 +        0, 0, VE, "profile" },
 +    { "hq",            NULL, 0, AV_OPT_TYPE_CONST, { PRORES_PROFILE_HQ },
 +        0, 0, VE, "profile" },
 +    { NULL }
 +};
 +
 +static const AVClass proresenc_class = {
 +    .class_name = "ProRes encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_prores_kostya_encoder = {
 +    .name           = "prores_kostya",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = encode_init,
 +    .close          = encode_close,
 +    .encode2        = encode_frame,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"),
 +    .pix_fmts       = (const enum PixelFormat[]) {
 +                          PIX_FMT_YUV422P10, PIX_FMT_YUV444P10, PIX_FMT_NONE
 +                      },
 +    .priv_class     = &proresenc_class,
 +};
@@@ -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