diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-03-01 01:13:16 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-03-01 03:17:11 +0100 |
commit | 79ae084e9b930f8b53ae0499c6a06636d194574d (patch) | |
tree | e7d829e566b01ef7e84a12b06a2bcb87a8164059 | |
parent | a77c8ade2ee20fc6149e4c689a3f196f53e85273 (diff) | |
parent | 882abda5a26ffb8e3d1c5852dfa7cdad0a291d2d (diff) | |
download | ffmpeg-79ae084e9b930f8b53ae0499c6a06636d194574d.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master: (58 commits)
amrnbdec: check frame size before decoding.
cscd: use negative error values to indicate decode_init() failures.
h264: prevent overreads in intra PCM decoding.
FATE: do not decode audio in the nuv test.
dxa: set audio stream time base using the sample rate
psx-str: do not allow seeking by bytes
asfdec: Do not set AVCodecContext.frame_size
vqf: set packet parameters after av_new_packet()
mpegaudiodec: use DSPUtil.butterflies_float().
FATE: add mp3 test for sample that exhibited false overreads
fate: add cdxl test for bit line plane arrangement
vmnc: return error on decode_init() failure.
libvorbis: add/update error messages
libvorbis: use AVFifoBuffer for output packet buffer
libvorbis: remove unneeded e_o_s check
libvorbis: check return values for functions that can return errors
libvorbis: use float input instead of s16
libvorbis: do not flush libvorbis analysis if dsp state was not initialized
libvorbis: use VBR by default, with default quality of 3
libvorbis: fix use of minrate/maxrate AVOptions
...
Conflicts:
Changelog
doc/APIchanges
libavcodec/avcodec.h
libavcodec/dpxenc.c
libavcodec/libvorbis.c
libavcodec/vmnc.c
libavformat/asfdec.c
libavformat/id3v2enc.c
libavformat/internal.h
libavformat/mp3enc.c
libavformat/utils.c
libavformat/version.h
libswscale/utils.c
tests/fate/video.mak
tests/ref/fate/nuv
tests/ref/fate/prores-alpha
tests/ref/lavf/ffm
tests/ref/vsynth1/prores
tests/ref/vsynth2/prores
Merged-by: Michael Niedermayer <michaelni@gmx.at>
64 files changed, 1217 insertions, 519 deletions
@@ -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, ©, &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 |