From 99a357f4c5091293bc42cb4bbd7bcae6a2624584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 28 Jan 2012 00:28:19 +0200 Subject: [PATCH 01/19] movenc: Write track durations with all bits set if duration is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to 14496-12, the duration should be all 1s if the duration is unknown. This is the case if writing a moov atom without any samples described in it (e.g. as in ismv files). Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index ace7b2f186..58d3c56e0a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1317,7 +1317,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) */ @@ -1361,7 +1364,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 */ From 53026339190132b79644bd2dec73ba9c9a902a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 17 Feb 2012 14:40:24 +0200 Subject: [PATCH 02/19] movenc: Write the unknown duration as 64 bit fields in ismv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is required for the files to play back properly in windows media player. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 58d3c56e0a..612bdcbbfd 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1305,6 +1305,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); @@ -1351,6 +1354,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); From 89baf35996a0feb8cf81535f74cef2946a92d477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 17 Feb 2012 23:10:21 +0200 Subject: [PATCH 03/19] dct-test: Remove a stray declaration of a nonexistent function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/dct-test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 133fdbf0d5..2c59cd99b5 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -48,8 +48,6 @@ void ff_mmx_idct(DCTELEM *data); void ff_mmxext_idct(DCTELEM *data); -void odivx_idct_c(short *block); - // BFIN void ff_bfin_idct(DCTELEM *block); void ff_bfin_fdct(DCTELEM *block); From 07333750592e983f8c382491c48f7b402213cca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 17 Feb 2012 23:12:25 +0200 Subject: [PATCH 04/19] dct-test: Add the missing ff_ prefix to the altivec functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/dct-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 2c59cd99b5..1787ef668a 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -53,8 +53,8 @@ void ff_bfin_idct(DCTELEM *block); void ff_bfin_fdct(DCTELEM *block); // ALTIVEC -void fdct_altivec(DCTELEM *block); -//void idct_altivec(DCTELEM *block);?? no routine +void ff_fdct_altivec(DCTELEM *block); +//void ff_idct_altivec(DCTELEM *block);?? no routine // ARM void ff_j_rev_dct_arm(DCTELEM *data); @@ -95,7 +95,7 @@ static const struct algo fdct_tab[] = { #endif #if HAVE_ALTIVEC - { "altivecfdct", fdct_altivec, NO_PERM, AV_CPU_FLAG_ALTIVEC }, + { "altivecfdct", ff_fdct_altivec, NO_PERM, AV_CPU_FLAG_ALTIVEC }, #endif #if ARCH_BFIN From 84c202cc37024bd78261e4222e46631ea73c48dd Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 15:00:47 -0800 Subject: [PATCH 05/19] huffyuv: error out on bit overrun. On EOF, get_bits() will continuously return 0, causing an infinite loop. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/huffyuv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index ebbfc4528a..0c5f6be3b3 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -184,7 +184,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; } From c0994e39d7fd63b4f4adfe4714fa6e41bff82a7c Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 14:51:29 -0800 Subject: [PATCH 06/19] mpc7: assign an error level + context to av_log() msg. --- libavcodec/mpc7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index 0739bf2b2f..2e8271a120 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){ From 3e13005cac6e076053276b515f5fcf59a3f4b65d Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 15:20:27 -0800 Subject: [PATCH 07/19] mp3on4: require a minimum framesize. If bufsize < headersize, init_get_bits() will be called with a negative number, causing it to fail and any subsequent call to get_bits() will crash because it reads from a NULL pointer. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/mpegaudiodec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index af125d5587..6c088626fc 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -1917,6 +1917,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 From ce7aee9b733134649a6ce2fa743e51733f33e67e Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Fri, 17 Feb 2012 14:13:40 -0800 Subject: [PATCH 08/19] dpcm: ignore extra unpaired bytes in stereo streams. Fixes: CVE-2011-3951 Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind --- libavcodec/dpcm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 1b0f6b005b..7f5dbfe3b9 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: @@ -317,7 +322,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_) \ From 32a659c758bf2ddd8ad48f18c06fa77444341286 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 15:51:27 -0800 Subject: [PATCH 09/19] aiff: don't skip block_align==0 check on COMM-after-SSND files. This prevents SIGFPEs when using block_align for divisions. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavformat/aiffdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index c6b51877b5..b3cbc112ca 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -263,12 +263,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; From b1af4e9c27e2cd4a7deab26b88feae8490d673ba Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 16 Feb 2012 21:42:55 -0800 Subject: [PATCH 10/19] vp8dsp: split long line. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/vp8dsp.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index 5429e98c2a..81e19f435b 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]); From c7e8639c70ec25be2c0afdcea61d992de5f1928e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 17 Feb 2012 10:27:41 +0200 Subject: [PATCH 11/19] rtpdec: Identify incorrectly signalled H263 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H263 in RTP can be packetized in two formats (RFC 2190, RFC 2429/4629). The former normally uses the static payload type 34, while the latter normally uses dynamic payload types with the SDP format names H263-1998 or H263-2000. Look for packets that don't look like proper RFC 2190 packets and switch to depacketizing them according to the new format if they match some heuristic criteria. Signed-off-by: Martin Storsjö --- libavformat/rtpdec_formats.h | 4 ++++ libavformat/rtpdec_h263.c | 14 +++++--------- libavformat/rtpdec_h263_rfc2190.c | 24 +++++++++++++++++++++++- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h index 7f18ca4104..60edecb4ed 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 af71ed63c3..ef2418e7c6 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; From 74699ac8c8b562e9f8d26e21482b89585365774a Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 16:27:36 -0800 Subject: [PATCH 12/19] mjpegb: don't return 0 at the end of frame decoding. Return 0 indicates "please return the same data again", i.e. it causes an infinite loop. Instead, return that we consumed the buffer if we finished decoding succesfully, or return an error if an error occurred. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/mjpegbdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index c89a5bd404..10c5addca0 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 = { From 41afac7f7a67c634c86b1d17fc930e9183d4aaa0 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 12:21:18 -0800 Subject: [PATCH 13/19] asf: prevent packet_size_left from going negative if hdrlen > pktlen. This prevents failed assertions further down in the packet processing where we require non-negative values for packet_size_left. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavformat/asfdec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index bae0eacd10..2922ecf515 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -789,6 +789,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; From 9d3050d3e95e307ebc34a943484c7add838d1220 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 16:57:00 -0800 Subject: [PATCH 14/19] wma: don't return 0 on invalid packets. Return 0 means "please return the same data again", i.e. it causes an infinite loop. Instead, return an error. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/wmadec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 41b2a8e7a7..b9fc21fd3e 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -817,8 +817,12 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, s->last_superframe_len = 0; return 0; } - if (buf_size < s->block_align) - return 0; + 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; + } buf_size = s->block_align; init_get_bits(&s->gb, buf, buf_size*8); From c742ab4e81bb9dcabfdab006d6b8b09a5808c4ce Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 14:18:22 -0800 Subject: [PATCH 15/19] vc1parse: call vc1_init_common(). The parser uses VLC tables initialized in vc1_common_init(), therefore we should call this function on parser init also. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/vc1.h | 1 + libavcodec/vc1_parser.c | 2 +- libavcodec/vc1dec.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index f895aad204..d07ad8937e 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 dfbb1f5119..bf29032c54 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 e48aabcfb2..8ab92b4177 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); From 6d702dc072ffc255cd0f709132e55661698313e7 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Wed, 15 Feb 2012 21:04:12 +0100 Subject: [PATCH 16/19] proresenc: force bitrate not to exceed given limit Apple ProRes Format Specifications mentions target data size for every frame, so make sure frame meets it. This also allows encoder to demand much smaller packet sizes for output. --- libavcodec/proresenc.c | 72 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/libavcodec/proresenc.c b/libavcodec/proresenc.c index 73f7f7d167..7e3e066875 100644 --- a/libavcodec/proresenc.c +++ b/libavcodec/proresenc.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; From 73328f24fae92eeed907a4908ca3147d874ff674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 16 Feb 2012 20:48:30 +0100 Subject: [PATCH 17/19] mov: Use defines for tfhd flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/isom.h | 7 +++++++ libavformat/mov.c | 16 +++++++++------- libavformat/movenc.c | 18 +++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index e74a552644..88eb44ae94 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -157,6 +157,13 @@ 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 + 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 690cd1ed46..74b2f2abf1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2167,14 +2167,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->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 & 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->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; } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 612bdcbbfd..6c17e5ad16 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2179,19 +2179,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"); @@ -2199,19 +2199,19 @@ 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; From 3eec23f3cd7b0d8ef0a545089f75b55390a8ddb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 16 Feb 2012 20:58:09 +0100 Subject: [PATCH 18/19] mov: Use defines for trun flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/isom.h | 7 +++++++ libavformat/mov.c | 15 ++++++++------- libavformat/movenc.c | 24 ++++++++++++------------ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 88eb44ae94..88cda27c43 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -164,6 +164,13 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #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 + 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 74b2f2abf1..5f1302d6c3 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2262,8 +2262,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; @@ -2274,14 +2274,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 & 0xffff0000)) || sample_flags & 0x2000000)) 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 6c17e5ad16..22c918391c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2229,7 +2229,7 @@ static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) 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++) { @@ -2237,16 +2237,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"); @@ -2256,20 +2256,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); } From 5be805d38cb43e6f0b85941f75946d09bc8cc13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 16 Feb 2012 21:12:12 +0100 Subject: [PATCH 19/19] mov: Use defines for sample flags in fragments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/isom.h | 10 ++++++++++ libavformat/mov.c | 2 +- libavformat/movenc.c | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 88cda27c43..32c4b3fd1d 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -171,6 +171,16 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #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 5f1302d6c3..fbc7223233 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2282,7 +2282,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb32(pb) : 0; sc->ctts_count++; if ((keyframe = st->codec->codec_type == AVMEDIA_TYPE_AUDIO || - (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS && !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 22c918391c..30c3061d74 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2214,7 +2214,8 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track, 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); } @@ -2223,7 +2224,8 @@ 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)