diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-02-19 01:36:23 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-02-19 01:47:10 +0100 |
commit | 4a519b6e036bb593d868c2a424da43512215c571 (patch) | |
tree | bbbd734383e7b2bfd005a1c19fe64d36d493b576 | |
parent | 57182b9f0fa15ebedbf5229e17bc77a70cc68d9d (diff) | |
parent | 5be805d38cb43e6f0b85941f75946d09bc8cc13f (diff) | |
download | ffmpeg-4a519b6e036bb593d868c2a424da43512215c571.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
mov: Use defines for sample flags in fragments
mov: Use defines for trun flags
mov: Use defines for tfhd flags
proresenc: force bitrate not to exceed given limit
vc1parse: call vc1_init_common().
wma: don't return 0 on invalid packets.
asf: prevent packet_size_left from going negative if hdrlen > pktlen.
mjpegb: don't return 0 at the end of frame decoding.
rtpdec: Identify incorrectly signalled H263
vp8dsp: split long line.
aiff: don't skip block_align==0 check on COMM-after-SSND files.
dpcm: ignore extra unpaired bytes in stereo streams.
mp3on4: require a minimum framesize.
mpc7: assign an error level + context to av_log() msg.
huffyuv: error out on bit overrun.
dct-test: Add the missing ff_ prefix to the altivec functions
dct-test: Remove a stray declaration of a nonexistent function
movenc: Write the unknown duration as 64 bit fields in ismv
movenc: Write track durations with all bits set if duration is unknown
Conflicts:
libavcodec/dct-test.c
libavcodec/wmadec.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavcodec/dct-test.c | 2 | ||||
-rw-r--r-- | libavcodec/dpcm.c | 7 | ||||
-rw-r--r-- | libavcodec/huffyuv.c | 2 | ||||
-rw-r--r-- | libavcodec/mjpegbdec.c | 4 | ||||
-rw-r--r-- | libavcodec/mpc7.c | 2 | ||||
-rw-r--r-- | libavcodec/mpegaudiodec.c | 4 | ||||
-rw-r--r-- | libavcodec/proresenc_kostya.c | 72 | ||||
-rw-r--r-- | libavcodec/vc1.h | 1 | ||||
-rw-r--r-- | libavcodec/vc1_parser.c | 2 | ||||
-rw-r--r-- | libavcodec/vc1dec.c | 4 | ||||
-rw-r--r-- | libavcodec/vp8dsp.h | 4 | ||||
-rw-r--r-- | libavcodec/wmadec.c | 8 | ||||
-rw-r--r-- | libavformat/aiffdec.c | 4 | ||||
-rw-r--r-- | libavformat/asfdec.c | 7 | ||||
-rw-r--r-- | libavformat/isom.h | 24 | ||||
-rw-r--r-- | libavformat/mov.c | 33 | ||||
-rw-r--r-- | libavformat/movenc.c | 64 | ||||
-rw-r--r-- | libavformat/rtpdec_formats.h | 4 | ||||
-rw-r--r-- | libavformat/rtpdec_h263.c | 14 | ||||
-rw-r--r-- | libavformat/rtpdec_h263_rfc2190.c | 24 | ||||
-rw-r--r-- | tests/ref/lavf/ismv | 12 |
21 files changed, 218 insertions, 80 deletions
diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 5a27b756b7..3a6ab96e39 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -54,7 +54,7 @@ void ff_bfin_fdct(DCTELEM *block); // ALTIVEC void ff_fdct_altivec(DCTELEM *block); -//void idct_altivec(DCTELEM *block);?? no routine +//void ff_idct_altivec(DCTELEM *block);?? no routine // ARM void ff_j_rev_dct_arm(DCTELEM *data); diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 8240221076..4915223bc8 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -183,6 +183,11 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, int stereo = s->channels - 1; int16_t *output_samples; + if (stereo && (buf_size & 1)) { + buf_size--; + buf_end--; + } + /* calculate output size */ switch(avctx->codec->id) { case CODEC_ID_ROQ_DPCM: @@ -320,7 +325,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, *got_frame_ptr = 1; *(AVFrame *)data = s->frame; - return buf_size; + return avpkt->size; } #define DPCM_DECODER(id_, name_, long_name_) \ diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index c46e93f03a..625d8fb186 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -212,7 +212,7 @@ static int read_len_table(uint8_t *dst, GetBitContext *gb){ if(repeat==0) repeat= get_bits(gb, 8); //printf("%d %d\n", val, repeat); - if(i+repeat > 256) { + if(i+repeat > 256 || get_bits_left(gb) < 0) { av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n"); return -1; } diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index fc77b14b44..b70311b795 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -69,7 +69,7 @@ read_header: if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g')) { av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n"); - return 0; + return AVERROR_INVALIDDATA; } field_size = get_bits_long(&hgb, 32); /* field size */ @@ -149,7 +149,7 @@ read_header: picture->quality*= FF_QP2LAMBDA; } - return buf_ptr - buf; + return buf_size; } AVCodec ff_mjpegb_decoder = { diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index e90c934912..6e4b8501c5 100644 --- a/libavcodec/mpc7.c +++ b/libavcodec/mpc7.c @@ -298,7 +298,7 @@ static int mpc7_decode_frame(AVCodecContext * avctx, void *data, bits_used = get_bits_count(&gb); bits_avail = buf_size * 8; if (!last_frame && ((bits_avail < bits_used) || (bits_used + 32 <= bits_avail))) { - av_log(NULL,0, "Error decoding frame: used %i of %i bits\n", bits_used, bits_avail); + av_log(avctx, AV_LOG_ERROR, "Error decoding frame: used %i of %i bits\n", bits_used, bits_avail); return -1; } if(c->frames_to_skip){ diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index 2ca30f2702..f47416133f 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -1914,6 +1914,10 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, m = s->mp3decctx[fr]; assert(m != NULL); + if (fsize < HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Frame size smaller than header size\n"); + return AVERROR_INVALIDDATA; + } header = (AV_RB32(buf) & 0x000fffff) | s->syncword; // patch header if (ff_mpa_check_header(header) < 0) // Bad header, discard block diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 242537b001..8259b2a664 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -139,11 +139,14 @@ struct TrellisNode { int score; }; +#define MAX_STORED_Q 16 + typedef struct ProresContext { AVClass *class; DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16]; - int16_t quants[16][64]; + int16_t quants[MAX_STORED_Q][64]; + int16_t custom_q[64]; ProresDSPContext dsp; ScanTable scantable; @@ -156,6 +159,8 @@ typedef struct ProresContext { int num_planes; int bits_per_mb; + int frame_size; + int profile; const struct prores_profile *profile_info; @@ -348,6 +353,15 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int slice_width_factor = av_log2(mbs_per_slice); int num_cblocks, pwidth; int plane_factor, is_chroma; + uint16_t *qmat; + + if (quant < MAX_STORED_Q) { + qmat = ctx->quants[quant]; + } else { + qmat = ctx->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->profile_info->quant[i] * quant; + } for (i = 0; i < ctx->num_planes; i++) { is_chroma = (i == 1 || i == 2); @@ -373,7 +387,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i], mbs_per_slice, ctx->blocks[0], num_cblocks, plane_factor, - ctx->quants[quant]); + qmat); total_size += sizes[i]; } return total_size; @@ -500,6 +514,8 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, int error, bits, bits_limit; int mbs, prev, cur, new_score; int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH]; + int overquant; + uint16_t *qmat; mbs = x + mbs_per_slice; @@ -526,7 +542,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, mbs_per_slice, num_cblocks[i]); } - for (q = min_quant; q <= max_quant; q++) { + for (q = min_quant; q < max_quant + 2; q++) { ctx->nodes[trellis_node + q].prev_node = -1; ctx->nodes[trellis_node + q].quant = q; } @@ -549,12 +565,43 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, slice_bits[q] = bits; slice_score[q] = error; } + if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) { + slice_bits[max_quant + 1] = slice_bits[max_quant]; + slice_score[max_quant + 1] = slice_score[max_quant] + 1; + overquant = max_quant; + } else { + for (q = max_quant + 1; q < 128; q++) { + bits = 0; + error = 0; + if (q < MAX_STORED_Q) { + qmat = ctx->quants[q]; + } else { + qmat = ctx->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->profile_info->quant[i] * q; + } + for (i = 0; i < ctx->num_planes; i++) { + bits += estimate_slice_plane(ctx, &error, i, + src, pic->linesize[i], + mbs_per_slice, + num_cblocks[i], plane_factor[i], + qmat); + } + if (bits <= ctx->bits_per_mb * mbs_per_slice) + break; + } + + slice_bits[max_quant + 1] = bits; + slice_score[max_quant + 1] = error; + overquant = q; + } + ctx->nodes[trellis_node + max_quant + 1].quant = overquant; bits_limit = mbs * ctx->bits_per_mb; - for (pq = min_quant; pq <= max_quant; pq++) { + for (pq = min_quant; pq < max_quant + 2; pq++) { prev = trellis_node - TRELLIS_WIDTH + pq; - for (q = min_quant; q <= max_quant; q++) { + for (q = min_quant; q < max_quant + 2; q++) { cur = trellis_node + q; bits = ctx->nodes[prev].bits + slice_bits[q]; @@ -578,7 +625,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, error = ctx->nodes[trellis_node + min_quant].score; pq = trellis_node + min_quant; - for (q = min_quant + 1; q <= max_quant; q++) { + for (q = min_quant + 1; q < max_quant + 2; q++) { if (ctx->nodes[trellis_node + q].score <= error) { error = ctx->nodes[trellis_node + q].score; pq = trellis_node + q; @@ -606,8 +653,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; - pkt_size = ctx->mb_width * ctx->mb_height * 64 * 3 * 12 - + ctx->num_slices * 2 + 200 + FF_MIN_BUFFER_SIZE; + pkt_size = ctx->frame_size + FF_MIN_BUFFER_SIZE; if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); @@ -762,9 +808,13 @@ static av_cold int encode_init(AVCodecContext *avctx) break; ctx->bits_per_mb = ctx->profile_info->br_tab[i]; + ctx->frame_size = ctx->num_slices * (2 + 2 * ctx->num_planes + + (2 * mps * ctx->bits_per_mb) / 8) + + 200; + min_quant = ctx->profile_info->min_quant; max_quant = ctx->profile_info->max_quant; - for (i = min_quant; i <= max_quant; i++) { + for (i = min_quant; i < MAX_STORED_Q; i++) { for (j = 0; j < 64; j++) ctx->quants[i][j] = ctx->profile_info->quant[j] * i; } @@ -773,6 +823,8 @@ static av_cold int encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n", ctx->profile, ctx->num_slices, ctx->bits_per_mb); + av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n", + ctx->frame_size); ctx->nodes = av_malloc((ctx->slices_width + 1) * TRELLIS_WIDTH * sizeof(*ctx->nodes)); @@ -780,7 +832,7 @@ static av_cold int encode_init(AVCodecContext *avctx) encode_close(avctx); return AVERROR(ENOMEM); } - for (i = min_quant; i <= max_quant; i++) { + for (i = min_quant; i < max_quant + 2; i++) { ctx->nodes[i].prev_node = -1; ctx->nodes[i].bits = 0; ctx->nodes[i].score = 0; diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index 61b34275b8..0f185309ba 100644 --- a/libavcodec/vc1.h +++ b/libavcodec/vc1.h @@ -447,5 +447,6 @@ int ff_vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContex int ff_vc1_parse_frame_header (VC1Context *v, GetBitContext *gb); int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext *gb); +int ff_vc1_init_common(VC1Context *v); #endif /* AVCODEC_VC1_H */ diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index f133e3a2d7..a2a0d4a507 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -188,7 +188,7 @@ static int vc1_parse_init(AVCodecParserContext *s) { VC1ParseContext *vpc = s->priv_data; vpc->v.s.slice_context_count = 1; - return 0; + return ff_vc1_init_common(&vpc->v); } AVCodecParser ff_vc1_parser = { diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index a10ec85f02..bffd7b8106 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -67,7 +67,7 @@ static const int offset_table2[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; * @param v The VC1Context to initialize * @return Status */ -static int vc1_init_common(VC1Context *v) +int ff_vc1_init_common(VC1Context *v) { static int done = 0; int i = 0; @@ -5274,7 +5274,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) avctx->idct_algo = FF_IDCT_WMV2; } - if (vc1_init_common(v) < 0) + if (ff_vc1_init_common(v) < 0) return -1; ff_vc1dsp_init(&v->vc1dsp); diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index 987fa59a72..951a5566a7 100644 --- a/libavcodec/vp8dsp.h +++ b/libavcodec/vp8dsp.h @@ -29,7 +29,9 @@ #include "dsputil.h" -typedef void (*vp8_mc_func)(uint8_t *dst/*align 8*/, int dstStride, uint8_t *src/*align 1*/, int srcStride, int h, int x, int y); +typedef void (*vp8_mc_func)(uint8_t *dst/*align 8*/, int dstStride, + uint8_t *src/*align 1*/, int srcStride, + int h, int x, int y); typedef struct VP8DSPContext { void (*vp8_luma_dc_wht)(DCTELEM block[4][4][16], DCTELEM dc[16]); diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 7d7cc7f7bf..c90e22ca8e 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -834,8 +834,12 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, s->last_superframe_len = 0; return 0; } - if (buf_size < s->block_align) - return AVERROR(EINVAL); + if (buf_size < s->block_align) { + av_log(avctx, AV_LOG_ERROR, + "Input packet size too small (%d < %d)\n", + buf_size, s->block_align); + return AVERROR_INVALIDDATA; + } if(s->block_align) buf_size = s->block_align; diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index fbbf6a41e7..239fca3452 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -270,12 +270,12 @@ static int aiff_read_header(AVFormatContext *s) } } +got_sound: if (!st->codec->block_align) { - av_log(s, AV_LOG_ERROR, "could not find COMM tag\n"); + av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); return -1; } -got_sound: /* Now positioned, get the sound data start and end */ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index e2f46dc005..b37cbb04d3 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -797,6 +797,13 @@ static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb) asf->packet_segments = 1; asf->packet_segsizetype = 0x80; } + if (rsize > packet_length - padsize) { + asf->packet_size_left = 0; + av_log(s, AV_LOG_ERROR, + "invalid packet header length %d for pktlen %d-%d at %"PRId64"\n", + rsize, packet_length, padsize, avio_tell(pb)); + return -1; + } asf->packet_size_left = packet_length - padsize - rsize; if (packet_length < asf->hdr.min_pktsize) padsize += asf->hdr.min_pktsize - packet_length; diff --git a/libavformat/isom.h b/libavformat/isom.h index 776b265099..32c81b7445 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -162,6 +162,30 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #define MP4DecSpecificDescrTag 0x05 #define MP4SLDescrTag 0x06 +#define MOV_TFHD_BASE_DATA_OFFSET 0x01 +#define MOV_TFHD_STSD_ID 0x02 +#define MOV_TFHD_DEFAULT_DURATION 0x08 +#define MOV_TFHD_DEFAULT_SIZE 0x10 +#define MOV_TFHD_DEFAULT_FLAGS 0x20 +#define MOV_TFHD_DURATION_IS_EMPTY 0x010000 + +#define MOV_TRUN_DATA_OFFSET 0x01 +#define MOV_TRUN_FIRST_SAMPLE_FLAGS 0x04 +#define MOV_TRUN_SAMPLE_DURATION 0x100 +#define MOV_TRUN_SAMPLE_SIZE 0x200 +#define MOV_TRUN_SAMPLE_FLAGS 0x400 +#define MOV_TRUN_SAMPLE_CTS 0x800 + +#define MOV_FRAG_SAMPLE_FLAG_DEGRADATION_PRIORITY_MASK 0x0000ffff +#define MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC 0x00010000 +#define MOV_FRAG_SAMPLE_FLAG_PADDING_MASK 0x000e0000 +#define MOV_FRAG_SAMPLE_FLAG_REDUNDANCY_MASK 0x00300000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDED_MASK 0x00c00000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_MASK 0x03000000 + +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO 0x02000000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES 0x01000000 + int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom); enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags); diff --git a/libavformat/mov.c b/libavformat/mov.c index 71b96c192f..c6680274d5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2257,14 +2257,16 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; } - if (flags & 0x01) frag->base_data_offset = avio_rb64(pb); - else frag->base_data_offset = frag->moof_offset; - if (flags & 0x02) frag->stsd_id = avio_rb32(pb); - else frag->stsd_id = trex->stsd_id; - - frag->duration = flags & 0x08 ? avio_rb32(pb) : trex->duration; - frag->size = flags & 0x10 ? avio_rb32(pb) : trex->size; - frag->flags = flags & 0x20 ? avio_rb32(pb) : trex->flags; + frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ? + avio_rb64(pb) : frag->moof_offset; + frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id; + + frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ? + avio_rb32(pb) : trex->duration; + frag->size = flags & MOV_TFHD_DEFAULT_SIZE ? + avio_rb32(pb) : trex->size; + frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ? + avio_rb32(pb) : trex->flags; av_dlog(c->fc, "frag flags 0x%x\n", frag->flags); return 0; } @@ -2353,8 +2355,8 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); sc->ctts_data = ctts_data; - if (flags & 0x001) data_offset = avio_rb32(pb); - if (flags & 0x004) first_sample_flags = avio_rb32(pb); + if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb); + if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb); dts = sc->track_end - sc->time_offset; offset = frag->base_data_offset + data_offset; distance = 0; @@ -2365,14 +2367,15 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned sample_duration = frag->duration; int keyframe; - if (flags & 0x100) sample_duration = avio_rb32(pb); - if (flags & 0x200) sample_size = avio_rb32(pb); - if (flags & 0x400) sample_flags = avio_rb32(pb); + if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb); + if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb); + if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb); sc->ctts_data[sc->ctts_count].count = 1; - sc->ctts_data[sc->ctts_count].duration = (flags & 0x800) ? avio_rb32(pb) : 0; + sc->ctts_data[sc->ctts_count].duration = (flags & MOV_TRUN_SAMPLE_CTS) ? + avio_rb32(pb) : 0; sc->ctts_count++; if ((keyframe = st->codec->codec_type == AVMEDIA_TYPE_AUDIO || - (flags & 0x004 && !i && !(sample_flags & 0xffff0000)) || sample_flags & 0x2000000)) + (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS && !i && !(sample_flags & ~MOV_FRAG_SAMPLE_FLAG_DEGRADATION_PRIORITY_MASK)) || sample_flags & MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO)) distance = 0; av_add_index_entry(st, offset, dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0); diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 72a66db84f..b5e8770353 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1342,6 +1342,9 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) { int version = track->track_duration < INT32_MAX ? 0 : 1; + if (track->mode == MODE_ISM) + version = 1; + (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */ ffio_wfourcc(pb, "mdhd"); avio_w8(pb, version); @@ -1354,7 +1357,10 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->time); /* modification time */ } avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */ - (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */ + if (!track->entry) + (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); + else + (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */ avio_wb16(pb, track->language); /* language */ avio_wb16(pb, 0); /* reserved (quality) */ @@ -1385,6 +1391,9 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) track->timescale, AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; + if (track->mode == MODE_ISM) + version = 1; + (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */ ffio_wfourcc(pb, "tkhd"); avio_w8(pb, version); @@ -1398,7 +1407,10 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) } avio_wb32(pb, track->track_id); /* track-id */ avio_wb32(pb, 0); /* reserved */ - (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); + if (!track->entry) + (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); + else + (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); avio_wb32(pb, 0); /* reserved */ avio_wb32(pb, 0); /* reserved */ @@ -2225,19 +2237,19 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track, int64_t moof_offset) { int64_t pos = avio_tell(pb); - /* default-sample-size + default-sample-duration + base-data-offset */ - uint32_t flags = 0x19; + uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION | + MOV_TFHD_BASE_DATA_OFFSET; if (!track->entry) { - flags |= 0x010000; /* duration-is-empty */ + flags |= MOV_TFHD_DURATION_IS_EMPTY; } else { - flags |= 0x20; /* default-sample-flags-present */ + flags |= MOV_TFHD_DEFAULT_FLAGS; } /* Don't set a default sample size, the silverlight player refuses * to play files with that set. Don't set a default sample duration, * WMP freaks out if it is set. */ if (track->mode == MODE_ISM) - flags &= ~0x18; + flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION); avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "tfhd"); @@ -2245,22 +2257,23 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track, avio_wb24(pb, flags); avio_wb32(pb, track->track_id); /* track-id */ - if (flags & 0x01) + if (flags & MOV_TFHD_BASE_DATA_OFFSET) avio_wb64(pb, moof_offset); - if (flags & 0x08) { + if (flags & MOV_TFHD_DEFAULT_DURATION) { track->default_duration = track->audio_vbr ? track->enc->frame_size : 1; avio_wb32(pb, track->default_duration); } - if (flags & 0x10) { + if (flags & MOV_TFHD_DEFAULT_SIZE) { track->default_size = track->entry ? track->cluster[0].size : 1; avio_wb32(pb, track->default_size); } else track->default_size = -1; - if (flags & 0x20) { + if (flags & MOV_TFHD_DEFAULT_FLAGS) { track->default_sample_flags = track->enc->codec_type == AVMEDIA_TYPE_VIDEO ? - 0x01010000 : 0x02000000; + (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) : + MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO; avio_wb32(pb, track->default_sample_flags); } @@ -2269,13 +2282,14 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track, static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) { - return entry->flags & MOV_SYNC_SAMPLE ? 0x02000000 : 0x01010000; + return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO : + (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC); } static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); - uint32_t flags = 1; /* data-offset-present */ + uint32_t flags = MOV_TRUN_DATA_OFFSET; int i; for (i = 0; i < track->entry; i++) { @@ -2283,16 +2297,16 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track) track->track_duration - track->cluster[i].dts + track->start_dts : track->cluster[i + 1].dts - track->cluster[i].dts; if (duration != track->default_duration) - flags |= 0x100; /* sample-duration-present */ + flags |= MOV_TRUN_SAMPLE_DURATION; if (track->cluster[i].size != track->default_size) - flags |= 0x200; /* sample-size-present */ + flags |= MOV_TRUN_SAMPLE_SIZE; if (i > 0 && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags) - flags |= 0x400; /* sample-flags-present */ + flags |= MOV_TRUN_SAMPLE_FLAGS; } - if (!(flags & 0x400)) - flags |= 0x4; /* first-sample-flags-present */ + if (!(flags & MOV_TRUN_SAMPLE_FLAGS)) + flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS; if (track->flags & MOV_TRACK_CTTS) - flags |= 0x800; /* sample-composition-time-offsets-present */ + flags |= MOV_TRUN_SAMPLE_CTS; avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "trun"); @@ -2302,20 +2316,20 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->entry); /* sample count */ track->moof_size_offset = avio_tell(pb); avio_wb32(pb, 0); /* data offset */ - if (flags & 0x4) /* first sample flags */ + if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) avio_wb32(pb, get_sample_flags(track, &track->cluster[0])); for (i = 0; i < track->entry; i++) { int64_t duration = i + 1 == track->entry ? track->track_duration - track->cluster[i].dts + track->start_dts : track->cluster[i + 1].dts - track->cluster[i].dts; - if (flags & 0x100) + if (flags & MOV_TRUN_SAMPLE_DURATION) avio_wb32(pb, duration); - if (flags & 0x200) + if (flags & MOV_TRUN_SAMPLE_SIZE) avio_wb32(pb, track->cluster[i].size); - if (flags & 0x400) + if (flags & MOV_TRUN_SAMPLE_FLAGS) avio_wb32(pb, get_sample_flags(track, &track->cluster[i])); - if (flags & 0x800) + if (flags & MOV_TRUN_SAMPLE_CTS) avio_wb32(pb, track->cluster[i].cts); } diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h index 41d9590016..73ffe1f49e 100644 --- a/libavformat/rtpdec_formats.h +++ b/libavformat/rtpdec_formats.h @@ -31,6 +31,10 @@ */ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p); +int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, int flags); + extern RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler; extern RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler; extern RTPDynamicProtocolHandler ff_g726_16_dynamic_handler; diff --git a/libavformat/rtpdec_h263.c b/libavformat/rtpdec_h263.c index 27173f013b..6c22a24715 100644 --- a/libavformat/rtpdec_h263.c +++ b/libavformat/rtpdec_h263.c @@ -23,13 +23,9 @@ #include "rtpdec_formats.h" #include "libavutil/intreadwrite.h" -static int h263_handle_packet(AVFormatContext *ctx, - PayloadContext *data, - AVStream *st, - AVPacket * pkt, - uint32_t * timestamp, - const uint8_t * buf, - int len, int flags) +int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, int flags) { uint8_t *ptr; uint16_t header; @@ -96,12 +92,12 @@ RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { .enc_name = "H263-1998", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = CODEC_ID_H263, - .parse_packet = h263_handle_packet, + .parse_packet = ff_h263_handle_packet, }; RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler = { .enc_name = "H263-2000", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = CODEC_ID_H263, - .parse_packet = h263_handle_packet, + .parse_packet = ff_h263_handle_packet, }; diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c index baec6a427c..a3a4825719 100644 --- a/libavformat/rtpdec_h263_rfc2190.c +++ b/libavformat/rtpdec_h263_rfc2190.c @@ -35,6 +35,7 @@ struct PayloadContext { uint8_t endbyte; int endbyte_bits; uint32_t timestamp; + int newformat; }; static PayloadContext *h263_new_context(void) @@ -58,9 +59,14 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, int flags) { - int f, p, i, sbit, ebit; /* Corresponding to header fields in the RFC */ + /* Corresponding to header fields in the RFC */ + int f, p, i, sbit, ebit, src, r; int header_size; + if (data->newformat) + return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf, len, + flags); + if (data->buf && data->timestamp != *timestamp) { /* Dropping old buffered, unfinished data */ uint8_t *p; @@ -80,6 +86,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, /* Mode A */ header_size = 4; i = buf[1] & 0x10; + r = ((buf[1] & 0x01) << 3) | ((buf[2] & 0xe0) >> 5); } else if (!p) { /* Mode B */ header_size = 8; @@ -89,6 +96,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, len, header_size); return AVERROR_INVALIDDATA; } + r = buf[3] & 0x03; i = buf[4] & 0x80; } else { /* Mode C */ @@ -99,10 +107,24 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, len, header_size); return AVERROR_INVALIDDATA; } + r = buf[3] & 0x03; i = buf[4] & 0x80; } sbit = (buf[0] >> 3) & 0x7; ebit = buf[0] & 0x7; + src = (buf[1] & 0xe0) >> 5; + if (!(buf[0] & 0xf8)) { /* Reserved bits in RFC 2429/4629 are zero */ + if ((src == 0 || src >= 6) && r) { + /* Invalid src for this format, and bits that should be zero + * according to RFC 2190 aren't zero. */ + av_log(ctx, AV_LOG_WARNING, + "Interpreting H263 RTP data as RFC 2429/4629 even though " + "signalled with a static payload type.\n"); + data->newformat = 1; + return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf, + len, flags); + } + } buf += header_size; len -= header_size; diff --git a/tests/ref/lavf/ismv b/tests/ref/lavf/ismv index 5922cb62af..cf0a5831ef 100644 --- a/tests/ref/lavf/ismv +++ b/tests/ref/lavf/ismv @@ -1,9 +1,9 @@ -c4e12d7ed2ab47d43b912eb160a2bea8 *./tests/data/lavf/lavf.ismv -312247 ./tests/data/lavf/lavf.ismv +eb116b60befadfd5c9118635d81c5a6e *./tests/data/lavf/lavf.ismv +312271 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0xbcc963fc -44c724f5dd12436d283aacc95065ad7f *./tests/data/lavf/lavf.ismv -321521 ./tests/data/lavf/lavf.ismv +90db70a6f33cf22db9ce242087b5870b *./tests/data/lavf/lavf.ismv +321545 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0x3998478f -c4e12d7ed2ab47d43b912eb160a2bea8 *./tests/data/lavf/lavf.ismv -312247 ./tests/data/lavf/lavf.ismv +eb116b60befadfd5c9118635d81c5a6e *./tests/data/lavf/lavf.ismv +312271 ./tests/data/lavf/lavf.ismv ./tests/data/lavf/lavf.ismv CRC=0xbcc963fc |