Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--doc/APIchanges8
-rw-r--r--doc/muxers.texi34
-rw-r--r--libavcodec/aacdec.c154
-rw-r--r--libavcodec/ac3enc.c28
-rw-r--r--libavcodec/ac3enc_fixed.c1
-rw-r--r--libavcodec/ac3enc_float.c1
-rw-r--r--libavcodec/ac3enc_opts_template.c6
-rw-r--r--libavcodec/amrnbdec.c8
-rw-r--r--libavcodec/avcodec.h34
-rw-r--r--libavcodec/cscd.c4
-rw-r--r--libavcodec/dpxenc.c3
-rw-r--r--libavcodec/eac3enc.c1
-rw-r--r--libavcodec/flvenc.c3
-rw-r--r--libavcodec/h261enc.c3
-rw-r--r--libavcodec/h263.h2
-rw-r--r--libavcodec/h264_cabac.c2
-rw-r--r--libavcodec/libvorbis.c308
-rw-r--r--libavcodec/mpeg12enc.c2
-rw-r--r--libavcodec/mpeg4videoenc.c3
-rw-r--r--libavcodec/mpegaudiodec.c7
-rw-r--r--libavcodec/mpegvideo.h35
-rw-r--r--libavcodec/mpegvideo_enc.c73
-rw-r--r--libavcodec/options.c28
-rw-r--r--libavcodec/proresdec_lgpl.c45
-rw-r--r--libavcodec/proresenc_kostya.c57
-rw-r--r--libavcodec/qtrle.c2
-rw-r--r--libavcodec/rpza.c4
-rw-r--r--libavcodec/rv10enc.c3
-rw-r--r--libavcodec/rv20enc.c3
-rw-r--r--libavcodec/version.h9
-rw-r--r--libavcodec/vmnc.c2
-rw-r--r--libavcodec/vp5.c5
-rw-r--r--libavcodec/vp6.c6
-rw-r--r--libavformat/asfdec.c26
-rw-r--r--libavformat/avformat.h16
-rw-r--r--libavformat/dxa.c2
-rw-r--r--libavformat/ffmdec.c2
-rw-r--r--libavformat/ffmenc.c2
-rw-r--r--libavformat/id3v2.c153
-rw-r--r--libavformat/id3v2.h57
-rw-r--r--libavformat/id3v2enc.c192
-rw-r--r--libavformat/internal.h5
-rw-r--r--libavformat/matroska.h6
-rw-r--r--libavformat/mov.c7
-rw-r--r--libavformat/mp3enc.c257
-rw-r--r--libavformat/omadec.c2
-rw-r--r--libavformat/omaenc.c2
-rw-r--r--libavformat/psxstr.c1
-rw-r--r--libavformat/rtpenc.c2
-rw-r--r--libavformat/swfdec.c2
-rw-r--r--libavformat/utils.c55
-rw-r--r--libavformat/version.h2
-rw-r--r--libavformat/vqf.c6
-rw-r--r--libswscale/utils.c2
-rwxr-xr-xtests/codec-regression.sh6
-rw-r--r--tests/fate/cdxl.mak3
-rw-r--r--tests/fate/mp3.mak5
-rw-r--r--tests/fate/video.mak2
-rw-r--r--tests/ref/fate/cdxl-bitline-ham611
-rw-r--r--tests/ref/fate/nuv19
-rw-r--r--tests/ref/lavf/ffm2
-rw-r--r--tests/ref/vsynth1/prores_kostya2
-rw-r--r--tests/ref/vsynth2/prores_kostya2
64 files changed, 1217 insertions, 519 deletions
diff --git a/Changelog b/Changelog
index d42d01c818..c1cb488ace 100644
--- a/Changelog
+++ b/Changelog
@@ -8,6 +8,7 @@ version next:
- Apple ProRes encoder
- ffprobe -count_packets and -count_frames options
- Sun Rasterfile Encoder
+- ID3v2 attached pictures reading and writing
version 0.10:
diff --git a/doc/APIchanges b/doc/APIchanges
index fe951d8303..5818f6a8ec 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,7 @@ libavutil: 2011-04-18
API changes, most recent first:
+<<<<<<< HEAD
2012-02-21 - xxxxxxx - lavc 54.4.100
Add av_get_pcm_codec() function.
@@ -35,6 +36,13 @@ API changes, most recent first:
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 --git a/doc/muxers.texi b/doc/muxers.texi
index ddce0e902c..f500f0ab0e 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -370,5 +370,39 @@ Wrap around segment index once it reaches @var{limit}.
ffmpeg -i in.mkv -c copy -map 0 -f segment -list out.list out%03d.nut
@end example
+@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
+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
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 3d38645599..74ad09902e 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -114,55 +114,6 @@ static VLC vlc_spectral[11];
static const char overread_err[] = "Input buffer exhausted before END element found\n";
-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];
- }
- // 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;
- }
-}
-
static int count_channels(uint8_t (*layout)[3], int tags)
{
int i, sum = 0;
@@ -455,6 +406,90 @@ static void flush(AVCodecContext *avctx)
}
/**
+ * 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
@@ -551,27 +586,6 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
}
/**
- * 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;
-}
-
-/**
* Decode GA "General Audio" specific configuration; reference: table 4.1.
*
* @param ac pointer to AACContext, may be null
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index d49873a6f6..9d72a3bd88 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -2138,6 +2138,17 @@ static av_cold int validate_options(AC3EncodeContext *s)
s->bit_alloc.sr_code = i % 3;
s->bitstream_id = s->eac3 ? 16 : 8 + s->bit_alloc.sr_shift;
+ /* select a default bit rate if not set by the user */
+ if (!avctx->bit_rate) {
+ switch (s->fbw_channels) {
+ case 1: avctx->bit_rate = 96000; break;
+ case 2: avctx->bit_rate = 192000; break;
+ case 3: avctx->bit_rate = 320000; break;
+ case 4: avctx->bit_rate = 384000; break;
+ case 5: avctx->bit_rate = 448000; break;
+ }
+ }
+
/* validate bit rate */
if (s->eac3) {
int max_br, min_br, wpf, min_br_dist, min_br_code;
@@ -2186,15 +2197,20 @@ static av_cold int validate_options(AC3EncodeContext *s)
wpf--;
s->frame_size_min = 2 * wpf;
} else {
+ int best_br = 0, best_code = 0, best_diff = INT_MAX;
for (i = 0; i < 19; i++) {
- if ((ff_ac3_bitrate_tab[i] >> s->bit_alloc.sr_shift)*1000 == avctx->bit_rate)
+ int br = (ff_ac3_bitrate_tab[i] >> s->bit_alloc.sr_shift) * 1000;
+ int diff = abs(br - avctx->bit_rate);
+ if (diff < best_diff) {
+ best_br = br;
+ best_code = i;
+ best_diff = diff;
+ }
+ if (!best_diff)
break;
}
- if (i == 19) {
- av_log(avctx, AV_LOG_ERROR, "invalid bit rate\n");
- return AVERROR(EINVAL);
- }
- s->frame_size_code = i << 1;
+ avctx->bit_rate = best_br;
+ s->frame_size_code = best_code << 1;
s->frame_size_min = 2 * ff_ac3_frame_size_tab[s->frame_size_code][s->bit_alloc.sr_code];
s->num_blks_code = 0x3;
s->num_blocks = 6;
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index 4b844783a9..24612c0949 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -157,4 +157,5 @@ AVCodec ff_ac3_fixed_encoder = {
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.priv_class = &ac3enc_class,
.channel_layouts = ff_ac3_channel_layouts,
+ .defaults = ac3_defaults,
};
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 0d4000c05a..073045c9e0 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -155,5 +155,6 @@ AVCodec ff_ac3_encoder = {
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.priv_class = &ac3enc_class,
.channel_layouts = ff_ac3_channel_layouts,
+ .defaults = ac3_defaults,
};
#endif
diff --git a/libavcodec/ac3enc_opts_template.c b/libavcodec/ac3enc_opts_template.c
index a5f848e200..fa8984476e 100644
--- a/libavcodec/ac3enc_opts_template.c
+++ b/libavcodec/ac3enc_opts_template.c
@@ -20,6 +20,7 @@
*/
#include "libavutil/opt.h"
+#include "internal.h"
#include "ac3.h"
#if AC3ENC_TYPE == AC3ENC_TYPE_AC3_FIXED
@@ -78,3 +79,8 @@ static const AVOption eac3_options[] = {
{"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.dbl = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "cpl_start_band"},
{NULL}
};
+
+static const AVCodecDefault ac3_defaults[] = {
+ { "b", "0" },
+ { NULL }
+};
diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c
index c560d69e88..dc7f95ccbc 100644
--- a/libavcodec/amrnbdec.c
+++ b/libavcodec/amrnbdec.c
@@ -200,6 +200,10 @@ static enum Mode unpack_bitstream(AMRContext *p, const uint8_t *buf,
p->bad_frame_indicator = !get_bits1(&gb); // quality bit
skip_bits(&gb, 2); // two padding bits
+ if (mode >= N_MODES || buf_size < frame_sizes_nb[mode] + 1) {
+ return NO_DATA;
+ }
+
if (mode < MODE_DTX)
ff_amr_bit_reorder((uint16_t *) &p->frame, sizeof(AMRNBFrame), buf + 1,
amr_unpacking_bitmaps_per_mode[mode]);
@@ -947,6 +951,10 @@ static int amrnb_decode_frame(AVCodecContext *avctx, void *data,
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", 0);
av_log(avctx, AV_LOG_INFO, "Note: libopencore_amrnb supports dtx\n");
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 3ece8fe86c..39f69eee44 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -582,17 +582,19 @@ typedef struct RcOverride{
#define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT).
/* Fx : Flag for h263+ extra options */
#define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction
-#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_FLAG_LOOP_FILTER 0x00000800 ///< loop filter
#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
@@ -1492,19 +1494,21 @@ typedef struct AVCodecContext {
int b_frame_strategy;
+#if FF_API_MPV_GLOBAL_OPTS
/**
* luma single coefficient elimination threshold
* - encoding: Set by user.
* - decoding: unused
*/
- int luma_elim_threshold;
+ attribute_deprecated int luma_elim_threshold;
/**
* chroma single coeff elimination threshold
* - encoding: Set by user.
* - decoding: unused
*/
- int chroma_elim_threshold;
+ attribute_deprecated int chroma_elim_threshold;
+#endif
/**
* qscale offset between IP and B-frames
@@ -1735,13 +1739,15 @@ typedef struct AVCodecContext {
*/
int inter_quant_bias;
+#if FF_API_COLOR_TABLE_ID
/**
* color table ID
* - encoding: unused
* - decoding: Which clrtable should be used for 8bit RGB images.
* Tables have to be stored somewhere. FIXME
*/
- int color_table_id;
+ attribute_deprecated int color_table_id;
+#endif
/**
* slice flags
@@ -1799,19 +1805,19 @@ typedef struct AVCodecContext {
*/
int noise_reduction;
+#if FF_API_INTER_THRESHOLD
/**
- *
- * - encoding: Set by user.
- * - decoding: unused
+ * @deprecated this field is unused
*/
- int inter_threshold;
+ attribute_deprecated int inter_threshold;
+#endif
+#if FF_API_MPV_GLOBAL_OPTS
/**
- * quantizer noise shaping
- * - encoding: Set by user.
- * - decoding: unused
+ * @deprecated use mpegvideo private options instead
*/
- int quantizer_noise_shaping;
+ attribute_deprecated int quantizer_noise_shaping;
+#endif
/**
* Motion estimation threshold below which no motion estimation is
diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c
index 4f9b70c88b..dafb0c9161 100644
--- a/libavcodec/cscd.c
+++ b/libavcodec/cscd.c
@@ -228,7 +228,7 @@ static av_cold int decode_init(AVCodecContext *avctx) {
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);
@@ -242,7 +242,7 @@ static av_cold int decode_init(AVCodecContext *avctx) {
c->decomp_buf = av_malloc(c->decomp_size + AV_LZO_OUTPUT_PADDING);
if (!c->decomp_buf) {
av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
- return 1;
+ return AVERROR(ENOMEM);
}
return 0;
}
diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c
index bde02bce1c..05a7134378 100644
--- a/libavcodec/dpxenc.c
+++ b/libavcodec/dpxenc.c
@@ -131,9 +131,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
memcpy (buf + 8, "V1.0", 4);
write32(buf + 20, 1); /* new image */
write32(buf + 24, HEADER_SIZE);
- if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
+ if (!(avctx->flags & CODEC_FLAG_BITEXACT))
memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100));
- }
write32(buf + 660, 0xFFFFFFFF); /* unencrypted */
/* Image information header */
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index f3b4418896..459fb90ce6 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -258,5 +258,6 @@ AVCodec ff_eac3_encoder = {
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"),
.priv_class = &eac3enc_class,
.channel_layouts = ff_ac3_channel_layouts,
+ .defaults = ac3_defaults,
};
#endif
diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c
index d1484b44e3..be9778c5ab 100644
--- a/libavcodec/flvenc.c
+++ b/libavcodec/flvenc.c
@@ -84,6 +84,8 @@ void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, in
}
}
+FF_MPV_GENERIC_CLASS(flv)
+
AVCodec ff_flv_encoder = {
.name = "flv",
.type = AVMEDIA_TYPE_VIDEO,
@@ -94,4 +96,5 @@ AVCodec ff_flv_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("Flash Video (FLV) / Sorenson Spark / Sorenson H.263"),
+ .priv_class = &flv_class,
};
diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index 35b4abd251..a2566988ea 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -321,6 +321,8 @@ static void h261_encode_block(H261Context * h, DCTELEM * block, int n){
}
}
+FF_MPV_GENERIC_CLASS(h261)
+
AVCodec ff_h261_encoder = {
.name = "h261",
.type = AVMEDIA_TYPE_VIDEO,
@@ -331,4 +333,5 @@ AVCodec ff_h261_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("H.261"),
+ .priv_class = &h261_class,
};
diff --git a/libavcodec/h263.h b/libavcodec/h263.h
index ed9da5352b..91dd548108 100644
--- a/libavcodec/h263.h
+++ b/libavcodec/h263.h
@@ -148,7 +148,7 @@ static inline int get_p_cbp(MpegEncContext * s,
int motion_x, int motion_y){
int cbp, i;
- if(s->flags & CODEC_FLAG_CBP_RD){
+ if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
int best_cbpy_score= INT_MAX;
int best_cbpc_score= INT_MAX;
int cbpc = (-1), cbpy= (-1);
diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c
index ea120ed74a..2c83348a5f 100644
--- a/libavcodec/h264_cabac.c
+++ b/libavcodec/h264_cabac.c
@@ -1998,6 +1998,8 @@ decode_intra_mb:
}
// The pixels are stored in the same order as levels in h->mb array.
+ if ((int) (h->cabac.bytestream_end - ptr) < mb_size)
+ return -1;
memcpy(h->mb, ptr, mb_size); ptr+=mb_size;
ff_init_cabac_decoder(&h->cabac, ptr, h->cabac.bytestream_end - ptr);
diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c
index 19dfa34fcc..f5ad49e68f 100644
--- a/libavcodec/libvorbis.c
+++ b/libavcodec/libvorbis.c
@@ -20,12 +20,13 @@
/**
* @file
- * Ogg Vorbis codec support via libvorbisenc.
+ * Vorbis encoding support via libvorbisenc.
* @author Mark Hills <mark@pogo.org.uk>
*/
#include <vorbis/vorbisenc.h>
+#include "libavutil/fifo.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "bytestream.h"
@@ -35,32 +36,41 @@
#undef NDEBUG
#include <assert.h>
+/* Number of samples the user should send in each call.
+ * This value is used because it is the LCD of all possible frame sizes, so
+ * an output packet will always start at the same point as one of the input
+ * packets.
+ */
#define OGGVORBIS_FRAME_SIZE 64
#define BUFFER_SIZE (1024 * 64)
typedef struct OggVorbisContext {
- AVClass *av_class;
- vorbis_info vi;
- vorbis_dsp_state vd;
- vorbis_block vb;
- uint8_t buffer[BUFFER_SIZE];
- int buffer_index;
- int eof;
-
- /* decoder */
- vorbis_comment vc;
- ogg_packet op;
-
- double iblock;
+ AVClass *av_class; /**< class for AVOptions */
+ vorbis_info vi; /**< vorbis_info used during init */
+ vorbis_dsp_state vd; /**< DSP state used for analysis */
+ vorbis_block vb; /**< vorbis_block used for analysis */
+ AVFifoBuffer *pkt_fifo; /**< output packet buffer */
+ int eof; /**< end-of-file flag */
+ int dsp_initialized; /**< vd has been initialized */
+ vorbis_comment vc; /**< VorbisComment info */
+ ogg_packet op; /**< ogg packet */
+ double iblock; /**< impulse block bias option */
} OggVorbisContext;
static const AVOption options[] = {
{ "iblock", "Sets the impulse block bias", offsetof(OggVorbisContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
{ NULL }
};
+
+static const AVCodecDefault defaults[] = {
+ { "b", "0" },
+ { NULL },
+};
+
static const AVClass class = { "libvorbis", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
+
static int vorbis_error_to_averror(int ov_err)
{
switch (ov_err) {
@@ -71,27 +81,34 @@ static int vorbis_error_to_averror(int ov_err)
}
}
-static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext)
+static av_cold int oggvorbis_init_encoder(vorbis_info *vi,
+ AVCodecContext *avctx)
{
- OggVorbisContext *context = avccontext->priv_data;
+ OggVorbisContext *s = avctx->priv_data;
double cfreq;
int ret;
- if (avccontext->flags & CODEC_FLAG_QSCALE) {
- /* variable bitrate */
- float q = avccontext->global_quality / (float)FF_QP2LAMBDA;
- if ((ret = vorbis_encode_setup_vbr(vi, avccontext->channels,
- avccontext->sample_rate,
+ if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) {
+ /* variable bitrate
+ * NOTE: we use the oggenc range of -1 to 10 for global_quality for
+ * user convenience, but libvorbis uses -0.1 to 1.0.
+ */
+ float q = avctx->global_quality / (float)FF_QP2LAMBDA;
+ /* default to 3 if the user did not set quality or bitrate */
+ if (!(avctx->flags & CODEC_FLAG_QSCALE))
+ q = 3.0;
+ if ((ret = vorbis_encode_setup_vbr(vi, avctx->channels,
+ avctx->sample_rate,
q / 10.0)))
goto error;
} else {
- int minrate = avccontext->rc_min_rate > 0 ? avccontext->rc_min_rate : -1;
- int maxrate = avccontext->rc_min_rate > 0 ? avccontext->rc_max_rate : -1;
+ int minrate = avctx->rc_min_rate > 0 ? avctx->rc_min_rate : -1;
+ int maxrate = avctx->rc_max_rate > 0 ? avctx->rc_max_rate : -1;
- /* constant bitrate */
- if ((ret = vorbis_encode_setup_managed(vi, avccontext->channels,
- avccontext->sample_rate, minrate,
- avccontext->bit_rate, maxrate)))
+ /* average bitrate */
+ if ((ret = vorbis_encode_setup_managed(vi, avctx->channels,
+ avctx->sample_rate, maxrate,
+ avctx->bit_rate, minrate)))
goto error;
/* variable bitrate by estimate, disable slow rate management */
@@ -101,43 +118,44 @@ static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avcco
}
/* 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; /* 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);
}
}
@@ -155,59 +173,64 @@ static int xiph_len(int l)
return 1 + l / 255 + l;
}
-static av_cold int oggvorbis_encode_close(AVCodecContext *avccontext)
+static av_cold int oggvorbis_encode_close(AVCodecContext *avctx)
{
- OggVorbisContext *context = avccontext->priv_data;
-/* ogg_packet op ; */
+ OggVorbisContext *s = avctx->priv_data;
- vorbis_analysis_wrote(&context->vd, 0); /* notify vorbisenc this is EOF */
+ /* notify vorbisenc this is EOF */
+ if (s->dsp_initialized)
+ vorbis_analysis_wrote(&s->vd, 0);
- vorbis_block_clear(&context->vb);
- vorbis_dsp_clear(&context->vd);
- vorbis_info_clear(&context->vi);
+ vorbis_block_clear(&s->vb);
+ vorbis_dsp_clear(&s->vd);
+ vorbis_info_clear(&s->vi);
- av_freep(&avccontext->coded_frame);
- av_freep(&avccontext->extradata);
+ av_fifo_free(s->pkt_fifo);
+ av_freep(&avctx->coded_frame);
+ av_freep(&avctx->extradata);
return 0;
}
-static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext)
+static av_cold int oggvorbis_encode_init(AVCodecContext *avctx)
{
- OggVorbisContext *context = avccontext->priv_data;
+ OggVorbisContext *s = avctx->priv_data;
ogg_packet header, header_comm, header_code;
uint8_t *p;
unsigned int offset;
int ret;
- vorbis_info_init(&context->vi);
- if ((ret = oggvorbis_init_encoder(&context->vi, avccontext))) {
- av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed\n");
+ vorbis_info_init(&s->vi);
+ if ((ret = oggvorbis_init_encoder(&s->vi, avctx))) {
+ av_log(avctx, AV_LOG_ERROR, "encoder setup failed\n");
goto error;
}
- if ((ret = vorbis_analysis_init(&context->vd, &context->vi))) {
+ if ((ret = vorbis_analysis_init(&s->vd, &s->vi))) {
+ av_log(avctx, AV_LOG_ERROR, "analysis init failed\n");
ret = vorbis_error_to_averror(ret);
goto error;
}
- if ((ret = vorbis_block_init(&context->vd, &context->vb))) {
+ s->dsp_initialized = 1;
+ if ((ret = vorbis_block_init(&s->vd, &s->vb))) {
+ av_log(avctx, AV_LOG_ERROR, "dsp init failed\n");
ret = vorbis_error_to_averror(ret);
goto error;
}
- vorbis_comment_init(&context->vc);
- vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT);
+ vorbis_comment_init(&s->vc);
+ vorbis_comment_add_tag(&s->vc, "encoder", LIBAVCODEC_IDENT);
- if ((ret = vorbis_analysis_headerout(&context->vd, &context->vc, &header,
- &header_comm, &header_code))) {
+ if ((ret = vorbis_analysis_headerout(&s->vd, &s->vc, &header, &header_comm,
+ &header_code))) {
ret = vorbis_error_to_averror(ret);
goto error;
}
- avccontext->extradata_size =
- 1 + xiph_len(header.bytes) + xiph_len(header_comm.bytes) +
- header_code.bytes;
- p = avccontext->extradata =
- av_malloc(avccontext->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ avctx->extradata_size = 1 + xiph_len(header.bytes) +
+ xiph_len(header_comm.bytes) +
+ header_code.bytes;
+ p = avctx->extradata = av_malloc(avctx->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
if (!p) {
ret = AVERROR(ENOMEM);
goto error;
@@ -222,100 +245,107 @@ static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext)
offset += header_comm.bytes;
memcpy(&p[offset], header_code.packet, header_code.bytes);
offset += header_code.bytes;
- assert(offset == avccontext->extradata_size);
+ assert(offset == avctx->extradata_size);
-#if 0
- vorbis_block_clear(&context->vb);
- vorbis_dsp_clear(&context->vd);
- vorbis_info_clear(&context->vi);
-#endif
- vorbis_comment_clear(&context->vc);
+ vorbis_comment_clear(&s->vc);
- avccontext->frame_size = OGGVORBIS_FRAME_SIZE;
+ avctx->frame_size = OGGVORBIS_FRAME_SIZE;
+
+ s->pkt_fifo = av_fifo_alloc(BUFFER_SIZE);
+ if (!s->pkt_fifo) {
+ ret = AVERROR(ENOMEM);
+ goto error;
+ }
- avccontext->coded_frame = avcodec_alloc_frame();
- if (!avccontext->coded_frame) {
+ avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
return 0;
error:
- oggvorbis_encode_close(avccontext);
+ oggvorbis_encode_close(avctx);
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\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\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 = {
@@ -327,7 +357,9 @@ AVCodec ff_libvorbis_encoder = {
.encode = oggvorbis_encode_frame,
.close = oggvorbis_encode_close,
.capabilities = CODEC_CAP_DELAY,
- .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
+ AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("libvorbis Vorbis"),
.priv_class = &class,
+ .defaults = defaults,
};
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index cc77fd1548..ddb9a34b37 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -939,6 +939,7 @@ static void mpeg1_encode_block(MpegEncContext *s,
static const AVOption mpeg1_options[] = {
COMMON_OPTS
+ FF_MPV_COMMON_OPTS
{ NULL },
};
@@ -946,6 +947,7 @@ static const AVOption mpeg2_options[] = {
COMMON_OPTS
{ "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
+ FF_MPV_COMMON_OPTS
{ NULL },
};
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 343c31644c..e31d2ce363 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -430,7 +430,7 @@ static inline int get_b_cbp(MpegEncContext * s, DCTELEM block[6][64],
{
int cbp = 0, i;
- if (s->flags & CODEC_FLAG_CBP_RD) {
+ if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
int score = 0;
const int lambda = s->lambda2 >> (FF_LAMBDA_SHIFT - 6);
@@ -1330,6 +1330,7 @@ void ff_mpeg4_encode_video_packet_header(MpegEncContext *s)
static const AVOption options[] = {
{ "data_partitioning", "Use data partitioning.", OFFSET(data_partitioning), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
+ FF_MPV_COMMON_OPTS
{ NULL },
};
diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c
index 75a3c5d372..00565875fc 100644
--- a/libavcodec/mpegaudiodec.c
+++ b/libavcodec/mpegaudiodec.c
@@ -31,6 +31,7 @@
#include "get_bits.h"
#include "mathops.h"
#include "mpegaudiodsp.h"
+#include "dsputil.h"
/*
* TODO:
@@ -82,6 +83,7 @@ typedef struct MPADecodeContext {
int err_recognition;
AVCodecContext* avctx;
MPADSPContext mpadsp;
+ DSPContext dsp;
AVFrame frame;
} MPADecodeContext;
@@ -434,6 +436,7 @@ static av_cold int decode_init(AVCodecContext * avctx)
s->avctx = avctx;
ff_mpadsp_init(&s->mpadsp);
+ ff_dsputil_init(&s->dsp, avctx);
avctx->sample_fmt= OUT_FMT;
s->err_recognition = avctx->err_recognition;
@@ -1155,6 +1158,9 @@ found2:
/* ms stereo ONLY */
/* NOTE: the 1/sqrt(2) normalization factor is included in the
global gain */
+#if CONFIG_FLOAT
+ s-> dsp.butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576);
+#else
tab0 = g0->sb_hybrid;
tab1 = g1->sb_hybrid;
for (i = 0; i < 576; i++) {
@@ -1163,6 +1169,7 @@ found2:
tab0[i] = tmp0 + tmp1;
tab1[i] = tmp0 - tmp1;
}
+#endif
}
}
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 06c56c9c5a..02f15da433 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -38,6 +38,8 @@
#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 {
@@ -695,6 +697,9 @@ typedef struct MpegEncContext {
int (*dct_quantize)(struct MpegEncContext *s, DCTELEM *block/*align 16*/, int n, int qscale, int *overflow);
int (*fast_dct_quantize)(struct MpegEncContext *s, DCTELEM *block/*align 16*/, int n, int qscale, int *overflow);
void (*denoise_dct)(struct MpegEncContext *s, DCTELEM *block);
+
+ int mpv_flags; ///< flags set by private options
+ int quantizer_noise_shaping;
} MpegEncContext;
#define REBASE_PICTURE(pic, new_ctx, old_ctx) (pic ? \
@@ -702,6 +707,36 @@ typedef struct MpegEncContext {
&new_ctx->picture[pic - old_ctx->picture] : pic - (Picture*)old_ctx + (Picture*)new_ctx)\
: NULL)
+/* mpegvideo_enc common options */
+#define FF_MPV_FLAG_SKIP_RD 0x0001
+#define FF_MPV_FLAG_STRICT_GOP 0x0002
+#define FF_MPV_FLAG_QP_RD 0x0004
+#define FF_MPV_FLAG_CBP_RD 0x0008
+
+#define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x)
+#define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+#define FF_MPV_COMMON_OPTS \
+{ "mpv_flags", "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "skip_rd", "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, { FF_MPV_FLAG_SKIP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "strict_gop", "Strictly enforce gop size", 0, AV_OPT_TYPE_CONST, { FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "qp_rd", "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { FF_MPV_FLAG_QP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "cbp_rd", "use rate distortion optimization for CBP", 0, AV_OPT_TYPE_CONST, { FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\
+ FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\
+{ "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\
+ FF_MPV_OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, { 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\
+{ "quantizer_noise_shaping", NULL, FF_MPV_OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },
+
+extern const AVOption ff_mpv_generic_options[];
+
+#define FF_MPV_GENERIC_CLASS(name) \
+static const AVClass name ## _class = {\
+ .class_name = #name " encoder",\
+ .item_name = av_default_item_name,\
+ .option = ff_mpv_generic_options,\
+ .version = LIBAVUTIL_VERSION_INT,\
+};
+
void ff_MPV_decode_defaults(MpegEncContext *s);
int ff_MPV_common_init(MpegEncContext *s);
void ff_MPV_common_end(MpegEncContext *s);
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 0441d8fa35..c780ffb598 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -63,6 +63,11 @@ static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int
static uint8_t default_mv_penalty[MAX_FCODE + 1][MAX_MV * 2 + 1];
static uint8_t default_fcode_tab[MAX_MV * 2 + 1];
+const AVOption ff_mpv_generic_options[] = {
+ FF_MPV_COMMON_OPTS
+ { NULL },
+};
+
void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64],
uint16_t (*qmat16)[2][64],
const uint16_t *quant_matrix,
@@ -352,8 +357,12 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx)
s->flags2 = avctx->flags2;
s->max_b_frames = avctx->max_b_frames;
s->codec_id = avctx->codec->id;
- s->luma_elim_threshold = avctx->luma_elim_threshold;
- s->chroma_elim_threshold = avctx->chroma_elim_threshold;
+#if FF_API_MPV_GLOBAL_OPTS
+ if (avctx->luma_elim_threshold)
+ s->luma_elim_threshold = avctx->luma_elim_threshold;
+ if (avctx->chroma_elim_threshold)
+ s->chroma_elim_threshold = avctx->chroma_elim_threshold;
+#endif
s->strict_std_compliance = avctx->strict_std_compliance;
s->quarter_sample = (avctx->flags & CODEC_FLAG_QPEL) != 0;
s->mpeg_quant = avctx->mpeg_quant;
@@ -373,13 +382,18 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx)
/* Fixed QSCALE */
s->fixed_qscale = !!(avctx->flags & CODEC_FLAG_QSCALE);
+#if FF_API_MPV_GLOBAL_OPTS
+ if (s->flags & CODEC_FLAG_QP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_QP_RD;
+#endif
+
s->adaptive_quant = (s->avctx->lumi_masking ||
s->avctx->dark_masking ||
s->avctx->temporal_cplx_masking ||
s->avctx->spatial_cplx_masking ||
s->avctx->p_masking ||
s->avctx->border_masking ||
- (s->flags & CODEC_FLAG_QP_RD)) &&
+ (s->mpv_flags & FF_MPV_FLAG_QP_RD)) &&
!s->fixed_qscale;
s->loop_filter = !!(s->flags & CODEC_FLAG_LOOP_FILTER);
@@ -488,12 +502,17 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx)
return -1;
}
- if ((s->flags & CODEC_FLAG_CBP_RD) && !avctx->trellis) {
+#if FF_API_MPV_GLOBAL_OPTS
+ if (s->flags & CODEC_FLAG_CBP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_CBP_RD;
+#endif
+
+ if ((s->mpv_flags & FF_MPV_FLAG_CBP_RD) && !avctx->trellis) {
av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quant\n");
return -1;
}
- if ((s->flags & CODEC_FLAG_QP_RD) &&
+ if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) &&
s->avctx->mb_decision != FF_MB_DECISION_RD) {
av_log(avctx, AV_LOG_ERROR, "QP RD needs mbd=2\n");
return -1;
@@ -610,6 +629,15 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx)
}
s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1;
+#if FF_API_MPV_GLOBAL_OPTS
+ if (avctx->flags2 & CODEC_FLAG2_SKIP_RD)
+ s->mpv_flags |= FF_MPV_FLAG_SKIP_RD;
+ if (avctx->flags2 & CODEC_FLAG2_STRICT_GOP)
+ s->mpv_flags |= FF_MPV_FLAG_STRICT_GOP;
+ if (avctx->quantizer_noise_shaping)
+ s->quantizer_noise_shaping = avctx->quantizer_noise_shaping;
+#endif
+
switch (avctx->codec->id) {
case CODEC_ID_MPEG1VIDEO:
s->out_format = FMT_MPEG1;
@@ -1301,7 +1329,7 @@ static int select_input_picture(MpegEncContext *s)
}
if (s->picture_in_gop_number + b_frames >= s->gop_size) {
- if ((s->flags2 & CODEC_FLAG2_STRICT_GOP) &&
+ if ((s->mpv_flags & FF_MPV_FLAG_STRICT_GOP) &&
s->gop_size > s->picture_in_gop_number) {
b_frames = s->gop_size - s->picture_in_gop_number - 1;
} else {
@@ -1726,7 +1754,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
s->lambda = s->lambda_table[mb_xy];
update_qscale(s);
- if (!(s->flags & CODEC_FLAG_QP_RD)) {
+ if (!(s->mpv_flags & FF_MPV_FLAG_QP_RD)) {
s->qscale = s->current_picture_ptr->f.qscale_table[mb_xy];
s->dquant = s->qscale - last_qp;
@@ -1746,7 +1774,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
}
}
ff_set_qscale(s, last_qp + s->dquant);
- } else if (s->flags & CODEC_FLAG_QP_RD)
+ } else if (s->mpv_flags & FF_MPV_FLAG_QP_RD)
ff_set_qscale(s, s->qscale + s->dquant);
wrap_y = s->linesize;
@@ -1934,7 +1962,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
}
}
- if (s->avctx->quantizer_noise_shaping) {
+ if (s->quantizer_noise_shaping) {
if (!skip_dct[0])
get_visual_weight(weight[0], ptr_y , wrap_y);
if (!skip_dct[1])
@@ -1975,7 +2003,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
} else
s->block_last_index[i] = -1;
}
- if (s->avctx->quantizer_noise_shaping) {
+ if (s->quantizer_noise_shaping) {
for (i = 0; i < mb_block_count; i++) {
if (!skip_dct[i]) {
s->block_last_index[i] =
@@ -1992,7 +2020,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
for (i = 4; i < mb_block_count; i++)
dct_single_coeff_elimination(s, i, s->chroma_elim_threshold);
- if (s->flags & CODEC_FLAG_CBP_RD) {
+ if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
for (i = 0; i < mb_block_count; i++) {
if (s->block_last_index[i] == -1)
s->coded_score[i] = INT_MAX / 256;
@@ -2513,7 +2541,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
s->mb_skipped=0;
s->dquant=0; //only for QP_RD
- if(mb_type & (mb_type-1) || (s->flags & CODEC_FLAG_QP_RD)){ // more than 1 MB type possible or CODEC_FLAG_QP_RD
+ if (mb_type & (mb_type-1) || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD
int next_block=0;
int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
@@ -2650,7 +2678,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
}
}
- if((s->flags & CODEC_FLAG_QP_RD) && dmin < INT_MAX){
+ if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && dmin < INT_MAX) {
if(best_s.mv_type==MV_TYPE_16X16){ //FIXME move 4mv after QPRD
const int last_qp= backup_s.qscale;
int qpi, qp, dc[6];
@@ -2715,7 +2743,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb,
&dmin, &next_block, 0, 0);
}
- if(!best_s.mb_intra && s->flags2&CODEC_FLAG2_SKIP_RD){
+ if (!best_s.mb_intra && s->mpv_flags & FF_MPV_FLAG_SKIP_RD) {
int coded=0;
for(i=0; i<6; i++)
coded |= s->block_last_index[i];
@@ -3755,7 +3783,7 @@ STOP_TIMER("init rem[]")
#ifdef REFINE_STATS
{START_TIMER
#endif
- analyze_gradient = last_non_zero > 2 || s->avctx->quantizer_noise_shaping >= 3;
+ analyze_gradient = last_non_zero > 2 || s->quantizer_noise_shaping >= 3;
if(analyze_gradient){
#ifdef REFINE_STATS
@@ -3813,7 +3841,7 @@ STOP_TIMER("dct")}
const int level= block[j];
int change, old_coeff;
- if(s->avctx->quantizer_noise_shaping < 3 && i > last_non_zero + 1)
+ if(s->quantizer_noise_shaping < 3 && i > last_non_zero + 1)
break;
if(level){
@@ -3831,7 +3859,7 @@ STOP_TIMER("dct")}
int score, new_coeff, unquant_change;
score=0;
- if(s->avctx->quantizer_noise_shaping < 2 && FFABS(new_level) > FFABS(level))
+ if(s->quantizer_noise_shaping < 2 && FFABS(new_level) > FFABS(level))
continue;
if(new_level){
@@ -4089,6 +4117,7 @@ int ff_dct_quantize_c(MpegEncContext *s,
static const AVOption h263_options[] = {
{ "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "structured_slices","Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
+ FF_MPV_COMMON_OPTS
{ NULL },
};
@@ -4117,6 +4146,7 @@ static const AVOption h263p_options[] = {
{ "aiv", "Use alternative inter VLC.", OFFSET(alt_inter_vlc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
{ "structured_slices", "Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
+ FF_MPV_COMMON_OPTS
{ NULL },
};
static const AVClass h263p_class = {
@@ -4140,6 +4170,8 @@ AVCodec ff_h263p_encoder = {
.priv_class = &h263p_class,
};
+FF_MPV_GENERIC_CLASS(msmpeg4v2)
+
AVCodec ff_msmpeg4v2_encoder = {
.name = "msmpeg4v2",
.type = AVMEDIA_TYPE_VIDEO,
@@ -4150,8 +4182,11 @@ AVCodec ff_msmpeg4v2_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"),
+ .priv_class = &msmpeg4v2_class,
};
+FF_MPV_GENERIC_CLASS(msmpeg4v3)
+
AVCodec ff_msmpeg4v3_encoder = {
.name = "msmpeg4",
.type = AVMEDIA_TYPE_VIDEO,
@@ -4162,8 +4197,11 @@ AVCodec ff_msmpeg4v3_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"),
+ .priv_class = &msmpeg4v3_class,
};
+FF_MPV_GENERIC_CLASS(wmv1)
+
AVCodec ff_wmv1_encoder = {
.name = "wmv1",
.type = AVMEDIA_TYPE_VIDEO,
@@ -4174,4 +4212,5 @@ AVCodec ff_wmv1_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("Windows Media Video 7"),
+ .priv_class = &wmv1_class,
};
diff --git a/libavcodec/options.c b/libavcodec/options.c
index 3be5861dde..04277dba4d 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -98,12 +98,16 @@ static const AVOption options[]={
{"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"},
{"bitexact", "use only bitexact stuff (except (i)dct)", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_BITEXACT }, INT_MIN, INT_MAX, A|V|S|D|E, "flags"},
{"aic", "h263 advanced intra coding / mpeg4 ac prediction", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_AC_PRED }, INT_MIN, INT_MAX, V|E, "flags"},
-{"cbp", "use rate distortion optimization for cbp", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_CBP_RD }, INT_MIN, INT_MAX, V|E, "flags"},
-{"qprd", "use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_QP_RD }, INT_MIN, INT_MAX, V|E, "flags"},
+#if FF_API_MPV_GLOBAL_OPTS
+{"cbp", "Deprecated, use mpegvideo private options instead", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_CBP_RD }, INT_MIN, INT_MAX, V|E, "flags"},
+{"qprd", "Deprecated, use mpegvideo private options instead", 0, AV_OPT_TYPE_CONST, {.dbl = CODEC_FLAG_QP_RD }, INT_MIN, INT_MAX, V|E, "flags"},
+#endif
{"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"},
@@ -167,8 +171,10 @@ static const AVOption options[]={
{"dc_clip", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = FF_BUG_DC_CLIP }, INT_MIN, INT_MAX, V|D, "bug"},
{"ms", "workaround various bugs in microsofts broken decoders", 0, AV_OPT_TYPE_CONST, {.dbl = FF_BUG_MS }, INT_MIN, INT_MAX, V|D, "bug"},
{"trunc", "trancated frames", 0, AV_OPT_TYPE_CONST, {.dbl = FF_BUG_TRUNCATED}, INT_MIN, INT_MAX, V|D, "bug"},
+#if FF_API_MPV_GLOBAL_OPTS
{"lelim", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)", OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
{"celim", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)", OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+#endif
{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.dbl = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"},
{"strict", "strictly conform to all the things in the spec no matter what consequences", 0, AV_OPT_TYPE_CONST, {.dbl = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"},
@@ -194,8 +200,8 @@ static const AVOption options[]={
{"rc_qmod_freq", "experimental quantizer modulation", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
{"rc_override_count", NULL, OFFSET(rc_override_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
{"rc_eq", "set rate control equation", OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E},
-{"maxrate", "set max video bitrate tolerance (in bits/s)", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"minrate", "set min video bitrate tolerance (in bits/s)", OFFSET(rc_min_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+{"maxrate", "set max bitrate tolerance (in bits/s)", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
+{"minrate", "set min bitrate tolerance (in bits/s)", OFFSET(rc_min_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
{"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, A|V|E},
{"rc_buf_aggressivity", "currently useless", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E},
{"i_qfactor", "qp factor between P and I frames", OFFSET(i_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = -0.8 }, -FLT_MAX, FLT_MAX, V|E},
@@ -296,7 +302,9 @@ static const AVOption options[]={
{"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
{"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.dbl = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
{"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.dbl = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
+#if FF_API_COLOR_TABLE_ID
{"color_table_id", NULL, OFFSET(color_table_id), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
+#endif
{"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
{"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"},
{"vlc", "variable length coder / huffman coder", 0, AV_OPT_TYPE_CONST, {.dbl = FF_CODER_TYPE_VLC }, INT_MIN, INT_MAX, V|E, "coder"},
@@ -317,10 +325,14 @@ static const AVOption options[]={
{"lmax", "max lagrange factor (VBR)", OFFSET(lmax), AV_OPT_TYPE_INT, {.dbl = 31*FF_QP2LAMBDA }, 0, INT_MAX, V|E},
{"nr", "noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
{"rc_init_occupancy", "number of bits which should be loaded into the rc buffer before decoding starts", OFFSET(rc_initial_buffer_occupancy), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+#if FF_API_INTER_THRESHOLD
{"inter_threshold", NULL, OFFSET(inter_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+#endif
{"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.dbl = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"},
{"error", NULL, OFFSET(error_rate), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"qns", "quantizer noise shaping", OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+#if FF_API_MPV_GLOBAL_OPTS
+{"qns", "deprecated, use mpegvideo private options instead", OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+#endif
{"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.dbl = 1 }, 0, INT_MAX, V|E|D, "threads"},
{"auto", "detect a good number of threads", 0, AV_OPT_TYPE_CONST, {.dbl = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"},
{"me_threshold", "motion estimaton threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
@@ -366,7 +378,9 @@ static const AVOption options[]={
{"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},
diff --git a/libavcodec/proresdec_lgpl.c b/libavcodec/proresdec_lgpl.c
index 882503a129..e358d7f9cb 100644
--- a/libavcodec/proresdec_lgpl.c
+++ b/libavcodec/proresdec_lgpl.c
@@ -165,6 +165,10 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
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);
@@ -411,7 +415,7 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
int data_size, uint16_t *out_ptr,
int linesize, int mbs_per_slice,
int blocks_per_mb, int plane_size_factor,
- const int16_t *qmat)
+ const int16_t *qmat, int is_chroma)
{
GetBitContext gb;
DCTELEM *block_ptr;
@@ -431,18 +435,33 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
/* inverse quantization, inverse transform and output */
block_ptr = td->blocks;
- 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);
+ 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;
+ }
}
- 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);
+ } 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;
+ }
}
}
}
@@ -523,7 +542,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(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_luma_scaled);
+ td->qmat_luma_scaled, 0);
/* decode U chroma plane */
decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size,
@@ -531,7 +550,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(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,
@@ -540,7 +559,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
(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);
+ td->qmat_chroma_scaled, 1);
return 0;
}
diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c
index 375dc5261c..7920d65ed1 100644
--- a/libavcodec/proresenc_kostya.c
+++ b/libavcodec/proresenc_kostya.c
@@ -171,7 +171,7 @@ typedef struct ProresContext {
static void get_slice_data(ProresContext *ctx, const uint16_t *src,
int linesize, int x, int y, int w, int h,
DCTELEM *blocks,
- int mbs_per_slice, int blocks_per_mb)
+ int mbs_per_slice, int blocks_per_mb, int is_chroma)
{
const uint16_t *esrc;
const int mb_width = 4 * blocks_per_mb;
@@ -189,37 +189,50 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src,
elinesize = linesize;
} else {
int bw, bh, pix;
- const int estride = 16 / sizeof(*ctx->emu_buf);
esrc = ctx->emu_buf;
- elinesize = 16;
+ elinesize = 16 * sizeof(*ctx->emu_buf);
bw = FFMIN(w - x, mb_width);
bh = FFMIN(h - y, 16);
for (j = 0; j < bh; j++) {
- memcpy(ctx->emu_buf + j * estride, src + j * linesize,
+ memcpy(ctx->emu_buf + j * 16,
+ (const uint8_t*)src + j * linesize,
bw * sizeof(*src));
- pix = ctx->emu_buf[j * estride + bw - 1];
+ pix = ctx->emu_buf[j * 16 + bw - 1];
for (k = bw; k < mb_width; k++)
- ctx->emu_buf[j * estride + k] = pix;
+ ctx->emu_buf[j * 16 + k] = pix;
}
for (; j < 16; j++)
- memcpy(ctx->emu_buf + j * estride,
- ctx->emu_buf + (bh - 1) * estride,
+ memcpy(ctx->emu_buf + j * 16,
+ ctx->emu_buf + (bh - 1) * 16,
mb_width * sizeof(*ctx->emu_buf));
}
- ctx->dsp.fdct(esrc, elinesize, blocks);
- blocks += 64;
- if (blocks_per_mb > 2) {
- ctx->dsp.fdct(src + 8, linesize, blocks);
+ if (!is_chroma) {
+ 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 + linesize * 4 + 8, linesize, blocks);
+ 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;
@@ -383,7 +396,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
get_slice_data(ctx, src, pic->linesize[i], xp, yp,
pwidth, avctx->height, ctx->blocks[0],
- mbs_per_slice, num_cblocks);
+ 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,
@@ -539,7 +552,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic,
get_slice_data(ctx, src, pic->linesize[i], xp, yp,
pwidth, avctx->height, ctx->blocks[i],
- mbs_per_slice, num_cblocks[i]);
+ mbs_per_slice, num_cblocks[i], is_chroma[i]);
}
for (q = min_quant; q < max_quant + 2; q++) {
@@ -676,9 +689,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
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, 0); // primaries
- bytestream_put_byte (&buf, 0); // transfer function
- bytestream_put_byte (&buf, 6); // colour matrix - ITU-R BT.601-4
+ 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
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index 606a2ea95d..e3a595c5ac 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -424,7 +424,7 @@ static av_cold int qtrle_decode_init(AVCodecContext *avctx)
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);
diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c
index 4c87b3c1b2..635b4069ef 100644
--- a/libavcodec/rpza.c
+++ b/libavcodec/rpza.c
@@ -183,6 +183,8 @@ static void rpza_decode_stream(RpzaContext *s)
color4[1] |= ((11 * ta + 21 * tb) >> 5);
color4[2] |= ((21 * ta + 11 * tb) >> 5);
+ if (s->size - stream_ptr < n_blocks * 4)
+ return;
while (n_blocks--) {
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
@@ -200,6 +202,8 @@ static void rpza_decode_stream(RpzaContext *s)
/* Fill block with 16 colors */
case 0x00:
+ if (s->size - stream_ptr < 16)
+ return;
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++){
diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c
index add7855b7f..3a4ee387ba 100644
--- a/libavcodec/rv10enc.c
+++ b/libavcodec/rv10enc.c
@@ -56,6 +56,8 @@ void ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number)
put_bits(&s->pb, 3, 0); /* ignored */
}
+FF_MPV_GENERIC_CLASS(rv10)
+
AVCodec ff_rv10_encoder = {
.name = "rv10",
.type = AVMEDIA_TYPE_VIDEO,
@@ -66,4 +68,5 @@ AVCodec ff_rv10_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("RealVideo 1.0"),
+ .priv_class = &rv10_class,
};
diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c
index 1eb21803ba..db5c86b8b2 100644
--- a/libavcodec/rv20enc.c
+++ b/libavcodec/rv20enc.c
@@ -57,6 +57,8 @@ void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){
}
}
+FF_MPV_GENERIC_CLASS(rv20)
+
AVCodec ff_rv20_encoder = {
.name = "rv20",
.type = AVMEDIA_TYPE_VIDEO,
@@ -67,4 +69,5 @@ AVCodec ff_rv20_encoder = {
.close = ff_MPV_encode_end,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("RealVideo 2.0"),
+ .priv_class = &rv20_class,
};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index ca0efb4fed..238866be6b 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -60,5 +60,14 @@
#ifndef FF_API_OLD_ENCODE_VIDEO
#define FF_API_OLD_ENCODE_VIDEO (LIBAVCODEC_VERSION_MAJOR < 55)
#endif
+#ifndef FF_API_MPV_GLOBAL_OPTS
+#define FF_API_MPV_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 55)
+#endif
+#ifndef FF_API_COLOR_TABLE_ID
+#define FF_API_COLOR_TABLE_ID (LIBAVCODEC_VERSION_MAJOR < 55)
+#endif
+#ifndef FF_API_INTER_THRESHOLD
+#define FF_API_INTER_THRESHOLD (LIBAVCODEC_VERSION_MAJOR < 55)
+#endif
#endif /* AVCODEC_VERSION_H */
diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c
index ac0b8252e4..a716b29b3c 100644
--- a/libavcodec/vmnc.c
+++ b/libavcodec/vmnc.c
@@ -484,7 +484,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp);
- return AVERROR_PATCHWELCOME;
+ return AVERROR_INVALIDDATA;
}
return 0;
diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c
index dc3c833f44..4c985525a2 100644
--- a/libavcodec/vp5.c
+++ b/libavcodec/vp5.c
@@ -57,6 +57,11 @@ static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
}
rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */
cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */
+ if (!rows || !cols) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid size %dx%d\n",
+ cols << 4, rows << 4);
+ return 0;
+ }
vp56_rac_gets(c, 8); /* number of displayed macroblock rows */
vp56_rac_gets(c, 8); /* number of displayed macroblock cols */
vp56_rac_gets(c, 2);
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index b9a9b237b6..8b975029d8 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -77,6 +77,10 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
cols = buf[3]; /* number of stored macroblock cols */
/* buf[4] is number of displayed macroblock rows */
/* buf[5] is number of displayed macroblock cols */
+ if (!rows || !cols) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid size %dx%d\n", cols << 4, rows << 4);
+ return 0;
+ }
if (!s->macroblocks || /* first frame */
16*cols != s->avctx->coded_width ||
@@ -97,7 +101,7 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
vrt_shift = 5;
s->sub_version = sub_version;
} else {
- if (!s->sub_version)
+ if (!s->sub_version || !s->avctx->coded_width || !s->avctx->coded_height)
return 0;
if (separated_coeff || !s->filter_header) {
diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
index b37cbb04d3..cdec63b481 100644
--- a/libavformat/asfdec.c
+++ b/libavformat/asfdec.c
@@ -26,7 +26,6 @@
#include "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/mathematics.h"
-#include "libavcodec/mpegaudio.h"
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
@@ -199,6 +198,8 @@ static int asf_read_file_properties(AVFormatContext *s, int64_t size)
asf->hdr.flags = avio_rl32(pb);
asf->hdr.min_pktsize = avio_rl32(pb);
asf->hdr.max_pktsize = avio_rl32(pb);
+ if (asf->hdr.min_pktsize >= (1U<<29))
+ return AVERROR_INVALIDDATA;
asf->hdr.max_bitrate = avio_rl32(pb);
s->packet_size = asf->hdr.max_pktsize;
@@ -317,25 +318,6 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
|| asf_st->ds_packet_size % asf_st->ds_chunk_size)
asf_st->ds_span = 0; // disable descrambling
}
- switch (st->codec->codec_id) {
- case CODEC_ID_MP3:
- st->codec->frame_size = MPA_FRAME_SIZE;
- break;
- case CODEC_ID_PCM_S16LE:
- case CODEC_ID_PCM_S16BE:
- case CODEC_ID_PCM_U16LE:
- case CODEC_ID_PCM_U16BE:
- case CODEC_ID_PCM_S8:
- case CODEC_ID_PCM_U8:
- case CODEC_ID_PCM_ALAW:
- case CODEC_ID_PCM_MULAW:
- st->codec->frame_size = 1;
- break;
- default:
- /* This is probably wrong, but it prevents a crash later */
- st->codec->frame_size = 1;
- break;
- }
} else if (type == AVMEDIA_TYPE_VIDEO &&
size - (avio_tell(pb) - pos1 + 24) >= 51) {
avio_rl32(pb);
@@ -612,7 +594,9 @@ static int asf_read_header(AVFormatContext *s)
if (gsize < 24)
return -1;
if (!ff_guidcmp(&g, &ff_asf_file_header)) {
- asf_read_file_properties(s, gsize);
+ int ret = asf_read_file_properties(s, gsize);
+ if (ret < 0)
+ return ret;
} else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
asf_read_stream_properties(s, gsize);
} else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 00a52e5da6..1dc74fc9ff 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -541,6 +541,13 @@ typedef struct AVIndexEntry {
#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */
#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */
#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */
+/**
+ * The stream is stored in the file as an attached picture/"cover art" (e.g.
+ * APIC frame in ID3v2). The single packet associated with it will be returned
+ * among the first few packets read from the file unless seeking takes place.
+ * It can also be accessed at any time in AVStream.attached_pic.
+ */
+#define AV_DISPOSITION_ATTACHED_PIC 0x0400
/**
* Stream structure.
@@ -615,6 +622,15 @@ typedef struct AVStream {
*/
AVRational avg_frame_rate;
+ /**
+ * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
+ * will contain the attached picture.
+ *
+ * decoding: set by libavformat, must not be modified by the caller.
+ * encoding: unused
+ */
+ AVPacket attached_pic;
+
/*****************************************************************
* All fields below this line are not part of the public API. They
* may not be used outside of libavformat and can be changed and
diff --git a/libavformat/dxa.c b/libavformat/dxa.c
index f4e13835b2..3d85193279 100644
--- a/libavformat/dxa.c
+++ b/libavformat/dxa.c
@@ -107,6 +107,8 @@ static int dxa_read_header(AVFormatContext *s)
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 && !url_feof(pb)){
tag = avio_rl32(pb);
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index f500511d44..6bcb98c72e 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -338,8 +338,6 @@ static int ffm_read_header(AVFormatContext *s)
codec->dct_algo = avio_rb32(pb);
codec->strict_std_compliance = avio_rb32(pb);
codec->max_b_frames = avio_rb32(pb);
- codec->luma_elim_threshold = avio_rb32(pb);
- codec->chroma_elim_threshold = avio_rb32(pb);
codec->mpeg_quant = avio_rb32(pb);
codec->intra_dc_precision = avio_rb32(pb);
codec->me_method = avio_rb32(pb);
diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
index eb21fd79bb..84ed697dd5 100644
--- a/libavformat/ffmenc.c
+++ b/libavformat/ffmenc.c
@@ -144,8 +144,6 @@ static int ffm_write_header(AVFormatContext *s)
avio_wb32(pb, codec->dct_algo);
avio_wb32(pb, codec->strict_std_compliance);
avio_wb32(pb, codec->max_b_frames);
- avio_wb32(pb, codec->luma_elim_threshold);
- avio_wb32(pb, codec->chroma_elim_threshold);
avio_wb32(pb, codec->mpeg_quant);
avio_wb32(pb, codec->intra_dc_precision);
avio_wb32(pb, codec->me_method);
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 250281c357..f14b13e92f 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -38,6 +38,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "avio_internal.h"
+#include "internal.h"
const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
{ "TALB", "album"},
@@ -99,6 +100,38 @@ const char ff_id3v2_3_tags[][4] = {
{ 0 },
};
+const char *ff_id3v2_picture_types[21] = {
+ "Other",
+ "32x32 pixels 'file icon'",
+ "Other file icon",
+ "Cover (front)",
+ "Cover (back)",
+ "Leaflet page",
+ "Media (e.g. label side of CD)",
+ "Lead artist/lead performer/soloist",
+ "Artist/performer",
+ "Conductor",
+ "Band/Orchestra",
+ "Composer",
+ "Lyricist/text writer",
+ "Recording Location",
+ "During recording",
+ "During performance",
+ "Movie/video screen capture",
+ "A bright coloured fish",
+ "Illustration",
+ "Band/artist logotype",
+ "Publisher/Studio logotype",
+};
+
+const CodecMime ff_id3v2_mime_tags[] = {
+ {"image/gif" , CODEC_ID_GIF},
+ {"image/jpeg", CODEC_ID_MJPEG},
+ {"image/png" , CODEC_ID_PNG},
+ {"image/tiff", CODEC_ID_TIFF},
+ {"", CODEC_ID_NONE},
+};
+
int ff_id3v2_match(const uint8_t *buf, const char * magic)
{
return buf[0] == magic[0] &&
@@ -394,6 +427,84 @@ finish:
av_dict_set(m, "date", date, 0);
}
+static void free_apic(void *obj)
+{
+ ID3v2ExtraMetaAPIC *apic = obj;
+ av_freep(&apic->data);
+ av_freep(&apic->description);
+ av_freep(&apic);
+}
+
+static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
+{
+ int enc, pic_type;
+ char mimetype[64];
+ const CodecMime *mime = ff_id3v2_mime_tags;
+ enum CodecID id = CODEC_ID_NONE;
+ ID3v2ExtraMetaAPIC *apic = NULL;
+ ID3v2ExtraMeta *new_extra = NULL;
+ int64_t end = avio_tell(pb) + taglen;
+
+ if (taglen <= 4)
+ goto fail;
+
+ new_extra = av_mallocz(sizeof(*new_extra));
+ apic = av_mallocz(sizeof(*apic));
+ if (!new_extra || !apic)
+ goto fail;
+
+ enc = avio_r8(pb);
+ taglen--;
+
+ /* mimetype */
+ taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
+ while (mime->id != CODEC_ID_NONE) {
+ if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
+ id = mime->id;
+ break;
+ }
+ mime++;
+ }
+ if (id == CODEC_ID_NONE) {
+ av_log(s, AV_LOG_WARNING, "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
+ goto fail;
+ }
+ apic->id = id;
+
+ /* picture type */
+ pic_type = avio_r8(pb);
+ taglen--;
+ if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) {
+ av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n", pic_type);
+ pic_type = 0;
+ }
+ apic->type = ff_id3v2_picture_types[pic_type];
+
+ /* description and picture data */
+ if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) {
+ av_log(s, AV_LOG_ERROR, "Error decoding attached picture description.\n");
+ goto fail;
+ }
+
+ apic->len = taglen;
+ apic->data = av_malloc(taglen);
+ if (!apic->data || avio_read(pb, apic->data, taglen) != taglen)
+ goto fail;
+
+ new_extra->tag = "APIC";
+ new_extra->data = apic;
+ new_extra->next = *extra_meta;
+ *extra_meta = new_extra;
+
+ return;
+
+fail:
+ if (apic)
+ free_apic(apic);
+ av_freep(&new_extra);
+ avio_seek(pb, end, SEEK_SET);
+}
+
typedef struct ID3v2EMFunc {
const char *tag3;
const char *tag4;
@@ -403,6 +514,7 @@ typedef struct ID3v2EMFunc {
static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
{ "GEO", "GEOB", read_geobtag, free_geobtag },
+ { "PIC", "APIC", read_apic, free_apic },
{ NULL }
};
@@ -620,7 +732,7 @@ seek:
return;
}
-void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta)
+void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta)
{
int len, ret;
uint8_t buf[ID3v2_HEADER_SIZE];
@@ -651,11 +763,6 @@ void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **e
merge_date(&s->metadata);
}
-void ff_id3v2_read(AVFormatContext *s, const char *magic)
-{
- ff_id3v2_read_all(s, magic, NULL);
-}
-
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
{
ID3v2ExtraMeta *current = *extra_meta, *next;
@@ -669,3 +776,37 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
current = next;
}
}
+
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
+{
+ ID3v2ExtraMeta *cur;
+
+ for (cur = *extra_meta; cur; cur = cur->next) {
+ ID3v2ExtraMetaAPIC *apic;
+ AVStream *st;
+
+ if (strcmp(cur->tag, "APIC"))
+ continue;
+ apic = cur->data;
+
+ if (!(st = avformat_new_stream(s, NULL)))
+ return AVERROR(ENOMEM);
+
+ st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = apic->id;
+ av_dict_set(&st->metadata, "title", apic->description, 0);
+ av_dict_set(&st->metadata, "comment", apic->type, 0);
+
+ av_init_packet(&st->attached_pic);
+ st->attached_pic.data = apic->data;
+ st->attached_pic.size = apic->len;
+ st->attached_pic.destruct = av_destruct_packet;
+ st->attached_pic.stream_index = st->index;
+
+ apic->data = NULL;
+ apic->len = 0;
+ }
+
+ return 0;
+}
diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h
index ebd4a67a33..5c12a47b32 100644
--- a/libavformat/id3v2.h
+++ b/libavformat/id3v2.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include "avformat.h"
+#include "internal.h"
#include "metadata.h"
#define ID3v2_HEADER_SIZE 10
@@ -45,6 +46,12 @@ enum ID3v2Encoding {
ID3v2_ENCODING_UTF8 = 3,
};
+typedef struct ID3v2EncContext {
+ int version; ///< ID3v2 minor version, either 3 or 4
+ int64_t size_pos; ///< offset of the tag total size
+ int len; ///< size of the tag written so far
+} ID3v2EncContext;
+
typedef struct ID3v2ExtraMeta {
const char *tag;
void *data;
@@ -59,6 +66,14 @@ typedef struct ID3v2ExtraMetaGEOB {
uint8_t *data;
} ID3v2ExtraMetaGEOB;
+typedef struct ID3v2ExtraMetaAPIC {
+ uint8_t *data;
+ int len;
+ const char *type;
+ uint8_t *description;
+ enum CodecID id;
+} ID3v2ExtraMetaAPIC;
+
/**
* Detect ID3v2 Header.
* @param buf must be ID3v2_HEADER_SIZE byte long
@@ -75,24 +90,40 @@ int ff_id3v2_match(const uint8_t *buf, const char *magic);
int ff_id3v2_tag_len(const uint8_t *buf);
/**
- * Read an ID3v2 tag (text tags only)
+ * Read an ID3v2 tag, including supported extra metadata
+ * @param extra_meta If not NULL, extra metadata is parsed into a list of
+ * ID3v2ExtraMeta structs and *extra_meta points to the head of the list
*/
-void ff_id3v2_read(AVFormatContext *s, const char *magic);
+void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta);
/**
- * Read an ID3v2 tag, including supported extra metadata (currently only GEOB)
- * @param extra_meta If not NULL, extra metadata is parsed into a list of
- * ID3v2ExtraMeta structs and *extra_meta points to the head of the list
+ * Initialize an ID3v2 tag.
+ */
+void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
+ const char *magic);
+
+/**
+ * Convert and write all global metadata from s into an ID3v2 tag.
+ */
+int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3);
+
+/**
+ * Write an attached picture from pkt into an ID3v2 tag.
+ */
+int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt);
+
+/**
+ * Finalize an opened ID3v2 tag.
*/
-void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta);
+void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb);
/**
- * Write an ID3v2 tag.
+ * Write an ID3v2 tag containing all global metadata from s.
* @param id3v2_version Subversion of ID3v2; supported values are 3 and 4
* @param magic magic bytes to identify the header
* If in doubt, use ID3v2_DEFAULT_MAGIC.
*/
-int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, const char *magic);
+int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, const char *magic);
/**
* Free memory allocated parsing special (non-text) metadata.
@@ -100,6 +131,12 @@ int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, const char *mag
*/
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta);
+/**
+ * Create a stream for each APIC (attached picture) extracted from the
+ * ID3v2 header.
+ */
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta);
+
extern const AVMetadataConv ff_id3v2_34_metadata_conv[];
extern const AVMetadataConv ff_id3v2_4_metadata_conv[];
@@ -120,4 +157,8 @@ extern const char ff_id3v2_4_tags[][4];
*/
extern const char ff_id3v2_3_tags[][4];
+extern const CodecMime ff_id3v2_mime_tags[];
+
+extern const char *ff_id3v2_picture_types[21];
+
#endif /* AVFORMAT_ID3V2_H */
diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c
index c3732e4789..1caadd6335 100644
--- a/libavformat/id3v2enc.c
+++ b/libavformat/id3v2enc.c
@@ -19,6 +19,8 @@
*/
#include <stdint.h>
+#include <string.h>
+
#include "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/intreadwrite.h"
@@ -26,12 +28,12 @@
#include "avio.h"
#include "id3v2.h"
-static void id3v2_put_size(AVFormatContext *s, int size)
+static void id3v2_put_size(AVIOContext *pb, int size)
{
- avio_w8(s->pb, size >> 21 & 0x7f);
- avio_w8(s->pb, size >> 14 & 0x7f);
- avio_w8(s->pb, size >> 7 & 0x7f);
- avio_w8(s->pb, size & 0x7f);
+ avio_w8(pb, size >> 21 & 0x7f);
+ avio_w8(pb, size >> 14 & 0x7f);
+ avio_w8(pb, size >> 7 & 0x7f);
+ avio_w8(pb, size & 0x7f);
}
static int string_is_ascii(const uint8_t *str)
@@ -40,17 +42,30 @@ static int string_is_ascii(const uint8_t *str)
return !*str;
}
+static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str,
+ enum ID3v2Encoding enc)
+{
+ int (*put)(AVIOContext*, const char*);
+
+ if (enc == ID3v2_ENCODING_UTF16BOM) {
+ avio_wl16(pb, 0xFEFF); /* BOM */
+ put = avio_put_str16le;
+ } else
+ put = avio_put_str;
+
+ put(pb, str);
+}
+
/**
* Write a text frame with one (normal frames) or two (TXXX frames) strings
* according to encoding (only UTF-8 or UTF-16+BOM supported).
* @return number of bytes written or a negative error code.
*/
-static int id3v2_put_ttag(AVFormatContext *s, const char *str1, const char *str2,
+static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *str1, const char *str2,
uint32_t tag, enum ID3v2Encoding enc)
{
int len;
uint8_t *pb;
- int (*put)(AVIOContext*, const char*);
AVIOContext *dyn_buf;
if (avio_open_dyn_buf(&dyn_buf) < 0)
return AVERROR(ENOMEM);
@@ -62,28 +77,26 @@ static int id3v2_put_ttag(AVFormatContext *s, const char *str1, const char *str2
enc = ID3v2_ENCODING_ISO8859;
avio_w8(dyn_buf, enc);
- if (enc == ID3v2_ENCODING_UTF16BOM) {
- avio_wl16(dyn_buf, 0xFEFF); /* BOM */
- put = avio_put_str16le;
- } else
- put = avio_put_str;
-
- put(dyn_buf, str1);
+ id3v2_encode_string(dyn_buf, str1, enc);
if (str2)
- put(dyn_buf, str2);
+ id3v2_encode_string(dyn_buf, str2, enc);
len = avio_close_dyn_buf(dyn_buf, &pb);
- avio_wb32(s->pb, tag);
- id3v2_put_size(s, len);
- avio_wb16(s->pb, 0);
- avio_write(s->pb, pb, len);
+ avio_wb32(avioc, tag);
+ /* ID3v2.3 frame size is not synchsafe */
+ if (id3->version == 3)
+ avio_wb32(avioc, len);
+ else
+ id3v2_put_size(avioc, len);
+ avio_wb16(avioc, 0);
+ avio_write(avioc, pb, len);
av_freep(&pb);
return len + ID3v2_HEADER_SIZE;
}
-static int id3v2_check_write_tag(AVFormatContext *s, AVDictionaryEntry *t, const char table[][4],
- enum ID3v2Encoding enc)
+static int id3v2_check_write_tag(ID3v2EncContext *id3, AVIOContext *pb, AVDictionaryEntry *t,
+ const char table[][4], enum ID3v2Encoding enc)
{
uint32_t tag;
int i;
@@ -93,7 +106,7 @@ static int id3v2_check_write_tag(AVFormatContext *s, AVDictionaryEntry *t, const
tag = AV_RB32(t->key);
for (i = 0; *table[i]; i++)
if (tag == AV_RB32(table[i]))
- return id3v2_put_ttag(s, t->value, NULL, tag, enc);
+ return id3v2_put_ttag(id3, pb, t->value, NULL, tag, enc);
return -1;
}
@@ -135,52 +148,137 @@ static void id3v2_3_metadata_split_date(AVDictionary **pm)
*pm = dst;
}
-int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version,
- const char *magic)
+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 == 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))) {
int ret;
- if ((ret = id3v2_check_write_tag(s, t, ff_id3v2_tags, enc)) > 0) {
- totlen += ret;
+ if ((ret = id3v2_check_write_tag(id3, s->pb, t, ff_id3v2_tags, enc)) > 0) {
+ id3->len += ret;
continue;
}
- if ((ret = id3v2_check_write_tag(s, t, id3v2_version == 3 ?
+ if ((ret = id3v2_check_write_tag(id3, s->pb, t, id3->version == 3 ?
ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) {
- totlen += ret;
+ id3->len += ret;
continue;
}
/* unknown tag, write as TXXX frame */
- if ((ret = id3v2_put_ttag(s, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
+ if ((ret = id3v2_put_ttag(id3, s->pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
return ret;
- totlen += ret;
+ id3->len += ret;
}
- cur_pos = avio_tell(s->pb);
- avio_seek(s->pb, size_pos, SEEK_SET);
- id3v2_put_size(s, totlen);
- avio_seek(s->pb, cur_pos, SEEK_SET);
+ return 0;
+}
+
+int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ AVDictionaryEntry *e;
+
+ AVIOContext *dyn_buf;
+ uint8_t *buf;
+ const CodecMime *mime = ff_id3v2_mime_tags;
+ const char *mimetype = NULL, *desc = "";
+ int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
+ ID3v2_ENCODING_UTF8;
+ int i, len, type = 0;
+
+ /* get the mimetype*/
+ while (mime->id != CODEC_ID_NONE) {
+ if (mime->id == st->codec->codec_id) {
+ mimetype = mime->str;
+ break;
+ }
+ mime++;
+ }
+ if (!mimetype) {
+ av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
+ "write an attached picture.\n", st->index);
+ return AVERROR(EINVAL);
+ }
+
+ /* get the picture type */
+ e = av_dict_get(st->metadata, "comment", NULL, 0);
+ for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
+ if (strstr(ff_id3v2_picture_types[i], e->value) == ff_id3v2_picture_types[i]) {
+ type = i;
+ break;
+ }
+ }
+
+ /* get the description */
+ if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
+ desc = e->value;
+
+ /* start writing */
+ if (avio_open_dyn_buf(&dyn_buf) < 0)
+ return AVERROR(ENOMEM);
+
+ avio_w8(dyn_buf, enc);
+ avio_put_str(dyn_buf, mimetype);
+ avio_w8(dyn_buf, type);
+ id3v2_encode_string(dyn_buf, desc, enc);
+ avio_write(dyn_buf, pkt->data, pkt->size);
+ len = avio_close_dyn_buf(dyn_buf, &buf);
+
+ avio_wb32(s->pb, MKBETAG('A', 'P', 'I', 'C'));
+ if (id3->version == 3)
+ avio_wb32(s->pb, len);
+ else
+ id3v2_put_size(s->pb, len);
+ avio_wb16(s->pb, 0);
+ avio_write(s->pb, buf, len);
+ av_freep(&buf);
+
+ id3->len += len + ID3v2_HEADER_SIZE;
+
+ return 0;
+}
+
+void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb)
+{
+ int64_t cur_pos = avio_tell(pb);
+ avio_seek(pb, id3->size_pos, SEEK_SET);
+ id3v2_put_size(pb, id3->len);
+ avio_seek(pb, cur_pos, SEEK_SET);
+}
+
+int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version,
+ const char *magic)
+{
+ ID3v2EncContext id3 = { 0 };
+ int ret;
+
+ ff_id3v2_start(&id3, s->pb, id3v2_version, magic);
+ if ((ret = ff_id3v2_write_metadata(s, &id3)) < 0)
+ return ret;
+ ff_id3v2_finish(&id3, s->pb);
+
return 0;
}
diff --git a/libavformat/internal.h b/libavformat/internal.h
index f2b89a3384..8bc34bdb9a 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -37,6 +37,11 @@ typedef struct AVCodecTag {
unsigned int tag;
} AVCodecTag;
+typedef struct CodecMime{
+ char str[32];
+ enum CodecID id;
+} CodecMime;
+
#ifdef __GNUC__
#define dynarray_add(tab, nb_ptr, elem)\
do {\
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index ab7e3269fa..6f6ab1e929 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -24,6 +24,7 @@
#include "libavcodec/avcodec.h"
#include "metadata.h"
+#include "internal.h"
/* EBML version supported */
#define EBML_VERSION 1
@@ -250,11 +251,6 @@ typedef struct CodecTags{
enum CodecID id;
}CodecTags;
-typedef struct CodecMime{
- char str[32];
- enum CodecID id;
-}CodecMime;
-
/* max. depth in the EBML tree structure */
#define EBML_MAX_DEPTH 16
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 15df2bf198..4ad2051efc 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1223,6 +1223,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
if (st->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
unsigned int color_depth, len;
int color_greyscale;
+ int color_table_id;
st->codec->codec_id = id;
avio_rb16(pb); /* version */
@@ -1250,9 +1251,9 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
st->codec->codec_tag=MKTAG('I', '4', '2', '0');
st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */
- st->codec->color_table_id = avio_rb16(pb); /* colortable id */
+ color_table_id = avio_rb16(pb); /* colortable id */
av_dlog(c->fc, "depth %d, ctab id %d\n",
- st->codec->bits_per_coded_sample, st->codec->color_table_id);
+ st->codec->bits_per_coded_sample, color_table_id);
/* figure out the palette situation */
color_depth = st->codec->bits_per_coded_sample & 0x1F;
color_greyscale = st->codec->bits_per_coded_sample & 0x20;
@@ -1282,7 +1283,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
if (color_index < 0)
color_index = 0;
}
- } else if (st->codec->color_table_id) {
+ } else if (color_table_id) {
const uint8_t *color_table;
/* if flag bit 3 is set, use the default palette */
color_count = 1 << color_depth;
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index 3bbc3e84f9..b2c1b4211e 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -84,6 +84,7 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
typedef struct MP3Context {
const AVClass *class;
+ ID3v2EncContext id3;
int id3v2_version;
int write_id3v1;
int64_t frames_offset;
@@ -93,60 +94,15 @@ typedef struct MP3Context {
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;
static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
@@ -155,8 +111,8 @@ static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
*/
static int mp3_write_xing(AVFormatContext *s)
{
- AVCodecContext *codec = s->streams[0]->codec;
MP3Context *mp3 = s->priv_data;
+ AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
int bitrate_idx;
int best_bitrate_idx = -1;
int best_bitrate_error= INT_MAX;
@@ -166,6 +122,9 @@ static int mp3_write_xing(AVFormatContext *s)
int srate_idx, i, channels;
int needed;
+ 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;
@@ -295,26 +254,7 @@ static void mp3_fix_xing(AVFormatContext *s)
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);
@@ -350,6 +290,175 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
}
}
+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)) {
+ 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;
+}
+
+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 */
+ 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,
+ .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;
@@ -371,7 +480,7 @@ AVOutputFormat ff_mp3_muxer = {
.extensions = "mp3",
.priv_data_size = sizeof(MP3Context),
.audio_codec = CODEC_ID_MP3,
- .video_codec = CODEC_ID_NONE,
+ .video_codec = CODEC_ID_PNG,
.write_header = mp3_write_header,
.write_packet = mp3_write_packet,
.write_trailer = mp3_write_trailer,
diff --git a/libavformat/omadec.c b/libavformat/omadec.c
index 97aaf175ab..a62b560504 100644
--- a/libavformat/omadec.c
+++ b/libavformat/omadec.c
@@ -270,7 +270,7 @@ static int oma_read_header(AVFormatContext *s)
ID3v2ExtraMeta *extra_meta = NULL;
OMAContext *oc = s->priv_data;
- ff_id3v2_read_all(s, ID3v2_EA3_MAGIC, &extra_meta);
+ ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta);
ret = avio_read(s->pb, buf, EA3_HEADER_SIZE);
if (ret < EA3_HEADER_SIZE)
return -1;
diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c
index e932b4bbc1..c3ee0e8de1 100644
--- a/libavformat/omaenc.c
+++ b/libavformat/omaenc.c
@@ -49,7 +49,7 @@ static av_cold int oma_write_header(AVFormatContext *s)
}
/* Metadata; OpenMG does not support ID3v2.4 */
- ff_id3v2_write(s, 3, ID3v2_EA3_MAGIC);
+ ff_id3v2_write_simple(s, 3, ID3v2_EA3_MAGIC);
ffio_wfourcc(s->pb, "EA3\0");
avio_w8(s->pb, EA3_HEADER_SIZE >> 7);
diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c
index d657197d6f..24f1c08617 100644
--- a/libavformat/psxstr.c
+++ b/libavformat/psxstr.c
@@ -299,4 +299,5 @@ AVInputFormat ff_str_demuxer = {
.read_header = str_read_header,
.read_packet = str_read_packet,
.read_close = str_read_close,
+ .flags = AVFMT_NO_BYTE_SEEK,
};
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index 32288684eb..88a0527566 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -112,7 +112,7 @@ static int rtp_write_header(AVFormatContext *s1)
if (s->max_packet_size) {
if (s1->pb->max_packet_size)
- s->max_packet_size = FFMIN(s->max_payload_size,
+ s->max_packet_size = FFMIN(s->max_packet_size,
s1->pb->max_packet_size);
} else
s->max_packet_size = s1->pb->max_packet_size;
diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c
index a84d3808bf..4a2c3d5403 100644
--- a/libavformat/swfdec.c
+++ b/libavformat/swfdec.c
@@ -113,7 +113,6 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codec->codec_id = ff_codec_get_id(swf_codec_tags, avio_r8(pb));
avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
- vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
len -= 8;
} else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
/* streaming found */
@@ -186,7 +185,6 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codec->codec_id = CODEC_ID_MJPEG;
avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
- vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
st = vst;
}
avio_rl16(pb); /* BITMAP_ID */
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 44cef9e8ab..e84cd7657a 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -545,11 +545,29 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
}
+static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
+ AVPacketList **plast_pktl){
+ AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
+ if (!pktl)
+ return NULL;
+
+ if (*packet_buffer)
+ (*plast_pktl)->next = pktl;
+ else
+ *packet_buffer = pktl;
+
+ /* add the packet in the buffered packet list */
+ *plast_pktl = pktl;
+ pktl->pkt= *pkt;
+ return &pktl->pkt;
+}
+
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
- int ret = 0;
+ int i, ret = 0;
AVDictionary *tmp = NULL;
+ ID3v2ExtraMeta *id3v2_extra_meta = NULL;
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
@@ -592,12 +610,25 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
/* 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->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
if ((ret = s->iformat->read_header(s)) < 0)
goto fail;
+ 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);
@@ -611,6 +642,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
return 0;
fail:
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
av_dict_free(&tmp);
if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
avio_close(s->pb);
@@ -621,23 +653,6 @@ fail:
/*******************************************************/
-static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
- AVPacketList **plast_pktl){
- AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
- if (!pktl)
- return NULL;
-
- if (*packet_buffer)
- (*plast_pktl)->next = pktl;
- else
- *packet_buffer = pktl;
-
- /* add the packet in the buffered packet list */
- *plast_pktl = pktl;
- pktl->pkt= *pkt;
- return &pktl->pkt;
-}
-
int av_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, i;
@@ -2722,6 +2737,8 @@ void avformat_free_context(AVFormatContext *s)
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_freep(&st->index_entries);
av_freep(&st->codec->extradata);
diff --git a/libavformat/version.h b/libavformat/version.h
index 1fafa17dfc..0dc68152c3 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,7 +30,7 @@
#include "libavutil/avutil.h"
#define LIBAVFORMAT_VERSION_MAJOR 54
-#define LIBAVFORMAT_VERSION_MINOR 1
+#define LIBAVFORMAT_VERSION_MINOR 2
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
diff --git a/libavformat/vqf.c b/libavformat/vqf.c
index 8cd69232ce..4664c0068f 100644
--- a/libavformat/vqf.c
+++ b/libavformat/vqf.c
@@ -220,12 +220,12 @@ static int vqf_read_packet(AVFormatContext *s, AVPacket *pkt)
int ret;
int size = (c->frame_bit_len - c->remaining_bits + 7)>>3;
- pkt->pos = avio_tell(s->pb);
- pkt->stream_index = 0;
-
if (av_new_packet(pkt, size+2) < 0)
return AVERROR(EIO);
+ pkt->pos = avio_tell(s->pb);
+ pkt->stream_index = 0;
+
pkt->data[0] = 8 - c->remaining_bits; // Number of bits to skip
pkt->data[1] = c->last_frame_bits;
ret = avio_read(s->pb, pkt->data+2, size);
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 129e6b7616..5952f5df9d 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -1046,7 +1046,7 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)
c->vLumBufSize= c->vLumFilterSize;
c->vChrBufSize= c->vChrFilterSize;
for (i=0; i<dstH; i++) {
- int chrI= (int64_t)i*c->chrDstH / dstH;
+ int chrI = (int64_t) i * c->chrDstH / dstH;
int nextSlice= FFMAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1,
((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));
diff --git a/tests/codec-regression.sh b/tests/codec-regression.sh
index 335ca3df2d..cd6512c725 100755
--- a/tests/codec-regression.sh
+++ b/tests/codec-regression.sh
@@ -38,13 +38,13 @@ fi
if [ -n "$do_mpeg2_ivlc_qprd" ]; then
# mpeg2 encoding intra vlc qprd
-do_video_encoding mpeg2ivlc-qprd.mpg "-vb 500k -bf 2 -trellis 1 -flags +qprd+mv0 -intra_vlc 1 -cmp 2 -subcmp 2 -mbd rd -vcodec mpeg2video -f mpeg2video"
+do_video_encoding mpeg2ivlc-qprd.mpg "-vb 500k -bf 2 -trellis 1 -flags +mv0 -mpv_flags +qp_rd -intra_vlc 1 -cmp 2 -subcmp 2 -mbd rd -vcodec mpeg2video -f mpeg2video"
do_video_decoding
fi
if [ -n "$do_mpeg2_422" ]; then
#mpeg2 4:2:2 encoding
-do_video_encoding mpeg2_422.mpg "-vb 1000k -bf 2 -trellis 1 -flags +qprd+mv0+ildct+ilme -intra_vlc 1 -mbd rd -vcodec mpeg2video -pix_fmt yuv422p -f mpeg2video"
+do_video_encoding mpeg2_422.mpg "-vb 1000k -bf 2 -trellis 1 -flags +mv0+ildct+ilme -mpv_flags +qp_rd -intra_vlc 1 -mbd rd -vcodec mpeg2video -pix_fmt yuv422p -f mpeg2video"
do_video_decoding
fi
@@ -143,7 +143,7 @@ do_video_decoding
fi
if [ -n "$do_mpeg4_qprd" ]; then
-do_video_encoding mpeg4-qprd.avi "-b 450k -bf 2 -trellis 1 -flags +mv4+qprd+mv0 -cmp 2 -subcmp 2 -mbd rd -an -vcodec mpeg4"
+do_video_encoding mpeg4-qprd.avi "-b 450k -bf 2 -trellis 1 -flags +mv4+mv0 -mpv_flags +qp_rd -cmp 2 -subcmp 2 -mbd rd -an -vcodec mpeg4"
do_video_decoding
fi
diff --git a/tests/fate/cdxl.mak b/tests/fate/cdxl.mak
index 82ac27e430..3a46c5ce50 100644
--- a/tests/fate/cdxl.mak
+++ b/tests/fate/cdxl.mak
@@ -10,5 +10,8 @@ fate-cdxl-pal8: CMD = framecrc -i $(SAMPLES)/cdxl/maku.cdxl -pix_fmt rgb24 -fram
FATE_CDXL += fate-cdxl-pal8-small
fate-cdxl-pal8-small: CMD = framecrc -i $(SAMPLES)/cdxl/fruit.cdxl -an -pix_fmt rgb24 -frames:v 46
+FATE_CDXL += fate-cdxl-bitline-ham6
+fate-cdxl-bitline-ham6: CMD = framecrc -i $(SAMPLES)/cdxl/bitline.cdxl -frames:v 10
+
FATE_TESTS += $(FATE_CDXL)
fate-cdxl: $(FATE_CDXL)
diff --git a/tests/fate/mp3.mak b/tests/fate/mp3.mak
index 9dfa829008..4c16cb84e0 100644
--- a/tests/fate/mp3.mak
+++ b/tests/fate/mp3.mak
@@ -33,6 +33,11 @@ fate-mp3-float-conf-si_block: CMD = pcm -acodec mp3float -i $(SAMPLES)/mp3-confo
fate-mp3-float-conf-si_block: CMP = stddev
fate-mp3-float-conf-si_block: REF = $(SAMPLES)/mp3-conformance/si_block.pcm
+FATE_MP3 += fate-mp3-float-extra_overread
+fate-mp3-float-extra_overread: CMD = pcm -c:a mp3float -i $(SAMPLES)/mpegaudio/extra_overread.mp3
+fate-mp3-float-extra_overread: CMP = stddev
+fate-mp3-float-extra_overread: REF = $(SAMPLES)/mpegaudio/extra_overread.pcm
+
FATE_TESTS += $(FATE_MP3)
fate-mp3: $(FATE_MP3)
$(FATE_MP3): CMP = stddev
diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index 84a98f6fcc..02aa39598c 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -143,7 +143,7 @@ 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
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_VIDEO += fate-qpeg
fate-qpeg: CMD = framecrc -i $(SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24
diff --git a/tests/ref/fate/cdxl-bitline-ham6 b/tests/ref/fate/cdxl-bitline-ham6
new file mode 100644
index 0000000000..8060f06024
--- /dev/null
+++ b/tests/ref/fate/cdxl-bitline-ham6
@@ -0,0 +1,11 @@
+#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
diff --git a/tests/ref/fate/nuv b/tests/ref/fate/nuv
index 0cc9001793..8838fbb646 100644
--- a/tests/ref/fate/nuv
+++ b/tests/ref/fate/nuv
@@ -1,29 +1,10 @@
#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
diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm
index 73e94ddfd6..4767b9968e 100644
--- a/tests/ref/lavf/ffm
+++ b/tests/ref/lavf/ffm
@@ -1,3 +1,3 @@
-4ef091d638bb20b8eaef5b3a0d6f97b7 *./tests/data/lavf/lavf.ffm
+8ce2ea9a73a1187647df7bf3c8e1b8fd *./tests/data/lavf/lavf.ffm
376832 ./tests/data/lavf/lavf.ffm
./tests/data/lavf/lavf.ffm CRC=0xf361ed74
diff --git a/tests/ref/vsynth1/prores_kostya b/tests/ref/vsynth1/prores_kostya
index 870e2845c6..032cda2c90 100644
--- a/tests/ref/vsynth1/prores_kostya
+++ b/tests/ref/vsynth1/prores_kostya
@@ -1,4 +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
diff --git a/tests/ref/vsynth2/prores_kostya b/tests/ref/vsynth2/prores_kostya
index 2b99c750e3..efdcd8fabd 100644
--- a/tests/ref/vsynth2/prores_kostya
+++ b/tests/ref/vsynth2/prores_kostya
@@ -1,4 +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