summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/ffmpeg/libavformat
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/ffmpeg/libavformat
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/ffmpeg/libavformat')
-rw-r--r--chromium/third_party/ffmpeg/libavformat/4xm.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/Makefile34
-rw-r--r--chromium/third_party/ffmpeg/libavformat/aacdec.c58
-rw-r--r--chromium/third_party/ffmpeg/libavformat/ac3dec.c17
-rw-r--r--chromium/third_party/ffmpeg/libavformat/adxdec.c7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/aiffdec.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/aiffenc.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/allformats.c11
-rw-r--r--chromium/third_party/ffmpeg/libavformat/amr.c17
-rw-r--r--chromium/third_party/ffmpeg/libavformat/apc.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/ape.c12
-rw-r--r--chromium/third_party/ffmpeg/libavformat/apetag.c13
-rw-r--r--chromium/third_party/ffmpeg/libavformat/asf.h3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/asfdec.c69
-rw-r--r--chromium/third_party/ffmpeg/libavformat/asfenc.c90
-rw-r--r--chromium/third_party/ffmpeg/libavformat/assdec.c20
-rw-r--r--chromium/third_party/ffmpeg/libavformat/astenc.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/audiointerleave.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avformat.h511
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avidec.c218
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avienc.c461
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avio.c45
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avio.h22
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avio_internal.h2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/aviobuf.c43
-rw-r--r--chromium/third_party/ffmpeg/libavformat/avisynth.c38
-rw-r--r--chromium/third_party/ffmpeg/libavformat/bink.c34
-rw-r--r--chromium/third_party/ffmpeg/libavformat/cafdec.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/cafenc.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/cinedec.c301
-rw-r--r--chromium/third_party/ffmpeg/libavformat/concatdec.c269
-rw-r--r--chromium/third_party/ffmpeg/libavformat/crcenc.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/dfa.c7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/dsfdec.c159
-rw-r--r--chromium/third_party/ffmpeg/libavformat/dvenc.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/dxa.c15
-rw-r--r--chromium/third_party/ffmpeg/libavformat/electronicarts.c12
-rw-r--r--chromium/third_party/ffmpeg/libavformat/ffmdec.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/file.c17
-rw-r--r--chromium/third_party/ffmpeg/libavformat/flac_picture.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/flacdec.c54
-rw-r--r--chromium/third_party/ffmpeg/libavformat/flacenc.c44
-rw-r--r--chromium/third_party/ffmpeg/libavformat/flvdec.c34
-rw-r--r--chromium/third_party/ffmpeg/libavformat/flvenc.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/format.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/framecrcenc.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/ftp.c10
-rw-r--r--chromium/third_party/ffmpeg/libavformat/gif.c20
-rw-r--r--chromium/third_party/ffmpeg/libavformat/golomb_tab.c1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/gxf.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/gxfenc.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/h263dec.c23
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hdsenc.c32
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hevc.c1140
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hevc.h98
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hls.c1453
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hlsenc.c36
-rw-r--r--chromium/third_party/ffmpeg/libavformat/hnm.c13
-rw-r--r--chromium/third_party/ffmpeg/libavformat/http.c391
-rw-r--r--chromium/third_party/ffmpeg/libavformat/httpauth.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/icodec.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/icoenc.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/id3v2.c198
-rw-r--r--chromium/third_party/ffmpeg/libavformat/id3v2.h28
-rw-r--r--chromium/third_party/ffmpeg/libavformat/id3v2enc.c24
-rw-r--r--chromium/third_party/ffmpeg/libavformat/idcin.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/idroqenc.c30
-rw-r--r--chromium/third_party/ffmpeg/libavformat/iff.c323
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2.h61
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2_alias_pix.c65
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2_brender_pix.c49
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2dec.c85
-rw-r--r--chromium/third_party/ffmpeg/libavformat/img2enc.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/internal.h41
-rw-r--r--chromium/third_party/ffmpeg/libavformat/ipmovie.c15
-rw-r--r--chromium/third_party/ffmpeg/libavformat/isom.c31
-rw-r--r--chromium/third_party/ffmpeg/libavformat/isom.h3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/iss.c15
-rw-r--r--chromium/third_party/ffmpeg/libavformat/jvdec.c94
-rw-r--r--chromium/third_party/ffmpeg/libavformat/libmodplug.c1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/libnut.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/librtmp.c144
-rw-r--r--chromium/third_party/ffmpeg/libavformat/libssh.c237
-rw-r--r--chromium/third_party/ffmpeg/libavformat/loasdec.c27
-rw-r--r--chromium/third_party/ffmpeg/libavformat/lxfdec.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/matroska.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/matroskadec.c1130
-rw-r--r--chromium/third_party/ffmpeg/libavformat/matroskaenc.c84
-rw-r--r--chromium/third_party/ffmpeg/libavformat/metadata.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/microdvddec.c44
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mlvdec.c471
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mms.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mmsh.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mmst.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mov.c358
-rw-r--r--chromium/third_party/ffmpeg/libavformat/movenc.c251
-rw-r--r--chromium/third_party/ffmpeg/libavformat/movenc.h3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mp3dec.c213
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mp3enc.c109
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpc.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpc8.c14
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpeg.c294
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpeg.h1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpegenc.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpegts.c1123
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpegts.h10
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mpegtsenc.c191
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mtv.c51
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mux.c220
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mvdec.c143
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mvi.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mxf.c46
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mxf.h29
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mxfdec.c275
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mxfenc.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/network.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/network.h13
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nistspheredec.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nut.c25
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nut.h4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nutdec.c140
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nutenc.c162
-rw-r--r--chromium/third_party/ffmpeg/libavformat/nuv.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggdec.c49
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggdec.h3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggenc.c40
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparsecelt.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparseogm.c15
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparseopus.c19
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparsetheora.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c79
-rw-r--r--chromium/third_party/ffmpeg/libavformat/oggparsevp8.c137
-rw-r--r--chromium/third_party/ffmpeg/libavformat/omadec.c14
-rw-r--r--chromium/third_party/ffmpeg/libavformat/options.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/options_table.h12
-rw-r--r--chromium/third_party/ffmpeg/libavformat/paf.c52
-rw-r--r--chromium/third_party/ffmpeg/libavformat/pcm.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/pjsdec.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/pmpdec.c10
-rw-r--r--chromium/third_party/ffmpeg/libavformat/psxstr.c1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/pva.c17
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rawdec.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rawenc.c41
-rw-r--r--chromium/third_party/ffmpeg/libavformat/replaygain.c125
-rw-r--r--chromium/third_party/ffmpeg/libavformat/replaygain.h38
-rw-r--r--chromium/third_party/ffmpeg/libavformat/riff.c23
-rw-r--r--chromium/third_party/ffmpeg/libavformat/riff.h22
-rw-r--r--chromium/third_party/ffmpeg/libavformat/riffdec.c18
-rw-r--r--chromium/third_party/ffmpeg/libavformat/riffenc.c58
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rl2.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rmdec.c54
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rpl.c9
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rsd.c7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtmppkt.c65
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtmppkt.h2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtmpproto.c36
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtpdec.h4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtpdec_asf.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c12
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c4
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtpenc.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtsp.c49
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtsp.h1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtspcodes.h110
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtspdec.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/rtspenc.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/sapenc.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/sdp.c18
-rw-r--r--chromium/third_party/ffmpeg/libavformat/sdr2.c121
-rw-r--r--chromium/third_party/ffmpeg/libavformat/segafilm.c49
-rw-r--r--chromium/third_party/ffmpeg/libavformat/segment.c37
-rw-r--r--chromium/third_party/ffmpeg/libavformat/sierravmd.c7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/siff.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/smacker.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/smjpegdec.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/smush.c50
-rw-r--r--chromium/third_party/ffmpeg/libavformat/spdifenc.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/subfile.c147
-rw-r--r--chromium/third_party/ffmpeg/libavformat/swfdec.c20
-rw-r--r--chromium/third_party/ffmpeg/libavformat/swfenc.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/takdec.c1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/tcp.c13
-rw-r--r--chromium/third_party/ffmpeg/libavformat/tee.c13
-rw-r--r--chromium/third_party/ffmpeg/libavformat/tls.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/txd.c5
-rw-r--r--chromium/third_party/ffmpeg/libavformat/udp.c66
-rw-r--r--chromium/third_party/ffmpeg/libavformat/uncodedframecrcenc.c172
-rw-r--r--chromium/third_party/ffmpeg/libavformat/utils.c2156
-rw-r--r--chromium/third_party/ffmpeg/libavformat/vc1test.c3
-rw-r--r--chromium/third_party/ffmpeg/libavformat/version.h7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/vqf.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wavdec.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wavenc.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wc3movie.c7
-rw-r--r--chromium/third_party/ffmpeg/libavformat/webvttdec.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/westwood_vqa.c6
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wtv.h2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wtv_common.c2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wtvdec.c23
-rw-r--r--chromium/third_party/ffmpeg/libavformat/wtvenc.c96
-rw-r--r--chromium/third_party/ffmpeg/libavformat/xmv.c8
-rw-r--r--chromium/third_party/ffmpeg/libavformat/xwma.c25
-rw-r--r--chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c1
205 files changed, 12801 insertions, 4378 deletions
diff --git a/chromium/third_party/ffmpeg/libavformat/4xm.c b/chromium/third_party/ffmpeg/libavformat/4xm.c
index 6e63c673993..23279c42fb7 100644
--- a/chromium/third_party/ffmpeg/libavformat/4xm.c
+++ b/chromium/third_party/ffmpeg/libavformat/4xm.c
@@ -319,8 +319,10 @@ static int fourxm_read_packet(AVFormatContext *s,
if (ret < 0) {
av_free_packet(pkt);
- } else
+ } else {
packet_read = 1;
+ av_shrink_packet(pkt, ret + 8);
+ }
break;
case snd__TAG:
diff --git a/chromium/third_party/ffmpeg/libavformat/Makefile b/chromium/third_party/ffmpeg/libavformat/Makefile
index cf3352b96de..00358e771b9 100644
--- a/chromium/third_party/ffmpeg/libavformat/Makefile
+++ b/chromium/third_party/ffmpeg/libavformat/Makefile
@@ -1,7 +1,6 @@
include $(SUBDIR)../config.mak
NAME = avformat
-FFLIBS = avcodec avutil
HEADERS = avformat.h \
avio.h \
@@ -50,7 +49,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \
rtpdec_xiph.o \
srtp.o
OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o
-OBJS-$(CONFIG_SHARED) += log2_tab.o
+OBJS-$(CONFIG_SHARED) += log2_tab.o golomb_tab.o
# muxers/demuxers
OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o
@@ -62,7 +61,7 @@ OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o
OBJS-$(CONFIG_ADP_DEMUXER) += adp.o
OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o
OBJS-$(CONFIG_ADX_MUXER) += rawenc.o
-OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o apetag.o
+OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o apetag.o img2.o
OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o
OBJS-$(CONFIG_AFC_DEMUXER) += afc.o
OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o pcm.o isom.o \
@@ -84,7 +83,7 @@ OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o
OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o
OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o
-OBJS-$(CONFIG_AVI_MUXER) += avienc.o
+OBJS-$(CONFIG_AVI_MUXER) += avienc.o avlanguage.o
OBJS-$(CONFIG_AVISYNTH) += avisynth.o
OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o
OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o
@@ -106,6 +105,7 @@ OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o
OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o
OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o
+OBJS-$(CONFIG_CINE_DEMUXER) += cinedec.o
OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o
OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o
@@ -117,6 +117,7 @@ OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o
OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o
OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddec.o rawdec.o
OBJS-$(CONFIG_DNXHD_MUXER) += rawenc.o
+OBJS-$(CONFIG_DSF_DEMUXER) += dsfdec.o
OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o
OBJS-$(CONFIG_DTSHD_DEMUXER) += dtshddec.o
OBJS-$(CONFIG_DTS_DEMUXER) += dtsdec.o rawdec.o
@@ -138,6 +139,7 @@ OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o
OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \
flac_picture.o \
oggparsevorbis.o \
+ replaygain.o \
vorbiscomment.o
OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \
vorbiscomment.o
@@ -166,6 +168,7 @@ OBJS-$(CONFIG_H264_DEMUXER) += h264dec.o rawdec.o
OBJS-$(CONFIG_H264_MUXER) += rawenc.o
OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o
OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o
+OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o
OBJS-$(CONFIG_HLS_DEMUXER) += hls.o
OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o
OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o
@@ -180,6 +183,8 @@ OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2enc.o img2.o
+OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER) += img2_alias_pix.o
+OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o
OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o
OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o
OBJS-$(CONFIG_IRCAM_DEMUXER) += ircamdec.o ircam.o pcm.o
@@ -202,7 +207,7 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o
OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \
isom.o rmsipr.o
OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \
- isom.o avc.o \
+ isom.o avc.o hevc.o \
flacenc_header.o avlanguage.o wv.o
OBJS-$(CONFIG_MD5_MUXER) += md5enc.o
OBJS-$(CONFIG_MGSTS_DEMUXER) += mgsts.o
@@ -212,14 +217,15 @@ OBJS-$(CONFIG_MJPEG_DEMUXER) += rawdec.o
OBJS-$(CONFIG_MJPEG_MUXER) += rawenc.o
OBJS-$(CONFIG_MLP_DEMUXER) += rawdec.o
OBJS-$(CONFIG_MLP_MUXER) += rawenc.o
+OBJS-$(CONFIG_MLV_DEMUXER) += mlvdec.o riffdec.o
OBJS-$(CONFIG_MM_DEMUXER) += mm.o
OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o
OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o
-OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o
-OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o \
+OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o replaygain.o
+OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o hevc.o \
movenchint.o mov_chan.o rtp.o
OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o
-OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o
+OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o
OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o
OBJS-$(CONFIG_MPC_DEMUXER) += mpc.o apetag.o img2.o
OBJS-$(CONFIG_MPC8_DEMUXER) += mpc8.o apetag.o img2.o
@@ -239,8 +245,8 @@ OBJS-$(CONFIG_MPL2_DEMUXER) += mpl2dec.o subtitles.o
OBJS-$(CONFIG_MPSUB_DEMUXER) += mpsubdec.o subtitles.o
OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o
OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o
-OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o
OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o
+OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o
OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o
OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o audiointerleave.o
OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o
@@ -261,8 +267,12 @@ OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \
oggparsespeex.o \
oggparsetheora.o \
oggparsevorbis.o \
+ oggparsevp8.o \
+ replaygain.o \
vorbiscomment.o \
flac_picture.o
+OBJS-$(CONFIG_OGA_MUXER) += oggenc.o \
+ vorbiscomment.o
OBJS-$(CONFIG_OGG_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_OMA_DEMUXER) += omadec.o pcm.o oma.o
@@ -351,6 +361,7 @@ OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o
OBJS-$(CONFIG_SAP_MUXER) += sapenc.o
OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o
OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o
+OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
OBJS-$(CONFIG_SEGMENT_MUXER) += segment.o
OBJS-$(CONFIG_SHORTEN_DEMUXER) += rawdec.o
@@ -386,6 +397,7 @@ OBJS-$(CONFIG_TRUEHD_MUXER) += rawenc.o
OBJS-$(CONFIG_TTA_DEMUXER) += tta.o apetag.o img2.o
OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o
OBJS-$(CONFIG_TXD_DEMUXER) += txd.o
+OBJS-$(CONFIG_UNCODEDFRAMECRC_MUXER) += uncodedframecrcenc.o framehash.o
OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o
OBJS-$(CONFIG_VC1_MUXER) += rawenc.o
OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o
@@ -411,7 +423,7 @@ OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o
OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o
OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv_common.o asfdec.o asf.o asfcrypt.o \
avlanguage.o mpegts.o isom.o
-OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv_common.o asf.o asfenc.o
+OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv_common.o mpegtsenc.o
OBJS-$(CONFIG_WV_DEMUXER) += wvdec.o wv.o apetag.o img2.o
OBJS-$(CONFIG_WV_MUXER) += wvenc.o wv.o apetag.o img2.o
OBJS-$(CONFIG_XA_DEMUXER) += xa.o
@@ -460,6 +472,7 @@ OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o
OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o
OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o
OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o
+OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o
OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o
OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o
OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o
@@ -472,6 +485,7 @@ SLIBOBJS-$(HAVE_GNU_WINDRES) += avformatres.o
SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h
+
TESTPROGS = seek \
srtp \
url \
diff --git a/chromium/third_party/ffmpeg/libavformat/aacdec.c b/chromium/third_party/ffmpeg/libavformat/aacdec.c
index d93e75ec52c..05cbaf78aa1 100644
--- a/chromium/third_party/ffmpeg/libavformat/aacdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/aacdec.c
@@ -38,28 +38,42 @@ static int adts_aac_probe(AVProbeData *p)
buf = buf0;
- for(; buf < end; buf= buf2+1) {
+ for (; buf < end; buf = buf2 + 1) {
buf2 = buf;
- for(frames = 0; buf2 < end; frames++) {
+ for (frames = 0; buf2 < end; frames++) {
uint32_t header = AV_RB16(buf2);
- if((header&0xFFF6) != 0xFFF0)
+ if ((header & 0xFFF6) != 0xFFF0) {
+ if (buf != buf0) {
+ // Found something that isn't an ADTS header, starting
+ // from a position other than the start of the buffer.
+ // Discard the count we've accumulated so far since it
+ // probably was a false positive.
+ frames = 0;
+ }
break;
+ }
fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF;
- if(fsize < 7)
+ if (fsize < 7)
break;
fsize = FFMIN(fsize, end - buf2);
buf2 += fsize;
}
max_frames = FFMAX(max_frames, frames);
- if(buf == buf0)
- first_frames= frames;
+ if (buf == buf0)
+ first_frames = frames;
}
- if (first_frames>=3) return AVPROBE_SCORE_EXTENSION + 1;
- else if(max_frames>500)return AVPROBE_SCORE_EXTENSION;
- else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2;
- else if(max_frames>=1) return 1;
- else return 0;
+
+ if (first_frames >= 3)
+ return AVPROBE_SCORE_EXTENSION + 1;
+ else if (max_frames > 100)
+ return AVPROBE_SCORE_EXTENSION;
+ else if (max_frames >= 3)
+ return AVPROBE_SCORE_EXTENSION / 2;
+ else if (max_frames >= 1)
+ return 1;
+ else
+ return 0;
}
static int adts_aac_read_header(AVFormatContext *s)
@@ -71,8 +85,8 @@ static int adts_aac_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codec->codec_id = s->iformat->raw_codec_id;
- st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
+ st->codec->codec_id = s->iformat->raw_codec_id;
+ st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
ff_id3v1_read(s);
if (s->pb->seekable &&
@@ -82,19 +96,19 @@ static int adts_aac_read_header(AVFormatContext *s)
avio_seek(s->pb, cur, SEEK_SET);
}
- //LCM of all possible ADTS sample rates
+ // LCM of all possible ADTS sample rates
avpriv_set_pts_info(st, 64, 1, 28224000);
return 0;
}
AVInputFormat ff_aac_demuxer = {
- .name = "aac",
- .long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"),
- .read_probe = adts_aac_probe,
- .read_header = adts_aac_read_header,
- .read_packet = ff_raw_read_partial_packet,
- .flags = AVFMT_GENERIC_INDEX,
- .extensions = "aac",
- .raw_codec_id = AV_CODEC_ID_AAC,
+ .name = "aac",
+ .long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"),
+ .read_probe = adts_aac_probe,
+ .read_header = adts_aac_read_header,
+ .read_packet = ff_raw_read_partial_packet,
+ .flags = AVFMT_GENERIC_INDEX,
+ .extensions = "aac",
+ .raw_codec_id = AV_CODEC_ID_AAC,
};
diff --git a/chromium/third_party/ffmpeg/libavformat/ac3dec.c b/chromium/third_party/ffmpeg/libavformat/ac3dec.c
index 3db23397d0d..58ef44d45a7 100644
--- a/chromium/third_party/ffmpeg/libavformat/ac3dec.c
+++ b/chromium/third_party/ffmpeg/libavformat/ac3dec.c
@@ -28,7 +28,7 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id)
{
int max_frames, first_frames = 0, frames;
const uint8_t *buf, *buf2, *end;
- AC3HeaderInfo hdr;
+ AC3HeaderInfo *phdr = NULL;
GetBitContext gbc;
enum AVCodecID codec_id = AV_CODEC_ID_AC3;
@@ -55,27 +55,28 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id)
init_get_bits(&gbc, buf3, 54);
}else
init_get_bits(&gbc, buf2, 54);
- if(avpriv_ac3_parse_header(&gbc, &hdr) < 0)
+ if(avpriv_ac3_parse_header2(&gbc, &phdr) < 0)
break;
- if(buf2 + hdr.frame_size > end)
+ if(buf2 + phdr->frame_size > end)
break;
if (buf[0] == 0x77 && buf[1] == 0x0B) {
- av_assert0(hdr.frame_size <= sizeof(buf3));
- for(i=8; i<hdr.frame_size; i+=2) {
+ av_assert0(phdr->frame_size <= sizeof(buf3));
+ for(i=8; i<phdr->frame_size; i+=2) {
buf3[i ] = buf[i+1];
buf3[i+1] = buf[i ];
}
}
- if(av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, gbc.buffer + 2, hdr.frame_size - 2))
+ if(av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, gbc.buffer + 2, phdr->frame_size - 2))
break;
- if (hdr.bitstream_id > 10)
+ if (phdr->bitstream_id > 10)
codec_id = AV_CODEC_ID_EAC3;
- buf2 += hdr.frame_size;
+ buf2 += phdr->frame_size;
}
max_frames = FFMAX(max_frames, frames);
if(buf == p->buf)
first_frames = frames;
}
+ av_freep(&phdr);
if(codec_id != expected_codec_id) return 0;
// keep this in sync with mp3 probe, both need to avoid
// issues with MPEG-files!
diff --git a/chromium/third_party/ffmpeg/libavformat/adxdec.c b/chromium/third_party/ffmpeg/libavformat/adxdec.c
index 0a0436f1847..fe22c3ae697 100644
--- a/chromium/third_party/ffmpeg/libavformat/adxdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/adxdec.c
@@ -78,13 +78,8 @@ static int adx_read_header(AVFormatContext *s)
c->header_size = avio_rb16(s->pb) + 4;
avio_seek(s->pb, -4, SEEK_CUR);
- if (ff_alloc_extradata(avctx, c->header_size))
+ if (ff_get_extradata(avctx, s->pb, c->header_size) < 0)
return AVERROR(ENOMEM);
- if (avio_read(s->pb, avctx->extradata, c->header_size) < c->header_size) {
- av_freep(&avctx->extradata);
- return AVERROR(EIO);
- }
- avctx->extradata_size = c->header_size;
ret = avpriv_adx_decode_header(avctx, avctx->extradata,
avctx->extradata_size, &c->header_size,
diff --git a/chromium/third_party/ffmpeg/libavformat/aiffdec.c b/chromium/third_party/ffmpeg/libavformat/aiffdec.c
index 6f82d9339a1..81bcc64a0c5 100644
--- a/chromium/third_party/ffmpeg/libavformat/aiffdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/aiffdec.c
@@ -237,7 +237,7 @@ static int aiff_read_header(AVFormatContext *s)
break;
case MKTAG('I', 'D', '3', ' '):
position = avio_tell(pb);
- ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size);
if (id3v2_extra_meta)
if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) {
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
@@ -278,9 +278,8 @@ static int aiff_read_header(AVFormatContext *s)
case MKTAG('w', 'a', 'v', 'e'):
if ((uint64_t)size > (1<<30))
return -1;
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, size);
if (st->codec->codec_id == AV_CODEC_ID_QDM2 && size>=12*4 && !st->codec->block_align) {
st->codec->block_align = AV_RB32(st->codec->extradata+11*4);
aiff->block_duration = AV_RB32(st->codec->extradata+9*4);
diff --git a/chromium/third_party/ffmpeg/libavformat/aiffenc.c b/chromium/third_party/ffmpeg/libavformat/aiffenc.c
index 6e3d8bc6add..90fc43346ce 100644
--- a/chromium/third_party/ffmpeg/libavformat/aiffenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/aiffenc.c
@@ -66,7 +66,7 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff)
return ret;
pict_list = pict_list->next;
}
- ff_id3v2_finish(&id3v2, pb);
+ ff_id3v2_finish(&id3v2, pb, s->metadata_header_padding);
end = avio_tell(pb);
size = end - pos;
diff --git a/chromium/third_party/ffmpeg/libavformat/allformats.c b/chromium/third_party/ffmpeg/libavformat/allformats.c
index f1039dda84b..0e7feea8f64 100644
--- a/chromium/third_party/ffmpeg/libavformat/allformats.c
+++ b/chromium/third_party/ffmpeg/libavformat/allformats.c
@@ -98,6 +98,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(CAVSVIDEO, cavsvideo);
REGISTER_DEMUXER (CDG, cdg);
REGISTER_DEMUXER (CDXL, cdxl);
+ REGISTER_DEMUXER (CINE, cine);
REGISTER_DEMUXER (CONCAT, concat);
REGISTER_MUXER (CRC, crc);
REGISTER_MUXDEMUX(DATA, data);
@@ -105,6 +106,7 @@ void av_register_all(void)
REGISTER_DEMUXER (DFA, dfa);
REGISTER_MUXDEMUX(DIRAC, dirac);
REGISTER_MUXDEMUX(DNXHD, dnxhd);
+ REGISTER_DEMUXER (DSF, dsf);
REGISTER_DEMUXER (DSICIN, dsicin);
REGISTER_MUXDEMUX(DTS, dts);
REGISTER_DEMUXER (DTSHD, dtshd);
@@ -135,7 +137,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(H263, h263);
REGISTER_MUXDEMUX(H264, h264);
REGISTER_MUXER (HDS, hds);
- REGISTER_DEMUXER (HEVC, hevc);
+ REGISTER_MUXDEMUX(HEVC, hevc);
REGISTER_MUXDEMUX(HLS, hls);
REGISTER_DEMUXER (HNM, hnm);
REGISTER_MUXDEMUX(ICO, ico);
@@ -145,6 +147,8 @@ void av_register_all(void)
REGISTER_MUXDEMUX(ILBC, ilbc);
REGISTER_MUXDEMUX(IMAGE2, image2);
REGISTER_MUXDEMUX(IMAGE2PIPE, image2pipe);
+ REGISTER_DEMUXER (IMAGE2_ALIAS_PIX, image2_alias_pix);
+ REGISTER_DEMUXER (IMAGE2_BRENDER_PIX, image2_brender_pix);
REGISTER_DEMUXER (INGENIENT, ingenient);
REGISTER_DEMUXER (IPMOVIE, ipmovie);
REGISTER_MUXER (IPOD, ipod);
@@ -168,6 +172,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(MICRODVD, microdvd);
REGISTER_MUXDEMUX(MJPEG, mjpeg);
REGISTER_MUXDEMUX(MLP, mlp);
+ REGISTER_DEMUXER (MLV, mlv);
REGISTER_DEMUXER (MM, mm);
REGISTER_MUXDEMUX(MMF, mmf);
REGISTER_MUXDEMUX(MOV, mov);
@@ -203,6 +208,7 @@ void av_register_all(void)
REGISTER_MUXER (NULL, null);
REGISTER_MUXDEMUX(NUT, nut);
REGISTER_DEMUXER (NUV, nuv);
+ REGISTER_MUXER (OGA, oga);
REGISTER_MUXDEMUX(OGG, ogg);
REGISTER_MUXDEMUX(OMA, oma);
REGISTER_MUXER (OPUS, opus);
@@ -249,6 +255,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(SAP, sap);
REGISTER_DEMUXER (SBG, sbg);
REGISTER_DEMUXER (SDP, sdp);
+ REGISTER_DEMUXER (SDR2, sdr2);
#if CONFIG_RTPDEC
ff_register_rtp_dynamic_payload_handlers();
ff_register_rdt_dynamic_payload_handlers();
@@ -284,6 +291,7 @@ void av_register_all(void)
REGISTER_DEMUXER (TTA, tta);
REGISTER_DEMUXER (TXD, txd);
REGISTER_DEMUXER (TTY, tty);
+ REGISTER_MUXER (UNCODEDFRAMECRC, uncodedframecrc);
REGISTER_MUXDEMUX(VC1, vc1);
REGISTER_MUXDEMUX(VC1T, vc1t);
REGISTER_DEMUXER (VIVO, vivo);
@@ -336,6 +344,7 @@ void av_register_all(void)
REGISTER_PROTOCOL(RTP, rtp);
REGISTER_PROTOCOL(SCTP, sctp);
REGISTER_PROTOCOL(SRTP, srtp);
+ REGISTER_PROTOCOL(SUBFILE, subfile);
REGISTER_PROTOCOL(TCP, tcp);
REGISTER_PROTOCOL(TLS, tls);
REGISTER_PROTOCOL(UDP, udp);
diff --git a/chromium/third_party/ffmpeg/libavformat/amr.c b/chromium/third_party/ffmpeg/libavformat/amr.c
index db9bb4e59da..60015255307 100644
--- a/chromium/third_party/ffmpeg/libavformat/amr.c
+++ b/chromium/third_party/ffmpeg/libavformat/amr.c
@@ -26,11 +26,15 @@ Only mono files are supported.
*/
-#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
+typedef struct {
+ uint64_t cumulated_size;
+ uint64_t block_count;
+} AMRContext;
+
static const char AMR_header[] = "#!AMR\n";
static const char AMRWB_header[] = "#!AMR-WB\n";
@@ -111,12 +115,13 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
AVCodecContext *enc = s->streams[0]->codec;
int read, size = 0, toc, mode;
int64_t pos = avio_tell(s->pb);
+ AMRContext *amr = s->priv_data;
if (url_feof(s->pb)) {
return AVERROR(EIO);
}
- // FIXME this is wrong, this should rather be in a AVParset
+ // FIXME this is wrong, this should rather be in a AVParser
toc = avio_r8(s->pb);
mode = (toc >> 3) & 0x0F;
@@ -137,8 +142,11 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
if (!size || av_new_packet(pkt, size))
return AVERROR(EIO);
- /* Both AMR formats have 50 frames per second */
- s->streams[0]->codec->bit_rate = size*8*50;
+ if (amr->cumulated_size < UINT64_MAX - size) {
+ amr->cumulated_size += size;
+ /* Both AMR formats have 50 frames per second */
+ s->streams[0]->codec->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50;
+ }
pkt->stream_index = 0;
pkt->pos = pos;
@@ -158,6 +166,7 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
AVInputFormat ff_amr_demuxer = {
.name = "amr",
.long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"),
+ .priv_data_size = sizeof(AMRContext),
.read_probe = amr_probe,
.read_header = amr_read_header,
.read_packet = amr_read_packet,
diff --git a/chromium/third_party/ffmpeg/libavformat/apc.c b/chromium/third_party/ffmpeg/libavformat/apc.c
index 08ae9351dcf..21bb514cd0b 100644
--- a/chromium/third_party/ffmpeg/libavformat/apc.c
+++ b/chromium/third_party/ffmpeg/libavformat/apc.c
@@ -52,11 +52,9 @@ static int apc_read_header(AVFormatContext *s)
avio_rl32(pb); /* number of samples */
st->codec->sample_rate = avio_rl32(pb);
- if (ff_alloc_extradata(st->codec, 2 * 4))
- return AVERROR(ENOMEM);
-
/* initial predictor values for adpcm decoder */
- avio_read(pb, st->codec->extradata, 2 * 4);
+ if (ff_get_extradata(st->codec, pb, 2 * 4) < 0)
+ return AVERROR(ENOMEM);
if (avio_rl32(pb)) {
st->codec->channels = 2;
diff --git a/chromium/third_party/ffmpeg/libavformat/ape.c b/chromium/third_party/ffmpeg/libavformat/ape.c
index 6f824800a39..d5a786a1989 100644
--- a/chromium/third_party/ffmpeg/libavformat/ape.c
+++ b/chromium/third_party/ffmpeg/libavformat/ape.c
@@ -264,7 +264,7 @@ static int ape_read_header(AVFormatContext * s)
}
if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) {
av_log(s, AV_LOG_ERROR,
- "Number of seek entries is less than number of frames: %zu vs. %"PRIu32"\n",
+ "Number of seek entries is less than number of frames: %"SIZE_SPECIFIER" vs. %"PRIu32"\n",
ape->seektablelength / sizeof(*ape->seektable), ape->totalframes);
return AVERROR_INVALIDDATA;
}
@@ -282,18 +282,20 @@ static int ape_read_header(AVFormatContext * s)
ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1);
if (ape->seektablelength > 0) {
- ape->seektable = av_malloc(ape->seektablelength);
+ ape->seektable = av_mallocz(ape->seektablelength);
if (!ape->seektable)
return AVERROR(ENOMEM);
for (i = 0; i < ape->seektablelength / sizeof(uint32_t) && !pb->eof_reached; i++)
ape->seektable[i] = avio_rl32(pb);
if (ape->fileversion < 3810) {
- ape->bittable = av_malloc(ape->totalframes);
+ ape->bittable = av_mallocz(ape->totalframes);
if (!ape->bittable)
return AVERROR(ENOMEM);
for (i = 0; i < ape->totalframes && !pb->eof_reached; i++)
ape->bittable[i] = avio_r8(pb);
}
+ if (pb->eof_reached)
+ av_log(s, AV_LOG_WARNING, "File truncated\n");
}
ape->frames[0].pos = ape->firstframe;
@@ -415,8 +417,10 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt)
AV_WL32(pkt->data , nblocks);
AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip);
ret = avio_read(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size);
- if (ret < 0)
+ if (ret < 0) {
+ av_free_packet(pkt);
return ret;
+ }
pkt->pts = ape->frames[ape->currentframe].pts;
pkt->stream_index = 0;
diff --git a/chromium/third_party/ffmpeg/libavformat/apetag.c b/chromium/third_party/ffmpeg/libavformat/apetag.c
index a376a0bc4a4..7d2f0b3222d 100644
--- a/chromium/third_party/ffmpeg/libavformat/apetag.c
+++ b/chromium/third_party/ffmpeg/libavformat/apetag.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "avformat.h"
@@ -88,13 +90,8 @@ static int ape_tag_read_field(AVFormatContext *s)
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
} else {
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, s->pb, size) < 0)
return AVERROR(ENOMEM);
- if (avio_read(pb, st->codec->extradata, size) != size) {
- av_freep(&st->codec->extradata);
- st->codec->extradata_size = 0;
- return AVERROR(EIO);
- }
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
}
} else {
@@ -144,14 +141,14 @@ int64_t ff_ape_parse_tag(AVFormatContext *s)
}
if (tag_bytes > file_size - APE_TAG_FOOTER_BYTES) {
- av_log(s, AV_LOG_ERROR, "Invalid tag size %u.\n", tag_bytes);
+ av_log(s, AV_LOG_ERROR, "Invalid tag size %"PRIu32".\n", tag_bytes);
return 0;
}
tag_start = file_size - tag_bytes - APE_TAG_FOOTER_BYTES;
fields = avio_rl32(pb); /* number of fields */
if (fields > 65536) {
- av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);
+ av_log(s, AV_LOG_ERROR, "Too many tag fields (%"PRIu32")\n", fields);
return 0;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/asf.h b/chromium/third_party/ffmpeg/libavformat/asf.h
index 904d3486e88..0c9598a8d8f 100644
--- a/chromium/third_party/ffmpeg/libavformat/asf.h
+++ b/chromium/third_party/ffmpeg/libavformat/asf.h
@@ -43,6 +43,7 @@ typedef struct ASFStream {
int timestamp;
int64_t duration;
int skip_to_key;
+ int pkt_clean;
int ds_span; /* descrambling */
int ds_packet_size;
@@ -188,6 +189,4 @@ extern const AVMetadataConv ff_asf_metadata_conv[];
extern AVInputFormat ff_asf_demuxer;
-void ff_put_guid(AVIOContext *s, const ff_asf_guid *g);
-
#endif /* AVFORMAT_ASF_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/asfdec.c b/chromium/third_party/ffmpeg/libavformat/asfdec.c
index a9b032682d5..a7d860927b1 100644
--- a/chromium/third_party/ffmpeg/libavformat/asfdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/asfdec.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
@@ -266,7 +268,7 @@ static void get_id3_tag(AVFormatContext *s, int len)
{
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
- ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len);
if (id3v2_extra_meta)
ff_id3v2_parse_apic(s, &id3v2_extra_meta);
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
@@ -943,13 +945,13 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
// the following checks prevent overflows and infinite loops
if (!packet_length || packet_length >= (1U << 29)) {
av_log(s, AV_LOG_ERROR,
- "invalid packet_length %d at:%"PRId64"\n",
+ "invalid packet_length %"PRIu32" at:%"PRId64"\n",
packet_length, avio_tell(pb));
return AVERROR_INVALIDDATA;
}
if (padsize >= packet_length) {
av_log(s, AV_LOG_ERROR,
- "invalid padsize %d at:%"PRId64"\n", padsize, avio_tell(pb));
+ "invalid padsize %"PRIu32" at:%"PRId64"\n", padsize, avio_tell(pb));
return AVERROR_INVALIDDATA;
}
@@ -968,7 +970,7 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
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",
+ "invalid packet header length %d for pktlen %"PRIu32"-%"PRIu32" at %"PRId64"\n",
rsize, packet_length, padsize, avio_tell(pb));
return AVERROR_INVALIDDATA;
}
@@ -1159,6 +1161,16 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
asf_st = asf->asf_st;
av_assert0(asf_st);
+ if (!asf_st->frag_offset && asf->packet_frag_offset) {
+ av_dlog(s, "skipping asf data pkt with fragment offset for "
+ "stream:%d, expected:%d but got %d from pkt)\n",
+ asf->stream_index, asf_st->frag_offset,
+ asf->packet_frag_offset);
+ avio_skip(pb, asf->packet_frag_size);
+ asf->packet_size_left -= asf->packet_frag_size;
+ continue;
+ }
+
if (asf->packet_replic_size == 1) {
// frag_offset is here used as the beginning timestamp
asf->packet_frag_timestamp = asf->packet_time_start;
@@ -1191,6 +1203,7 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll;
asf_st->pkt.stream_index = asf->stream_index;
asf_st->pkt.pos = asf_st->packet_pos = asf->packet_pos;
+ asf_st->pkt_clean = 0;
if (asf_st->pkt.data && asf_st->palette_changed) {
uint8_t *pal;
@@ -1231,6 +1244,11 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
continue;
}
+ if (asf->packet_frag_offset != asf_st->frag_offset && !asf_st->pkt_clean) {
+ memset(asf_st->pkt.data + asf_st->frag_offset, 0, asf_st->pkt.size - asf_st->frag_offset);
+ asf_st->pkt_clean = 1;
+ }
+
ret = avio_read(pb, asf_st->pkt.data + asf->packet_frag_offset,
asf->packet_frag_size);
if (ret != asf->packet_frag_size) {
@@ -1450,30 +1468,30 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
return pts;
}
-static void asf_build_simple_index(AVFormatContext *s, int stream_index)
+static int asf_build_simple_index(AVFormatContext *s, int stream_index)
{
ff_asf_guid g;
ASFContext *asf = s->priv_data;
int64_t current_pos = avio_tell(s->pb);
+ int ret = 0;
- if(avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET) < 0) {
- asf->index_read= -1;
- return;
+ if((ret = avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET)) < 0) {
+ return ret;
}
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
/* the data object can be followed by other top-level objects,
* skip them until the simple index object is reached */
while (ff_guidcmp(&g, &ff_asf_simple_index_header)) {
int64_t gsize = avio_rl64(s->pb);
if (gsize < 24 || url_feof(s->pb)) {
- avio_seek(s->pb, current_pos, SEEK_SET);
- asf->index_read= -1;
- return;
+ goto end;
}
avio_skip(s->pb, gsize - 24);
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
}
{
@@ -1481,7 +1499,8 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
int pct, ict;
int i;
int64_t av_unused gsize = avio_rl64(s->pb);
- ff_get_guid(s->pb, &g);
+ if ((ret = ff_get_guid(s->pb, &g)) < 0)
+ goto end;
itime = avio_rl64(s->pb);
pct = avio_rl32(s->pb);
ict = avio_rl32(s->pb);
@@ -1504,7 +1523,12 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
}
asf->index_read = ict > 1;
}
+end:
+// if (url_feof(s->pb)) {
+// ret = 0;
+// }
avio_seek(s->pb, current_pos, SEEK_SET);
+ return ret;
}
static int asf_read_seek(AVFormatContext *s, int stream_index,
@@ -1512,6 +1536,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
{
ASFContext *asf = s->priv_data;
AVStream *st = s->streams[stream_index];
+ int ret = 0;
if (s->packet_size <= 0)
return -1;
@@ -1525,10 +1550,20 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
return ret;
}
- if (!asf->index_read)
- asf_build_simple_index(s, stream_index);
+ /* explicitly handle the case of seeking to 0 */
+ if (!pts) {
+ asf_reset_header(s);
+ avio_seek(s->pb, s->data_offset, SEEK_SET);
+ return 0;
+ }
+
+ if (!asf->index_read) {
+ ret = asf_build_simple_index(s, stream_index);
+ if (ret < 0)
+ asf->index_read = -1;
+ }
- if ((asf->index_read > 0 && st->index_entries)) {
+ if (asf->index_read > 0 && st->index_entries) {
int index = av_index_search_timestamp(st, pts, flags);
if (index >= 0) {
/* find the position */
diff --git a/chromium/third_party/ffmpeg/libavformat/asfenc.c b/chromium/third_party/ffmpeg/libavformat/asfenc.c
index b4a3ffb7ef6..cccbf858c7a 100644
--- a/chromium/third_party/ffmpeg/libavformat/asfenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/asfenc.c
@@ -34,6 +34,7 @@
#define ASF_INDEXED_INTERVAL 10000000
#define ASF_INDEX_BLOCK (1<<9)
+#define ASF_PAYLOADS_PER_PACKET 63
#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
#define ASF_PACKET_ERROR_CORRECTION_FLAGS \
@@ -223,12 +224,6 @@ static const AVCodecTag codec_asf_bmp_tags[] = {
#define PREROLL_TIME 3100
-void ff_put_guid(AVIOContext *s, const ff_asf_guid *g)
-{
- av_assert0(sizeof(*g) == 16);
- avio_write(s, *g, sizeof(*g));
-}
-
static void put_str16(AVIOContext *s, const char *tag)
{
int len;
@@ -358,7 +353,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
AVIOContext *pb = s->pb;
AVDictionaryEntry *tags[5];
int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
- int has_title;
+ int has_title, has_aspect_ratio = 0;
int metadata_count;
AVCodecContext *enc;
int64_t header_offset, cur_pos, hpos;
@@ -384,6 +379,10 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
bit_rate += enc->bit_rate;
+ if ( enc->codec_type == AVMEDIA_TYPE_VIDEO
+ && enc->sample_aspect_ratio.num > 0
+ && enc->sample_aspect_ratio.den > 0)
+ has_aspect_ratio++;
}
if (asf->is_streamed) {
@@ -410,14 +409,46 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2); /* ??? */
avio_wl32(pb, s->packet_size); /* packet size */
avio_wl32(pb, s->packet_size); /* packet size */
- avio_wl32(pb, bit_rate); /* Nominal data rate in bps */
+ avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
end_header(pb, hpos);
/* unknown headers */
hpos = put_header(pb, &ff_asf_head1_guid);
ff_put_guid(pb, &ff_asf_head2_guid);
- avio_wl32(pb, 6);
- avio_wl16(pb, 0);
+ avio_wl16(pb, 6);
+ if (has_aspect_ratio) {
+ int64_t hpos2;
+ avio_wl32(pb, 26 + has_aspect_ratio * 84);
+ hpos2 = put_header(pb, &ff_asf_metadata_header);
+ avio_wl16(pb, 2 * has_aspect_ratio);
+ for (n = 0; n < s->nb_streams; n++) {
+ enc = s->streams[n]->codec;
+ if ( enc->codec_type == AVMEDIA_TYPE_VIDEO
+ && enc->sample_aspect_ratio.num > 0
+ && enc->sample_aspect_ratio.den > 0) {
+ AVRational sar = enc->sample_aspect_ratio;
+ avio_wl16(pb, 0);
+ // the stream number is set like this below
+ avio_wl16(pb, n + 1);
+ avio_wl16(pb, 26); // name_len
+ avio_wl16(pb, 3); // value_type
+ avio_wl32(pb, 4); // value_len
+ avio_put_str16le(pb, "AspectRatioX");
+ avio_wl32(pb, sar.num);
+ avio_wl16(pb, 0);
+ // the stream number is set like this below
+ avio_wl16(pb, n + 1);
+ avio_wl16(pb, 26); // name_len
+ avio_wl16(pb, 3); // value_type
+ avio_wl32(pb, 4); // value_len
+ avio_put_str16le(pb, "AspectRatioY");
+ avio_wl32(pb, sar.den);
+ }
+ }
+ end_header(pb, hpos2);
+ } else {
+ avio_wl32(pb, 0);
+ }
end_header(pb, hpos);
/* title and other infos */
@@ -497,7 +528,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
/* WAVEFORMATEX header */
- int wavsize = ff_put_wav_header(pb, enc);
+ int wavsize = ff_put_wav_header(pb, enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
if (wavsize < 0)
return -1;
@@ -525,7 +556,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
avio_wl16(pb, 40 + enc->extradata_size); /* size */
/* BITMAPINFOHEADER header */
- ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1);
+ ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1, 0);
}
end_header(pb, hpos);
}
@@ -536,14 +567,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
ff_put_guid(pb, &ff_asf_codec_comment1_header);
avio_wl32(pb, s->nb_streams);
for (n = 0; n < s->nb_streams; n++) {
- AVCodec *p;
+ const AVCodecDescriptor *codec_desc;
const char *desc;
- int len;
- uint8_t *buf;
- AVIOContext *dyn_buf;
- enc = s->streams[n]->codec;
- p = avcodec_find_encoder(enc->codec_id);
+ enc = s->streams[n]->codec;
+ codec_desc = avcodec_descriptor_get(enc->codec_id);
if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
avio_wl16(pb, 2);
@@ -555,17 +583,24 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
if (enc->codec_id == AV_CODEC_ID_WMAV2)
desc = "Windows Media Audio V8";
else
- desc = p ? p->name : enc->codec_name;
+ desc = codec_desc ? codec_desc->name : NULL;
- if (avio_open_dyn_buf(&dyn_buf) < 0)
- return AVERROR(ENOMEM);
+ if (desc) {
+ AVIOContext *dyn_buf;
+ uint8_t *buf;
+ int len;
- avio_put_str16le(dyn_buf, desc);
- len = avio_close_dyn_buf(dyn_buf, &buf);
- avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2
+ if (avio_open_dyn_buf(&dyn_buf) < 0)
+ return AVERROR(ENOMEM);
- avio_write(pb, buf, len);
- av_freep(&buf);
+ avio_put_str16le(dyn_buf, desc);
+ len = avio_close_dyn_buf(dyn_buf, &buf);
+ avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2
+
+ avio_write(pb, buf, len);
+ av_freep(&buf);
+ } else
+ avio_wl16(pb, 0);
avio_wl16(pb, 0); /* no parameters */
@@ -617,6 +652,7 @@ static int asf_write_header(AVFormatContext *s)
ASFContext *asf = s->priv_data;
s->packet_size = PACKET_SIZE;
+ s->max_interleave_delta = 0;
asf->nb_packets = 0;
asf->index_ptr = av_malloc(sizeof(ASFIndex) * ASF_INDEX_BLOCK);
@@ -823,6 +859,8 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
flush_packet(s);
else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
flush_packet(s);
+ else if (asf->packet_nb_payloads == ASF_PAYLOADS_PER_PACKET)
+ flush_packet(s);
}
stream->seq++;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/assdec.c b/chromium/third_party/ffmpeg/libavformat/assdec.c
index c9bd63b3c4d..bb953c7276f 100644
--- a/chromium/third_party/ffmpeg/libavformat/assdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/assdec.c
@@ -27,16 +27,16 @@
#include "libavcodec/internal.h"
#include "libavutil/bprint.h"
-typedef struct ASSContext{
+typedef struct ASSContext {
FFDemuxSubtitlesQueue q;
-}ASSContext;
+} ASSContext;
static int ass_probe(AVProbeData *p)
{
- const char *header= "[Script Info]";
+ const char *header = "[Script Info]";
- if( !memcmp(p->buf , header, strlen(header))
- || !memcmp(p->buf+3, header, strlen(header)))
+ if (!memcmp(p->buf, header, strlen(header)) ||
+ !memcmp(p->buf + 3, header, strlen(header)))
return AVPROBE_SCORE_MAX;
return 0;
@@ -94,9 +94,9 @@ static int ass_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 64, 1, 100);
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
- st->codec->codec_id= AV_CODEC_ID_SSA;
+ st->codec->codec_id = AV_CODEC_ID_SSA;
- header_remaining= INT_MAX;
+ header_remaining = INT_MAX;
av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED);
@@ -108,9 +108,9 @@ static int ass_read_header(AVFormatContext *s)
break;
if (!memcmp(line.str, "[Events]", 8))
- header_remaining= 2;
- else if (line.str[0]=='[')
- header_remaining= INT_MAX;
+ header_remaining = 2;
+ else if (line.str[0] == '[')
+ header_remaining = INT_MAX;
if (header_remaining) {
av_bprintf(&header, "%s", line.str);
diff --git a/chromium/third_party/ffmpeg/libavformat/astenc.c b/chromium/third_party/ffmpeg/libavformat/astenc.c
index edd802cbf39..cf7a12c95d1 100644
--- a/chromium/third_party/ffmpeg/libavformat/astenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/astenc.c
@@ -113,7 +113,7 @@ static int ast_write_packet(AVFormatContext *s, AVPacket *pkt)
AVCodecContext *enc = s->streams[0]->codec;
int size = pkt->size / enc->channels;
- if (enc->frame_number == 1)
+ if (s->streams[0]->nb_frames == 0)
ast->fbs = size;
ffio_wfourcc(pb, "BLCK");
@@ -135,7 +135,7 @@ static int ast_write_trailer(AVFormatContext *s)
ASTMuxContext *ast = s->priv_data;
AVCodecContext *enc = s->streams[0]->codec;
int64_t file_size = avio_tell(pb);
- int64_t samples = (file_size - 64 - (32 * enc->frame_number)) / enc->block_align; /* PCM_S16BE_PLANAR */
+ int64_t samples = (file_size - 64 - (32 * s->streams[0]->nb_frames)) / enc->block_align; /* PCM_S16BE_PLANAR */
av_log(s, AV_LOG_DEBUG, "total samples: %"PRId64"\n", samples);
diff --git a/chromium/third_party/ffmpeg/libavformat/audiointerleave.c b/chromium/third_party/ffmpeg/libavformat/audiointerleave.c
index 2aa95f3dc6a..6d24ff5c7fe 100644
--- a/chromium/third_party/ffmpeg/libavformat/audiointerleave.c
+++ b/chromium/third_party/ffmpeg/libavformat/audiointerleave.c
@@ -34,7 +34,7 @@ void ff_audio_interleave_close(AVFormatContext *s)
AudioInterleaveContext *aic = st->priv_data;
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
- av_fifo_free(aic->fifo);
+ av_fifo_freep(&aic->fifo);
}
}
diff --git a/chromium/third_party/ffmpeg/libavformat/avformat.h b/chromium/third_party/ffmpeg/libavformat/avformat.h
index 6bd54cec64d..55a3cfbd35d 100644
--- a/chromium/third_party/ffmpeg/libavformat/avformat.h
+++ b/chromium/third_party/ffmpeg/libavformat/avformat.h
@@ -173,6 +173,58 @@
*
* @defgroup lavf_encoding Muxing
* @{
+ * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write
+ * it into files or other output bytestreams in the specified container format.
+ *
+ * The main API functions for muxing are avformat_write_header() for writing the
+ * file header, av_write_frame() / av_interleaved_write_frame() for writing the
+ * packets and av_write_trailer() for finalizing the file.
+ *
+ * At the beginning of the muxing process, the caller must first call
+ * avformat_alloc_context() to create a muxing context. The caller then sets up
+ * the muxer by filling the various fields in this context:
+ *
+ * - The @ref AVFormatContext.oformat "oformat" field must be set to select the
+ * muxer that will be used.
+ * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb
+ * "pb" field must be set to an opened IO context, either returned from
+ * avio_open2() or a custom one.
+ * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must
+ * be created with the avformat_new_stream() function. The caller should fill
+ * the @ref AVStream.codec "stream codec context" information, such as the
+ * codec @ref AVCodecContext.codec_type "type", @ref AVCodecContext.codec_id
+ * "id" and other parameters (e.g. width / height, the pixel or sample format,
+ * etc.) as known. The @ref AVCodecContext.time_base "codec timebase" should
+ * be set to the timebase that the caller desires to use for this stream (note
+ * that the timebase actually used by the muxer can be different, as will be
+ * described later).
+ * - The caller may fill in additional information, such as @ref
+ * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream"
+ * metadata, @ref AVFormatContext.chapters "chapters", @ref
+ * AVFormatContext.programs "programs", etc. as described in the
+ * AVFormatContext documentation. Whether such information will actually be
+ * stored in the output depends on what the container format and the muxer
+ * support.
+ *
+ * When the muxing context is fully set up, the caller must call
+ * avformat_write_header() to initialize the muxer internals and write the file
+ * header. Whether anything actually is written to the IO context at this step
+ * depends on the muxer, but this function must always be called. Any muxer
+ * private options must be passed in the options parameter to this function.
+ *
+ * The data is then sent to the muxer by repeatedly calling av_write_frame() or
+ * av_interleaved_write_frame() (consult those functions' documentation for
+ * discussion on the difference between them; only one of them may be used with
+ * a single muxing context, they should not be mixed). Do note that the timing
+ * information on the packets sent to the muxer must be in the corresponding
+ * AVStream's timebase. That timebase is set by the muxer (in the
+ * avformat_write_header() step) and may be different from the timebase the
+ * caller set on the codec context.
+ *
+ * Once all the data has been written, the caller must call av_write_trailer()
+ * to flush any buffered packets and finalize the output file, then close the IO
+ * context (if any) and finally free the muxing context with
+ * avformat_free_context().
* @}
*
* @defgroup lavf_io I/O Read/Write
@@ -209,6 +261,8 @@
struct AVFormatContext;
+struct AVDeviceInfoList;
+struct AVDeviceCapabilitiesQuery;
/**
* @defgroup metadata_api Public Metadata API
@@ -290,6 +344,7 @@ struct AVFormatContext;
* Allocate and read the payload of a packet and initialize its
* fields with default values.
*
+ * @param s associated IO context
* @param pkt packet
* @param size desired payload size
* @return >0 (read size) if OK, AVERROR_xxx otherwise
@@ -305,6 +360,7 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size);
* when there is no reasonable way to know (an upper bound of)
* the final size.
*
+ * @param s associated IO context
* @param pkt packet
* @param size amount of data to read
* @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data
@@ -338,6 +394,8 @@ typedef struct AVProbeData {
} AVProbeData;
#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4)
+#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)
+
#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension
#define AVPROBE_SCORE_MAX 100 ///< maximum score
@@ -453,6 +511,37 @@ typedef struct AVOutputFormat {
void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
int64_t *dts, int64_t *wall);
+ /**
+ * Allows sending messages from application to device.
+ */
+ int (*control_message)(struct AVFormatContext *s, int type,
+ void *data, size_t data_size);
+
+ /**
+ * Write an uncoded AVFrame.
+ *
+ * See av_write_uncoded_frame() for details.
+ *
+ * The library will free *frame afterwards, but the muxer can prevent it
+ * by setting the pointer to NULL.
+ */
+ int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
+ AVFrame **frame, unsigned flags);
+ /**
+ * Returns device list with it properties.
+ * @see avdevice_list_devices() for more details.
+ */
+ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
+ /**
+ * Initialize device capabilities submodule.
+ * @see avdevice_capabilities_create() for more details.
+ */
+ int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
+ /**
+ * Free device capabilities submodule.
+ * @see avdevice_capabilities_free() for more details.
+ */
+ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVOutputFormat;
/**
* @}
@@ -581,6 +670,24 @@ typedef struct AVInputFormat {
* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
*/
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
+
+ /**
+ * Returns device list with it properties.
+ * @see avdevice_list_devices() for more details.
+ */
+ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
+
+ /**
+ * Initialize device capabilities submodule.
+ * @see avdevice_capabilities_create() for more details.
+ */
+ int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
+
+ /**
+ * Free device capabilities submodule.
+ * @see avdevice_capabilities_free() for more details.
+ */
+ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVInputFormat;
/**
* @}
@@ -740,6 +847,30 @@ typedef struct AVStream {
*/
AVPacket attached_pic;
+ /**
+ * An array of side data that applies to the whole stream (i.e. the
+ * container does not allow it to change between packets).
+ *
+ * There may be no overlap between the side data in this array and side data
+ * in the packets. I.e. a given side data is either exported by the muxer
+ * (demuxing) / set by the caller (muxing) in this array, then it never
+ * appears in the packets, or the side data is exported / sent through
+ * the packets (always in the first packet where the value becomes known or
+ * changes), then it does not appear in this array.
+ *
+ * - demuxing: Set by libavformat when the stream is created.
+ * - muxing: May be set by the caller before avformat_write_header().
+ *
+ * Freed by libavformat in avformat_free_context().
+ *
+ * @see av_format_inject_global_side_data()
+ */
+ AVPacketSideData *side_data;
+ /**
+ * The number of elements in the AVStream.side_data array.
+ */
+ int nb_side_data;
+
/*****************************************************************
* 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
@@ -756,9 +887,16 @@ typedef struct AVStream {
int64_t last_dts;
int64_t duration_gcd;
int duration_count;
+ int64_t rfps_duration_sum;
double (*duration_error)[2][MAX_STD_TIMEBASES];
int64_t codec_info_duration;
int64_t codec_info_duration_fields;
+
+ /**
+ * 0 -> decoder has not been searched for yet.
+ * >0 -> decoder found
+ * <0 -> decoder with codec_id == -found_decoder has not been found
+ */
int found_decoder;
int64_t last_duration;
@@ -892,6 +1030,29 @@ typedef struct AVStream {
*/
int pts_wrap_behavior;
+ /**
+ * Internal data to prevent doing update_initial_durations() twice
+ */
+ int update_initial_durations_done;
+
+ /**
+ * Internal data to generate dts from pts
+ */
+ int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
+ uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
+
+ /**
+ * Internal data to analyze DTS and detect faulty mpeg streams
+ */
+ int64_t last_dts_for_order_check;
+ uint8_t dts_ordered;
+ uint8_t dts_misordered;
+
+ /**
+ * Internal data to inject global side data
+ */
+ int inject_global_side_data;
+
} AVStream;
AVRational av_stream_get_r_frame_rate(const AVStream *s);
@@ -943,6 +1104,13 @@ typedef struct AVChapter {
/**
+ * Callback used by devices to communicate with application.
+ */
+typedef int (*av_format_control_message)(struct AVFormatContext *s, int type,
+ void *data, size_t data_size);
+
+
+/**
* The duration of a video can be estimated through various ways, and this enum can be used
* to know how the duration was estimated.
*/
@@ -952,6 +1120,8 @@ enum AVDurationEstimationMethod {
AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate)
};
+typedef struct AVFormatInternal AVFormatInternal;
+
/**
* Format I/O context.
* New fields can be added to the end with minor version bumps.
@@ -962,32 +1132,41 @@ enum AVDurationEstimationMethod {
*/
typedef struct AVFormatContext {
/**
- * A class for logging and AVOptions. Set by avformat_alloc_context().
+ * A class for logging and @ref avoptions. Set by avformat_alloc_context().
* Exports (de)muxer private options if they exist.
*/
const AVClass *av_class;
/**
- * Can only be iformat or oformat, not both at the same time.
+ * The input container format.
*
- * decoding: set by avformat_open_input().
- * encoding: set by the user.
+ * Demuxing only, set by avformat_open_input().
*/
struct AVInputFormat *iformat;
+
+ /**
+ * The output container format.
+ *
+ * Muxing only, must be set by the caller before avformat_write_header().
+ */
struct AVOutputFormat *oformat;
/**
* Format private data. This is an AVOptions-enabled struct
* if and only if iformat/oformat.priv_class is not NULL.
+ *
+ * - muxing: set by avformat_write_header()
+ * - demuxing: set by avformat_open_input()
*/
void *priv_data;
/**
* I/O context.
*
- * decoding: either set by the user before avformat_open_input() (then
- * the user must close it manually) or set by avformat_open_input().
- * encoding: set by the user.
+ * - demuxing: either set by the user before avformat_open_input() (then
+ * the user must close it manually) or set by avformat_open_input().
+ * - muxing: set by the user before avformat_write_header(). The caller must
+ * take care of closing / freeing the IO context.
*
* Do NOT set this field if AVFMT_NOFILE flag is set in
* iformat/oformat.flags. In such a case, the (de)muxer will handle
@@ -996,39 +1175,60 @@ typedef struct AVFormatContext {
AVIOContext *pb;
/* stream info */
- int ctx_flags; /**< Format-specific flags, see AVFMTCTX_xx */
+ /**
+ * Flags signalling stream properties. A combination of AVFMTCTX_*.
+ * Set by libavformat.
+ */
+ int ctx_flags;
/**
+ * Number of elements in AVFormatContext.streams.
+ *
+ * Set by avformat_new_stream(), must not be modified by any other code.
+ */
+ unsigned int nb_streams;
+ /**
* A list of all streams in the file. New streams are created with
* avformat_new_stream().
*
- * decoding: streams are created by libavformat in avformat_open_input().
- * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
- * appear in av_read_frame().
- * encoding: streams are created by the user before avformat_write_header().
+ * - demuxing: streams are created by libavformat in avformat_open_input().
+ * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
+ * appear in av_read_frame().
+ * - muxing: streams are created by the user before avformat_write_header().
+ *
+ * Freed by libavformat in avformat_free_context().
*/
- unsigned int nb_streams;
AVStream **streams;
- char filename[1024]; /**< input or output filename */
+ /**
+ * input or output filename
+ *
+ * - demuxing: set by avformat_open_input()
+ * - muxing: may be set by the caller before avformat_write_header()
+ */
+ char filename[1024];
/**
- * Decoding: position of the first frame of the component, in
+ * Position of the first frame of the component, in
* AV_TIME_BASE fractional seconds. NEVER set this value directly:
* It is deduced from the AVStream values.
+ *
+ * Demuxing only, set by libavformat.
*/
int64_t start_time;
/**
- * Decoding: duration of the stream, in AV_TIME_BASE fractional
+ * Duration of the stream, in AV_TIME_BASE fractional
* seconds. Only set this value if you know none of the individual stream
* durations and also do not set any of them. This is deduced from the
* AVStream values if not set.
+ *
+ * Demuxing only, set by libavformat.
*/
int64_t duration;
/**
- * Decoding: total stream bitrate in bit/s, 0 if not
+ * Total stream bitrate in bit/s, 0 if not
* available. Never set it directly if the file_size and the
* duration are known as FFmpeg can compute it automatically.
*/
@@ -1037,6 +1237,10 @@ typedef struct AVFormatContext {
unsigned int packet_size;
int max_delay;
+ /**
+ * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*.
+ * Set by the user before avformat_open_input() / avformat_write_header().
+ */
int flags;
#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames.
#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index.
@@ -1048,19 +1252,29 @@ typedef struct AVFormatContext {
#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted
#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet.
+/**
+ * When muxing, try to avoid writing any random/volatile data to the output.
+ * This includes any random IDs, real-time timestamps/dates, muxer version, etc.
+ *
+ * This flag is mainly intended for testing.
+ */
+#define AVFMT_FLAG_BITEXACT 0x0400
#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Enable RTP MP4A-LATM payload
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted)
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Don't merge side data but keep it separate.
/**
- * decoding: size of data to probe; encoding: unused.
+ * Maximum size of the data read from input for determining
+ * the input container format.
+ * Demuxing only, set by the caller before avformat_open_input().
*/
unsigned int probesize;
/**
- * decoding: maximum time (in AV_TIME_BASE units) during which the input should
- * be analyzed in avformat_find_stream_info().
+ * Maximum duration (in AV_TIME_BASE units) of the data read
+ * from input in avformat_find_stream_info().
+ * Demuxing only, set by the caller before avformat_find_stream_info().
*/
int max_analyze_duration;
@@ -1095,8 +1309,8 @@ typedef struct AVFormatContext {
* accurate seeking (depends on demuxer).
* Demuxers for which a full in-memory index is mandatory will ignore
* this.
- * muxing : unused
- * demuxing: set by user
+ * - muxing: unused
+ * - demuxing: set by user
*/
unsigned int max_index_size;
@@ -1114,41 +1328,54 @@ typedef struct AVFormatContext {
* in the trailer. To write chapters in the trailer, nb_chapters
* must be zero when write_header is called and non-zero when
* write_trailer is called.
- * muxing : set by user
- * demuxing: set by libavformat
+ * - muxing: set by user
+ * - demuxing: set by libavformat
*/
unsigned int nb_chapters;
AVChapter **chapters;
+ /**
+ * Metadata that applies to the whole file.
+ *
+ * - demuxing: set by libavformat in avformat_open_input()
+ * - muxing: may be set by the caller before avformat_write_header()
+ *
+ * Freed by libavformat in avformat_free_context().
+ */
AVDictionary *metadata;
/**
* Start time of the stream in real world time, in microseconds
- * since the unix epoch (00:00 1st January 1970). That is, pts=0
- * in the stream was captured at this real world time.
- * - encoding: Set by user.
- * - decoding: Unused.
+ * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the
+ * stream was captured at this real world time.
+ * - muxing: Set by the caller before avformat_write_header(). If set to
+ * either 0 or AV_NOPTS_VALUE, then the current wall-time will
+ * be used.
+ * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that
+ * the value may become known after some number of frames
+ * have been received.
*/
int64_t start_time_realtime;
/**
- * decoding: number of frames used to probe fps
+ * The number of frames used for determining the framerate in
+ * avformat_find_stream_info().
+ * Demuxing only, set by the caller before avformat_find_stream_info().
*/
int fps_probe_size;
/**
* Error recognition; higher values will detect more errors but may
* misdetect some more or less valid parts as errors.
- * - encoding: unused
- * - decoding: Set by user.
+ * Demuxing only, set by the caller before avformat_open_input().
*/
int error_recognition;
/**
* Custom interrupt callbacks for the I/O layer.
*
- * decoding: set by the user before avformat_open_input().
- * encoding: set by the user before avformat_write_header()
+ * demuxing: set by the user before avformat_open_input().
+ * muxing: set by the user before avformat_write_header()
* (mainly useful for AVFMT_NOFILE formats). The callback
* should also be passed to avio_open2() if it's used to
* open the file.
@@ -1162,6 +1389,24 @@ typedef struct AVFormatContext {
#define FF_FDEBUG_TS 0x0001
/**
+ * Maximum buffering duration for interleaving.
+ *
+ * To ensure all the streams are interleaved correctly,
+ * av_interleaved_write_frame() will wait until it has at least one packet
+ * for each stream before actually writing any packets to the output file.
+ * When some streams are "sparse" (i.e. there are large gaps between
+ * successive packets), this can result in excessive buffering.
+ *
+ * This field specifies the maximum difference between the timestamps of the
+ * first and the last packet in the muxing queue, above which libavformat
+ * will output a packet regardless of whether it has queued a packet for all
+ * the streams.
+ *
+ * Muxing only, set by the caller before avformat_write_header().
+ */
+ int64_t max_interleave_delta;
+
+ /**
* Transport stream id.
* This will be moved into demuxer private options. Thus no API/ABI compatibility
*/
@@ -1235,14 +1480,14 @@ typedef struct AVFormatContext {
/**
* Correct single timestamp overflows
* - encoding: unused
- * - decoding: Set by user via AVOPtions (NO direct access)
+ * - decoding: Set by user via AVOptions (NO direct access)
*/
unsigned int correct_ts_overflow;
/**
* Force seeking to any (also non key) frames.
* - encoding: unused
- * - decoding: Set by user via AVOPtions (NO direct access)
+ * - decoding: Set by user via AVOptions (NO direct access)
*/
int seek2any;
@@ -1313,6 +1558,12 @@ typedef struct AVFormatContext {
AVRational offset_timebase;
/**
+ * An opaque field for libavformat internal usage.
+ * Must not be accessed in any way by callers.
+ */
+ AVFormatInternal *internal;
+
+ /**
* IO repositioned flag.
* This is set by avformat when the underlaying IO context read pointer
* is repositioned, for example when doing byte based seeking.
@@ -1343,6 +1594,31 @@ typedef struct AVFormatContext {
* Demuxing: Set by user via av_format_set_subtitle_codec (NO direct access).
*/
AVCodec *subtitle_codec;
+
+ /**
+ * Number of bytes to be written as padding in a metadata header.
+ * Demuxing: Unused.
+ * Muxing: Set by user via av_format_set_metadata_header_padding.
+ */
+ int metadata_header_padding;
+
+ /**
+ * User data.
+ * This is a place for some private data of the user.
+ * Mostly usable with control_message_cb or any future callbacks in device's context.
+ */
+ void *opaque;
+
+ /**
+ * Callback used by devices to communicate with application.
+ */
+ av_format_control_message control_message_cb;
+
+ /**
+ * Output timestamp offset, in microseconds.
+ * Muxing: set by user via AVOptions (NO direct access)
+ */
+ int64_t output_ts_offset;
} AVFormatContext;
int av_format_get_probe_score(const AVFormatContext *s);
@@ -1352,6 +1628,18 @@ AVCodec * av_format_get_audio_codec(const AVFormatContext *s);
void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c);
AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s);
void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c);
+int av_format_get_metadata_header_padding(const AVFormatContext *s);
+void av_format_set_metadata_header_padding(AVFormatContext *s, int c);
+void * av_format_get_opaque(const AVFormatContext *s);
+void av_format_set_opaque(AVFormatContext *s, void *opaque);
+av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s);
+void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback);
+
+/**
+ * This function will cause global side data to be injected in the next packet
+ * of each stream as well as after any subsequent seek.
+ */
+void av_format_inject_global_side_data(AVFormatContext *s);
/**
* Returns the method used to set ctx->duration.
@@ -1465,6 +1753,7 @@ const AVClass *avformat_get_class(void);
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
*
+ * @param s media file handle
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
* will be initialized to use this codec. This is needed for e.g. codec-specific
* defaults to be set, so codec should be provided if it is known.
@@ -1522,6 +1811,7 @@ AVInputFormat *av_find_input_format(const char *short_name);
/**
* Guess the file format.
*
+ * @param pd data to be probed
* @param is_opened Whether the file is already opened; determines whether
* demuxers with or without AVFMT_NOFILE are probed.
*/
@@ -1530,6 +1820,7 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
/**
* Guess the file format.
*
+ * @param pd data to be probed
* @param is_opened Whether the file is already opened; determines whether
* demuxers with or without AVFMT_NOFILE are probed.
* @param score_max A probe score larger that this is required to accept a
@@ -1733,6 +2024,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt);
/**
* Seek to the keyframe at timestamp.
* 'timestamp' in 'stream_index'.
+ *
+ * @param s media file handle
* @param stream_index If stream_index is (-1), a default
* stream is selected, and timestamp is automatically converted
* from AV_TIME_BASE units to the stream specific time_base.
@@ -1760,6 +2053,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
* keyframes (this may not be supported by all demuxers).
* If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.
*
+ * @param s media file handle
* @param stream_index index of the stream which is used as time base reference
* @param min_ts smallest acceptable timestamp
* @param ts target timestamp
@@ -1859,50 +2153,109 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options);
/**
* Write a packet to an output media file.
*
- * The packet shall contain one audio or video frame.
- * The packet must be correctly interleaved according to the container
- * specification, if not then av_interleaved_write_frame must be used.
+ * This function passes the packet directly to the muxer, without any buffering
+ * or reordering. The caller is responsible for correctly interleaving the
+ * packets if the format requires it. Callers that want libavformat to handle
+ * the interleaving should call av_interleaved_write_frame() instead of this
+ * function.
*
* @param s media file handle
- * @param pkt The packet, which contains the stream_index, buf/buf_size,
- * dts/pts, ...
- * This can be NULL (at any time, not just at the end), in
- * order to immediately flush data buffered within the muxer,
- * for muxers that buffer up data internally before writing it
- * to the output.
+ * @param pkt The packet containing the data to be written. Note that unlike
+ * av_interleaved_write_frame(), this function does not take
+ * ownership of the packet passed to it (though some muxers may make
+ * an internal reference to the input packet).
+ * <br>
+ * This parameter can be NULL (at any time, not just at the end), in
+ * order to immediately flush data buffered within the muxer, for
+ * muxers that buffer up data internally before writing it to the
+ * output.
+ * <br>
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be
+ * set to the index of the corresponding stream in @ref
+ * AVFormatContext.streams "s->streams". It is very strongly
+ * recommended that timing information (@ref AVPacket.pts "pts", @ref
+ * AVPacket.dts "dts", @ref AVPacket.duration "duration") is set to
+ * correct values.
* @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
+ *
+ * @see av_interleaved_write_frame()
*/
int av_write_frame(AVFormatContext *s, AVPacket *pkt);
/**
* Write a packet to an output media file ensuring correct interleaving.
*
- * The packet must contain one audio or video frame.
- * If the packets are already correctly interleaved, the application should
- * call av_write_frame() instead as it is slightly faster. It is also important
- * to keep in mind that completely non-interleaved input will need huge amounts
- * of memory to interleave with this, so it is preferable to interleave at the
- * demuxer level.
+ * This function will buffer the packets internally as needed to make sure the
+ * packets in the output file are properly interleaved in the order of
+ * increasing dts. Callers doing their own interleaving should call
+ * av_write_frame() instead of this function.
*
* @param s media file handle
- * @param pkt The packet containing the data to be written. pkt->buf must be set
- * to a valid AVBufferRef describing the packet data. Libavformat takes
- * ownership of this reference and will unref it when it sees fit. The caller
- * must not access the data through this reference after this function returns.
- * This can be NULL (at any time, not just at the end), to flush the
- * interleaving queues.
- * Packet's @ref AVPacket.stream_index "stream_index" field must be set to the
- * index of the corresponding stream in @ref AVFormatContext.streams
- * "s.streams".
- * It is very strongly recommended that timing information (@ref AVPacket.pts
- * "pts", @ref AVPacket.dts "dts" @ref AVPacket.duration "duration") is set to
- * correct values.
- *
- * @return 0 on success, a negative AVERROR on error.
+ * @param pkt The packet containing the data to be written.
+ * <br>
+ * If the packet is reference-counted, this function will take
+ * ownership of this reference and unreference it later when it sees
+ * fit.
+ * The caller must not access the data through this reference after
+ * this function returns. If the packet is not reference-counted,
+ * libavformat will make a copy.
+ * <br>
+ * This parameter can be NULL (at any time, not just at the end), to
+ * flush the interleaving queues.
+ * <br>
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be
+ * set to the index of the corresponding stream in @ref
+ * AVFormatContext.streams "s->streams". It is very strongly
+ * recommended that timing information (@ref AVPacket.pts "pts", @ref
+ * AVPacket.dts "dts", @ref AVPacket.duration "duration") is set to
+ * correct values.
+ *
+ * @return 0 on success, a negative AVERROR on error. Libavformat will always
+ * take care of freeing the packet, even if this function fails.
+ *
+ * @see av_write_frame(), AVFormatContext.max_interleave_delta
*/
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
/**
+ * Write a uncoded frame to an output media file.
+ *
+ * The frame must be correctly interleaved according to the container
+ * specification; if not, then av_interleaved_write_frame() must be used.
+ *
+ * See av_interleaved_write_frame() for details.
+ */
+int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
+ AVFrame *frame);
+
+/**
+ * Write a uncoded frame to an output media file.
+ *
+ * If the muxer supports it, this function allows to write an AVFrame
+ * structure directly, without encoding it into a packet.
+ * It is mostly useful for devices and similar special muxers that use raw
+ * video or PCM data and will not serialize it into a byte stream.
+ *
+ * To test whether it is possible to use it with a given muxer and stream,
+ * use av_write_uncoded_frame_query().
+ *
+ * The caller gives up ownership of the frame and must not access it
+ * afterwards.
+ *
+ * @return >=0 for success, a negative code on error
+ */
+int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
+ AVFrame *frame);
+
+/**
+ * Test whether a muxer supports uncoded frame.
+ *
+ * @return >=0 if an uncoded frame can be written to that muxer and stream,
+ * <0 if not
+ */
+int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
+
+/**
* Write the stream trailer to an output media file and free the
* file private data.
*
@@ -2002,7 +2355,7 @@ void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size);
* @param dump_payload True if the payload must be displayed, too.
* @param st AVStream that the packet belongs to
*/
-void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st);
+void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st);
/**
@@ -2016,8 +2369,8 @@ void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st);
* @param dump_payload True if the payload must be displayed, too.
* @param st AVStream that the packet belongs to
*/
-void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
- AVStream *st);
+void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,
+ const AVStream *st);
/**
* Get the AVCodecID for the given codec tag tag.
@@ -2025,6 +2378,7 @@ void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
*
* @param tags list of supported codec_id-codec_tag pairs, as stored
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
+ * @param tag codec tag to match to a codec ID
*/
enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag);
@@ -2034,6 +2388,7 @@ enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned i
*
* @param tags list of supported codec_id-codec_tag pairs, as stored
* in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
+ * @param id codec ID to match to a codec tag
*/
unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id);
@@ -2053,6 +2408,9 @@ int av_find_default_stream_index(AVFormatContext *s);
/**
* Get the index for a specific timestamp.
+ *
+ * @param st stream that the timestamp belongs to
+ * @param timestamp timestamp to retrieve the index for
* @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond
* to the timestamp which is <= the requested one, if backward
* is 0, then it will be >=
@@ -2097,7 +2455,13 @@ void av_url_split(char *proto, int proto_size,
char *path, int path_size,
const char *url);
-
+/**
+ * log a nice Dump of input format context or output format context
+ * @param ic already initialized Format Context, must not be NULL.
+ * @param index index of the stream to dump information about
+ * @param url name of file or URL of stream to print information about
+ * @param is_output Select whether specified context is of input(0) or output(1)
+ */
void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
@@ -2149,6 +2513,7 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size);
* Return a positive value if the given filename has one of the given
* extensions, 0 otherwise.
*
+ * @param filename file name to check against the given extensions
* @param extensions a comma-separated list of filename extensions
*/
int av_match_ext(const char *filename, const char *extensions);
@@ -2156,6 +2521,8 @@ int av_match_ext(const char *filename, const char *extensions);
/**
* Test if the given container can store a codec.
*
+ * @param ofmt container to check for compatibility
+ * @param codec_id codec to potentially store in container
* @param std_compliance standards compliance level, one of FF_COMPLIANCE_*
*
* @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot.
@@ -2183,6 +2550,14 @@ const struct AVCodecTag *avformat_get_riff_video_tags(void);
* @return the table mapping RIFF FourCCs for audio to AVCodecID.
*/
const struct AVCodecTag *avformat_get_riff_audio_tags(void);
+/**
+ * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID.
+ */
+const struct AVCodecTag *avformat_get_mov_video_tags(void);
+/**
+ * @return the table mapping MOV FourCCs for audio to AVCodecID.
+ */
+const struct AVCodecTag *avformat_get_mov_audio_tags(void);
/**
* @}
diff --git a/chromium/third_party/ffmpeg/libavformat/avidec.c b/chromium/third_party/ffmpeg/libavformat/avidec.c
index 1c6b18c9805..0db9f32ef92 100644
--- a/chromium/third_party/ffmpeg/libavformat/avidec.c
+++ b/chromium/third_party/ffmpeg/libavformat/avidec.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <stdint.h>
+#include <inttypes.h>
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
@@ -34,6 +34,8 @@
#include "dv.h"
#include "internal.h"
#include "riff.h"
+#include "libavcodec/bytestream.h"
+#include "libavcodec/exif.h"
typedef struct AVIStream {
int64_t frame_offset; /* current frame (video) or byte (audio) counter
@@ -222,7 +224,7 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num)
if (last_pos == pos || pos == base - 8)
avi->non_interleaved = 1;
- if (last_pos != pos && (len || !ast->sample_size))
+ if (last_pos != pos && len)
av_add_index_entry(st, pos, ast->cum_len, len, 0,
key ? AVINDEX_KEYFRAME : 0);
@@ -350,6 +352,7 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end)
uint16_t size = avio_rl16(s->pb);
const char *name = NULL;
char buffer[64] = { 0 };
+ size = FFMIN(size, tag_end - avio_tell(s->pb));
size -= avio_read(s->pb, buffer,
FFMIN(size, sizeof(buffer) - 1));
switch (tag) {
@@ -378,6 +381,84 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end)
}
}
+static int avi_extract_stream_metadata(AVStream *st)
+{
+ GetByteContext gb;
+ uint8_t *data = st->codec->extradata;
+ int data_size = st->codec->extradata_size;
+ int tag, offset;
+
+ if (!data || data_size < 8) {
+ return AVERROR_INVALIDDATA;
+ }
+
+ bytestream2_init(&gb, data, data_size);
+
+ tag = bytestream2_get_le32(&gb);
+
+ switch (tag) {
+ case MKTAG('A', 'V', 'I', 'F'):
+ // skip 4 byte padding
+ bytestream2_skip(&gb, 4);
+ offset = bytestream2_tell(&gb);
+ bytestream2_init(&gb, data + offset, data_size - offset);
+
+ // decode EXIF tags from IFD, AVI is always little-endian
+ return avpriv_exif_decode_ifd(st->codec, &gb, 1, 0, &st->metadata);
+ break;
+ case MKTAG('C', 'A', 'S', 'I'):
+ avpriv_request_sample(st->codec, "RIFF stream data tag type CASI (%u)", tag);
+ break;
+ case MKTAG('Z', 'o', 'r', 'a'):
+ avpriv_request_sample(st->codec, "RIFF stream data tag type Zora (%u)", tag);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int calculate_bitrate(AVFormatContext *s)
+{
+ AVIContext *avi = s->priv_data;
+ int i, j;
+ int64_t lensum = 0;
+ int64_t maxpos = 0;
+
+ for (i = 0; i<s->nb_streams; i++) {
+ int64_t len = 0;
+ AVStream *st = s->streams[i];
+
+ if (!st->nb_index_entries)
+ continue;
+
+ for (j = 0; j < st->nb_index_entries; j++)
+ len += st->index_entries[j].size;
+ maxpos = FFMAX(maxpos, st->index_entries[j-1].pos);
+ lensum += len;
+ }
+ if (maxpos < avi->io_fsize*9/10) // index does not cover the whole file
+ return 0;
+ if (lensum*9/10 > maxpos || lensum < maxpos*9/10) // frame sum and filesize mismatch
+ return 0;
+
+ for (i = 0; i<s->nb_streams; i++) {
+ int64_t len = 0;
+ AVStream *st = s->streams[i];
+ int64_t duration;
+
+ for (j = 0; j < st->nb_index_entries; j++)
+ len += st->index_entries[j].size;
+
+ if (st->nb_index_entries < 2 || st->codec->bit_rate > 0)
+ continue;
+ duration = st->index_entries[j-1].timestamp - st->index_entries[0].timestamp;
+ st->codec->bit_rate = av_rescale(8*len, st->time_base.den, duration * st->time_base.num);
+ }
+ return 1;
+}
+
static int avi_read_header(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
@@ -556,7 +637,7 @@ static int avi_read_header(AVFormatContext *s)
ast->rate = avio_rl32(pb);
if (!(ast->scale && ast->rate)) {
av_log(s, AV_LOG_WARNING,
- "scale/rate is %u/%u which is invalid. "
+ "scale/rate is %"PRIu32"/%"PRIu32" which is invalid. "
"(This file has been generated by broken software.)\n",
ast->scale,
ast->rate);
@@ -590,6 +671,7 @@ static int avi_read_header(AVFormatContext *s)
codec_type = AVMEDIA_TYPE_VIDEO;
ast->sample_size = 0;
+ st->avg_frame_rate = av_inv_q(st->time_base);
break;
case MKTAG('a', 'u', 'd', 's'):
codec_type = AVMEDIA_TYPE_AUDIO;
@@ -654,11 +736,8 @@ static int avi_read_header(AVFormatContext *s)
st->codec->extradata_size = esize - 10 * 4;
} else
st->codec->extradata_size = size - 10 * 4;
- if (ff_alloc_extradata(st->codec, st->codec->extradata_size))
+ if (ff_get_extradata(st->codec, pb, st->codec->extradata_size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb,
- st->codec->extradata,
- st->codec->extradata_size);
}
// FIXME: check if the encoder really did this correctly
@@ -691,6 +770,8 @@ static int avi_read_header(AVFormatContext *s)
/* This is needed to get the pict type which is necessary
* for generating correct pts. */
st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ if (st->codec->codec_tag == MKTAG('V', 'S', 'S', 'H'))
+ st->need_parsing = AVSTREAM_PARSE_FULL;
if (st->codec->codec_tag == 0 && st->codec->height > 0 &&
st->codec->extradata_size < 1U << 30) {
@@ -783,13 +864,17 @@ static int avi_read_header(AVFormatContext *s)
st = s->streams[stream_index];
if (size<(1<<30)) {
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, st->codec->extradata_size);
}
if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
avio_r8(pb);
+
+ ret = avi_extract_stream_metadata(st);
+ if (ret < 0) {
+ av_log(s, AV_LOG_WARNING, "could not decoding EXIF data in stream header.\n");
+ }
}
break;
case MKTAG('i', 'n', 'd', 'x'):
@@ -864,8 +949,13 @@ fail:
if (!avi->index_loaded && pb->seekable)
avi_load_index(s);
+ calculate_bitrate(s);
avi->index_loaded |= 1;
- avi->non_interleaved |= guess_ni_flag(s) | (s->flags & AVFMT_FLAG_SORT_DTS);
+
+ if ((ret = guess_ni_flag(s)) < 0)
+ return ret;
+
+ avi->non_interleaved |= ret | (s->flags & AVFMT_FLAG_SORT_DTS);
dict_entry = av_dict_get(s->metadata, "ISFT", NULL, 0);
if (dict_entry && !strcmp(dict_entry->value, "PotEncoder"))
@@ -905,12 +995,14 @@ fail:
static int read_gab2_sub(AVStream *st, AVPacket *pkt)
{
if (pkt->size >= 7 &&
+ pkt->size < INT_MAX - AVPROBE_PADDING_SIZE &&
!strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data + 5) == 2) {
uint8_t desc[256];
int score = AVPROBE_SCORE_EXTENSION, ret;
AVIStream *ast = st->priv_data;
AVInputFormat *sub_demuxer;
AVRational time_base;
+ int size;
AVIOContext *pb = avio_alloc_context(pkt->data + 7,
pkt->size - 7,
0, NULL, NULL, NULL, NULL);
@@ -928,9 +1020,15 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt)
avio_rl16(pb); /* flags? */
avio_rl32(pb); /* data size */
- pd = (AVProbeData) { .buf = pb->buf_ptr,
- .buf_size = pb->buf_end - pb->buf_ptr };
- if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score)))
+ size = pb->buf_end - pb->buf_ptr;
+ pd = (AVProbeData) { .buf = av_mallocz(size + AVPROBE_PADDING_SIZE),
+ .buf_size = size };
+ if (!pd.buf)
+ goto error;
+ memcpy(pd.buf, pb->buf_ptr, size);
+ sub_demuxer = av_probe_input_format2(&pd, 1, &score);
+ av_freep(&pd.buf);
+ if (!sub_demuxer)
goto error;
if (!(ast->sub_ctx = avformat_alloc_context()))
@@ -1063,7 +1161,7 @@ start_sync:
ast = st->priv_data;
if (!ast) {
- av_log(s, AV_LOG_WARNING, "Skiping foreign stream %d packet\n", n);
+ av_log(s, AV_LOG_WARNING, "Skipping foreign stream %d packet\n", n);
continue;
}
@@ -1129,7 +1227,7 @@ start_sync:
ast->packet_size = size + 8;
ast->remaining = size;
- if (size || !ast->sample_size) {
+ if (size) {
uint64_t pos = avio_tell(pb) - 8;
if (!st->index_entries || !st->nb_index_entries ||
st->index_entries[st->nb_index_entries - 1].pos < pos) {
@@ -1316,7 +1414,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
AVIndexEntry *e;
int index;
- index = av_index_search_timestamp(st, ast->frame_offset, 0);
+ index = av_index_search_timestamp(st, ast->frame_offset, AVSEEK_FLAG_ANY);
e = &st->index_entries[index];
if (index >= 0 && e->timestamp == ast->frame_offset) {
@@ -1456,14 +1554,69 @@ static int avi_read_idx1(AVFormatContext *s, int size)
return 0;
}
+/* Scan the index and consider any file with streams more than
+ * 2 seconds or 64MB apart non-interleaved. */
+static int check_stream_max_drift(AVFormatContext *s)
+{
+ int64_t min_pos, pos;
+ int i;
+ int *idx = av_mallocz_array(s->nb_streams, sizeof(*idx));
+ if (!idx)
+ return AVERROR(ENOMEM);
+ for (min_pos = pos = 0; min_pos != INT64_MAX; pos = min_pos + 1LU) {
+ int64_t max_dts = INT64_MIN / 2;
+ int64_t min_dts = INT64_MAX / 2;
+ int64_t max_buffer = 0;
+
+ min_pos = INT64_MAX;
+
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+ int n = st->nb_index_entries;
+ while (idx[i] < n && st->index_entries[idx[i]].pos < pos)
+ idx[i]++;
+ if (idx[i] < n) {
+ int64_t dts;
+ dts = av_rescale_q(st->index_entries[idx[i]].timestamp /
+ FFMAX(ast->sample_size, 1),
+ st->time_base, AV_TIME_BASE_Q);
+ min_dts = FFMIN(min_dts, dts);
+ min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos);
+ }
+ }
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+
+ if (idx[i] && min_dts != INT64_MAX / 2) {
+ int64_t dts;
+ dts = av_rescale_q(st->index_entries[idx[i] - 1].timestamp /
+ FFMAX(ast->sample_size, 1),
+ st->time_base, AV_TIME_BASE_Q);
+ max_dts = FFMAX(max_dts, dts);
+ max_buffer = FFMAX(max_buffer,
+ av_rescale(dts - min_dts,
+ st->codec->bit_rate,
+ AV_TIME_BASE));
+ }
+ }
+ if (max_dts - min_dts > 2 * AV_TIME_BASE ||
+ max_buffer > 1024 * 1024 * 8 * 8) {
+ av_free(idx);
+ return 1;
+ }
+ }
+ av_free(idx);
+ return 0;
+}
+
static int guess_ni_flag(AVFormatContext *s)
{
int i;
int64_t last_start = 0;
int64_t first_end = INT64_MAX;
int64_t oldpos = avio_tell(s->pb);
- int *idx;
- int64_t min_pos, pos;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
@@ -1487,35 +1640,11 @@ static int guess_ni_flag(AVFormatContext *s)
first_end = st->index_entries[n - 1].pos;
}
avio_seek(s->pb, oldpos, SEEK_SET);
+
if (last_start > first_end)
return 1;
- idx= av_calloc(s->nb_streams, sizeof(*idx));
- if (!idx)
- return 0;
- for (min_pos=pos=0; min_pos!=INT64_MAX; pos= min_pos+1LU) {
- int64_t max_dts = INT64_MIN/2, min_dts= INT64_MAX/2;
- min_pos = INT64_MAX;
- for (i=0; i<s->nb_streams; i++) {
- AVStream *st = s->streams[i];
- AVIStream *ast = st->priv_data;
- int n= st->nb_index_entries;
- while (idx[i]<n && st->index_entries[idx[i]].pos < pos)
- idx[i]++;
- if (idx[i] < n) {
- min_dts = FFMIN(min_dts, av_rescale_q(st->index_entries[idx[i]].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q));
- min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos);
- }
- if (idx[i])
- max_dts = FFMAX(max_dts, av_rescale_q(st->index_entries[idx[i]-1].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q));
- }
- if (max_dts - min_dts > 2*AV_TIME_BASE) {
- av_free(idx);
- return 1;
- }
- }
- av_free(idx);
- return 0;
+ return check_stream_max_drift(s);
}
static int avi_load_index(AVFormatContext *s)
@@ -1734,6 +1863,7 @@ AVInputFormat ff_avi_demuxer = {
.name = "avi",
.long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
.priv_data_size = sizeof(AVIContext),
+ .extensions = "avi",
.read_probe = avi_probe,
.read_header = avi_read_header,
.read_packet = avi_read_packet,
diff --git a/chromium/third_party/ffmpeg/libavformat/avienc.c b/chromium/third_party/ffmpeg/libavformat/avienc.c
index 45f7a203da8..89e2a539a05 100644
--- a/chromium/third_party/ffmpeg/libavformat/avienc.c
+++ b/chromium/third_party/ffmpeg/libavformat/avienc.c
@@ -32,6 +32,8 @@
#include "libavutil/dict.h"
#include "libavutil/avassert.h"
#include "libavutil/timestamp.h"
+#include "libavutil/pixdesc.h"
+#include "libavcodec/raw.h"
/*
* TODO:
@@ -64,9 +66,9 @@ typedef struct {
int entry;
AVIIndex indexes;
-} AVIStream ;
+} AVIStream;
-static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id)
+static inline AVIIentry *avi_get_ientry(AVIIndex *idx, int ent_id)
{
int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
int id = ent_id % AVI_INDEX_CLUSTER_SIZE;
@@ -74,15 +76,15 @@ static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id)
}
static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
- const char* riff_tag, const char* list_tag)
+ const char *riff_tag, const char *list_tag)
{
- AVIContext *avi= s->priv_data;
+ AVIContext *avi = s->priv_data;
int64_t loff;
int i;
avi->riff_id++;
- for (i=0; i<s->nb_streams; i++){
- AVIStream *avist= s->streams[i]->priv_data;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
avist->indexes.entry = 0;
}
@@ -93,10 +95,10 @@ static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
return loff;
}
-static char* avi_stream2fourcc(char* tag, int index, enum AVMediaType type)
+static char *avi_stream2fourcc(char *tag, int index, enum AVMediaType type)
{
- tag[0] = '0' + index/10;
- tag[1] = '0' + index%10;
+ tag[0] = '0' + index / 10;
+ tag[1] = '0' + index % 10;
if (type == AVMEDIA_TYPE_VIDEO) {
tag[2] = 'd';
tag[3] = 'c';
@@ -112,31 +114,30 @@ static char* avi_stream2fourcc(char* tag, int index, enum AVMediaType type)
return tag;
}
-static int avi_write_counters(AVFormatContext* s, int riff_id)
+static int avi_write_counters(AVFormatContext *s, int riff_id)
{
AVIOContext *pb = s->pb;
AVIContext *avi = s->priv_data;
int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
int64_t file_size;
- AVCodecContext* stream;
+ AVCodecContext *stream;
file_size = avio_tell(pb);
- for(n = 0; n < s->nb_streams; n++) {
- AVIStream *avist= s->streams[n]->priv_data;
+ for (n = 0; n < s->nb_streams; n++) {
+ AVIStream *avist = s->streams[n]->priv_data;
av_assert0(avist->frames_hdr_strm);
stream = s->streams[n]->codec;
avio_seek(pb, avist->frames_hdr_strm, SEEK_SET);
ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
- if(au_ssize == 0) {
+ if (au_ssize == 0)
avio_wl32(pb, avist->packet_count);
- } else {
+ else
avio_wl32(pb, avist->audio_strm_length / au_ssize);
- }
- if(stream->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
nb_frames = FFMAX(nb_frames, avist->packet_count);
}
- if(riff_id == 1) {
+ if (riff_id == 1) {
av_assert0(avi->frames_hdr_all);
avio_seek(pb, avi->frames_hdr_all, SEEK_SET);
avio_wl32(pb, nb_frames);
@@ -154,6 +155,7 @@ static int avi_write_header(AVFormatContext *s)
AVCodecContext *stream, *video_enc;
int64_t list1, list2, strh, strf;
AVDictionaryEntry *t = NULL;
+ int padding;
if (s->nb_streams > AVI_MAX_STREAM_COUNT) {
av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n",
@@ -161,9 +163,9 @@ static int avi_write_header(AVFormatContext *s)
return AVERROR(EINVAL);
}
- for(n=0;n<s->nb_streams;n++) {
- s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream));
- if(!s->streams[n]->priv_data)
+ for (n = 0; n < s->nb_streams; n++) {
+ s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream));
+ if (!s->streams[n]->priv_data)
return AVERROR(ENOMEM);
}
@@ -177,8 +179,8 @@ static int avi_write_header(AVFormatContext *s)
bitrate = 0;
video_enc = NULL;
- for(n=0;n<s->nb_streams;n++) {
- stream = s->streams[n]->codec;
+ for (n = 0; n < s->nb_streams; n++) {
+ stream = s->streams[n]->codec;
bitrate += stream->bit_rate;
if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
video_enc = stream;
@@ -186,23 +188,23 @@ static int avi_write_header(AVFormatContext *s)
nb_frames = 0;
- if(video_enc){
- avio_wl32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den));
- } else {
+ if (video_enc)
+ avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_enc->time_base.num /
+ video_enc->time_base.den));
+ else
avio_wl32(pb, 0);
- }
avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */
avio_wl32(pb, 0); /* padding */
if (!pb->seekable)
- avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
+ avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
else
- avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
+ avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */
avio_wl32(pb, nb_frames); /* nb frames, filled later */
avio_wl32(pb, 0); /* initial frame */
avio_wl32(pb, s->nb_streams); /* nb streams */
avio_wl32(pb, 1024 * 1024); /* suggested buffer size */
- if(video_enc){
+ if (video_enc) {
avio_wl32(pb, video_enc->width);
avio_wl32(pb, video_enc->height);
} else {
@@ -215,8 +217,8 @@ static int avi_write_header(AVFormatContext *s)
avio_wl32(pb, 0); /* reserved */
/* stream list */
- for(i=0;i<n;i++) {
- AVIStream *avist= s->streams[i]->priv_data;
+ for (i = 0; i < n; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
list2 = ff_start_tag(pb, "LIST");
ffio_wfourcc(pb, "strl");
@@ -224,21 +226,30 @@ static int avi_write_header(AVFormatContext *s)
/* stream generic header */
strh = ff_start_tag(pb, "strh");
- switch(stream->codec_type) {
+ switch (stream->codec_type) {
case AVMEDIA_TYPE_SUBTITLE:
// XSUB subtitles behave like video tracks, other subtitles
// are not (yet) supported.
if (stream->codec_id != AV_CODEC_ID_XSUB) {
- av_log(s, AV_LOG_ERROR, "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n");
+ av_log(s, AV_LOG_ERROR,
+ "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n");
return AVERROR_PATCHWELCOME;
}
- case AVMEDIA_TYPE_VIDEO: ffio_wfourcc(pb, "vids"); break;
- case AVMEDIA_TYPE_AUDIO: ffio_wfourcc(pb, "auds"); break;
-// case AVMEDIA_TYPE_TEXT : ffio_wfourcc(pb, "txts"); break;
- case AVMEDIA_TYPE_DATA : ffio_wfourcc(pb, "dats"); break;
+ case AVMEDIA_TYPE_VIDEO:
+ ffio_wfourcc(pb, "vids");
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ ffio_wfourcc(pb, "auds");
+ break;
+// case AVMEDIA_TYPE_TEXT:
+// ffio_wfourcc(pb, "txts");
+// break;
+ case AVMEDIA_TYPE_DATA:
+ ffio_wfourcc(pb, "dats");
+ break;
}
- if(stream->codec_type == AVMEDIA_TYPE_VIDEO ||
- stream->codec_id == AV_CODEC_ID_XSUB)
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO ||
+ stream->codec_id == AV_CODEC_ID_XSUB)
avio_wl32(pb, stream->codec_tag);
else
avio_wl32(pb, 1);
@@ -256,23 +267,25 @@ static int avi_write_header(AVFormatContext *s)
au_scale = 1;
}
avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
- if(stream->codec_id == AV_CODEC_ID_XSUB)
+ if (stream->codec_id == AV_CODEC_ID_XSUB)
au_scale = au_byterate = 0;
avio_wl32(pb, au_scale); /* scale */
avio_wl32(pb, au_byterate); /* rate */
avio_wl32(pb, 0); /* start */
- avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */
+ /* remember this offset to fill later */
+ avist->frames_hdr_strm = avio_tell(pb);
if (!pb->seekable)
- avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
+ /* FIXME: this may be broken, but who cares */
+ avio_wl32(pb, AVI_MAX_RIFF_SIZE);
else
- avio_wl32(pb, 0); /* length, XXX: filled later */
+ avio_wl32(pb, 0); /* length, XXX: filled later */
/* suggested buffer size */ //FIXME set at the end to largest chunk
- if(stream->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
avio_wl32(pb, 1024 * 1024);
- else if(stream->codec_type == AVMEDIA_TYPE_AUDIO)
+ else if (stream->codec_type == AVMEDIA_TYPE_AUDIO)
avio_wl32(pb, 12 * 1024);
else
avio_wl32(pb, 0);
@@ -283,45 +296,60 @@ static int avi_write_header(AVFormatContext *s)
avio_wl16(pb, stream->height);
ff_end_tag(pb, strh);
- if(stream->codec_type != AVMEDIA_TYPE_DATA){
- int ret;
-
- strf = ff_start_tag(pb, "strf");
- switch(stream->codec_type) {
- case AVMEDIA_TYPE_SUBTITLE:
- // XSUB subtitles behave like video tracks, other subtitles
- // are not (yet) supported.
- if (stream->codec_id != AV_CODEC_ID_XSUB) break;
- case AVMEDIA_TYPE_VIDEO:
- ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0);
- break;
- case AVMEDIA_TYPE_AUDIO:
- if ((ret = ff_put_wav_header(pb, stream)) < 0) {
- return ret;
+ if (stream->codec_type != AVMEDIA_TYPE_DATA) {
+ int ret;
+ enum AVPixelFormat pix_fmt;
+
+ strf = ff_start_tag(pb, "strf");
+ switch (stream->codec_type) {
+ case AVMEDIA_TYPE_SUBTITLE:
+ /* XSUB subtitles behave like video tracks, other subtitles
+ * are not (yet) supported. */
+ if (stream->codec_id != AV_CODEC_ID_XSUB)
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ /* WMP expects RGB 5:5:5 rawvideo in avi to have bpp set to 16. */
+ if ( !stream->codec_tag
+ && stream->codec_id == AV_CODEC_ID_RAWVIDEO
+ && stream->pix_fmt == AV_PIX_FMT_RGB555LE
+ && stream->bits_per_coded_sample == 15)
+ stream->bits_per_coded_sample = 16;
+ ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0);
+ pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi,
+ stream->bits_per_coded_sample);
+ if ( !stream->codec_tag
+ && stream->codec_id == AV_CODEC_ID_RAWVIDEO
+ && stream->pix_fmt != pix_fmt
+ && stream->pix_fmt != AV_PIX_FMT_NONE)
+ av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n",
+ av_get_pix_fmt_name(stream->pix_fmt));
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ if ((ret = ff_put_wav_header(pb, stream, 0)) < 0)
+ return ret;
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR,
+ "Invalid or not supported codec type '%s' found in the input\n",
+ (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?"));
+ return AVERROR(EINVAL);
}
- break;
- default:
- av_log(s, AV_LOG_ERROR,
- "Invalid or not supported codec type '%s' found in the input\n",
- (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?"));
- return AVERROR(EINVAL);
- }
- ff_end_tag(pb, strf);
- if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) {
- ff_riff_write_info_tag(s->pb, "strn", t->value);
- t = NULL;
- }
- if(stream->codec_id == AV_CODEC_ID_XSUB
- && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
- const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
- t = NULL;
- if (langstr) {
- char* str = av_asprintf("Subtitle - %s-xx;02", langstr);
- ff_riff_write_info_tag(s->pb, "strn", str);
- av_free(str);
+ ff_end_tag(pb, strf);
+ if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) {
+ ff_riff_write_info_tag(s->pb, "strn", t->value);
+ t = NULL;
+ }
+ if (stream->codec_id == AV_CODEC_ID_XSUB
+ && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
+ const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
+ t = NULL;
+ if (langstr) {
+ char* str = av_asprintf("Subtitle - %s-xx;02", langstr);
+ ff_riff_write_info_tag(s->pb, "strn", str);
+ av_free(str);
+ }
}
}
- }
if (pb->seekable) {
unsigned char tag[5];
@@ -330,47 +358,47 @@ static int avi_write_header(AVFormatContext *s)
/* Starting to lay out AVI OpenDML master index.
* We want to make it JUNK entry for now, since we'd
* like to get away without making AVI an OpenDML one
- * for compatibility reasons.
- */
- avist->indexes.entry = avist->indexes.ents_allocated = 0;
+ * for compatibility reasons. */
+ avist->indexes.entry = avist->indexes.ents_allocated = 0;
avist->indexes.indx_start = ff_start_tag(pb, "JUNK");
- avio_wl16(pb, 4); /* wLongsPerEntry */
- avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
- avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
- avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */
+ avio_wl16(pb, 4); /* wLongsPerEntry */
+ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
+ avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
+ avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */
ffio_wfourcc(pb, avi_stream2fourcc(tag, i, stream->codec_type));
- /* dwChunkId */
- avio_wl64(pb, 0); /* dwReserved[3]
- avio_wl32(pb, 0); Must be 0. */
- for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
- avio_wl64(pb, 0);
+ /* dwChunkId */
+ avio_wl64(pb, 0); /* dwReserved[3] */
+ // avio_wl32(pb, 0); /* Must be 0. */
+ for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
+ avio_wl64(pb, 0);
ff_end_tag(pb, avist->indexes.indx_start);
}
- if( stream->codec_type == AVMEDIA_TYPE_VIDEO
- && s->streams[i]->sample_aspect_ratio.num>0
- && s->streams[i]->sample_aspect_ratio.den>0){
- int vprp= ff_start_tag(pb, "vprp");
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO &&
+ s->streams[i]->sample_aspect_ratio.num > 0 &&
+ s->streams[i]->sample_aspect_ratio.den > 0) {
+ int vprp = ff_start_tag(pb, "vprp");
AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio,
- (AVRational){stream->width, stream->height});
+ (AVRational) { stream->width,
+ stream->height });
int num, den;
av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
- avio_wl32(pb, 0); //video format = unknown
- avio_wl32(pb, 0); //video standard= unknown
- avio_wl32(pb, lrintf(1.0/av_q2d(stream->time_base)));
- avio_wl32(pb, stream->width );
+ avio_wl32(pb, 0); // video format = unknown
+ avio_wl32(pb, 0); // video standard = unknown
+ avio_wl32(pb, lrintf(1.0 / av_q2d(stream->time_base)));
+ avio_wl32(pb, stream->width);
avio_wl32(pb, stream->height);
avio_wl16(pb, den);
avio_wl16(pb, num);
- avio_wl32(pb, stream->width );
+ avio_wl32(pb, stream->width);
avio_wl32(pb, stream->height);
- avio_wl32(pb, 1); //progressive FIXME
+ avio_wl32(pb, 1); // progressive FIXME
avio_wl32(pb, stream->height);
- avio_wl32(pb, stream->width );
+ avio_wl32(pb, stream->width);
avio_wl32(pb, stream->height);
- avio_wl32(pb, stream->width );
+ avio_wl32(pb, stream->width);
avio_wl32(pb, 0);
avio_wl32(pb, 0);
@@ -388,8 +416,8 @@ static int avi_write_header(AVFormatContext *s)
ffio_wfourcc(pb, "odml");
ffio_wfourcc(pb, "dmlh");
avio_wl32(pb, 248);
- for (i = 0; i < 248; i+= 4)
- avio_wl32(pb, 0);
+ for (i = 0; i < 248; i += 4)
+ avio_wl32(pb, 0);
ff_end_tag(pb, avi->odml_list);
}
@@ -397,11 +425,18 @@ static int avi_write_header(AVFormatContext *s)
ff_riff_write_info(s);
+
+ padding = s->metadata_header_padding;
+ if (padding < 0)
+ padding = 1016;
+
/* some padding for easier tag editing */
- list2 = ff_start_tag(pb, "JUNK");
- for (i = 0; i < 1016; i += 4)
- avio_wl32(pb, 0);
- ff_end_tag(pb, list2);
+ if (padding) {
+ list2 = ff_start_tag(pb, "JUNK");
+ for (i = padding; i > 0; i -= 4)
+ avio_wl32(pb, 0);
+ ff_end_tag(pb, list2);
+ }
avi->movi_list = ff_start_tag(pb, "LIST");
ffio_wfourcc(pb, "movi");
@@ -427,47 +462,47 @@ static int avi_write_ix(AVFormatContext *s)
return AVERROR(EINVAL);
}
- for (i=0;i<s->nb_streams;i++) {
- AVIStream *avist= s->streams[i]->priv_data;
- int64_t ix, pos;
-
- avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
- ix_tag[3] = '0' + i;
-
- /* Writing AVI OpenDML leaf index chunk */
- ix = avio_tell(pb);
- ffio_wfourcc(pb, ix_tag); /* ix?? */
- avio_wl32(pb, avist->indexes.entry * 8 + 24);
- /* chunk size */
- avio_wl16(pb, 2); /* wLongsPerEntry */
- avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
- avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
- avio_wl32(pb, avist->indexes.entry);
- /* nEntriesInUse */
- ffio_wfourcc(pb, tag); /* dwChunkId */
- avio_wl64(pb, avi->movi_list);/* qwBaseOffset */
- avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */
-
- for (j=0; j<avist->indexes.entry; j++) {
- AVIIentry* ie = avi_get_ientry(&avist->indexes, j);
- avio_wl32(pb, ie->pos + 8);
- avio_wl32(pb, ((uint32_t)ie->len & ~0x80000000) |
+ for (i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
+ int64_t ix, pos;
+
+ avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
+ ix_tag[3] = '0' + i;
+
+ /* Writing AVI OpenDML leaf index chunk */
+ ix = avio_tell(pb);
+ ffio_wfourcc(pb, ix_tag); /* ix?? */
+ avio_wl32(pb, avist->indexes.entry * 8 + 24);
+ /* chunk size */
+ avio_wl16(pb, 2); /* wLongsPerEntry */
+ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
+ avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
+ avio_wl32(pb, avist->indexes.entry);
+ /* nEntriesInUse */
+ ffio_wfourcc(pb, tag); /* dwChunkId */
+ avio_wl64(pb, avi->movi_list); /* qwBaseOffset */
+ avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */
+
+ for (j = 0; j < avist->indexes.entry; j++) {
+ AVIIentry *ie = avi_get_ientry(&avist->indexes, j);
+ avio_wl32(pb, ie->pos + 8);
+ avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) |
(ie->flags & 0x10 ? 0 : 0x80000000));
- }
- avio_flush(pb);
- pos = avio_tell(pb);
-
- /* Updating one entry in the AVI OpenDML master index */
- avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
- ffio_wfourcc(pb, "indx"); /* enabling this entry */
- avio_skip(pb, 8);
- avio_wl32(pb, avi->riff_id); /* nEntriesInUse */
- avio_skip(pb, 16*avi->riff_id);
- avio_wl64(pb, ix); /* qwOffset */
- avio_wl32(pb, pos - ix); /* dwSize */
- avio_wl32(pb, avist->indexes.entry); /* dwDuration */
-
- avio_seek(pb, pos, SEEK_SET);
+ }
+ avio_flush(pb);
+ pos = avio_tell(pb);
+
+ /* Updating one entry in the AVI OpenDML master index */
+ avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
+ ffio_wfourcc(pb, "indx"); /* enabling this entry */
+ avio_skip(pb, 8);
+ avio_wl32(pb, avi->riff_id); /* nEntriesInUse */
+ avio_skip(pb, 16 * avi->riff_id);
+ avio_wl64(pb, ix); /* qwOffset */
+ avio_wl32(pb, pos - ix); /* dwSize */
+ avio_wl32(pb, avist->indexes.entry); /* dwDuration */
+
+ avio_seek(pb, pos, SEEK_SET);
}
return 0;
}
@@ -482,31 +517,31 @@ static int avi_write_idx1(AVFormatContext *s)
if (pb->seekable) {
AVIStream *avist;
- AVIIentry* ie = 0, *tie;
+ AVIIentry *ie = 0, *tie;
int empty, stream_id = -1;
idx_chunk = ff_start_tag(pb, "idx1");
- for(i=0; i<s->nb_streams; i++){
- avist= s->streams[i]->priv_data;
- avist->entry=0;
+ for (i = 0; i < s->nb_streams; i++) {
+ avist = s->streams[i]->priv_data;
+ avist->entry = 0;
}
do {
empty = 1;
- for (i=0; i<s->nb_streams; i++) {
- avist= s->streams[i]->priv_data;
- if (avist->indexes.entry <= avist->entry)
- continue;
-
- tie = avi_get_ientry(&avist->indexes, avist->entry);
- if (empty || tie->pos < ie->pos) {
- ie = tie;
- stream_id = i;
- }
- empty = 0;
+ for (i = 0; i < s->nb_streams; i++) {
+ avist = s->streams[i]->priv_data;
+ if (avist->indexes.entry <= avist->entry)
+ continue;
+
+ tie = avi_get_ientry(&avist->indexes, avist->entry);
+ if (empty || tie->pos < ie->pos) {
+ ie = tie;
+ stream_id = i;
+ }
+ empty = 0;
}
if (!empty) {
- avist= s->streams[stream_id]->priv_data;
+ avist = s->streams[stream_id]->priv_data;
avi_stream2fourcc(tag, stream_id,
s->streams[stream_id]->codec->codec_type);
ffio_wfourcc(pb, tag);
@@ -525,28 +560,29 @@ static int avi_write_idx1(AVFormatContext *s)
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- AVIContext *avi = s->priv_data;
- AVIOContext *pb = s->pb;
unsigned char tag[5];
- unsigned int flags=0;
- const int stream_index= pkt->stream_index;
- AVIStream *avist= s->streams[stream_index]->priv_data;
- AVCodecContext *enc= s->streams[stream_index]->codec;
- int size= pkt->size;
+ unsigned int flags = 0;
+ const int stream_index = pkt->stream_index;
+ int size = pkt->size;
+ AVIContext *avi = s->priv_data;
+ AVIOContext *pb = s->pb;
+ AVIStream *avist = s->streams[stream_index]->priv_data;
+ AVCodecContext *enc = s->streams[stream_index]->codec;
av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index);
- while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count){
+ while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE &&
+ pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
AVPacket empty_packet;
- if(pkt->dts - avist->packet_count > 60000){
+ if (pkt->dts - avist->packet_count > 60000) {
av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count);
return AVERROR(EINVAL);
}
av_init_packet(&empty_packet);
- empty_packet.size= 0;
- empty_packet.data= NULL;
- empty_packet.stream_index= stream_index;
+ empty_packet.size = 0;
+ empty_packet.data = NULL;
+ empty_packet.stream_index = stream_index;
avi_write_packet(s, &empty_packet);
av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count);
}
@@ -555,7 +591,6 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
// Make sure to put an OpenDML chunk when the file size exceeds the limits
if (pb->seekable &&
(avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
-
avi_write_ix(s);
ff_end_tag(pb, avi->movi_list);
@@ -567,32 +602,32 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
}
avi_stream2fourcc(tag, stream_index, enc->codec_type);
- if(pkt->flags&AV_PKT_FLAG_KEY)
+ if (pkt->flags & AV_PKT_FLAG_KEY)
flags = 0x10;
- if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
- avist->audio_strm_length += size;
- }
+ if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
+ avist->audio_strm_length += size;
if (s->pb->seekable) {
- AVIIndex* idx = &avist->indexes;
+ AVIIndex *idx = &avist->indexes;
int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
if (idx->ents_allocated <= idx->entry) {
idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
if (!idx->cluster) {
idx->ents_allocated = 0;
- idx->entry = 0;
+ idx->entry = 0;
return AVERROR(ENOMEM);
}
- idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry));
+ idx->cluster[cl] =
+ av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
if (!idx->cluster[cl])
return AVERROR(ENOMEM);
idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
}
idx->cluster[cl][id].flags = flags;
- idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list;
- idx->cluster[cl][id].len = size;
+ idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list;
+ idx->cluster[cl][id].len = size;
idx->entry++;
}
@@ -613,7 +648,7 @@ static int avi_write_trailer(AVFormatContext *s)
int i, j, n, nb_frames;
int64_t file_size;
- if (pb->seekable){
+ if (pb->seekable) {
if (avi->riff_id == 1) {
ff_end_tag(pb, avi->movi_list);
res = avi_write_idx1(s);
@@ -628,17 +663,17 @@ static int avi_write_trailer(AVFormatContext *s)
ffio_wfourcc(pb, "LIST"); /* Making this AVI OpenDML one */
avio_skip(pb, 16);
- for (n=nb_frames=0;n<s->nb_streams;n++) {
+ for (n = nb_frames = 0; n < s->nb_streams; n++) {
AVCodecContext *stream = s->streams[n]->codec;
- AVIStream *avist= s->streams[n]->priv_data;
+ AVIStream *avist = s->streams[n]->priv_data;
if (stream->codec_type == AVMEDIA_TYPE_VIDEO) {
if (nb_frames < avist->packet_count)
nb_frames = avist->packet_count;
} else {
- if (stream->codec_id == AV_CODEC_ID_MP2 || stream->codec_id == AV_CODEC_ID_MP3) {
+ if (stream->codec_id == AV_CODEC_ID_MP2 ||
+ stream->codec_id == AV_CODEC_ID_MP3)
nb_frames += avist->packet_count;
- }
}
}
avio_wl32(pb, nb_frames);
@@ -648,29 +683,29 @@ static int avi_write_trailer(AVFormatContext *s)
}
}
- for (i=0; i<s->nb_streams; i++) {
- AVIStream *avist= s->streams[i]->priv_data;
- for (j=0; j<avist->indexes.ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
- av_freep(&avist->indexes.cluster[j]);
- av_freep(&avist->indexes.cluster);
- avist->indexes.ents_allocated = avist->indexes.entry = 0;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
+ for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++)
+ av_freep(&avist->indexes.cluster[j]);
+ av_freep(&avist->indexes.cluster);
+ avist->indexes.ents_allocated = avist->indexes.entry = 0;
}
return res;
}
AVOutputFormat ff_avi_muxer = {
- .name = "avi",
- .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
- .mime_type = "video/x-msvideo",
- .extensions = "avi",
- .priv_data_size = sizeof(AVIContext),
- .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3,
- .video_codec = AV_CODEC_ID_MPEG4,
- .write_header = avi_write_header,
- .write_packet = avi_write_packet,
- .write_trailer = avi_write_trailer,
- .codec_tag = (const AVCodecTag* const []){
+ .name = "avi",
+ .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
+ .mime_type = "video/x-msvideo",
+ .extensions = "avi",
+ .priv_data_size = sizeof(AVIContext),
+ .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3,
+ .video_codec = AV_CODEC_ID_MPEG4,
+ .write_header = avi_write_header,
+ .write_packet = avi_write_packet,
+ .write_trailer = avi_write_trailer,
+ .codec_tag = (const AVCodecTag * const []) {
ff_codec_bmp_tags, ff_codec_wav_tags, 0
},
};
diff --git a/chromium/third_party/ffmpeg/libavformat/avio.c b/chromium/third_party/ffmpeg/libavformat/avio.c
index 225d9821a0a..4edaaa62150 100644
--- a/chromium/third_party/ffmpeg/libavformat/avio.c
+++ b/chromium/third_party/ffmpeg/libavformat/avio.c
@@ -215,18 +215,12 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"0123456789+-."
-int ffurl_alloc(URLContext **puc, const char *filename, int flags,
- const AVIOInterruptCB *int_cb)
+static struct URLProtocol *url_find_protocol(const char *filename)
{
URLProtocol *up = NULL;
char proto_str[128], proto_nested[128], *ptr;
size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
- if (!first_protocol) {
- av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
- "Missing call to av_register_all()?\n");
- }
-
if (filename[proto_len] != ':' &&
(filename[proto_len] != ',' || !strchr(filename + proto_len + 1, ':')) ||
is_dos_path(filename))
@@ -243,13 +237,31 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
while (up = ffurl_protocol_next(up)) {
if (!strcmp(proto_str, up->name))
- return url_alloc_for_protocol(puc, up, filename, flags, int_cb);
+ break;
if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
!strcmp(proto_nested, up->name))
- return url_alloc_for_protocol(puc, up, filename, flags, int_cb);
+ break;
+ }
+
+ return up;
+}
+
+int ffurl_alloc(URLContext **puc, const char *filename, int flags,
+ const AVIOInterruptCB *int_cb)
+{
+ URLProtocol *p = NULL;
+
+ if (!first_protocol) {
+ av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
+ "Missing call to av_register_all()?\n");
}
+
+ p = url_find_protocol(filename);
+ if (p)
+ return url_alloc_for_protocol(puc, p, filename, flags, int_cb);
+
*puc = NULL;
- if (!strcmp("https", proto_str))
+ if (av_strstart("https:", filename, NULL))
av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile with openssl or gnutls enabled.\n");
return AVERROR_PROTOCOL_NOT_FOUND;
}
@@ -258,11 +270,13 @@ int ffurl_open(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options)
{
int ret = ffurl_alloc(puc, filename, flags, int_cb);
- if (ret)
+ if (ret < 0)
return ret;
if (options && (*puc)->prot->priv_data_class &&
(ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
goto fail;
+ if ((ret = av_opt_set_dict(*puc, options)) < 0)
+ goto fail;
ret = ffurl_connect(*puc, options);
if (!ret)
return 0;
@@ -376,11 +390,18 @@ int ffurl_close(URLContext *h)
}
+const char *avio_find_protocol_name(const char *url)
+{
+ URLProtocol *p = url_find_protocol(url);
+
+ return p ? p->name : NULL;
+}
+
int avio_check(const char *url, int flags)
{
URLContext *h;
int ret = ffurl_alloc(&h, url, flags, NULL);
- if (ret)
+ if (ret < 0)
return ret;
if (h->prot->url_check) {
diff --git a/chromium/third_party/ffmpeg/libavformat/avio.h b/chromium/third_party/ffmpeg/libavformat/avio.h
index 4f4ac3cbaf9..4004b6fda91 100644
--- a/chromium/third_party/ffmpeg/libavformat/avio.h
+++ b/chromium/third_party/ffmpeg/libavformat/avio.h
@@ -146,11 +146,27 @@ typedef struct AVIOContext {
* This field is internal to libavformat and access from outside is not allowed.
*/
int writeout_count;
+
+ /**
+ * Original buffer size
+ * used internally after probing and ensure seekback to reset the buffer size
+ * This field is internal to libavformat and access from outside is not allowed.
+ */
+ int orig_buffer_size;
} AVIOContext;
/* unbuffered I/O */
/**
+ * Return the name of the protocol that will handle the passed URL.
+ *
+ * NULL is returned if no protocol could be found for the given URL.
+ *
+ * @return Name of the protocol or NULL.
+ */
+const char *avio_find_protocol_name(const char *url);
+
+/**
* Return AVIO_FLAG_* access flags corresponding to the access permissions
* of the resource in url, or a negative value corresponding to an
* AVERROR code in case of failure. The returned access flags are
@@ -366,6 +382,7 @@ int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
+ * @param url resource to access
* @param flags flags which control how the resource indicated by url
* is to be opened
* @return >= 0 in case of success, a negative value corresponding to an
@@ -381,6 +398,7 @@ int avio_open(AVIOContext **s, const char *url, int flags);
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
+ * @param url resource to access
* @param flags flags which control how the resource indicated by url
* is to be opened
* @param int_cb an interrupt callback to be used at the protocols level
@@ -454,6 +472,8 @@ const char *avio_enum_protocols(void **opaque, int output);
/**
* Pause and resume playing - only meaningful if using a network streaming
* protocol (e.g. MMS).
+ *
+ * @param h IO context from which to call the read_pause function pointer
* @param pause 1 for pause, 0 for resume
*/
int avio_pause(AVIOContext *h, int pause);
@@ -461,6 +481,8 @@ int avio_pause(AVIOContext *h, int pause);
/**
* Seek to a given timestamp relative to some component stream.
* Only meaningful if using a network streaming protocol (e.g. MMS.).
+ *
+ * @param h IO context from which to call the seek function pointers
* @param stream_index The stream index that the timestamp is relative to.
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
* units from the beginning of the presentation.
diff --git a/chromium/third_party/ffmpeg/libavformat/avio_internal.h b/chromium/third_party/ffmpeg/libavformat/avio_internal.h
index 8441d49971f..f4bc39c6003 100644
--- a/chromium/third_party/ffmpeg/libavformat/avio_internal.h
+++ b/chromium/third_party/ffmpeg/libavformat/avio_internal.h
@@ -105,6 +105,8 @@ void ffio_init_checksum(AVIOContext *s,
unsigned long ffio_get_checksum(AVIOContext *s);
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
unsigned int len);
+unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
+ unsigned int len);
/**
* Open a write only packetized memory stream with a maximum packet
diff --git a/chromium/third_party/ffmpeg/libavformat/aviobuf.c b/chromium/third_party/ffmpeg/libavformat/aviobuf.c
index 8b4511d177d..32a1f92cb83 100644
--- a/chromium/third_party/ffmpeg/libavformat/aviobuf.c
+++ b/chromium/third_party/ffmpeg/libavformat/aviobuf.c
@@ -78,6 +78,7 @@ int ffio_init_context(AVIOContext *s,
int64_t (*seek)(void *opaque, int64_t offset, int whence))
{
s->buffer = buffer;
+ s->orig_buffer_size =
s->buffer_size = buffer_size;
s->buf_ptr = buffer;
s->opaque = opaque;
@@ -201,12 +202,14 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
int64_t offset1;
int64_t pos;
int force = whence & AVSEEK_FORCE;
+ int buffer_size;
whence &= ~AVSEEK_FORCE;
if(!s)
return AVERROR(EINVAL);
- pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
+ buffer_size = s->buf_end - s->buffer;
+ pos = s->pos - (s->write_flag ? 0 : buffer_size);
if (whence != SEEK_CUR && whence != SEEK_SET)
return AVERROR(EINVAL);
@@ -219,7 +222,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
}
offset1 = offset - pos;
if (!s->must_flush && (!s->direct || !s->seek) &&
- offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
+ offset1 >= 0 && offset1 <= buffer_size) {
/* can do the seek inside the buffer */
s->buf_ptr = s->buffer + offset1;
} else if ((!s->seekable ||
@@ -232,9 +235,20 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
if (s->eof_reached)
return AVERROR_EOF;
s->buf_ptr = s->buf_end + offset - s->pos;
- } else {
+ } else if(!s->write_flag && offset1 < 0 && -offset1 < buffer_size>>1 && s->seek && offset > 0) {
int64_t res;
+ pos -= FFMIN(buffer_size>>1, pos);
+ if ((res = s->seek(s->opaque, pos, SEEK_SET)) < 0)
+ return res;
+ s->buf_end =
+ s->buf_ptr = s->buffer;
+ s->pos = pos;
+ s->eof_reached = 0;
+ fill_buffer(s);
+ return avio_seek(s, offset, SEEK_SET | force);
+ } else {
+ int64_t res;
if (s->write_flag) {
flush_buffer(s);
s->must_flush = 1;
@@ -421,14 +435,14 @@ static void fill_buffer(AVIOContext *s)
}
/* make buffer smaller in case it ended up large after probing */
- if (s->read_packet && s->buffer_size > max_buffer_size) {
+ if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) {
if (dst == s->buffer) {
- ffio_set_buf_size(s, max_buffer_size);
+ ffio_set_buf_size(s, s->orig_buffer_size);
s->checksum_ptr = dst = s->buffer;
}
- av_assert0(len >= max_buffer_size);
- len = max_buffer_size;
+ av_assert0(len >= s->orig_buffer_size);
+ len = s->orig_buffer_size;
}
if (s->read_packet)
@@ -455,6 +469,12 @@ unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
}
+unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
+ unsigned int len)
+{
+ return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), checksum, buf, len);
+}
+
unsigned long ffio_get_checksum(AVIOContext *s)
{
s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
@@ -749,10 +769,11 @@ int ffio_ensure_seekback(AVIOContext *s, int buf_size)
uint8_t *buffer;
int max_buffer_size = s->max_packet_size ?
s->max_packet_size : IO_BUFFER_SIZE;
+ int filled = s->buf_end - s->buffer;
buf_size += s->buf_ptr - s->buffer + max_buffer_size;
- if (buf_size < s->buffer_size || s->seekable)
+ if (buf_size < filled || s->seekable)
return 0;
av_assert0(!s->write_flag);
@@ -760,7 +781,7 @@ int ffio_ensure_seekback(AVIOContext *s, int buf_size)
if (!buffer)
return AVERROR(ENOMEM);
- memcpy(buffer, s->buffer, s->buffer_size);
+ memcpy(buffer, s->buffer, filled);
av_free(s->buffer);
s->buf_ptr = buffer + (s->buf_ptr - s->buffer);
s->buf_end = buffer + (s->buf_end - s->buffer);
@@ -778,6 +799,7 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size)
av_free(s->buffer);
s->buffer = buffer;
+ s->orig_buffer_size =
s->buffer_size = buf_size;
s->buf_ptr = buffer;
url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
@@ -1036,7 +1058,7 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
{
- DynBuffer *d = s->opaque;
+ DynBuffer *d;
int size;
static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
int padding = 0;
@@ -1045,6 +1067,7 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
*pbuffer = NULL;
return 0;
}
+ d = s->opaque;
/* don't attempt to pad fixed-size packet buffers */
if (!s->max_packet_size) {
diff --git a/chromium/third_party/ffmpeg/libavformat/avisynth.c b/chromium/third_party/ffmpeg/libavformat/avisynth.c
index 2f438d90270..c01d7e484cd 100644
--- a/chromium/third_party/ffmpeg/libavformat/avisynth.c
+++ b/chromium/third_party/ffmpeg/libavformat/avisynth.c
@@ -294,6 +294,7 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st)
st->codec->channels = avs->vi->nchannels;
st->time_base = (AVRational) { 1,
avs->vi->audio_samples_per_second };
+ st->duration = avs->vi->num_audio_samples;
switch (avs->vi->sample_type) {
case AVS_SAMPLE_INT8:
@@ -401,10 +402,10 @@ static void avisynth_next_stream(AVFormatContext *s, AVStream **st,
{
AviSynthContext *avs = s->priv_data;
- pkt->stream_index = avs->curr_stream++;
+ avs->curr_stream++;
avs->curr_stream %= s->nb_streams;
- *st = s->streams[pkt->stream_index];
+ *st = s->streams[avs->curr_stream];
if ((*st)->discard == AVDISCARD_ALL)
*discard = 1;
else
@@ -432,10 +433,6 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt,
if (discard)
return 0;
- pkt->pts = n;
- pkt->dts = n;
- pkt->duration = 1;
-
#ifdef USING_AVISYNTH
/* Define the bpp values for the new AviSynth 2.6 colorspaces.
* Since AvxSynth doesn't have these functions, special-case
@@ -459,17 +456,21 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt,
(int64_t)avs->vi->height) * bits) / 8;
if (!pkt->size)
return AVERROR_UNKNOWN;
- if (av_new_packet(pkt, (int)pkt->size) < 0) {
- av_free(pkt);
+
+ if (av_new_packet(pkt, pkt->size) < 0)
return AVERROR(ENOMEM);
- }
+
+ pkt->pts = n;
+ pkt->dts = n;
+ pkt->duration = 1;
+ pkt->stream_index = avs->curr_stream;
frame = avs_library.avs_get_frame(avs->clip, n);
error = avs_library.avs_clip_get_error(avs->clip);
if (error) {
av_log(s, AV_LOG_ERROR, "%s\n", error);
avs->error = 1;
- av_freep(&pkt->data);
+ av_packet_unref(pkt);
return AVERROR_UNKNOWN;
}
@@ -550,24 +551,25 @@ static int avisynth_read_packet_audio(AVFormatContext *s, AVPacket *pkt,
if (discard)
return 0;
- pkt->pts = n;
- pkt->dts = n;
- pkt->duration = samples;
-
pkt->size = avs_bytes_per_channel_sample(avs->vi) *
samples * avs->vi->nchannels;
if (!pkt->size)
return AVERROR_UNKNOWN;
- pkt->data = av_malloc(pkt->size);
- if (!pkt->data)
+
+ if (av_new_packet(pkt, pkt->size) < 0)
return AVERROR(ENOMEM);
+ pkt->pts = n;
+ pkt->dts = n;
+ pkt->duration = samples;
+ pkt->stream_index = avs->curr_stream;
+
avs_library.avs_get_audio(avs->clip, pkt->data, n, samples);
error = avs_library.avs_clip_get_error(avs->clip);
if (error) {
av_log(s, AV_LOG_ERROR, "%s\n", error);
avs->error = 1;
- av_freep(&pkt->data);
+ av_packet_unref(pkt);
return AVERROR_UNKNOWN;
}
return 0;
@@ -600,8 +602,6 @@ static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
if (avs->error)
return AVERROR_UNKNOWN;
- av_free_packet(pkt);
-
/* If either stream reaches EOF, try to read the other one before
* giving up. */
avisynth_next_stream(s, &st, pkt, &discard);
diff --git a/chromium/third_party/ffmpeg/libavformat/bink.c b/chromium/third_party/ffmpeg/libavformat/bink.c
index 6db73cce3aa..395c8d9aa89 100644
--- a/chromium/third_party/ffmpeg/libavformat/bink.c
+++ b/chromium/third_party/ffmpeg/libavformat/bink.c
@@ -28,6 +28,8 @@
* http://wiki.multimedia.cx/index.php?title=Bink_Container
*/
+#include <inttypes.h>
+
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
@@ -59,8 +61,10 @@ static int probe(AVProbeData *p)
{
const uint8_t *b = p->buf;
- if ( b[0] == 'B' && b[1] == 'I' && b[2] == 'K' &&
- (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i') &&
+ if (((b[0] == 'B' && b[1] == 'I' && b[2] == 'K' &&
+ (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i')) ||
+ (b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
+ (b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g'))) &&
AV_RL32(b+8) > 0 && // num_frames
AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
@@ -79,6 +83,7 @@ static int read_header(AVFormatContext *s)
uint32_t pos, next_pos;
uint16_t flags;
int keyframe;
+ int ret;
vst = avformat_new_stream(s, NULL);
if (!vst)
@@ -108,7 +113,9 @@ static int read_header(AVFormatContext *s)
fps_num = avio_rl32(pb);
fps_den = avio_rl32(pb);
if (fps_num == 0 || fps_den == 0) {
- av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den);
+ av_log(s, AV_LOG_ERROR,
+ "invalid header: invalid fps (%"PRIu32"/%"PRIu32")\n",
+ fps_num, fps_den);
return AVERROR(EIO);
}
avpriv_set_pts_info(vst, 64, fps_den, fps_num);
@@ -116,15 +123,20 @@ static int read_header(AVFormatContext *s)
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codec->codec_id = AV_CODEC_ID_BINKVIDEO;
- if (ff_alloc_extradata(vst->codec, 4))
+
+ if ((vst->codec->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) {
+ av_log(s, AV_LOG_WARNING, "Bink 2 video is not implemented\n");
+ vst->codec->codec_id = AV_CODEC_ID_NONE;
+ }
+
+ if (ff_get_extradata(vst->codec, pb, 4) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, vst->codec->extradata, 4);
bink->num_audio_tracks = avio_rl32(pb);
if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) {
av_log(s, AV_LOG_ERROR,
- "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%d)\n",
+ "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%"PRIu32")\n",
bink->num_audio_tracks);
return AVERROR(EIO);
}
@@ -177,11 +189,12 @@ static int read_header(AVFormatContext *s)
av_log(s, AV_LOG_ERROR, "invalid frame index table\n");
return AVERROR(EIO);
}
- av_add_index_entry(vst, pos, i, next_pos - pos, 0,
- keyframe ? AVINDEX_KEYFRAME : 0);
+ if ((ret = av_add_index_entry(vst, pos, i, next_pos - pos, 0,
+ keyframe ? AVINDEX_KEYFRAME : 0)) < 0)
+ return ret;
}
- avio_skip(pb, 4);
+ avio_seek(pb, vst->index_entries[0].pos, SEEK_SET);
bink->current_track = -1;
return 0;
@@ -217,7 +230,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
uint32_t audio_size = avio_rl32(pb);
if (audio_size > bink->remain_packet_size - 4) {
av_log(s, AV_LOG_ERROR,
- "frame %"PRId64": audio size in header (%u) > size of packet left (%u)\n",
+ "frame %"PRId64": audio size in header (%"PRIu32") > size of packet left (%"PRIu32")\n",
bink->video_pts, audio_size, bink->remain_packet_size);
return AVERROR(EIO);
}
@@ -280,4 +293,5 @@ AVInputFormat ff_bink_demuxer = {
.read_header = read_header,
.read_packet = read_packet,
.read_seek = read_seek,
+ .flags = AVFMT_SHOW_IDS,
};
diff --git a/chromium/third_party/ffmpeg/libavformat/cafdec.c b/chromium/third_party/ffmpeg/libavformat/cafdec.c
index e954c65683b..a8edbca039b 100644
--- a/chromium/third_party/ffmpeg/libavformat/cafdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/cafdec.c
@@ -25,6 +25,8 @@
* Core Audio Format demuxer
*/
+#include <inttypes.h>
+
#include "avformat.h"
#include "internal.h"
#include "isom.h"
@@ -154,9 +156,8 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size)
avio_skip(pb, size - ALAC_NEW_KUKI);
}
} else {
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, size);
}
return 0;
@@ -286,7 +287,8 @@ static int read_header(AVFormatContext *s)
default:
#define _(x) ((x) >= ' ' ? (x) : ' ')
- av_log(s, AV_LOG_WARNING, "skipping CAF chunk: %08X (%c%c%c%c), size %"PRId64"\n",
+ av_log(s, AV_LOG_WARNING,
+ "skipping CAF chunk: %08"PRIX32" (%c%c%c%c), size %"PRId64"\n",
tag, _(tag>>24), _((tag>>16)&0xFF), _((tag>>8)&0xFF), _(tag&0xFF), size);
#undef _
case MKBETAG('f','r','e','e'):
diff --git a/chromium/third_party/ffmpeg/libavformat/cafenc.c b/chromium/third_party/ffmpeg/libavformat/cafenc.c
index cd3a0be907f..f94101ab020 100644
--- a/chromium/third_party/ffmpeg/libavformat/cafenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/cafenc.c
@@ -108,9 +108,13 @@ static int caf_write_header(AVFormatContext *s)
unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id);
int64_t chunk_size = 0;
+ if (s->nb_streams != 1) {
+ av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n");
+ return AVERROR(EINVAL);
+ }
+
switch (enc->codec_id) {
case AV_CODEC_ID_AAC:
- case AV_CODEC_ID_AC3:
av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n");
return AVERROR_PATCHWELCOME;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/cinedec.c b/chromium/third_party/ffmpeg/libavformat/cinedec.c
new file mode 100644
index 00000000000..372088495e1
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/cinedec.c
@@ -0,0 +1,301 @@
+/*
+ * Phanton Cine demuxer
+ * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Phantom Cine demuxer
+ * @author Peter Ross <pross@xvid.org>
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "libavcodec/bmp.h"
+#include "avformat.h"
+#include "internal.h"
+
+typedef struct {
+ uint64_t pts;
+} CineDemuxContext;
+
+/** Compression */
+enum {
+ CC_RGB = 0, /**< Gray */
+ CC_LEAD = 1, /**< LEAD (M)JPEG */
+ CC_UNINT = 2 /**< Uninterpolated color image (CFA field indicates color ordering) */
+};
+
+/** Color Filter Array */
+enum {
+ CFA_NONE = 0, /**< GRAY */
+ CFA_VRI = 1, /**< GBRG/RGGB */
+ CFA_VRIV6 = 2, /**< BGGR/GRBG */
+ CFA_BAYER = 3, /**< GB/RG */
+ CFA_BAYERFLIP = 4, /**< RG/GB */
+
+ CFA_TLGRAY = 0x80000000,
+ CFA_TRGRAY = 0x40000000,
+ CFA_BLGRAY = 0x20000000,
+ CFA_BRGRAY = 0x10000000
+};
+
+static int cine_read_probe(AVProbeData *p)
+{
+ int HeaderSize;
+ if (p->buf[0] == 'C' && p->buf[1] == 'I' && // Type
+ (HeaderSize = AV_RL16(p->buf + 2)) >= 0x2C && // HeaderSize
+ AV_RL16(p->buf + 4) <= CC_UNINT && // Compression
+ AV_RL16(p->buf + 6) <= 1 && // Version
+ AV_RL32(p->buf + 20) && // ImageCount
+ AV_RL32(p->buf + 24) >= HeaderSize && // OffImageHeader
+ AV_RL32(p->buf + 28) >= HeaderSize && // OffSetup
+ AV_RL32(p->buf + 32) >= HeaderSize) // OffImageOffsets
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+static int set_metadata_int(AVDictionary **dict, const char *key, int value)
+{
+ if (value) {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%i", value);
+ return av_dict_set(dict, key, buf, 0);
+ }
+ return 0;
+}
+
+static int cine_read_header(AVFormatContext *avctx)
+{
+ AVIOContext *pb = avctx->pb;
+ AVStream *st;
+ unsigned int version, compression, offImageHeader, offSetup, offImageOffsets, biBitCount, length, CFA;
+ int vflip;
+ char *description;
+ uint64_t i;
+
+ st = avformat_new_stream(avctx, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+ st->codec->codec_tag = 0;
+
+ /* CINEFILEHEADER structure */
+ avio_skip(pb, 4); // Type, Headersize
+
+ compression = avio_rl16(pb);
+ version = avio_rl16(pb);
+ if (version != 1) {
+ avpriv_request_sample(avctx, "uknown version %i", version);
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_skip(pb, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber
+
+ st->duration = avio_rl32(pb);
+ offImageHeader = avio_rl32(pb);
+ offSetup = avio_rl32(pb);
+ offImageOffsets = avio_rl32(pb);
+
+ avio_skip(pb, 8); // TriggerTime
+
+ /* BITMAPINFOHEADER structure */
+ avio_seek(pb, offImageHeader, SEEK_SET);
+ avio_skip(pb, 4); //biSize
+ st->codec->width = avio_rl32(pb);
+ st->codec->height = avio_rl32(pb);
+
+ if (avio_rl16(pb) != 1) // biPlanes
+ return AVERROR_INVALIDDATA;
+
+ biBitCount = avio_rl16(pb);
+ if (biBitCount != 8 && biBitCount != 16 && biBitCount != 24 && biBitCount != 48) {
+ avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
+ return AVERROR_INVALIDDATA;
+ }
+
+ switch (avio_rl32(pb)) {
+ case BMP_RGB:
+ vflip = 0;
+ break;
+ case 0x100: /* BI_PACKED */
+ st->codec->codec_tag = MKTAG('B', 'I', 'T', 0);
+ vflip = 1;
+ break;
+ default:
+ avpriv_request_sample(avctx, "unknown bitmap compression");
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_skip(pb, 4); // biSizeImage
+
+ /* parse SETUP structure */
+ avio_seek(pb, offSetup, SEEK_SET);
+ avio_skip(pb, 140); // FrameRatae16 .. descriptionOld
+ if (avio_rl16(pb) != 0x5453)
+ return AVERROR_INVALIDDATA;
+ length = avio_rl16(pb);
+ if (length < 0x163C) {
+ avpriv_request_sample(avctx, "short SETUP header");
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_skip(pb, 616); // Binning .. bFlipH
+ if (!avio_rl32(pb) ^ vflip) {
+ st->codec->extradata = av_strdup("BottomUp");
+ st->codec->extradata_size = 9;
+ }
+
+ avio_skip(pb, 4); // Grid
+
+ avpriv_set_pts_info(st, 64, 1, avio_rl32(pb));
+
+ avio_skip(pb, 20); // Shutter .. bEnableColor
+
+ set_metadata_int(&st->metadata, "camera_version", avio_rl32(pb));
+ set_metadata_int(&st->metadata, "firmware_version", avio_rl32(pb));
+ set_metadata_int(&st->metadata, "software_version", avio_rl32(pb));
+ set_metadata_int(&st->metadata, "recording_timezone", avio_rl32(pb));
+
+ CFA = avio_rl32(pb);
+
+ set_metadata_int(&st->metadata, "brightness", avio_rl32(pb));
+ set_metadata_int(&st->metadata, "contrast", avio_rl32(pb));
+ set_metadata_int(&st->metadata, "gamma", avio_rl32(pb));
+
+ avio_skip(pb, 72); // Reserved1 .. WBView
+
+ st->codec->bits_per_coded_sample = avio_rl32(pb);
+
+ if (compression == CC_RGB) {
+ if (biBitCount == 8) {
+ st->codec->pix_fmt = AV_PIX_FMT_GRAY8;
+ } else if (biBitCount == 16) {
+ st->codec->pix_fmt = AV_PIX_FMT_GRAY16LE;
+ } else if (biBitCount == 24) {
+ st->codec->pix_fmt = AV_PIX_FMT_BGR24;
+ } else if (biBitCount == 48) {
+ st->codec->pix_fmt = AV_PIX_FMT_BGR48LE;
+ } else {
+ avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
+ return AVERROR_INVALIDDATA;
+ }
+ } else if (compression == CC_UNINT) {
+ switch (CFA & 0xFFFFFF) {
+ case CFA_BAYER:
+ if (biBitCount == 8) {
+ st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG8;
+ } else if (biBitCount == 16) {
+ st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE;
+ } else {
+ avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ case CFA_BAYERFLIP:
+ if (biBitCount == 8) {
+ st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB8;
+ } else if (biBitCount == 16) {
+ st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE;
+ } else {
+ avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ default:
+ avpriv_request_sample(avctx, "unsupported Color Field Array (CFA) %i", CFA & 0xFFFFFF);
+ return AVERROR_INVALIDDATA;
+ }
+ } else { //CC_LEAD
+ avpriv_request_sample(avctx, "unsupported compression %i", compression);
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_skip(pb, 696); // Conv8Min ... ImHeightAcq
+
+#define DESCRIPTION_SIZE 4096
+ description = av_malloc(DESCRIPTION_SIZE + 1);
+ if (!description)
+ return AVERROR(ENOMEM);
+ i = avio_get_str(pb, DESCRIPTION_SIZE, description, DESCRIPTION_SIZE + 1);
+ if (i < DESCRIPTION_SIZE)
+ avio_skip(pb, DESCRIPTION_SIZE - i);
+ if (description[0])
+ av_dict_set(&st->metadata, "description", description, AV_DICT_DONT_STRDUP_VAL);
+ else
+ av_free(description);
+
+ /* parse image offsets */
+ avio_seek(pb, offImageOffsets, SEEK_SET);
+ for (i = 0; i < st->duration; i++)
+ av_add_index_entry(st, avio_rl64(pb), i, 0, 0, AVINDEX_KEYFRAME);
+
+ return 0;
+}
+
+static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt)
+{
+ CineDemuxContext *cine = avctx->priv_data;
+ AVStream *st = avctx->streams[0];
+ AVIOContext *pb = avctx->pb;
+ int n, size, ret;
+
+ if (cine->pts >= st->duration)
+ return AVERROR_EOF;
+
+ avio_seek(pb, st->index_entries[cine->pts].pos, SEEK_SET);
+ n = avio_rl32(pb);
+ if (n < 8)
+ return AVERROR_INVALIDDATA;
+ avio_skip(pb, n - 8);
+ size = avio_rl32(pb);
+
+ ret = av_get_packet(pb, pkt, size);
+ if (ret < 0)
+ return ret;
+
+ pkt->pts = cine->pts++;
+ pkt->stream_index = 0;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ return 0;
+}
+
+static int cine_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
+{
+ CineDemuxContext *cine = avctx->priv_data;
+
+ if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
+ return AVERROR(ENOSYS);
+
+ if (!avctx->pb->seekable)
+ return AVERROR(EIO);
+
+ cine->pts = timestamp;
+ return 0;
+}
+
+AVInputFormat ff_cine_demuxer = {
+ .name = "cine",
+ .long_name = NULL_IF_CONFIG_SMALL("Phantom Cine"),
+ .priv_data_size = sizeof(CineDemuxContext),
+ .read_probe = cine_read_probe,
+ .read_header = cine_read_header,
+ .read_packet = cine_read_packet,
+ .read_seek = cine_read_seek,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/concatdec.c b/chromium/third_party/ffmpeg/libavformat/concatdec.c
index 428c749ab24..4590dc59232 100644
--- a/chromium/third_party/ffmpeg/libavformat/concatdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/concatdec.c
@@ -18,17 +18,31 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avformat.h"
#include "internal.h"
#include "url.h"
+typedef enum ConcatMatchMode {
+ MATCH_ONE_TO_ONE,
+ MATCH_EXACT_ID,
+} ConcatMatchMode;
+
+typedef struct ConcatStream {
+ AVBitStreamFilterContext *bsf;
+ int out_stream_index;
+} ConcatStream;
+
typedef struct {
char *url;
int64_t start_time;
int64_t duration;
+ ConcatStream *streams;
+ int nb_streams;
} ConcatFile;
typedef struct {
@@ -39,6 +53,8 @@ typedef struct {
AVFormatContext *avf;
int safe;
int seekable;
+ ConcatMatchMode stream_match_mode;
+ unsigned auto_convert;
} ConcatContext;
static int concat_probe(AVProbeData *probe)
@@ -85,18 +101,28 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
ConcatContext *cat = avf->priv_data;
ConcatFile *file;
char *url = NULL;
- size_t url_len;
+ const char *proto;
+ size_t url_len, proto_len;
int ret;
if (cat->safe > 0 && !safe_filename(filename)) {
av_log(avf, AV_LOG_ERROR, "Unsafe file name '%s'\n", filename);
FAIL(AVERROR(EPERM));
}
- url_len = strlen(avf->filename) + strlen(filename) + 16;
- if (!(url = av_malloc(url_len)))
- FAIL(AVERROR(ENOMEM));
- ff_make_absolute_url(url, url_len, avf->filename, filename);
- av_freep(&filename);
+
+ proto = avio_find_protocol_name(filename);
+ proto_len = proto ? strlen(proto) : 0;
+ if (!memcmp(filename, proto, proto_len) &&
+ (filename[proto_len] == ':' || filename[proto_len] == ',')) {
+ url = filename;
+ filename = NULL;
+ } else {
+ url_len = strlen(avf->filename) + strlen(filename) + 16;
+ if (!(url = av_malloc(url_len)))
+ FAIL(AVERROR(ENOMEM));
+ ff_make_absolute_url(url, url_len, avf->filename, filename);
+ av_freep(&filename);
+ }
if (cat->nb_files >= *nb_files_alloc) {
size_t n = FFMAX(*nb_files_alloc * 2, 16);
@@ -124,6 +150,130 @@ fail:
return ret;
}
+static int copy_stream_props(AVStream *st, AVStream *source_st)
+{
+ int ret;
+
+ if (st->codec->codec_id || !source_st->codec->codec_id) {
+ if (st->codec->extradata_size < source_st->codec->extradata_size) {
+ ret = ff_alloc_extradata(st->codec,
+ source_st->codec->extradata_size);
+ if (ret < 0)
+ return ret;
+ }
+ memcpy(st->codec->extradata, source_st->codec->extradata,
+ source_st->codec->extradata_size);
+ return 0;
+ }
+ if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0)
+ return ret;
+ st->r_frame_rate = source_st->r_frame_rate;
+ st->avg_frame_rate = source_st->avg_frame_rate;
+ st->time_base = source_st->time_base;
+ st->sample_aspect_ratio = source_st->sample_aspect_ratio;
+ return 0;
+}
+
+static int detect_stream_specific(AVFormatContext *avf, int idx)
+{
+ ConcatContext *cat = avf->priv_data;
+ AVStream *st = cat->avf->streams[idx];
+ ConcatStream *cs = &cat->cur_file->streams[idx];
+ AVBitStreamFilterContext *bsf;
+
+ if (cat->auto_convert && st->codec->codec_id == AV_CODEC_ID_H264 &&
+ (st->codec->extradata_size < 4 || AV_RB32(st->codec->extradata) != 1)) {
+ av_log(cat->avf, AV_LOG_INFO,
+ "Auto-inserting h264_mp4toannexb bitstream filter\n");
+ if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) {
+ av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
+ "required for H.264 streams\n");
+ return AVERROR_BSF_NOT_FOUND;
+ }
+ cs->bsf = bsf;
+ }
+ return 0;
+}
+
+static int match_streams_one_to_one(AVFormatContext *avf)
+{
+ ConcatContext *cat = avf->priv_data;
+ AVStream *st;
+ int i, ret;
+
+ for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
+ if (i < avf->nb_streams) {
+ st = avf->streams[i];
+ } else {
+ if (!(st = avformat_new_stream(avf, NULL)))
+ return AVERROR(ENOMEM);
+ }
+ if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
+ return ret;
+ cat->cur_file->streams[i].out_stream_index = i;
+ }
+ return 0;
+}
+
+static int match_streams_exact_id(AVFormatContext *avf)
+{
+ ConcatContext *cat = avf->priv_data;
+ AVStream *st;
+ int i, j, ret;
+
+ for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
+ st = cat->avf->streams[i];
+ for (j = 0; j < avf->nb_streams; j++) {
+ if (avf->streams[j]->id == st->id) {
+ av_log(avf, AV_LOG_VERBOSE,
+ "Match slave stream #%d with stream #%d id 0x%x\n",
+ i, j, st->id);
+ if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
+ return ret;
+ cat->cur_file->streams[i].out_stream_index = j;
+ }
+ }
+ }
+ return 0;
+}
+
+static int match_streams(AVFormatContext *avf)
+{
+ ConcatContext *cat = avf->priv_data;
+ ConcatStream *map;
+ int i, ret;
+
+ if (cat->cur_file->nb_streams >= cat->avf->nb_streams)
+ return 0;
+ map = av_realloc(cat->cur_file->streams,
+ cat->avf->nb_streams * sizeof(*map));
+ if (!map)
+ return AVERROR(ENOMEM);
+ cat->cur_file->streams = map;
+ memset(map + cat->cur_file->nb_streams, 0,
+ (cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map));
+
+ for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++)
+ map[i].out_stream_index = -1;
+ switch (cat->stream_match_mode) {
+ case MATCH_ONE_TO_ONE:
+ ret = match_streams_one_to_one(avf);
+ break;
+ case MATCH_EXACT_ID:
+ ret = match_streams_exact_id(avf);
+ break;
+ default:
+ ret = AVERROR_BUG;
+ }
+ if (ret < 0)
+ return ret;
+ for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++)
+ if ((ret = detect_stream_specific(avf, i)) < 0)
+ return ret;
+ cat->cur_file->nb_streams = cat->avf->nb_streams;
+ return 0;
+}
+
static int open_file(AVFormatContext *avf, unsigned fileno)
{
ConcatContext *cat = avf->priv_data;
@@ -132,9 +282,16 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
if (cat->avf)
avformat_close_input(&cat->avf);
+
+ cat->avf = avformat_alloc_context();
+ if (!cat->avf)
+ return AVERROR(ENOMEM);
+
+ cat->avf->interrupt_callback = avf->interrupt_callback;
if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
(ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url);
+ avformat_close_input(&cat->avf);
return ret;
}
cat->cur_file = file;
@@ -142,6 +299,8 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
file->start_time = !fileno ? 0 :
cat->files[fileno - 1].start_time +
cat->files[fileno - 1].duration;
+ if ((ret = match_streams(avf)) < 0)
+ return ret;
return 0;
}
@@ -152,8 +311,10 @@ static int concat_read_close(AVFormatContext *avf)
if (cat->avf)
avformat_close_input(&cat->avf);
- for (i = 0; i < cat->nb_files; i++)
+ for (i = 0; i < cat->nb_files; i++) {
av_freep(&cat->files[i].url);
+ av_freep(&cat->files[i].streams);
+ }
av_freep(&cat->files);
return 0;
}
@@ -166,7 +327,6 @@ static int concat_read_header(AVFormatContext *avf)
int ret, line = 0, i;
unsigned nb_files_alloc = 0;
ConcatFile *file = NULL;
- AVStream *st, *source_st;
int64_t time = 0;
while (1) {
@@ -200,6 +360,17 @@ static int concat_read_header(AVFormatContext *avf)
FAIL(ret);
}
file->duration = dur;
+ } else if (!strcmp(keyword, "stream")) {
+ if (!avformat_new_stream(avf, NULL))
+ FAIL(AVERROR(ENOMEM));
+ } else if (!strcmp(keyword, "exact_stream_id")) {
+ if (!avf->nb_streams) {
+ av_log(avf, AV_LOG_ERROR, "Line %d: exact_stream_id without stream\n",
+ line);
+ FAIL(AVERROR_INVALIDDATA);
+ }
+ avf->streams[avf->nb_streams - 1]->id =
+ strtol(get_keyword(&cursor), NULL, 0);
} else if (!strcmp(keyword, "ffconcat")) {
char *ver_kw = get_keyword(&cursor);
char *ver_val = get_keyword(&cursor);
@@ -234,20 +405,10 @@ static int concat_read_header(AVFormatContext *avf)
cat->seekable = 1;
}
+ cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID :
+ MATCH_ONE_TO_ONE;
if ((ret = open_file(avf, 0)) < 0)
FAIL(ret);
- for (i = 0; i < cat->avf->nb_streams; i++) {
- if (!(st = avformat_new_stream(avf, NULL)))
- FAIL(AVERROR(ENOMEM));
- source_st = cat->avf->streams[i];
- if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0)
- FAIL(ret);
- st->r_frame_rate = source_st->r_frame_rate;
- st->avg_frame_rate = source_st->avg_frame_rate;
- st->time_base = source_st->time_base;
- st->sample_aspect_ratio = source_st->sample_aspect_ratio;
- }
-
return 0;
fail:
@@ -268,17 +429,77 @@ static int open_next_file(AVFormatContext *avf)
return open_file(avf, fileno);
}
+static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
+{
+ AVStream *st = avf->streams[cs->out_stream_index];
+ AVBitStreamFilterContext *bsf;
+ AVPacket pkt2;
+ int ret;
+
+ av_assert0(cs->out_stream_index >= 0);
+ for (bsf = cs->bsf; bsf; bsf = bsf->next) {
+ pkt2 = *pkt;
+ ret = av_bitstream_filter_filter(bsf, st->codec, NULL,
+ &pkt2.data, &pkt2.size,
+ pkt->data, pkt->size,
+ !!(pkt->flags & AV_PKT_FLAG_KEY));
+ if (ret < 0) {
+ av_packet_unref(pkt);
+ return ret;
+ }
+ av_assert0(pkt2.buf);
+ if (ret == 0 && pkt2.data != pkt->data) {
+ if ((ret = av_copy_packet(&pkt2, pkt)) < 0) {
+ av_free(pkt2.data);
+ return ret;
+ }
+ ret = 1;
+ }
+ if (ret > 0) {
+ av_free_packet(pkt);
+ pkt2.buf = av_buffer_create(pkt2.data, pkt2.size,
+ av_buffer_default_free, NULL, 0);
+ if (!pkt2.buf) {
+ av_free(pkt2.data);
+ return AVERROR(ENOMEM);
+ }
+ }
+ *pkt = pkt2;
+ }
+ return 0;
+}
+
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
ConcatContext *cat = avf->priv_data;
int ret;
int64_t delta;
+ ConcatStream *cs;
while (1) {
- if ((ret = av_read_frame(cat->avf, pkt)) != AVERROR_EOF ||
- (ret = open_next_file(avf)) < 0)
- break;
+ ret = av_read_frame(cat->avf, pkt);
+ if (ret == AVERROR_EOF) {
+ if ((ret = open_next_file(avf)) < 0)
+ return ret;
+ continue;
+ }
+ if (ret < 0)
+ return ret;
+ if ((ret = match_streams(avf)) < 0) {
+ av_packet_unref(pkt);
+ return ret;
+ }
+ cs = &cat->cur_file->streams[pkt->stream_index];
+ if (cs->out_stream_index < 0) {
+ av_packet_unref(pkt);
+ continue;
+ }
+ pkt->stream_index = cs->out_stream_index;
+ break;
}
+ if ((ret = filter_packet(avf, cs, pkt)))
+ return ret;
+
delta = av_rescale_q(cat->cur_file->start_time - cat->avf->start_time,
AV_TIME_BASE_Q,
cat->avf->streams[pkt->stream_index]->time_base);
@@ -384,6 +605,8 @@ static int concat_seek(AVFormatContext *avf, int stream,
static const AVOption options[] = {
{ "safe", "enable safe mode",
OFFSET(safe), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, DEC },
+ { "auto_convert", "automatically convert bitstream format",
+ OFFSET(auto_convert), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
{ NULL }
};
diff --git a/chromium/third_party/ffmpeg/libavformat/crcenc.c b/chromium/third_party/ffmpeg/libavformat/crcenc.c
index ac0638037e4..3fdfea5207f 100644
--- a/chromium/third_party/ffmpeg/libavformat/crcenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/crcenc.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/adler32.h"
#include "avformat.h"
@@ -48,7 +50,7 @@ static int crc_write_trailer(struct AVFormatContext *s)
CRCState *crc = s->priv_data;
char buf[64];
- snprintf(buf, sizeof(buf), "CRC=0x%08x\n", crc->crcval);
+ snprintf(buf, sizeof(buf), "CRC=0x%08"PRIx32"\n", crc->crcval);
avio_write(s->pb, buf, strlen(buf));
return 0;
diff --git a/chromium/third_party/ffmpeg/libavformat/dfa.c b/chromium/third_party/ffmpeg/libavformat/dfa.c
index 9cd13e24d95..dfa0590e2e2 100644
--- a/chromium/third_party/ffmpeg/libavformat/dfa.c
+++ b/chromium/third_party/ffmpeg/libavformat/dfa.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
@@ -98,12 +100,13 @@ static int dfa_read_packet(AVFormatContext *s, AVPacket *pkt)
first = 0;
frame_size = AV_RL32(pkt->data + pkt->size - 8);
if (frame_size > INT_MAX - 4) {
- av_log(s, AV_LOG_ERROR, "Too large chunk size: %d\n", frame_size);
+ av_log(s, AV_LOG_ERROR, "Too large chunk size: %"PRIu32"\n", frame_size);
return AVERROR(EIO);
}
if (AV_RL32(pkt->data + pkt->size - 12) == MKTAG('E', 'O', 'F', 'R')) {
if (frame_size) {
- av_log(s, AV_LOG_WARNING, "skipping %d bytes of end-of-frame marker chunk\n",
+ av_log(s, AV_LOG_WARNING,
+ "skipping %"PRIu32" bytes of end-of-frame marker chunk\n",
frame_size);
avio_skip(pb, frame_size);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/dsfdec.c b/chromium/third_party/ffmpeg/libavformat/dsfdec.c
new file mode 100644
index 00000000000..ae198b2e93b
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/dsfdec.c
@@ -0,0 +1,159 @@
+/*
+ * DSD Stream File (DSF) demuxer
+ * Copyright (c) 2014 Peter Ross
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+#include "id3v2.h"
+
+typedef struct {
+ uint64_t data_end;
+} DSFContext;
+
+static int dsf_probe(AVProbeData *p)
+{
+ if (p->buf_size < 12 || memcmp(p->buf, "DSD ", 4) || AV_RL64(p->buf + 4) != 28)
+ return 0;
+ return AVPROBE_SCORE_MAX;
+}
+
+static const uint64_t dsf_channel_layout[] = {
+ 0,
+ AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO,
+ AV_CH_LAYOUT_SURROUND,
+ AV_CH_LAYOUT_QUAD,
+ AV_CH_LAYOUT_4POINT0,
+ AV_CH_LAYOUT_5POINT0_BACK,
+ AV_CH_LAYOUT_5POINT1_BACK,
+};
+
+static void read_id3(AVFormatContext *s, uint64_t id3pos)
+{
+ ID3v2ExtraMeta *id3v2_extra_meta = NULL;
+ if (avio_seek(s->pb, id3pos, SEEK_SET) < 0)
+ return;
+
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0);
+ if (id3v2_extra_meta)
+ ff_id3v2_parse_apic(s, &id3v2_extra_meta);
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
+}
+
+static int dsf_read_header(AVFormatContext *s)
+{
+ DSFContext *dsf = s->priv_data;
+ AVIOContext *pb = s->pb;
+ AVStream *st;
+ uint64_t id3pos;
+ unsigned int channel_type;
+
+ avio_skip(pb, 4);
+ if (avio_rl64(pb) != 28)
+ return AVERROR_INVALIDDATA;
+
+ /* create primary stream before any id3 coverart streams */
+ st = avformat_new_stream(s, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ avio_skip(pb, 8);
+ id3pos = avio_rl64(pb);
+ if (pb->seekable) {
+ read_id3(s, id3pos);
+ avio_seek(pb, 28, SEEK_SET);
+ }
+
+ /* fmt chunk */
+
+ if (avio_rl32(pb) != MKTAG('f', 'm', 't', ' ') || avio_rl64(pb) != 52)
+ return AVERROR_INVALIDDATA;
+
+ if (avio_rl32(pb) != 1) {
+ avpriv_request_sample(s, "unknown format version");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (avio_rl32(pb)) {
+ avpriv_request_sample(s, "unknown format id");
+ return AVERROR_INVALIDDATA;
+ }
+
+ channel_type = avio_rl32(pb);
+ if (channel_type < FF_ARRAY_ELEMS(dsf_channel_layout))
+ st->codec->channel_layout = dsf_channel_layout[channel_type];
+ if (!st->codec->channel_layout)
+ avpriv_request_sample(s, "channel type %i", channel_type);
+
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ st->codec->channels = avio_rl32(pb);
+ st->codec->sample_rate = avio_rl32(pb) / 8;
+
+ switch(avio_rl32(pb)) {
+ case 1: st->codec->codec_id = AV_CODEC_ID_DSD_LSBF_PLANAR; break;
+ case 8: st->codec->codec_id = AV_CODEC_ID_DSD_MSBF_PLANAR; break;
+ default:
+ avpriv_request_sample(s, "unknown most significant bit");
+ return AVERROR_INVALIDDATA;
+ }
+
+ avio_skip(pb, 8);
+ st->codec->block_align = avio_rl32(pb);
+ if (st->codec->block_align > INT_MAX / st->codec->channels) {
+ avpriv_request_sample(s, "block_align overflow");
+ return AVERROR_INVALIDDATA;
+ }
+ st->codec->block_align *= st->codec->channels;
+ avio_skip(pb, 4);
+
+ /* data chunk */
+
+ dsf->data_end = avio_tell(pb);
+ if (avio_rl32(pb) != MKTAG('d', 'a', 't', 'a'))
+ return AVERROR_INVALIDDATA;
+ dsf->data_end += avio_rl64(pb);
+
+ return 0;
+}
+
+static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ DSFContext *dsf = s->priv_data;
+ AVIOContext *pb = s->pb;
+ AVStream *st = s->streams[0];
+ int64_t pos = avio_tell(pb);
+
+ if (pos >= dsf->data_end)
+ return AVERROR_EOF;
+
+ pkt->stream_index = 0;
+ return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codec->block_align));
+}
+
+AVInputFormat ff_dsf_demuxer = {
+ .name = "dsf",
+ .long_name = NULL_IF_CONFIG_SMALL("DSD Stream File (DSF)"),
+ .priv_data_size = sizeof(DSFContext),
+ .read_probe = dsf_probe,
+ .read_header = dsf_read_header,
+ .read_packet = dsf_read_packet,
+ .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/dvenc.c b/chromium/third_party/ffmpeg/libavformat/dvenc.c
index 43f65c37b9c..defcf2a16e3 100644
--- a/chromium/third_party/ffmpeg/libavformat/dvenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/dvenc.c
@@ -334,7 +334,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s)
if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*MAX_AUDIO_FRAME_SIZE))) {
while (i > 0) {
i--;
- av_fifo_free(c->audio_data[i]);
+ av_fifo_freep(&c->audio_data[i]);
}
goto bail_out;
}
@@ -350,7 +350,7 @@ static void dv_delete_mux(DVMuxContext *c)
{
int i;
for (i=0; i < c->n_ast; i++)
- av_fifo_free(c->audio_data[i]);
+ av_fifo_freep(&c->audio_data[i]);
}
static int dv_write_header(AVFormatContext *s)
diff --git a/chromium/third_party/ffmpeg/libavformat/dxa.c b/chromium/third_party/ffmpeg/libavformat/dxa.c
index 22ee2a97a54..ea5b4f7163a 100644
--- a/chromium/third_party/ffmpeg/libavformat/dxa.c
+++ b/chromium/third_party/ffmpeg/libavformat/dxa.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
@@ -169,7 +171,10 @@ static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt)
}
avio_seek(s->pb, c->vidpos, SEEK_SET);
while(!url_feof(s->pb) && c->frames){
- avio_read(s->pb, buf, 4);
+ if ((ret = avio_read(s->pb, buf, 4)) != 4) {
+ av_log(s, AV_LOG_ERROR, "failed reading chunk type\n");
+ return ret < 0 ? ret : AVERROR_INVALIDDATA;
+ }
switch(AV_RL32(buf)){
case MKTAG('N', 'U', 'L', 'L'):
if(av_new_packet(pkt, 4 + pal_size) < 0)
@@ -187,10 +192,14 @@ static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt)
avio_read(s->pb, pal + 4, 768);
break;
case MKTAG('F', 'R', 'A', 'M'):
- avio_read(s->pb, buf + 4, DXA_EXTRA_SIZE - 4);
+ if ((ret = avio_read(s->pb, buf + 4, DXA_EXTRA_SIZE - 4)) != DXA_EXTRA_SIZE - 4) {
+ av_log(s, AV_LOG_ERROR, "failed reading dxa_extra\n");
+ return ret < 0 ? ret : AVERROR_INVALIDDATA;
+ }
size = AV_RB32(buf + 5);
if(size > 0xFFFFFF){
- av_log(s, AV_LOG_ERROR, "Frame size is too big: %d\n", size);
+ av_log(s, AV_LOG_ERROR, "Frame size is too big: %"PRIu32"\n",
+ size);
return AVERROR_INVALIDDATA;
}
if(av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size) < 0)
diff --git a/chromium/third_party/ffmpeg/libavformat/electronicarts.c b/chromium/third_party/ffmpeg/libavformat/electronicarts.c
index dd8cf5d6449..1acaa14c8cf 100644
--- a/chromium/third_party/ffmpeg/libavformat/electronicarts.c
+++ b/chromium/third_party/ffmpeg/libavformat/electronicarts.c
@@ -25,6 +25,8 @@
* by Robin Kay (komadori at gekkou.co.uk)
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
@@ -152,7 +154,7 @@ static int process_audio_header_elements(AVFormatContext *s)
break;
case 0x8A:
av_log(s, AV_LOG_DEBUG,
- "element 0x%02x set to 0x%08x\n",
+ "element 0x%02x set to 0x%08"PRIx32"\n",
subbyte, read_arbitrary(pb));
av_log(s, AV_LOG_DEBUG, "exited audio subheader\n");
in_subheader = 0;
@@ -171,7 +173,7 @@ static int process_audio_header_elements(AVFormatContext *s)
break;
default:
av_log(s, AV_LOG_DEBUG,
- "element 0x%02x set to 0x%08x\n",
+ "element 0x%02x set to 0x%08"PRIx32"\n",
subbyte, read_arbitrary(pb));
break;
}
@@ -183,7 +185,7 @@ static int process_audio_header_elements(AVFormatContext *s)
break;
default:
av_log(s, AV_LOG_DEBUG,
- "header element 0x%02x set to 0x%08x\n",
+ "header element 0x%02x set to 0x%08"PRIx32"\n",
byte, read_arbitrary(pb));
break;
}
@@ -351,13 +353,13 @@ static int process_ea_header(AVFormatContext *s)
int i;
for (i = 0; i < 5 && (!ea->audio_codec || !ea->video_codec); i++) {
- unsigned int startpos = avio_tell(pb);
+ uint64_t startpos = avio_tell(pb);
int err = 0;
blockid = avio_rl32(pb);
size = avio_rl32(pb);
if (i == 0)
- ea->big_endian = size > 0x000FFFFF;
+ ea->big_endian = size > av_bswap32(size);
if (ea->big_endian)
size = av_bswap32(size);
diff --git a/chromium/third_party/ffmpeg/libavformat/ffmdec.c b/chromium/third_party/ffmpeg/libavformat/ffmdec.c
index 679d926da16..9d89b166435 100644
--- a/chromium/third_party/ffmpeg/libavformat/ffmdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/ffmdec.c
@@ -280,9 +280,8 @@ static int ffm2_read_header(AVFormatContext *s)
codec->flags2 = avio_rb32(pb);
codec->debug = avio_rb32(pb);
if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
- if (ff_alloc_extradata(codec, avio_rb32(pb)))
+ if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, codec->extradata, codec->extradata_size);
}
avio_seek(pb, next, SEEK_SET);
id = avio_rb32(pb);
@@ -468,9 +467,8 @@ static int ffm_read_header(AVFormatContext *s)
goto fail;
}
if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
- if (ff_alloc_extradata(codec, avio_rb32(pb)))
+ if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, codec->extradata, codec->extradata_size);
}
}
diff --git a/chromium/third_party/ffmpeg/libavformat/file.c b/chromium/third_party/ffmpeg/libavformat/file.c
index 2defc75e5f7..6511328de7d 100644
--- a/chromium/third_party/ffmpeg/libavformat/file.c
+++ b/chromium/third_party/ffmpeg/libavformat/file.c
@@ -54,7 +54,7 @@ typedef struct FileContext {
} FileContext;
static const AVOption file_options[] = {
- { "truncate", "Truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+ { "truncate", "truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
{ "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ NULL }
};
@@ -104,25 +104,30 @@ static int file_get_handle(URLContext *h)
static int file_check(URLContext *h, int mask)
{
-#if HAVE_ACCESS && defined(R_OK)
int ret = 0;
- if (access(h->filename, F_OK) < 0)
+ const char *filename = h->filename;
+ av_strstart(filename, "file:", &filename);
+
+ {
+#if HAVE_ACCESS && defined(R_OK)
+ if (access(filename, F_OK) < 0)
return AVERROR(errno);
if (mask&AVIO_FLAG_READ)
- if (access(h->filename, R_OK) >= 0)
+ if (access(filename, R_OK) >= 0)
ret |= AVIO_FLAG_READ;
if (mask&AVIO_FLAG_WRITE)
- if (access(h->filename, W_OK) >= 0)
+ if (access(filename, W_OK) >= 0)
ret |= AVIO_FLAG_WRITE;
#else
struct stat st;
- int ret = stat(h->filename, &st);
+ ret = stat(filename, &st);
if (ret < 0)
return AVERROR(errno);
ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
#endif
+ }
return ret;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/flac_picture.c b/chromium/third_party/ffmpeg/libavformat/flac_picture.c
index 12d73e488f9..5f2026d1d0e 100644
--- a/chromium/third_party/ffmpeg/libavformat/flac_picture.c
+++ b/chromium/third_party/ffmpeg/libavformat/flac_picture.c
@@ -107,9 +107,10 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
ret = AVERROR_INVALIDDATA;
goto fail;
}
- if (!(data = av_buffer_alloc(len))) {
+ if (!(data = av_buffer_alloc(len + FF_INPUT_BUFFER_PADDING_SIZE))) {
RETURN_ERROR(AVERROR(ENOMEM));
}
+ memset(data->data + len, 0, FF_INPUT_BUFFER_PADDING_SIZE);
if (avio_read(pb, data->data, len) != len) {
av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n");
if (s->error_recognition & AV_EF_EXPLODE)
diff --git a/chromium/third_party/ffmpeg/libavformat/flacdec.c b/chromium/third_party/ffmpeg/libavformat/flacdec.c
index 29310b831f1..cd752e1a20f 100644
--- a/chromium/third_party/ffmpeg/libavformat/flacdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/flacdec.c
@@ -26,6 +26,7 @@
#include "rawdec.h"
#include "oggdec.h"
#include "vorbiscomment.h"
+#include "replaygain.h"
#include "libavcodec/bytestream.h"
static int flac_read_header(AVFormatContext *s)
@@ -143,6 +144,10 @@ static int flac_read_header(AVFormatContext *s)
}
}
+ ret = ff_replaygain_export(st, s->metadata);
+ if (ret < 0)
+ return ret;
+
return 0;
fail:
@@ -157,12 +162,61 @@ static int flac_probe(AVProbeData *p)
return AVPROBE_SCORE_EXTENSION;
}
+static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ AVPacket pkt, out_pkt;
+ AVStream *st = s->streams[stream_index];
+ AVCodecParserContext *parser;
+ int ret;
+ int64_t pts = AV_NOPTS_VALUE;
+
+ if (avio_seek(s->pb, *ppos, SEEK_SET) < 0)
+ return AV_NOPTS_VALUE;
+
+ av_init_packet(&pkt);
+ parser = av_parser_init(st->codec->codec_id);
+ if (!parser){
+ return AV_NOPTS_VALUE;
+ }
+ parser->flags |= PARSER_FLAG_USE_CODEC_TS;
+
+ for (;;){
+ ret = ff_raw_read_partial_packet(s, &pkt);
+ if (ret < 0){
+ if (ret == AVERROR(EAGAIN))
+ continue;
+ else
+ break;
+ }
+ av_init_packet(&out_pkt);
+ ret = av_parser_parse2(parser, st->codec,
+ &out_pkt.data, &out_pkt.size, pkt.data, pkt.size,
+ pkt.pts, pkt.dts, *ppos);
+
+ av_free_packet(&pkt);
+ if (out_pkt.size){
+ int size = out_pkt.size;
+ if (parser->pts != AV_NOPTS_VALUE){
+ // seeking may not have started from beginning of a frame
+ // calculate frame start position from next frame backwards
+ *ppos = parser->next_frame_offset - size;
+ pts = parser->pts;
+ break;
+ }
+ }
+ }
+ av_parser_close(parser);
+ return pts;
+}
+
AVInputFormat ff_flac_demuxer = {
.name = "flac",
.long_name = NULL_IF_CONFIG_SMALL("raw FLAC"),
.read_probe = flac_probe,
.read_header = flac_read_header,
.read_packet = ff_raw_read_partial_packet,
+ .read_timestamp = flac_read_timestamp,
.flags = AVFMT_GENERIC_INDEX,
.extensions = "flac",
.raw_codec_id = AV_CODEC_ID_FLAC,
diff --git a/chromium/third_party/ffmpeg/libavformat/flacenc.c b/chromium/third_party/ffmpeg/libavformat/flacenc.c
index 87e93625f28..d92801807ef 100644
--- a/chromium/third_party/ffmpeg/libavformat/flacenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/flacenc.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/opt.h"
#include "libavcodec/flac.h"
#include "avformat.h"
#include "avio_internal.h"
@@ -27,6 +28,11 @@
#include "libavcodec/bytestream.h"
+typedef struct FlacMuxerContext {
+ const AVClass *class;
+ int write_header;
+} FlacMuxerContext;
+
static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
int last_block)
{
@@ -65,7 +71,12 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
static int flac_write_header(struct AVFormatContext *s)
{
int ret;
+ int padding = s->metadata_header_padding;
AVCodecContext *codec = s->streams[0]->codec;
+ FlacMuxerContext *c = s->priv_data;
+
+ if (!c->write_header)
+ return 0;
if (s->nb_streams > 1) {
av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
@@ -76,20 +87,27 @@ static int flac_write_header(struct AVFormatContext *s)
return AVERROR(EINVAL);
}
+ if (padding < 0)
+ padding = 8192;
+ /* The FLAC specification states that 24 bits are used to represent the
+ * size of a metadata block so we must clip this value to 2^24-1. */
+ padding = av_clip_c(padding, 0, 16777215);
+
ret = ff_flac_write_header(s->pb, codec, 0);
if (ret)
return ret;
- ret = flac_write_block_comment(s->pb, &s->metadata, 0,
- codec->flags & CODEC_FLAG_BITEXACT);
+ ret = flac_write_block_comment(s->pb, &s->metadata, !padding,
+ s->flags & AVFMT_FLAG_BITEXACT);
if (ret)
return ret;
/* The command line flac encoder defaults to placing a seekpoint
* every 10s. So one might add padding to allow that later
* but there seems to be no simple way to get the duration here.
- * So let's try the flac default of 8192 bytes */
- flac_write_block_padding(s->pb, 8192, 1);
+ * So just add the amount requested by the user. */
+ if (padding)
+ flac_write_block_padding(s->pb, padding, 1);
return ret;
}
@@ -100,6 +118,10 @@ static int flac_write_trailer(struct AVFormatContext *s)
uint8_t *streaminfo;
enum FLACExtradataFormat format;
int64_t file_size;
+ FlacMuxerContext *c = s->priv_data;
+
+ if (!c->write_header)
+ return 0;
if (!avpriv_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo))
return -1;
@@ -123,9 +145,22 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt)
return 0;
}
+static const AVOption flacenc_options[] = {
+ { "write_header", "Write the file header", offsetof(FlacMuxerContext, write_header), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+ { NULL },
+};
+
+static const AVClass flac_muxer_class = {
+ .class_name = "flac muxer",
+ .item_name = av_default_item_name,
+ .option = flacenc_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVOutputFormat ff_flac_muxer = {
.name = "flac",
.long_name = NULL_IF_CONFIG_SMALL("raw FLAC"),
+ .priv_data_size = sizeof(FlacMuxerContext),
.mime_type = "audio/x-flac",
.extensions = "flac",
.audio_codec = AV_CODEC_ID_FLAC,
@@ -134,4 +169,5 @@ AVOutputFormat ff_flac_muxer = {
.write_packet = flac_write_packet,
.write_trailer = flac_write_trailer,
.flags = AVFMT_NOTIMESTAMPS,
+ .priv_class = &flac_muxer_class,
};
diff --git a/chromium/third_party/ffmpeg/libavformat/flvdec.c b/chromium/third_party/ffmpeg/libavformat/flvdec.c
index 1024001a473..c0eddd3820d 100644
--- a/chromium/third_party/ffmpeg/libavformat/flvdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/flvdec.c
@@ -256,6 +256,7 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
return 1; // 1 byte body size adjustment for flv_read_packet()
case FLV_CODECID_H264:
vcodec->codec_id = AV_CODEC_ID_H264;
+ vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
return 3; // not 4, reading packet type will consume one byte
case FLV_CODECID_MPEG4:
vcodec->codec_id = AV_CODEC_ID_MPEG4;
@@ -295,7 +296,7 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc,
int64_t initial_pos = avio_tell(ioc);
if (vstream->nb_index_entries>0) {
- av_log(s, AV_LOG_WARNING, "Skiping duplicate index\n");
+ av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n");
return 0;
}
@@ -579,7 +580,7 @@ static int flv_read_header(AVFormatContext *s)
flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO;
av_log(s, AV_LOG_WARNING,
"Broken FLV file, which says no streams present, "
- "this might fail\n");
+ "this might fail.\n");
}
s->ctx_flags |= AVFMTCTX_NOHEADER;
@@ -614,9 +615,8 @@ static int flv_read_close(AVFormatContext *s)
static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
{
av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, s->pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(s->pb, st->codec->extradata, st->codec->extradata_size);
return 0;
}
@@ -772,7 +772,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
size = avio_rb24(s->pb);
dts = avio_rb24(s->pb);
dts |= avio_r8(s->pb) << 24;
- av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts);
+ av_dlog(s, "type:%d, size:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, dts, avio_tell(s->pb));
if (url_feof(s->pb))
return AVERROR_EOF;
avio_skip(s->pb, 3); /* stream id, always 0 */
@@ -820,7 +820,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
} else {
av_log(s, AV_LOG_DEBUG,
- "skipping flv packet: type %d, size %d, flags %d\n",
+ "Skipping flv packet: type %d, size %d, flags %d.\n",
type, size, flags);
skip:
avio_seek(s->pb, next, SEEK_SET);
@@ -916,7 +916,7 @@ retry_duration:
flv->last_channels =
channels = st->codec->channels;
} else {
- AVCodecContext ctx;
+ AVCodecContext ctx = {0};
ctx.sample_rate = sample_rate;
flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK);
sample_rate = ctx.sample_rate;
@@ -934,15 +934,20 @@ retry_duration:
// sign extension
int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
pts = dts + cts;
- if (cts < 0) { // dts are wrong
+ if (cts < 0) { // dts might be wrong
+ if (!flv->wrong_dts)
+ av_log(s, AV_LOG_WARNING,
+ "Negative cts, previous timestamps might be wrong.\n");
flv->wrong_dts = 1;
+ } else if (FFABS(dts - pts) > 1000*60*15) {
av_log(s, AV_LOG_WARNING,
- "negative cts, previous timestamps might be wrong\n");
+ "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
+ dts = pts = AV_NOPTS_VALUE;
}
- if (flv->wrong_dts)
- dts = AV_NOPTS_VALUE;
}
if (type == 0 && (!st->codec->extradata || st->codec->codec_id == AV_CODEC_ID_AAC)) {
+ AVDictionaryEntry *t;
+
if (st->codec->extradata) {
if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
return ret;
@@ -951,8 +956,15 @@ retry_duration:
}
if ((ret = flv_get_extradata(s, st, size)) < 0)
return ret;
+
+ /* Workaround for buggy Omnia A/XE encoder */
+ t = av_dict_get(s->metadata, "Encoder", NULL, 0);
+ if (st->codec->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE"))
+ st->codec->extradata_size = 2;
+
if (st->codec->codec_id == AV_CODEC_ID_AAC && 0) {
MPEG4AudioConfig cfg;
+
if (avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
st->codec->extradata_size * 8, 1) >= 0) {
st->codec->channels = cfg.channels;
diff --git a/chromium/third_party/ffmpeg/libavformat/flvenc.c b/chromium/third_party/ffmpeg/libavformat/flvenc.c
index a1b498d9e1d..c16f8ebb4a7 100644
--- a/chromium/third_party/ffmpeg/libavformat/flvenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/flvenc.c
@@ -233,6 +233,9 @@ static int flv_write_header(AVFormatContext *s)
audio_enc = enc;
if (get_audio_flags(s, enc) < 0)
return AVERROR_INVALIDDATA;
+ if (enc->codec_id == AV_CODEC_ID_PCM_S16BE)
+ av_log(s, AV_LOG_WARNING,
+ "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
break;
case AVMEDIA_TYPE_DATA:
if (enc->codec_id != AV_CODEC_ID_TEXT) {
@@ -539,7 +542,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
if (enc->codec_type == AVMEDIA_TYPE_DATA) {
int data_size;
- int metadata_size_pos = avio_tell(pb);
+ int64_t metadata_size_pos = avio_tell(pb);
avio_w8(pb, AMF_DATA_TYPE_STRING);
put_amf_string(pb, "onTextData");
avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
diff --git a/chromium/third_party/ffmpeg/libavformat/format.c b/chromium/third_party/ffmpeg/libavformat/format.c
index 36c0131c12e..95060f373d7 100644
--- a/chromium/third_party/ffmpeg/libavformat/format.c
+++ b/chromium/third_party/ffmpeg/libavformat/format.c
@@ -33,6 +33,9 @@ static AVInputFormat *first_iformat = NULL;
/** head of registered output format linked list */
static AVOutputFormat *first_oformat = NULL;
+static AVInputFormat **last_iformat = &first_iformat;
+static AVOutputFormat **last_oformat = &first_oformat;
+
AVInputFormat *av_iformat_next(AVInputFormat *f)
{
if (f)
@@ -51,20 +54,22 @@ AVOutputFormat *av_oformat_next(AVOutputFormat *f)
void av_register_input_format(AVInputFormat *format)
{
- AVInputFormat **p = &first_iformat;
+ AVInputFormat **p = last_iformat;
format->next = NULL;
while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
p = &(*p)->next;
+ last_iformat = &format->next;
}
void av_register_output_format(AVOutputFormat *format)
{
- AVOutputFormat **p = &first_oformat;
+ AVOutputFormat **p = last_oformat;
format->next = NULL;
while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
p = &(*p)->next;
+ last_oformat = &format->next;
}
int av_match_ext(const char *filename, const char *extensions)
diff --git a/chromium/third_party/ffmpeg/libavformat/framecrcenc.c b/chromium/third_party/ffmpeg/libavformat/framecrcenc.c
index dbe49b5ba1e..4a96083953f 100644
--- a/chromium/third_party/ffmpeg/libavformat/framecrcenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/framecrcenc.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/adler32.h"
#include "libavutil/avstring.h"
#include "avformat.h"
@@ -29,7 +31,7 @@ static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
uint32_t crc = av_adler32_update(0, pkt->data, pkt->size);
char buf[256];
- snprintf(buf, sizeof(buf), "%d, %10"PRId64", %10"PRId64", %8d, %8d, 0x%08x",
+ snprintf(buf, sizeof(buf), "%d, %10"PRId64", %10"PRId64", %8d, %8d, 0x%08"PRIx32,
pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size, crc);
if (pkt->flags != AV_PKT_FLAG_KEY)
av_strlcatf(buf, sizeof(buf), ", F=0x%0X", pkt->flags);
diff --git a/chromium/third_party/ffmpeg/libavformat/ftp.c b/chromium/third_party/ffmpeg/libavformat/ftp.c
index ed9a3db419b..dae8aa086d2 100644
--- a/chromium/third_party/ffmpeg/libavformat/ftp.c
+++ b/chromium/third_party/ffmpeg/libavformat/ftp.c
@@ -572,13 +572,15 @@ static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
return AVERROR(EINVAL);
}
- if (h->is_streamed)
+ if (h->is_streamed)
return AVERROR(EIO);
- /* XXX: Simulate behaviour of lseek in file protocol, which could be treated as a reference */
- new_pos = FFMAX(0, new_pos);
- fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos;
+ if (new_pos < 0) {
+ av_log(h, AV_LOG_ERROR, "Seeking to nagative position.\n");
+ return AVERROR(EINVAL);
+ }
+ fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos;
if (fake_pos != s->position) {
if ((err = ftp_abort(h)) < 0)
return err;
diff --git a/chromium/third_party/ffmpeg/libavformat/gif.c b/chromium/third_party/ffmpeg/libavformat/gif.c
index e52498d42b4..e8171214400 100644
--- a/chromium/third_party/ffmpeg/libavformat/gif.c
+++ b/chromium/third_party/ffmpeg/libavformat/gif.c
@@ -28,10 +28,19 @@
#include "libavutil/log.h"
#include "libavutil/opt.h"
-static int gif_image_write_header(AVIOContext *pb, int width, int height,
+static int gif_image_write_header(AVFormatContext *s, int width, int height,
int loop_count, uint32_t *palette)
{
+ AVIOContext *pb = s->pb;
+ AVRational sar = s->streams[0]->codec->sample_aspect_ratio;
int i;
+ int64_t aspect = 0;
+
+ if (sar.num > 0 && sar.den > 0) {
+ aspect = sar.num * 64LL / sar.den - 15;
+ if (aspect < 0 || aspect > 255)
+ aspect = 0;
+ }
avio_write(pb, "GIF", 3);
avio_write(pb, "89a", 3);
@@ -41,7 +50,7 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height,
if (palette) {
avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */
avio_w8(pb, 0x1f); /* background color index */
- avio_w8(pb, 0); /* aspect ratio */
+ avio_w8(pb, aspect);
for (i = 0; i < 256; i++) {
const uint32_t v = palette[i] & 0xffffff;
avio_wb24(pb, v);
@@ -49,7 +58,7 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height,
} else {
avio_w8(pb, 0); /* flags */
avio_w8(pb, 0); /* background color index */
- avio_w8(pb, 0); /* aspect ratio */
+ avio_w8(pb, aspect);
}
@@ -79,7 +88,6 @@ typedef struct {
static int gif_write_header(AVFormatContext *s)
{
GIFContext *gif = s->priv_data;
- AVIOContext *pb = s->pb;
AVCodecContext *video_enc;
int width, height;
uint32_t palette[AVPALETTE_COUNT];
@@ -99,9 +107,9 @@ static int gif_write_header(AVFormatContext *s)
avpriv_set_pts_info(s->streams[0], 64, 1, 100);
if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) {
av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8);
- gif_image_write_header(pb, width, height, gif->loop, NULL);
+ gif_image_write_header(s, width, height, gif->loop, NULL);
} else {
- gif_image_write_header(pb, width, height, gif->loop, palette);
+ gif_image_write_header(s, width, height, gif->loop, palette);
}
avio_flush(s->pb);
diff --git a/chromium/third_party/ffmpeg/libavformat/golomb_tab.c b/chromium/third_party/ffmpeg/libavformat/golomb_tab.c
new file mode 100644
index 00000000000..063fae36471
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/golomb_tab.c
@@ -0,0 +1 @@
+#include "libavcodec/golomb.c"
diff --git a/chromium/third_party/ffmpeg/libavformat/gxf.c b/chromium/third_party/ffmpeg/libavformat/gxf.c
index c36479a8213..479a8fb394d 100644
--- a/chromium/third_party/ffmpeg/libavformat/gxf.c
+++ b/chromium/third_party/ffmpeg/libavformat/gxf.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "avformat.h"
@@ -293,7 +295,9 @@ static void gxf_read_index(AVFormatContext *s, int pkt_len) {
}
st = s->streams[0];
if (map_cnt > 1000) {
- av_log(s, AV_LOG_ERROR, "too many index entries %u (%x)\n", map_cnt, map_cnt);
+ av_log(s, AV_LOG_ERROR,
+ "too many index entries %"PRIu32" (%"PRIx32")\n",
+ map_cnt, map_cnt);
map_cnt = 1000;
}
if (pkt_len < 4 * map_cnt) {
diff --git a/chromium/third_party/ffmpeg/libavformat/gxfenc.c b/chromium/third_party/ffmpeg/libavformat/gxfenc.c
index 5fa510057d3..12031f7cd91 100644
--- a/chromium/third_party/ffmpeg/libavformat/gxfenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/gxfenc.c
@@ -949,7 +949,7 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *st = s->streams[pkt->stream_index];
int64_t pos = avio_tell(pb);
int padding = 0;
- int packet_start_offset = avio_tell(pb) / 1024;
+ unsigned packet_start_offset = avio_tell(pb) / 1024;
int ret;
gxf_write_packet_header(pb, PKT_MEDIA);
diff --git a/chromium/third_party/ffmpeg/libavformat/h263dec.c b/chromium/third_party/ffmpeg/libavformat/h263dec.c
index e6e0345b690..145fb859021 100644
--- a/chromium/third_party/ffmpeg/libavformat/h263dec.c
+++ b/chromium/third_party/ffmpeg/libavformat/h263dec.c
@@ -31,24 +31,37 @@ static int h263_probe(AVProbeData *p)
int res_change=0;
int src_fmt, last_src_fmt=-1;
int last_gn=0;
+ int tr, last_tr = -1;
for(i=0; i<p->buf_size; i++){
code = (code<<8) + p->buf[i];
- if ((code & 0xfffffc0000) == 0x800000) {
- src_fmt= (code>>2)&3;
+ if ((code & 0xfffffc000000) == 0x80000000) {
+ tr = (code >> 18) & 0xFF;
+ src_fmt= (code>>10)&7;
if( src_fmt != last_src_fmt
&& last_src_fmt>0 && last_src_fmt<6
&& src_fmt<6)
res_change++;
- if((code&0x300)==0x200 && src_fmt){
+ if (tr == last_tr) {
+ invalid_psc++;
+ continue;
+ }
+
+ if (src_fmt != 7 && !(code&(1<<9)) && (code&(1<<5))) {
+ invalid_psc++;
+ continue;
+ }
+
+ if((code&0x30000)==0x20000 && src_fmt){
valid_psc++;
last_gn=0;
}else
invalid_psc++;
last_src_fmt= src_fmt;
- } else if((code & 0xffff800000) == 0x800000) {
- int gn= (code>>(23-5)) & 0x1F;
+ last_tr = tr;
+ } else if((code & 0xffff80000000) == 0x80000000) {
+ int gn= (code>>(31-5)) & 0x1F;
if(gn<last_gn){
invalid_psc++;
}else
diff --git a/chromium/third_party/ffmpeg/libavformat/hdsenc.c b/chromium/third_party/ffmpeg/libavformat/hdsenc.c
index 08ae5490d24..fb0a94892aa 100644
--- a/chromium/third_party/ffmpeg/libavformat/hdsenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/hdsenc.c
@@ -89,7 +89,7 @@ static int parse_header(OutputStream *os, const uint8_t *buf, int buf_size)
if (size > buf_size)
return AVERROR_INVALIDDATA;
if (type == 8 || type == 9) {
- if (os->nb_extra_packets > FF_ARRAY_ELEMS(os->extra_packets))
+ if (os->nb_extra_packets >= FF_ARRAY_ELEMS(os->extra_packets))
return AVERROR_INVALIDDATA;
os->extra_packet_sizes[os->nb_extra_packets] = size;
os->extra_packets[os->nb_extra_packets] = av_malloc(size);
@@ -204,7 +204,10 @@ static int write_manifest(AVFormatContext *s, int final)
avio_printf(out, "</manifest>\n");
avio_flush(out);
avio_close(out);
- rename(temp_filename, filename);
+ if (rename(temp_filename, filename) == -1) {
+ av_log(s, AV_LOG_ERROR, "failed to rename file %s to %s\n", temp_filename, filename);
+ return AVERROR(errno);
+ }
return 0;
}
@@ -286,7 +289,10 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
update_size(out, afrt_pos);
update_size(out, 0);
avio_close(out);
- rename(temp_filename, filename);
+ if (rename(temp_filename, filename) == -1) {
+ av_log(s, AV_LOG_ERROR, "failed to rename file %s to %s\n", temp_filename, filename);
+ return AVERROR(errno);
+ }
return 0;
}
@@ -323,7 +329,14 @@ static int hds_write_header(AVFormatContext *s)
int ret = 0, i;
AVOutputFormat *oformat;
- mkdir(s->filename, 0777);
+ if (mkdir(s->filename, 0777)) {
+ int is_error = errno != EEXIST;
+ av_log(s, is_error ? AV_LOG_ERROR : AV_LOG_VERBOSE, "Failed to create directory %s\n", s->filename);
+ if (is_error) {
+ ret = AVERROR(errno);
+ goto fail;
+ }
+ }
oformat = av_guess_format("flv", NULL, NULL);
if (!oformat) {
@@ -412,7 +425,9 @@ static int hds_write_header(AVFormatContext *s)
snprintf(os->temp_filename, sizeof(os->temp_filename),
"%s/stream%d_temp", s->filename, i);
- init_file(s, os, 0);
+ ret = init_file(s, os, 0);
+ if (ret < 0)
+ goto fail;
if (!os->has_video && c->min_frag_duration <= 0) {
av_log(s, AV_LOG_WARNING,
@@ -475,7 +490,10 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, int final,
snprintf(target_filename, sizeof(target_filename),
"%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index);
- rename(os->temp_filename, target_filename);
+ if (rename(os->temp_filename, target_filename) == -1) {
+ av_log(s, AV_LOG_ERROR, "failed to rename file %s to %s\n", os->temp_filename, target_filename);
+ return AVERROR(errno);
+ }
add_fragment(os, target_filename, os->frag_start_ts, end_ts - os->frag_start_ts);
if (!final) {
@@ -509,7 +527,7 @@ static int hds_write_packet(AVFormatContext *s, AVPacket *pkt)
HDSContext *c = s->priv_data;
AVStream *st = s->streams[pkt->stream_index];
OutputStream *os = &c->streams[s->streams[pkt->stream_index]->id];
- int64_t end_dts = (os->fragment_index) * c->min_frag_duration;
+ int64_t end_dts = os->fragment_index * (int64_t)c->min_frag_duration;
int ret;
if (st->first_dts == AV_NOPTS_VALUE)
diff --git a/chromium/third_party/ffmpeg/libavformat/hevc.c b/chromium/third_party/ffmpeg/libavformat/hevc.c
new file mode 100644
index 00000000000..96323861532
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/hevc.c
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/get_bits.h"
+#include "libavcodec/golomb.h"
+#include "libavcodec/hevc.h"
+#include "libavutil/intreadwrite.h"
+#include "avc.h"
+#include "avio.h"
+#include "hevc.h"
+
+#define MAX_SPATIAL_SEGMENTATION 4096 // max. value of u(12) field
+
+typedef struct HVCCNALUnitArray {
+ uint8_t array_completeness;
+ uint8_t NAL_unit_type;
+ uint16_t numNalus;
+ uint16_t *nalUnitLength;
+ uint8_t **nalUnit;
+} HVCCNALUnitArray;
+
+typedef struct HEVCDecoderConfigurationRecord {
+ uint8_t configurationVersion;
+ uint8_t general_profile_space;
+ uint8_t general_tier_flag;
+ uint8_t general_profile_idc;
+ uint32_t general_profile_compatibility_flags;
+ uint64_t general_constraint_indicator_flags;
+ uint8_t general_level_idc;
+ uint16_t min_spatial_segmentation_idc;
+ uint8_t parallelismType;
+ uint8_t chromaFormat;
+ uint8_t bitDepthLumaMinus8;
+ uint8_t bitDepthChromaMinus8;
+ uint16_t avgFrameRate;
+ uint8_t constantFrameRate;
+ uint8_t numTemporalLayers;
+ uint8_t temporalIdNested;
+ uint8_t lengthSizeMinusOne;
+ uint8_t numOfArrays;
+ HVCCNALUnitArray *array;
+} HEVCDecoderConfigurationRecord;
+
+typedef struct HVCCProfileTierLevel {
+ uint8_t profile_space;
+ uint8_t tier_flag;
+ uint8_t profile_idc;
+ uint32_t profile_compatibility_flags;
+ uint64_t constraint_indicator_flags;
+ uint8_t level_idc;
+} HVCCProfileTierLevel;
+
+static void hvcc_update_ptl(HEVCDecoderConfigurationRecord *hvcc,
+ HVCCProfileTierLevel *ptl)
+{
+ /*
+ * The value of general_profile_space in all the parameter sets must be
+ * identical.
+ */
+ hvcc->general_profile_space = ptl->profile_space;
+
+ /*
+ * The level indication general_level_idc must indicate a level of
+ * capability equal to or greater than the highest level indicated for the
+ * highest tier in all the parameter sets.
+ */
+ if (hvcc->general_tier_flag < ptl->tier_flag)
+ hvcc->general_level_idc = ptl->level_idc;
+ else
+ hvcc->general_level_idc = FFMAX(hvcc->general_level_idc, ptl->level_idc);
+
+ /*
+ * The tier indication general_tier_flag must indicate a tier equal to or
+ * greater than the highest tier indicated in all the parameter sets.
+ */
+ hvcc->general_tier_flag = FFMAX(hvcc->general_tier_flag, ptl->tier_flag);
+
+ /*
+ * The profile indication general_profile_idc must indicate a profile to
+ * which the stream associated with this configuration record conforms.
+ *
+ * If the sequence parameter sets are marked with different profiles, then
+ * the stream may need examination to determine which profile, if any, the
+ * entire stream conforms to. If the entire stream is not examined, or the
+ * examination reveals that there is no profile to which the entire stream
+ * conforms, then the entire stream must be split into two or more
+ * sub-streams with separate configuration records in which these rules can
+ * be met.
+ *
+ * Note: set the profile to the highest value for the sake of simplicity.
+ */
+ hvcc->general_profile_idc = FFMAX(hvcc->general_profile_idc, ptl->profile_idc);
+
+ /*
+ * Each bit in general_profile_compatibility_flags may only be set if all
+ * the parameter sets set that bit.
+ */
+ hvcc->general_profile_compatibility_flags &= ptl->profile_compatibility_flags;
+
+ /*
+ * Each bit in general_constraint_indicator_flags may only be set if all
+ * the parameter sets set that bit.
+ */
+ hvcc->general_constraint_indicator_flags &= ptl->constraint_indicator_flags;
+}
+
+static void hvcc_parse_ptl(GetBitContext *gb,
+ HEVCDecoderConfigurationRecord *hvcc,
+ unsigned int max_sub_layers_minus1)
+{
+ unsigned int i;
+ HVCCProfileTierLevel general_ptl;
+ uint8_t sub_layer_profile_present_flag[MAX_SUB_LAYERS];
+ uint8_t sub_layer_level_present_flag[MAX_SUB_LAYERS];
+
+ general_ptl.profile_space = get_bits(gb, 2);
+ general_ptl.tier_flag = get_bits1(gb);
+ general_ptl.profile_idc = get_bits(gb, 5);
+ general_ptl.profile_compatibility_flags = get_bits_long(gb, 32);
+ general_ptl.constraint_indicator_flags = get_bits64(gb, 48);
+ general_ptl.level_idc = get_bits(gb, 8);
+ hvcc_update_ptl(hvcc, &general_ptl);
+
+ for (i = 0; i < max_sub_layers_minus1; i++) {
+ sub_layer_profile_present_flag[i] = get_bits1(gb);
+ sub_layer_level_present_flag[i] = get_bits1(gb);
+ }
+
+ if (max_sub_layers_minus1 > 0)
+ for (i = max_sub_layers_minus1; i < 8; i++)
+ skip_bits(gb, 2); // reserved_zero_2bits[i]
+
+ for (i = 0; i < max_sub_layers_minus1; i++) {
+ if (sub_layer_profile_present_flag[i]) {
+ /*
+ * sub_layer_profile_space[i] u(2)
+ * sub_layer_tier_flag[i] u(1)
+ * sub_layer_profile_idc[i] u(5)
+ * sub_layer_profile_compatibility_flag[i][0..31] u(32)
+ * sub_layer_progressive_source_flag[i] u(1)
+ * sub_layer_interlaced_source_flag[i] u(1)
+ * sub_layer_non_packed_constraint_flag[i] u(1)
+ * sub_layer_frame_only_constraint_flag[i] u(1)
+ * sub_layer_reserved_zero_44bits[i] u(44)
+ */
+ skip_bits_long(gb, 32);
+ skip_bits_long(gb, 32);
+ skip_bits (gb, 24);
+ }
+
+ if (sub_layer_level_present_flag[i])
+ skip_bits(gb, 8);
+ }
+}
+
+static void skip_sub_layer_hrd_parameters(GetBitContext *gb,
+ unsigned int cpb_cnt_minus1,
+ uint8_t sub_pic_hrd_params_present_flag)
+{
+ unsigned int i;
+
+ for (i = 0; i <= cpb_cnt_minus1; i++) {
+ get_ue_golomb_long(gb); // bit_rate_value_minus1
+ get_ue_golomb_long(gb); // cpb_size_value_minus1
+
+ if (sub_pic_hrd_params_present_flag) {
+ get_ue_golomb_long(gb); // cpb_size_du_value_minus1
+ get_ue_golomb_long(gb); // bit_rate_du_value_minus1
+ }
+
+ skip_bits1(gb); // cbr_flag
+ }
+}
+
+static void skip_hrd_parameters(GetBitContext *gb, uint8_t cprms_present_flag,
+ unsigned int max_sub_layers_minus1)
+{
+ unsigned int i;
+ uint8_t sub_pic_hrd_params_present_flag = 0;
+ uint8_t nal_hrd_parameters_present_flag = 0;
+ uint8_t vcl_hrd_parameters_present_flag = 0;
+
+ if (cprms_present_flag) {
+ nal_hrd_parameters_present_flag = get_bits1(gb);
+ vcl_hrd_parameters_present_flag = get_bits1(gb);
+
+ if (nal_hrd_parameters_present_flag ||
+ vcl_hrd_parameters_present_flag) {
+ sub_pic_hrd_params_present_flag = get_bits1(gb);
+
+ if (sub_pic_hrd_params_present_flag)
+ /*
+ * tick_divisor_minus2 u(8)
+ * du_cpb_removal_delay_increment_length_minus1 u(5)
+ * sub_pic_cpb_params_in_pic_timing_sei_flag u(1)
+ * dpb_output_delay_du_length_minus1 u(5)
+ */
+ skip_bits(gb, 19);
+
+ /*
+ * bit_rate_scale u(4)
+ * cpb_size_scale u(4)
+ */
+ skip_bits(gb, 8);
+
+ if (sub_pic_hrd_params_present_flag)
+ skip_bits(gb, 4); // cpb_size_du_scale
+
+ /*
+ * initial_cpb_removal_delay_length_minus1 u(5)
+ * au_cpb_removal_delay_length_minus1 u(5)
+ * dpb_output_delay_length_minus1 u(5)
+ */
+ skip_bits(gb, 15);
+ }
+ }
+
+ for (i = 0; i <= max_sub_layers_minus1; i++) {
+ unsigned int cpb_cnt_minus1 = 0;
+ uint8_t low_delay_hrd_flag = 0;
+ uint8_t fixed_pic_rate_within_cvs_flag = 0;
+ uint8_t fixed_pic_rate_general_flag = get_bits1(gb);
+
+ if (!fixed_pic_rate_general_flag)
+ fixed_pic_rate_within_cvs_flag = get_bits1(gb);
+
+ if (fixed_pic_rate_within_cvs_flag)
+ get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1
+ else
+ low_delay_hrd_flag = get_bits1(gb);
+
+ if (!low_delay_hrd_flag)
+ cpb_cnt_minus1 = get_ue_golomb_long(gb);
+
+ if (nal_hrd_parameters_present_flag)
+ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
+ sub_pic_hrd_params_present_flag);
+
+ if (vcl_hrd_parameters_present_flag)
+ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
+ sub_pic_hrd_params_present_flag);
+ }
+}
+
+static void skip_timing_info(GetBitContext *gb)
+{
+ skip_bits_long(gb, 32); // num_units_in_tick
+ skip_bits_long(gb, 32); // time_scale
+
+ if (get_bits1(gb)) // poc_proportional_to_timing_flag
+ get_ue_golomb_long(gb); // num_ticks_poc_diff_one_minus1
+}
+
+static void hvcc_parse_vui(GetBitContext *gb,
+ HEVCDecoderConfigurationRecord *hvcc,
+ unsigned int max_sub_layers_minus1)
+{
+ unsigned int min_spatial_segmentation_idc;
+
+ if (get_bits1(gb)) // aspect_ratio_info_present_flag
+ if (get_bits(gb, 8) == 255) // aspect_ratio_idc
+ skip_bits_long(gb, 32); // sar_width u(16), sar_height u(16)
+
+ if (get_bits1(gb)) // overscan_info_present_flag
+ skip_bits1(gb); // overscan_appropriate_flag
+
+ if (get_bits1(gb)) { // video_signal_type_present_flag
+ skip_bits(gb, 4); // video_format u(3), video_full_range_flag u(1)
+
+ if (get_bits1(gb)) // colour_description_present_flag
+ /*
+ * colour_primaries u(8)
+ * transfer_characteristics u(8)
+ * matrix_coeffs u(8)
+ */
+ skip_bits(gb, 24);
+ }
+
+ if (get_bits1(gb)) { // chroma_loc_info_present_flag
+ get_ue_golomb_long(gb); // chroma_sample_loc_type_top_field
+ get_ue_golomb_long(gb); // chroma_sample_loc_type_bottom_field
+ }
+
+ /*
+ * neutral_chroma_indication_flag u(1)
+ * field_seq_flag u(1)
+ * frame_field_info_present_flag u(1)
+ */
+ skip_bits(gb, 3);
+
+ if (get_bits1(gb)) { // default_display_window_flag
+ get_ue_golomb_long(gb); // def_disp_win_left_offset
+ get_ue_golomb_long(gb); // def_disp_win_right_offset
+ get_ue_golomb_long(gb); // def_disp_win_top_offset
+ get_ue_golomb_long(gb); // def_disp_win_bottom_offset
+ }
+
+ if (get_bits1(gb)) { // vui_timing_info_present_flag
+ skip_timing_info(gb);
+
+ if (get_bits1(gb)) // vui_hrd_parameters_present_flag
+ skip_hrd_parameters(gb, 1, max_sub_layers_minus1);
+ }
+
+ if (get_bits1(gb)) { // bitstream_restriction_flag
+ /*
+ * tiles_fixed_structure_flag u(1)
+ * motion_vectors_over_pic_boundaries_flag u(1)
+ * restricted_ref_pic_lists_flag u(1)
+ */
+ skip_bits(gb, 3);
+
+ min_spatial_segmentation_idc = get_ue_golomb_long(gb);
+
+ /*
+ * unsigned int(12) min_spatial_segmentation_idc;
+ *
+ * The min_spatial_segmentation_idc indication must indicate a level of
+ * spatial segmentation equal to or less than the lowest level of
+ * spatial segmentation indicated in all the parameter sets.
+ */
+ hvcc->min_spatial_segmentation_idc = FFMIN(hvcc->min_spatial_segmentation_idc,
+ min_spatial_segmentation_idc);
+
+ get_ue_golomb_long(gb); // max_bytes_per_pic_denom
+ get_ue_golomb_long(gb); // max_bits_per_min_cu_denom
+ get_ue_golomb_long(gb); // log2_max_mv_length_horizontal
+ get_ue_golomb_long(gb); // log2_max_mv_length_vertical
+ }
+}
+
+static void skip_sub_layer_ordering_info(GetBitContext *gb)
+{
+ get_ue_golomb_long(gb); // max_dec_pic_buffering_minus1
+ get_ue_golomb_long(gb); // max_num_reorder_pics
+ get_ue_golomb_long(gb); // max_latency_increase_plus1
+}
+
+static int hvcc_parse_vps(GetBitContext *gb,
+ HEVCDecoderConfigurationRecord *hvcc)
+{
+ unsigned int vps_max_sub_layers_minus1;
+
+ /*
+ * vps_video_parameter_set_id u(4)
+ * vps_reserved_three_2bits u(2)
+ * vps_max_layers_minus1 u(6)
+ */
+ skip_bits(gb, 12);
+
+ vps_max_sub_layers_minus1 = get_bits(gb, 3);
+
+ /*
+ * numTemporalLayers greater than 1 indicates that the stream to which this
+ * configuration record applies is temporally scalable and the contained
+ * number of temporal layers (also referred to as temporal sub-layer or
+ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
+ * indicates that the stream is not temporally scalable. Value 0 indicates
+ * that it is unknown whether the stream is temporally scalable.
+ */
+ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
+ vps_max_sub_layers_minus1 + 1);
+
+ /*
+ * vps_temporal_id_nesting_flag u(1)
+ * vps_reserved_0xffff_16bits u(16)
+ */
+ skip_bits(gb, 17);
+
+ hvcc_parse_ptl(gb, hvcc, vps_max_sub_layers_minus1);
+
+ /* nothing useful for hvcC past this point */
+ return 0;
+}
+
+static void skip_scaling_list_data(GetBitContext *gb)
+{
+ int i, j, k, num_coeffs;
+
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < (i == 3 ? 2 : 6); j++)
+ if (!get_bits1(gb)) // scaling_list_pred_mode_flag[i][j]
+ get_ue_golomb_long(gb); // scaling_list_pred_matrix_id_delta[i][j]
+ else {
+ num_coeffs = FFMIN(64, 1 << (4 + (i << 1)));
+
+ if (i > 1)
+ get_se_golomb_long(gb); // scaling_list_dc_coef_minus8[i-2][j]
+
+ for (k = 0; k < num_coeffs; k++)
+ get_se_golomb_long(gb); // scaling_list_delta_coef
+ }
+}
+
+static int parse_rps(GetBitContext *gb, unsigned int rps_idx,
+ unsigned int num_rps,
+ unsigned int num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT])
+{
+ unsigned int i;
+
+ if (rps_idx && get_bits1(gb)) { // inter_ref_pic_set_prediction_flag
+ /* this should only happen for slice headers, and this isn't one */
+ if (rps_idx >= num_rps)
+ return AVERROR_INVALIDDATA;
+
+ skip_bits1 (gb); // delta_rps_sign
+ get_ue_golomb_long(gb); // abs_delta_rps_minus1
+
+ num_delta_pocs[rps_idx] = 0;
+
+ /*
+ * From libavcodec/hevc_ps.c:
+ *
+ * if (is_slice_header) {
+ * //foo
+ * } else
+ * rps_ridx = &sps->st_rps[rps - sps->st_rps - 1];
+ *
+ * where:
+ * rps: &sps->st_rps[rps_idx]
+ * sps->st_rps: &sps->st_rps[0]
+ * is_slice_header: rps_idx == num_rps
+ *
+ * thus:
+ * if (num_rps != rps_idx)
+ * rps_ridx = &sps->st_rps[rps_idx - 1];
+ *
+ * NumDeltaPocs[RefRpsIdx]: num_delta_pocs[rps_idx - 1]
+ */
+ for (i = 0; i < num_delta_pocs[rps_idx - 1]; i++) {
+ uint8_t use_delta_flag = 0;
+ uint8_t used_by_curr_pic_flag = get_bits1(gb);
+ if (!used_by_curr_pic_flag)
+ use_delta_flag = get_bits1(gb);
+
+ if (used_by_curr_pic_flag || use_delta_flag)
+ num_delta_pocs[rps_idx]++;
+ }
+ } else {
+ unsigned int num_negative_pics = get_ue_golomb_long(gb);
+ unsigned int num_positive_pics = get_ue_golomb_long(gb);
+
+ num_delta_pocs[rps_idx] = num_negative_pics + num_positive_pics;
+
+ for (i = 0; i < num_negative_pics; i++) {
+ get_ue_golomb_long(gb); // delta_poc_s0_minus1[rps_idx]
+ skip_bits1 (gb); // used_by_curr_pic_s0_flag[rps_idx]
+ }
+
+ for (i = 0; i < num_positive_pics; i++) {
+ get_ue_golomb_long(gb); // delta_poc_s1_minus1[rps_idx]
+ skip_bits1 (gb); // used_by_curr_pic_s1_flag[rps_idx]
+ }
+ }
+
+ return 0;
+}
+
+static int hvcc_parse_sps(GetBitContext *gb,
+ HEVCDecoderConfigurationRecord *hvcc)
+{
+ unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4;
+ unsigned int num_short_term_ref_pic_sets, num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT];
+
+ skip_bits(gb, 4); // sps_video_parameter_set_id
+
+ sps_max_sub_layers_minus1 = get_bits (gb, 3);
+
+ /*
+ * numTemporalLayers greater than 1 indicates that the stream to which this
+ * configuration record applies is temporally scalable and the contained
+ * number of temporal layers (also referred to as temporal sub-layer or
+ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
+ * indicates that the stream is not temporally scalable. Value 0 indicates
+ * that it is unknown whether the stream is temporally scalable.
+ */
+ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
+ sps_max_sub_layers_minus1 + 1);
+
+ hvcc->temporalIdNested = get_bits1(gb);
+
+ hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1);
+
+ get_ue_golomb_long(gb); // sps_seq_parameter_set_id
+
+ hvcc->chromaFormat = get_ue_golomb_long(gb);
+
+ if (hvcc->chromaFormat == 3)
+ skip_bits1(gb); // separate_colour_plane_flag
+
+ get_ue_golomb_long(gb); // pic_width_in_luma_samples
+ get_ue_golomb_long(gb); // pic_height_in_luma_samples
+
+ if (get_bits1(gb)) { // conformance_window_flag
+ get_ue_golomb_long(gb); // conf_win_left_offset
+ get_ue_golomb_long(gb); // conf_win_right_offset
+ get_ue_golomb_long(gb); // conf_win_top_offset
+ get_ue_golomb_long(gb); // conf_win_bottom_offset
+ }
+
+ hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb);
+ hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb);
+ log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb);
+
+ /* sps_sub_layer_ordering_info_present_flag */
+ i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1;
+ for (; i <= sps_max_sub_layers_minus1; i++)
+ skip_sub_layer_ordering_info(gb);
+
+ get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3
+ get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size
+ get_ue_golomb_long(gb); // log2_min_transform_block_size_minus2
+ get_ue_golomb_long(gb); // log2_diff_max_min_transform_block_size
+ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter
+ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra
+
+ if (get_bits1(gb) && // scaling_list_enabled_flag
+ get_bits1(gb)) // sps_scaling_list_data_present_flag
+ skip_scaling_list_data(gb);
+
+ skip_bits1(gb); // amp_enabled_flag
+ skip_bits1(gb); // sample_adaptive_offset_enabled_flag
+
+ if (get_bits1(gb)) { // pcm_enabled_flag
+ skip_bits (gb, 4); // pcm_sample_bit_depth_luma_minus1
+ skip_bits (gb, 4); // pcm_sample_bit_depth_chroma_minus1
+ get_ue_golomb_long(gb); // log2_min_pcm_luma_coding_block_size_minus3
+ get_ue_golomb_long(gb); // log2_diff_max_min_pcm_luma_coding_block_size
+ skip_bits1 (gb); // pcm_loop_filter_disabled_flag
+ }
+
+ num_short_term_ref_pic_sets = get_ue_golomb_long(gb);
+ if (num_short_term_ref_pic_sets > MAX_SHORT_TERM_RPS_COUNT)
+ return AVERROR_INVALIDDATA;
+
+ for (i = 0; i < num_short_term_ref_pic_sets; i++) {
+ int ret = parse_rps(gb, i, num_short_term_ref_pic_sets, num_delta_pocs);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (get_bits1(gb)) { // long_term_ref_pics_present_flag
+ for (i = 0; i < get_ue_golomb_long(gb); i++) { // num_long_term_ref_pics_sps
+ int len = FFMIN(log2_max_pic_order_cnt_lsb_minus4 + 4, 16);
+ skip_bits (gb, len); // lt_ref_pic_poc_lsb_sps[i]
+ skip_bits1(gb); // used_by_curr_pic_lt_sps_flag[i]
+ }
+ }
+
+ skip_bits1(gb); // sps_temporal_mvp_enabled_flag
+ skip_bits1(gb); // strong_intra_smoothing_enabled_flag
+
+ if (get_bits1(gb)) // vui_parameters_present_flag
+ hvcc_parse_vui(gb, hvcc, sps_max_sub_layers_minus1);
+
+ /* nothing useful for hvcC past this point */
+ return 0;
+}
+
+static int hvcc_parse_pps(GetBitContext *gb,
+ HEVCDecoderConfigurationRecord *hvcc)
+{
+ uint8_t tiles_enabled_flag, entropy_coding_sync_enabled_flag;
+
+ get_ue_golomb_long(gb); // pps_pic_parameter_set_id
+ get_ue_golomb_long(gb); // pps_seq_parameter_set_id
+
+ /*
+ * dependent_slice_segments_enabled_flag u(1)
+ * output_flag_present_flag u(1)
+ * num_extra_slice_header_bits u(3)
+ * sign_data_hiding_enabled_flag u(1)
+ * cabac_init_present_flag u(1)
+ */
+ skip_bits(gb, 7);
+
+ get_ue_golomb_long(gb); // num_ref_idx_l0_default_active_minus1
+ get_ue_golomb_long(gb); // num_ref_idx_l1_default_active_minus1
+ get_se_golomb_long(gb); // init_qp_minus26
+
+ /*
+ * constrained_intra_pred_flag u(1)
+ * transform_skip_enabled_flag u(1)
+ */
+ skip_bits(gb, 2);
+
+ if (get_bits1(gb)) // cu_qp_delta_enabled_flag
+ get_ue_golomb_long(gb); // diff_cu_qp_delta_depth
+
+ get_se_golomb_long(gb); // pps_cb_qp_offset
+ get_se_golomb_long(gb); // pps_cr_qp_offset
+
+ /*
+ * weighted_pred_flag u(1)
+ * weighted_bipred_flag u(1)
+ * transquant_bypass_enabled_flag u(1)
+ */
+ skip_bits(gb, 3);
+
+ tiles_enabled_flag = get_bits1(gb);
+ entropy_coding_sync_enabled_flag = get_bits1(gb);
+
+ if (entropy_coding_sync_enabled_flag && tiles_enabled_flag)
+ hvcc->parallelismType = 0; // mixed-type parallel decoding
+ else if (entropy_coding_sync_enabled_flag)
+ hvcc->parallelismType = 3; // wavefront-based parallel decoding
+ else if (tiles_enabled_flag)
+ hvcc->parallelismType = 2; // tile-based parallel decoding
+ else
+ hvcc->parallelismType = 1; // slice-based parallel decoding
+
+ /* nothing useful for hvcC past this point */
+ return 0;
+}
+
+static uint8_t *nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len,
+ uint32_t *dst_len)
+{
+ uint8_t *dst;
+ uint32_t i, len;
+
+ dst = av_malloc(src_len);
+ if (!dst)
+ return NULL;
+
+ /* NAL unit header (2 bytes) */
+ i = len = 0;
+ while (i < 2 && i < src_len)
+ dst[len++] = src[i++];
+
+ while (i + 2 < src_len)
+ if (!src[i] && !src[i + 1] && src[i + 2] == 3) {
+ dst[len++] = src[i++];
+ dst[len++] = src[i++];
+ i++; // remove emulation_prevention_three_byte
+ } else
+ dst[len++] = src[i++];
+
+ while (i < src_len)
+ dst[len++] = src[i++];
+
+ *dst_len = len;
+ return dst;
+}
+
+
+
+static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type)
+{
+ skip_bits1(gb); // forbidden_zero_bit
+
+ *nal_type = get_bits(gb, 6);
+
+ /*
+ * nuh_layer_id u(6)
+ * nuh_temporal_id_plus1 u(3)
+ */
+ skip_bits(gb, 9);
+}
+
+static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
+ uint8_t nal_type, int ps_array_completeness,
+ HEVCDecoderConfigurationRecord *hvcc)
+{
+ int ret;
+ uint8_t index;
+ uint16_t numNalus;
+ HVCCNALUnitArray *array;
+
+ for (index = 0; index < hvcc->numOfArrays; index++)
+ if (hvcc->array[index].NAL_unit_type == nal_type)
+ break;
+
+ if (index >= hvcc->numOfArrays) {
+ uint8_t i;
+
+ ret = av_reallocp_array(&hvcc->array, index + 1, sizeof(HVCCNALUnitArray));
+ if (ret < 0)
+ return ret;
+
+ for (i = hvcc->numOfArrays; i <= index; i++)
+ memset(&hvcc->array[i], 0, sizeof(HVCCNALUnitArray));
+ hvcc->numOfArrays = index + 1;
+ }
+
+ array = &hvcc->array[index];
+ numNalus = array->numNalus;
+
+ ret = av_reallocp_array(&array->nalUnit, numNalus + 1, sizeof(uint8_t*));
+ if (ret < 0)
+ return ret;
+
+ ret = av_reallocp_array(&array->nalUnitLength, numNalus + 1, sizeof(uint16_t));
+ if (ret < 0)
+ return ret;
+
+ array->nalUnit [numNalus] = nal_buf;
+ array->nalUnitLength[numNalus] = nal_size;
+ array->NAL_unit_type = nal_type;
+ array->numNalus++;
+
+ /*
+ * When the sample entry name is ‘hvc1’, the default and mandatory value of
+ * array_completeness is 1 for arrays of all types of parameter sets, and 0
+ * for all other arrays. When the sample entry name is ‘hev1’, the default
+ * value of array_completeness is 0 for all arrays.
+ */
+ if (nal_type == NAL_VPS || nal_type == NAL_SPS || nal_type == NAL_PPS)
+ array->array_completeness = ps_array_completeness;
+
+ return 0;
+}
+
+static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
+ int ps_array_completeness,
+ HEVCDecoderConfigurationRecord *hvcc)
+{
+ int ret = 0;
+ GetBitContext gbc;
+ uint8_t nal_type;
+ uint8_t *rbsp_buf;
+ uint32_t rbsp_size;
+
+ rbsp_buf = nal_unit_extract_rbsp(nal_buf, nal_size, &rbsp_size);
+ if (!rbsp_buf) {
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
+
+ ret = init_get_bits8(&gbc, rbsp_buf, rbsp_size);
+ if (ret < 0)
+ goto end;
+
+ nal_unit_parse_header(&gbc, &nal_type);
+
+ /*
+ * Note: only 'declarative' SEI messages are allowed in
+ * hvcC. Perhaps the SEI playload type should be checked
+ * and non-declarative SEI messages discarded?
+ */
+ switch (nal_type) {
+ case NAL_VPS:
+ case NAL_SPS:
+ case NAL_PPS:
+ case NAL_SEI_PREFIX:
+ case NAL_SEI_SUFFIX:
+ ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
+ ps_array_completeness, hvcc);
+ if (ret < 0)
+ goto end;
+ else if (nal_type == NAL_VPS)
+ ret = hvcc_parse_vps(&gbc, hvcc);
+ else if (nal_type == NAL_SPS)
+ ret = hvcc_parse_sps(&gbc, hvcc);
+ else if (nal_type == NAL_PPS)
+ ret = hvcc_parse_pps(&gbc, hvcc);
+ if (ret < 0)
+ goto end;
+ break;
+ default:
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+
+end:
+ av_free(rbsp_buf);
+ return ret;
+}
+
+static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc)
+{
+ memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));
+ hvcc->configurationVersion = 1;
+ hvcc->lengthSizeMinusOne = 3; // 4 bytes
+
+ /*
+ * The following fields have all their valid bits set by default,
+ * the ProfileTierLevel parsing code will unset them when needed.
+ */
+ hvcc->general_profile_compatibility_flags = 0xffffffff;
+ hvcc->general_constraint_indicator_flags = 0xffffffffffff;
+
+ /*
+ * Initialize this field with an invalid value which can be used to detect
+ * whether we didn't see any VUI (in wich case it should be reset to zero).
+ */
+ hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;
+}
+
+static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc)
+{
+ uint8_t i;
+
+ for (i = 0; i < hvcc->numOfArrays; i++) {
+ hvcc->array[i].numNalus = 0;
+ av_freep(&hvcc->array[i].nalUnit);
+ av_freep(&hvcc->array[i].nalUnitLength);
+ }
+
+ hvcc->numOfArrays = 0;
+ av_freep(&hvcc->array);
+}
+
+static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
+{
+ uint8_t i;
+ uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
+
+ /*
+ * We only support writing HEVCDecoderConfigurationRecord version 1.
+ */
+ hvcc->configurationVersion = 1;
+
+ /*
+ * If min_spatial_segmentation_idc is invalid, reset to 0 (unspecified).
+ */
+ if (hvcc->min_spatial_segmentation_idc > MAX_SPATIAL_SEGMENTATION)
+ hvcc->min_spatial_segmentation_idc = 0;
+
+ /*
+ * parallelismType indicates the type of parallelism that is used to meet
+ * the restrictions imposed by min_spatial_segmentation_idc when the value
+ * of min_spatial_segmentation_idc is greater than 0.
+ */
+ if (!hvcc->min_spatial_segmentation_idc)
+ hvcc->parallelismType = 0;
+
+ /*
+ * It's unclear how to properly compute these fields, so
+ * let's always set them to values meaning 'unspecified'.
+ */
+ hvcc->avgFrameRate = 0;
+ hvcc->constantFrameRate = 0;
+
+ av_dlog(NULL, "configurationVersion: %"PRIu8"\n",
+ hvcc->configurationVersion);
+ av_dlog(NULL, "general_profile_space: %"PRIu8"\n",
+ hvcc->general_profile_space);
+ av_dlog(NULL, "general_tier_flag: %"PRIu8"\n",
+ hvcc->general_tier_flag);
+ av_dlog(NULL, "general_profile_idc: %"PRIu8"\n",
+ hvcc->general_profile_idc);
+ av_dlog(NULL, "general_profile_compatibility_flags: 0x%08"PRIx32"\n",
+ hvcc->general_profile_compatibility_flags);
+ av_dlog(NULL, "general_constraint_indicator_flags: 0x%012"PRIx64"\n",
+ hvcc->general_constraint_indicator_flags);
+ av_dlog(NULL, "general_level_idc: %"PRIu8"\n",
+ hvcc->general_level_idc);
+ av_dlog(NULL, "min_spatial_segmentation_idc: %"PRIu16"\n",
+ hvcc->min_spatial_segmentation_idc);
+ av_dlog(NULL, "parallelismType: %"PRIu8"\n",
+ hvcc->parallelismType);
+ av_dlog(NULL, "chromaFormat: %"PRIu8"\n",
+ hvcc->chromaFormat);
+ av_dlog(NULL, "bitDepthLumaMinus8: %"PRIu8"\n",
+ hvcc->bitDepthLumaMinus8);
+ av_dlog(NULL, "bitDepthChromaMinus8: %"PRIu8"\n",
+ hvcc->bitDepthChromaMinus8);
+ av_dlog(NULL, "avgFrameRate: %"PRIu16"\n",
+ hvcc->avgFrameRate);
+ av_dlog(NULL, "constantFrameRate: %"PRIu8"\n",
+ hvcc->constantFrameRate);
+ av_dlog(NULL, "numTemporalLayers: %"PRIu8"\n",
+ hvcc->numTemporalLayers);
+ av_dlog(NULL, "temporalIdNested: %"PRIu8"\n",
+ hvcc->temporalIdNested);
+ av_dlog(NULL, "lengthSizeMinusOne: %"PRIu8"\n",
+ hvcc->lengthSizeMinusOne);
+ av_dlog(NULL, "numOfArrays: %"PRIu8"\n",
+ hvcc->numOfArrays);
+ for (i = 0; i < hvcc->numOfArrays; i++) {
+ av_dlog(NULL, "array_completeness[%"PRIu8"]: %"PRIu8"\n",
+ i, hvcc->array[i].array_completeness);
+ av_dlog(NULL, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n",
+ i, hvcc->array[i].NAL_unit_type);
+ av_dlog(NULL, "numNalus[%"PRIu8"]: %"PRIu16"\n",
+ i, hvcc->array[i].numNalus);
+ for (j = 0; j < hvcc->array[i].numNalus; j++)
+ av_dlog(NULL,
+ "nalUnitLength[%"PRIu8"][%"PRIu16"]: %"PRIu16"\n",
+ i, j, hvcc->array[i].nalUnitLength[j]);
+ }
+
+ /*
+ * We need at least one of each: VPS, SPS and PPS.
+ */
+ for (i = 0; i < hvcc->numOfArrays; i++)
+ switch (hvcc->array[i].NAL_unit_type) {
+ case NAL_VPS:
+ vps_count += hvcc->array[i].numNalus;
+ break;
+ case NAL_SPS:
+ sps_count += hvcc->array[i].numNalus;
+ break;
+ case NAL_PPS:
+ pps_count += hvcc->array[i].numNalus;
+ break;
+ default:
+ break;
+ }
+ if (!vps_count || vps_count > MAX_VPS_COUNT ||
+ !sps_count || sps_count > MAX_SPS_COUNT ||
+ !pps_count || pps_count > MAX_PPS_COUNT)
+ return AVERROR_INVALIDDATA;
+
+ /* unsigned int(8) configurationVersion = 1; */
+ avio_w8(pb, hvcc->configurationVersion);
+
+ /*
+ * unsigned int(2) general_profile_space;
+ * unsigned int(1) general_tier_flag;
+ * unsigned int(5) general_profile_idc;
+ */
+ avio_w8(pb, hvcc->general_profile_space << 6 |
+ hvcc->general_tier_flag << 5 |
+ hvcc->general_profile_idc);
+
+ /* unsigned int(32) general_profile_compatibility_flags; */
+ avio_wb32(pb, hvcc->general_profile_compatibility_flags);
+
+ /* unsigned int(48) general_constraint_indicator_flags; */
+ avio_wb32(pb, hvcc->general_constraint_indicator_flags >> 16);
+ avio_wb16(pb, hvcc->general_constraint_indicator_flags);
+
+ /* unsigned int(8) general_level_idc; */
+ avio_w8(pb, hvcc->general_level_idc);
+
+ /*
+ * bit(4) reserved = ‘1111’b;
+ * unsigned int(12) min_spatial_segmentation_idc;
+ */
+ avio_wb16(pb, hvcc->min_spatial_segmentation_idc | 0xf000);
+
+ /*
+ * bit(6) reserved = ‘111111’b;
+ * unsigned int(2) parallelismType;
+ */
+ avio_w8(pb, hvcc->parallelismType | 0xfc);
+
+ /*
+ * bit(6) reserved = ‘111111’b;
+ * unsigned int(2) chromaFormat;
+ */
+ avio_w8(pb, hvcc->chromaFormat | 0xfc);
+
+ /*
+ * bit(5) reserved = ‘11111’b;
+ * unsigned int(3) bitDepthLumaMinus8;
+ */
+ avio_w8(pb, hvcc->bitDepthLumaMinus8 | 0xf8);
+
+ /*
+ * bit(5) reserved = ‘11111’b;
+ * unsigned int(3) bitDepthChromaMinus8;
+ */
+ avio_w8(pb, hvcc->bitDepthChromaMinus8 | 0xf8);
+
+ /* bit(16) avgFrameRate; */
+ avio_wb16(pb, hvcc->avgFrameRate);
+
+ /*
+ * bit(2) constantFrameRate;
+ * bit(3) numTemporalLayers;
+ * bit(1) temporalIdNested;
+ * unsigned int(2) lengthSizeMinusOne;
+ */
+ avio_w8(pb, hvcc->constantFrameRate << 6 |
+ hvcc->numTemporalLayers << 3 |
+ hvcc->temporalIdNested << 2 |
+ hvcc->lengthSizeMinusOne);
+
+ /* unsigned int(8) numOfArrays; */
+ avio_w8(pb, hvcc->numOfArrays);
+
+ for (i = 0; i < hvcc->numOfArrays; i++) {
+ /*
+ * bit(1) array_completeness;
+ * unsigned int(1) reserved = 0;
+ * unsigned int(6) NAL_unit_type;
+ */
+ avio_w8(pb, hvcc->array[i].array_completeness << 7 |
+ hvcc->array[i].NAL_unit_type & 0x3f);
+
+ /* unsigned int(16) numNalus; */
+ avio_wb16(pb, hvcc->array[i].numNalus);
+
+ for (j = 0; j < hvcc->array[i].numNalus; j++) {
+ /* unsigned int(16) nalUnitLength; */
+ avio_wb16(pb, hvcc->array[i].nalUnitLength[j]);
+
+ /* bit(8*nalUnitLength) nalUnit; */
+ avio_write(pb, hvcc->array[i].nalUnit[j],
+ hvcc->array[i].nalUnitLength[j]);
+ }
+ }
+
+ return 0;
+}
+
+int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
+ int size, int filter_ps, int *ps_count)
+{
+ int num_ps = 0, ret = 0;
+ uint8_t *buf, *end, *start = NULL;
+
+ if (!filter_ps) {
+ ret = ff_avc_parse_nal_units(pb, buf_in, size);
+ goto end;
+ }
+
+ ret = ff_avc_parse_nal_units_buf(buf_in, &start, &size);
+ if (ret < 0)
+ goto end;
+
+ ret = 0;
+ buf = start;
+ end = start + size;
+
+ while (end - buf > 4) {
+ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
+ uint8_t type = (buf[4] >> 1) & 0x3f;
+
+ buf += 4;
+
+ switch (type) {
+ case NAL_VPS:
+ case NAL_SPS:
+ case NAL_PPS:
+ num_ps++;
+ break;
+ default:
+ ret += 4 + len;
+ avio_wb32(pb, len);
+ avio_write(pb, buf, len);
+ break;
+ }
+
+ buf += len;
+ }
+
+end:
+ av_free(start);
+ if (ps_count)
+ *ps_count = num_ps;
+ return ret;
+}
+
+int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
+ int *size, int filter_ps, int *ps_count)
+{
+ AVIOContext *pb;
+ int ret;
+
+ ret = avio_open_dyn_buf(&pb);
+ if (ret < 0)
+ return ret;
+
+ ret = ff_hevc_annexb2mp4(pb, buf_in, *size, filter_ps, ps_count);
+ *size = avio_close_dyn_buf(pb, buf_out);
+
+ return ret;
+}
+
+int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
+ int size, int ps_array_completeness)
+{
+ int ret = 0;
+ uint8_t *buf, *end, *start = NULL;
+ HEVCDecoderConfigurationRecord hvcc;
+
+ hvcc_init(&hvcc);
+
+ if (size < 6) {
+ /* We can't write a valid hvcC from the provided data */
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ } else if (*data == 1) {
+ /* Data is already hvcC-formatted */
+ avio_write(pb, data, size);
+ goto end;
+ } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) {
+ /* Not a valid Annex B start code prefix */
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+
+ ret = ff_avc_parse_nal_units_buf(data, &start, &size);
+ if (ret < 0)
+ goto end;
+
+ buf = start;
+ end = start + size;
+
+ while (end - buf > 4) {
+ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
+ uint8_t type = (buf[4] >> 1) & 0x3f;
+
+ buf += 4;
+
+ switch (type) {
+ case NAL_VPS:
+ case NAL_SPS:
+ case NAL_PPS:
+ case NAL_SEI_PREFIX:
+ case NAL_SEI_SUFFIX:
+ ret = hvcc_add_nal_unit(buf, len, ps_array_completeness, &hvcc);
+ if (ret < 0)
+ goto end;
+ break;
+ default:
+ break;
+ }
+
+ buf += len;
+ }
+
+ ret = hvcc_write(pb, &hvcc);
+
+end:
+ hvcc_close(&hvcc);
+ av_free(start);
+ return ret;
+}
diff --git a/chromium/third_party/ffmpeg/libavformat/hevc.h b/chromium/third_party/ffmpeg/libavformat/hevc.h
new file mode 100644
index 00000000000..796eaf40b16
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/hevc.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * internal header for HEVC (de)muxer utilities
+ */
+
+#ifndef AVFORMAT_HEVC_H
+#define AVFORMAT_HEVC_H
+
+#include <stdint.h>
+#include "avio.h"
+
+/**
+ * Writes Annex B formatted HEVC NAL units to the provided AVIOContext.
+ *
+ * The NAL units are converted to an MP4-compatible format (start code prefixes
+ * are replaced by 4-byte size fields, as per ISO/IEC 14496-15).
+ *
+ * If filter_ps is non-zero, any HEVC parameter sets found in the input will be
+ * discarded, and *ps_count will be set to the number of discarded PS NAL units.
+ *
+ * @param pb address of the AVIOContext where the data shall be written
+ * @param buf_in address of the buffer holding the input data
+ * @param size size (in bytes) of the input buffer
+ * @param filter_ps whether to write parameter set NAL units to the output (0)
+ * or to discard them (non-zero)
+ * @param ps_count address of the variable where the number of discarded
+ * parameter set NAL units shall be written, may be NULL
+ * @return the amount (in bytes) of data written in case of success, a negative
+ * value corresponding to an AVERROR code in case of failure
+ */
+int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
+ int size, int filter_ps, int *ps_count);
+
+/**
+ * Writes Annex B formatted HEVC NAL units to a data buffer.
+ *
+ * The NAL units are converted to an MP4-compatible format (start code prefixes
+ * are replaced by 4-byte size fields, as per ISO/IEC 14496-15).
+ *
+ * If filter_ps is non-zero, any HEVC parameter sets found in the input will be
+ * discarded, and *ps_count will be set to the number of discarded PS NAL units.
+ *
+ * On output, *size holds the size (in bytes) of the output data buffer.
+ *
+ * @param buf_in address of the buffer holding the input data
+ * @param size address of the variable holding the size (in bytes) of the input
+ * buffer (on input) and of the output buffer (on output)
+ * @param buf_out address of the variable holding the address of the output
+ * buffer
+ * @param filter_ps whether to write parameter set NAL units to the output (0)
+ * or to discard them (non-zero)
+ * @param ps_count address of the variable where the number of discarded
+ * parameter set NAL units shall be written, may be NULL
+ * @return the amount (in bytes) of data written in case of success, a negative
+ * value corresponding to an AVERROR code in case of failure
+ */
+int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
+ int *size, int filter_ps, int *ps_count);
+
+/**
+ * Writes HEVC extradata (parameter sets, declarative SEI NAL units) to the
+ * provided AVIOContext.
+ *
+ * If the extradata is Annex B format, it gets converted to hvcC format before
+ * writing.
+ *
+ * @param pb address of the AVIOContext where the hvcC shall be written
+ * @param data address of the buffer holding the data needed to write the hvcC
+ * @param size size (in bytes) of the data buffer
+ * @param ps_array_completeness whether all parameter sets are in the hvcC (1)
+ * or there may be additional parameter sets in the bitstream (0)
+ * @return >=0 in case of success, a negative value corresponding to an AVERROR
+ * code in case of failure
+ */
+int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
+ int size, int ps_array_completeness);
+
+#endif /* AVFORMAT_HEVC_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/hls.c b/chromium/third_party/ffmpeg/libavformat/hls.c
index 471a62dc9c4..3897723b7de 100644
--- a/chromium/third_party/ffmpeg/libavformat/hls.c
+++ b/chromium/third_party/ffmpeg/libavformat/hls.c
@@ -1,6 +1,7 @@
/*
* Apple HTTP Live Streaming demuxer
* Copyright (c) 2010 Martin Storsjo
+ * Copyright (c) 2013 Anssi Hannula
*
* This file is part of FFmpeg.
*
@@ -26,6 +27,7 @@
*/
#include "libavutil/avstring.h"
+#include "libavutil/avassert.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
@@ -35,9 +37,16 @@
#include "internal.h"
#include "avio_internal.h"
#include "url.h"
+#include "id3v2.h"
#define INITIAL_BUFFER_SIZE 32768
+#define MAX_FIELD_LEN 64
+#define MAX_CHARACTERISTICS_LEN 512
+
+#define MPEG_TIME_BASE 90000
+#define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE}
+
/*
* An apple http stream consists of a playlist with media segment files,
* played sequentially. There may be several playlists with the same
@@ -57,19 +66,28 @@ enum KeyType {
struct segment {
int64_t duration;
- char url[MAX_URL_SIZE];
- char key[MAX_URL_SIZE];
+ int64_t url_offset;
+ int64_t size;
+ char *url;
+ char *key;
enum KeyType key_type;
uint8_t iv[16];
};
+struct rendition;
+
+enum PlaylistType {
+ PLS_TYPE_UNSPECIFIED,
+ PLS_TYPE_EVENT,
+ PLS_TYPE_VOD
+};
+
/*
- * Each variant has its own demuxer. If it currently is active,
+ * Each playlist has its own demuxer. If it currently is active,
* it has an open AVIOContext too, and potentially an AVPacket
* containing the next packet from this stream.
*/
-struct variant {
- int bandwidth;
+struct playlist {
char url[MAX_URL_SIZE];
AVIOContext pb;
uint8_t* read_buffer;
@@ -81,27 +99,82 @@ struct variant {
int stream_offset;
int finished;
+ enum PlaylistType type;
int64_t target_duration;
int start_seq_no;
int n_segments;
struct segment **segments;
int needed, cur_needed;
int cur_seq_no;
+ int64_t cur_seg_offset;
int64_t last_load_time;
char key_url[MAX_URL_SIZE];
uint8_t key[16];
+
+ /* ID3 timestamp handling (elementary audio streams have ID3 timestamps
+ * (and possibly other ID3 tags) in the beginning of each segment) */
+ int is_id3_timestamped; /* -1: not yet known */
+ int64_t id3_mpegts_timestamp; /* in mpegts tb */
+ int64_t id3_offset; /* in stream original tb */
+ uint8_t* id3_buf; /* temp buffer for id3 parsing */
+ unsigned int id3_buf_size;
+ AVDictionary *id3_initial; /* data from first id3 tag */
+ int id3_found; /* ID3 tag found at some point */
+ int id3_changed; /* ID3 tag data has changed at some point */
+ ID3v2ExtraMeta *id3_deferred_extra; /* stored here until subdemuxer is opened */
+
+ int64_t seek_timestamp;
+ int seek_flags;
+ int seek_stream_index; /* into subdemuxer stream array */
+
+ /* Renditions associated with this playlist, if any.
+ * Alternative rendition playlists have a single rendition associated
+ * with them, and variant main Media Playlists may have
+ * multiple (playlist-less) renditions associated with them. */
+ int n_renditions;
+ struct rendition **renditions;
+};
+
+/*
+ * Renditions are e.g. alternative subtitle or audio streams.
+ * The rendition may either be an external playlist or it may be
+ * contained in the main Media Playlist of the variant (in which case
+ * playlist is NULL).
+ */
+struct rendition {
+ enum AVMediaType type;
+ struct playlist *playlist;
+ char group_id[MAX_FIELD_LEN];
+ char language[MAX_FIELD_LEN];
+ char name[MAX_FIELD_LEN];
+ int disposition;
+};
+
+struct variant {
+ int bandwidth;
+
+ /* every variant contains at least the main Media Playlist in index 0 */
+ int n_playlists;
+ struct playlist **playlists;
+
+ char audio_group[MAX_FIELD_LEN];
+ char video_group[MAX_FIELD_LEN];
+ char subtitles_group[MAX_FIELD_LEN];
};
typedef struct HLSContext {
int n_variants;
struct variant **variants;
+ int n_playlists;
+ struct playlist **playlists;
+ int n_renditions;
+ struct rendition **renditions;
+
int cur_seq_no;
- int end_of_segment;
int first_packet;
int64_t first_timestamp;
- int64_t seek_timestamp;
- int seek_flags;
+ int64_t cur_timestamp;
AVIOInterruptCB *interrupt_callback;
char *user_agent; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context
char *cookies; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context
@@ -116,13 +189,42 @@ static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
return len;
}
-static void free_segment_list(struct variant *var)
+static void free_segment_list(struct playlist *pls)
+{
+ int i;
+ for (i = 0; i < pls->n_segments; i++) {
+ av_free(pls->segments[i]->key);
+ av_free(pls->segments[i]->url);
+ av_free(pls->segments[i]);
+ }
+ av_freep(&pls->segments);
+ pls->n_segments = 0;
+}
+
+static void free_playlist_list(HLSContext *c)
{
int i;
- for (i = 0; i < var->n_segments; i++)
- av_free(var->segments[i]);
- av_freep(&var->segments);
- var->n_segments = 0;
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
+ free_segment_list(pls);
+ av_freep(&pls->renditions);
+ av_freep(&pls->id3_buf);
+ av_dict_free(&pls->id3_initial);
+ ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
+ av_free_packet(&pls->pkt);
+ av_free(pls->pb.buffer);
+ if (pls->input)
+ ffurl_close(pls->input);
+ if (pls->ctx) {
+ pls->ctx->pb = NULL;
+ avformat_close_input(&pls->ctx);
+ }
+ av_free(pls);
+ }
+ av_freep(&c->playlists);
+ av_freep(&c->cookies);
+ av_freep(&c->user_agent);
+ c->n_playlists = 0;
}
static void free_variant_list(HLSContext *c)
@@ -130,23 +232,22 @@ static void free_variant_list(HLSContext *c)
int i;
for (i = 0; i < c->n_variants; i++) {
struct variant *var = c->variants[i];
- free_segment_list(var);
- av_free_packet(&var->pkt);
- av_free(var->pb.buffer);
- if (var->input)
- ffurl_close(var->input);
- if (var->ctx) {
- var->ctx->pb = NULL;
- avformat_close_input(&var->ctx);
- }
+ av_freep(&var->playlists);
av_free(var);
}
av_freep(&c->variants);
- av_freep(&c->cookies);
- av_freep(&c->user_agent);
c->n_variants = 0;
}
+static void free_rendition_list(HLSContext *c)
+{
+ int i;
+ for (i = 0; i < c->n_renditions; i++)
+ av_free(c->renditions[i]);
+ av_freep(&c->renditions);
+ c->n_renditions = 0;
+}
+
/*
* Used to reset a statically allocated AVPacket to a clean slate,
* containing no data.
@@ -157,29 +258,72 @@ static void reset_packet(AVPacket *pkt)
pkt->data = NULL;
}
-static struct variant *new_variant(HLSContext *c, int bandwidth,
- const char *url, const char *base)
+static struct playlist *new_playlist(HLSContext *c, const char *url,
+ const char *base)
{
- struct variant *var = av_mallocz(sizeof(struct variant));
- if (!var)
+ struct playlist *pls = av_mallocz(sizeof(struct playlist));
+ if (!pls)
return NULL;
- reset_packet(&var->pkt);
- var->bandwidth = bandwidth;
- ff_make_absolute_url(var->url, sizeof(var->url), base, url);
- dynarray_add(&c->variants, &c->n_variants, var);
- return var;
+ reset_packet(&pls->pkt);
+ ff_make_absolute_url(pls->url, sizeof(pls->url), base, url);
+ pls->seek_timestamp = AV_NOPTS_VALUE;
+
+ pls->is_id3_timestamped = -1;
+ pls->id3_mpegts_timestamp = AV_NOPTS_VALUE;
+
+ dynarray_add(&c->playlists, &c->n_playlists, pls);
+ return pls;
}
struct variant_info {
char bandwidth[20];
+ /* variant group ids: */
+ char audio[MAX_FIELD_LEN];
+ char video[MAX_FIELD_LEN];
+ char subtitles[MAX_FIELD_LEN];
};
+static struct variant *new_variant(HLSContext *c, struct variant_info *info,
+ const char *url, const char *base)
+{
+ struct variant *var;
+ struct playlist *pls;
+
+ pls = new_playlist(c, url, base);
+ if (!pls)
+ return NULL;
+
+ var = av_mallocz(sizeof(struct variant));
+ if (!var)
+ return NULL;
+
+ if (info) {
+ var->bandwidth = atoi(info->bandwidth);
+ strcpy(var->audio_group, info->audio);
+ strcpy(var->video_group, info->video);
+ strcpy(var->subtitles_group, info->subtitles);
+ }
+
+ dynarray_add(&c->variants, &c->n_variants, var);
+ dynarray_add(&var->playlists, &var->n_playlists, pls);
+ return var;
+}
+
static void handle_variant_args(struct variant_info *info, const char *key,
int key_len, char **dest, int *dest_len)
{
if (!strncmp(key, "BANDWIDTH=", key_len)) {
*dest = info->bandwidth;
*dest_len = sizeof(info->bandwidth);
+ } else if (!strncmp(key, "AUDIO=", key_len)) {
+ *dest = info->audio;
+ *dest_len = sizeof(info->audio);
+ } else if (!strncmp(key, "VIDEO=", key_len)) {
+ *dest = info->video;
+ *dest_len = sizeof(info->video);
+ } else if (!strncmp(key, "SUBTITLES=", key_len)) {
+ *dest = info->subtitles;
+ *dest_len = sizeof(info->subtitles);
}
}
@@ -204,10 +348,153 @@ static void handle_key_args(struct key_info *info, const char *key,
}
}
+struct rendition_info {
+ char type[16];
+ char uri[MAX_URL_SIZE];
+ char group_id[MAX_FIELD_LEN];
+ char language[MAX_FIELD_LEN];
+ char assoc_language[MAX_FIELD_LEN];
+ char name[MAX_FIELD_LEN];
+ char defaultr[4];
+ char forced[4];
+ char characteristics[MAX_CHARACTERISTICS_LEN];
+};
+
+static struct rendition *new_rendition(HLSContext *c, struct rendition_info *info,
+ const char *url_base)
+{
+ struct rendition *rend;
+ enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
+ char *characteristic;
+ char *chr_ptr;
+ char *saveptr;
+
+ if (!strcmp(info->type, "AUDIO"))
+ type = AVMEDIA_TYPE_AUDIO;
+ else if (!strcmp(info->type, "VIDEO"))
+ type = AVMEDIA_TYPE_VIDEO;
+ else if (!strcmp(info->type, "SUBTITLES"))
+ type = AVMEDIA_TYPE_SUBTITLE;
+ else if (!strcmp(info->type, "CLOSED-CAPTIONS"))
+ /* CLOSED-CAPTIONS is ignored since we do not support CEA-608 CC in
+ * AVC SEI RBSP anyway */
+ return NULL;
+
+ if (type == AVMEDIA_TYPE_UNKNOWN)
+ return NULL;
+
+ /* URI is mandatory for subtitles as per spec */
+ if (type == AVMEDIA_TYPE_SUBTITLE && !info->uri[0])
+ return NULL;
+
+ /* TODO: handle subtitles (each segment has to parsed separately) */
+ if (type == AVMEDIA_TYPE_SUBTITLE)
+ return NULL;
+
+ rend = av_mallocz(sizeof(struct rendition));
+ if (!rend)
+ return NULL;
+
+ dynarray_add(&c->renditions, &c->n_renditions, rend);
+
+ rend->type = type;
+ strcpy(rend->group_id, info->group_id);
+ strcpy(rend->language, info->language);
+ strcpy(rend->name, info->name);
+
+ /* add the playlist if this is an external rendition */
+ if (info->uri[0]) {
+ rend->playlist = new_playlist(c, info->uri, url_base);
+ if (rend->playlist)
+ dynarray_add(&rend->playlist->renditions,
+ &rend->playlist->n_renditions, rend);
+ }
+
+ if (info->assoc_language[0]) {
+ int langlen = strlen(rend->language);
+ if (langlen < sizeof(rend->language) - 3) {
+ rend->language[langlen] = ',';
+ strncpy(rend->language + langlen + 1, info->assoc_language,
+ sizeof(rend->language) - langlen - 2);
+ }
+ }
+
+ if (!strcmp(info->defaultr, "YES"))
+ rend->disposition |= AV_DISPOSITION_DEFAULT;
+ if (!strcmp(info->forced, "YES"))
+ rend->disposition |= AV_DISPOSITION_FORCED;
+
+ chr_ptr = info->characteristics;
+ while ((characteristic = av_strtok(chr_ptr, ",", &saveptr))) {
+ if (!strcmp(characteristic, "public.accessibility.describes-music-and-sound"))
+ rend->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
+ else if (!strcmp(characteristic, "public.accessibility.describes-video"))
+ rend->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED;
+
+ chr_ptr = NULL;
+ }
+
+ return rend;
+}
+
+static void handle_rendition_args(struct rendition_info *info, const char *key,
+ int key_len, char **dest, int *dest_len)
+{
+ if (!strncmp(key, "TYPE=", key_len)) {
+ *dest = info->type;
+ *dest_len = sizeof(info->type);
+ } else if (!strncmp(key, "URI=", key_len)) {
+ *dest = info->uri;
+ *dest_len = sizeof(info->uri);
+ } else if (!strncmp(key, "GROUP-ID=", key_len)) {
+ *dest = info->group_id;
+ *dest_len = sizeof(info->group_id);
+ } else if (!strncmp(key, "LANGUAGE=", key_len)) {
+ *dest = info->language;
+ *dest_len = sizeof(info->language);
+ } else if (!strncmp(key, "ASSOC-LANGUAGE=", key_len)) {
+ *dest = info->assoc_language;
+ *dest_len = sizeof(info->assoc_language);
+ } else if (!strncmp(key, "NAME=", key_len)) {
+ *dest = info->name;
+ *dest_len = sizeof(info->name);
+ } else if (!strncmp(key, "DEFAULT=", key_len)) {
+ *dest = info->defaultr;
+ *dest_len = sizeof(info->defaultr);
+ } else if (!strncmp(key, "FORCED=", key_len)) {
+ *dest = info->forced;
+ *dest_len = sizeof(info->forced);
+ } else if (!strncmp(key, "CHARACTERISTICS=", key_len)) {
+ *dest = info->characteristics;
+ *dest_len = sizeof(info->characteristics);
+ }
+ /*
+ * ignored:
+ * - AUTOSELECT: client may autoselect based on e.g. system language
+ * - INSTREAM-ID: EIA-608 closed caption number ("CC1".."CC4")
+ */
+}
+
+/* used by parse_playlist to allocate a new variant+playlist when the
+ * playlist is detected to be a Media Playlist (not Master Playlist)
+ * and we have no parent Master Playlist (parsing of which would have
+ * allocated the variant and playlist already) */
+static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url)
+{
+ if (*pls)
+ return 0;
+ if (!new_variant(c, NULL, url, NULL))
+ return AVERROR(ENOMEM);
+ *pls = c->playlists[c->n_playlists - 1];
+ return 0;
+}
+
+/* pls = NULL => Master Playlist or parentless Media Playlist
+ * pls = !NULL => parented Media Playlist, playlist+variant allocated */
static int parse_playlist(HLSContext *c, const char *url,
- struct variant *var, AVIOContext *in)
+ struct playlist *pls, AVIOContext *in)
{
- int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
+ int ret = 0, is_segment = 0, is_variant = 0;
int64_t duration = 0;
enum KeyType key_type = KEY_NONE;
uint8_t iv[16] = "";
@@ -216,7 +503,11 @@ static int parse_playlist(HLSContext *c, const char *url,
char line[MAX_URL_SIZE];
const char *ptr;
int close_in = 0;
+ int64_t seg_offset = 0;
+ int64_t seg_size = -1;
uint8_t *new_url = NULL;
+ struct variant_info variant_info;
+ char tmp_str[MAX_URL_SIZE];
if (!in) {
AVDictionary *opts = NULL;
@@ -245,18 +536,18 @@ static int parse_playlist(HLSContext *c, const char *url,
goto fail;
}
- if (var) {
- free_segment_list(var);
- var->finished = 0;
+ if (pls) {
+ free_segment_list(pls);
+ pls->finished = 0;
+ pls->type = PLS_TYPE_UNSPECIFIED;
}
while (!url_feof(in)) {
read_chomp_line(in, line, sizeof(line));
if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
- struct variant_info info = {{0}};
is_variant = 1;
+ memset(&variant_info, 0, sizeof(variant_info));
ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
- &info);
- bandwidth = atoi(info.bandwidth);
+ &variant_info);
} else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
struct key_info info = {{0}};
ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
@@ -270,49 +561,58 @@ static int parse_playlist(HLSContext *c, const char *url,
has_iv = 1;
}
av_strlcpy(key, info.uri, sizeof(key));
+ } else if (av_strstart(line, "#EXT-X-MEDIA:", &ptr)) {
+ struct rendition_info info = {{0}};
+ ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_rendition_args,
+ &info);
+ new_rendition(c, &info, url);
} else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
- if (!var) {
- var = new_variant(c, 0, url, NULL);
- if (!var) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- }
- var->target_duration = atoi(ptr) * AV_TIME_BASE;
+ ret = ensure_playlist(c, &pls, url);
+ if (ret < 0)
+ goto fail;
+ pls->target_duration = atoi(ptr) * AV_TIME_BASE;
} else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
- if (!var) {
- var = new_variant(c, 0, url, NULL);
- if (!var) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- }
- var->start_seq_no = atoi(ptr);
+ ret = ensure_playlist(c, &pls, url);
+ if (ret < 0)
+ goto fail;
+ pls->start_seq_no = atoi(ptr);
+ } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) {
+ ret = ensure_playlist(c, &pls, url);
+ if (ret < 0)
+ goto fail;
+ if (!strcmp(ptr, "EVENT"))
+ pls->type = PLS_TYPE_EVENT;
+ else if (!strcmp(ptr, "VOD"))
+ pls->type = PLS_TYPE_VOD;
} else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
- if (var)
- var->finished = 1;
+ if (pls)
+ pls->finished = 1;
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
is_segment = 1;
duration = atof(ptr) * AV_TIME_BASE;
+ } else if (av_strstart(line, "#EXT-X-BYTERANGE:", &ptr)) {
+ seg_size = atoi(ptr);
+ ptr = strchr(ptr, '@');
+ if (ptr)
+ seg_offset = atoi(ptr+1);
} else if (av_strstart(line, "#", NULL)) {
continue;
} else if (line[0]) {
if (is_variant) {
- if (!new_variant(c, bandwidth, line, url)) {
+ if (!new_variant(c, &variant_info, line, url)) {
ret = AVERROR(ENOMEM);
goto fail;
}
is_variant = 0;
- bandwidth = 0;
}
if (is_segment) {
struct segment *seg;
- if (!var) {
- var = new_variant(c, 0, url, NULL);
- if (!var) {
+ if (!pls) {
+ if (!new_variant(c, 0, url, NULL)) {
ret = AVERROR(ENOMEM);
goto fail;
}
+ pls = c->playlists[c->n_playlists - 1];
}
seg = av_malloc(sizeof(struct segment));
if (!seg) {
@@ -324,19 +624,49 @@ static int parse_playlist(HLSContext *c, const char *url,
if (has_iv) {
memcpy(seg->iv, iv, sizeof(iv));
} else {
- int seq = var->start_seq_no + var->n_segments;
+ int seq = pls->start_seq_no + pls->n_segments;
memset(seg->iv, 0, sizeof(seg->iv));
AV_WB32(seg->iv + 12, seq);
}
- ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
- ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
- dynarray_add(&var->segments, &var->n_segments, seg);
+
+ if (key_type != KEY_NONE) {
+ ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, key);
+ seg->key = av_strdup(tmp_str);
+ if (!seg->key) {
+ av_free(seg);
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ } else {
+ seg->key = NULL;
+ }
+
+ ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, line);
+ seg->url = av_strdup(tmp_str);
+ if (!seg->url) {
+ av_free(seg->key);
+ av_free(seg);
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ dynarray_add(&pls->segments, &pls->n_segments, seg);
is_segment = 0;
+
+ seg->size = seg_size;
+ if (seg_size >= 0) {
+ seg->url_offset = seg_offset;
+ seg_offset += seg_size;
+ seg_size = -1;
+ } else {
+ seg->url_offset = 0;
+ seg_offset = 0;
+ }
}
}
}
- if (var)
- var->last_load_time = av_gettime();
+ if (pls)
+ pls->last_load_time = av_gettime();
fail:
av_free(new_url);
@@ -345,11 +675,237 @@ fail:
return ret;
}
-static int open_input(HLSContext *c, struct variant *var)
+enum ReadFromURLMode {
+ READ_NORMAL,
+ READ_COMPLETE,
+};
+
+/* read from URLContext, limiting read to current segment */
+static int read_from_url(struct playlist *pls, uint8_t *buf, int buf_size,
+ enum ReadFromURLMode mode)
+{
+ int ret;
+ struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no];
+
+ /* limit read if the segment was only a part of a file */
+ if (seg->size >= 0)
+ buf_size = FFMIN(buf_size, seg->size - pls->cur_seg_offset);
+
+ if (mode == READ_COMPLETE)
+ ret = ffurl_read_complete(pls->input, buf, buf_size);
+ else
+ ret = ffurl_read(pls->input, buf, buf_size);
+
+ if (ret > 0)
+ pls->cur_seg_offset += ret;
+
+ return ret;
+}
+
+/* Parse the raw ID3 data and pass contents to caller */
+static void parse_id3(AVFormatContext *s, AVIOContext *pb,
+ AVDictionary **metadata, int64_t *dts,
+ ID3v2ExtraMetaAPIC **apic, ID3v2ExtraMeta **extra_meta)
+{
+ static const char id3_priv_owner_ts[] = "com.apple.streaming.transportStreamTimestamp";
+ ID3v2ExtraMeta *meta;
+
+ ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta);
+ for (meta = *extra_meta; meta; meta = meta->next) {
+ if (!strcmp(meta->tag, "PRIV")) {
+ ID3v2ExtraMetaPRIV *priv = meta->data;
+ if (priv->datasize == 8 && !strcmp(priv->owner, id3_priv_owner_ts)) {
+ /* 33-bit MPEG timestamp */
+ int64_t ts = AV_RB64(priv->data);
+ av_log(s, AV_LOG_DEBUG, "HLS ID3 audio timestamp %"PRId64"\n", ts);
+ if ((ts & ~((1ULL << 33) - 1)) == 0)
+ *dts = ts;
+ else
+ av_log(s, AV_LOG_ERROR, "Invalid HLS ID3 audio timestamp %"PRId64"\n", ts);
+ }
+ } else if (!strcmp(meta->tag, "APIC") && apic)
+ *apic = meta->data;
+ }
+}
+
+/* Check if the ID3 metadata contents have changed */
+static int id3_has_changed_values(struct playlist *pls, AVDictionary *metadata,
+ ID3v2ExtraMetaAPIC *apic)
+{
+ AVDictionaryEntry *entry = NULL;
+ AVDictionaryEntry *oldentry;
+ /* check that no keys have changed values */
+ while ((entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
+ oldentry = av_dict_get(pls->id3_initial, entry->key, NULL, AV_DICT_MATCH_CASE);
+ if (!oldentry || strcmp(oldentry->value, entry->value) != 0)
+ return 1;
+ }
+
+ /* check if apic appeared */
+ if (apic && (pls->ctx->nb_streams != 2 || !pls->ctx->streams[1]->attached_pic.data))
+ return 1;
+
+ if (apic) {
+ int size = pls->ctx->streams[1]->attached_pic.size;
+ if (size != apic->buf->size - FF_INPUT_BUFFER_PADDING_SIZE)
+ return 1;
+
+ if (memcmp(apic->buf->data, pls->ctx->streams[1]->attached_pic.data, size) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Parse ID3 data and handle the found data */
+static void handle_id3(AVIOContext *pb, struct playlist *pls)
+{
+ AVDictionary *metadata = NULL;
+ ID3v2ExtraMetaAPIC *apic = NULL;
+ ID3v2ExtraMeta *extra_meta = NULL;
+ int64_t timestamp = AV_NOPTS_VALUE;
+
+ parse_id3(pls->ctx, pb, &metadata, &timestamp, &apic, &extra_meta);
+
+ if (timestamp != AV_NOPTS_VALUE) {
+ pls->id3_mpegts_timestamp = timestamp;
+ pls->id3_offset = 0;
+ }
+
+ if (!pls->id3_found) {
+ /* initial ID3 tags */
+ av_assert0(!pls->id3_deferred_extra);
+ pls->id3_found = 1;
+
+ /* get picture attachment and set text metadata */
+ if (pls->ctx->nb_streams)
+ ff_id3v2_parse_apic(pls->ctx, &extra_meta);
+ else
+ /* demuxer not yet opened, defer picture attachment */
+ pls->id3_deferred_extra = extra_meta;
+
+ av_dict_copy(&pls->ctx->metadata, metadata, 0);
+ pls->id3_initial = metadata;
+
+ } else {
+ if (!pls->id3_changed && id3_has_changed_values(pls, metadata, apic)) {
+ avpriv_report_missing_feature(pls->ctx, "Changing ID3 metadata in HLS audio elementary stream");
+ pls->id3_changed = 1;
+ }
+ av_dict_free(&metadata);
+ }
+
+ if (!pls->id3_deferred_extra)
+ ff_id3v2_free_extra_meta(&extra_meta);
+}
+
+/* Intercept and handle ID3 tags between URLContext and AVIOContext */
+static void intercept_id3(struct playlist *pls, uint8_t *buf,
+ int buf_size, int *len)
+{
+ /* intercept id3 tags, we do not want to pass them to the raw
+ * demuxer on all segment switches */
+ int bytes;
+ int id3_buf_pos = 0;
+ int fill_buf = 0;
+
+ /* gather all the id3 tags */
+ while (1) {
+ /* see if we can retrieve enough data for ID3 header */
+ if (*len < ID3v2_HEADER_SIZE && buf_size >= ID3v2_HEADER_SIZE) {
+ bytes = read_from_url(pls, buf + *len, ID3v2_HEADER_SIZE - *len, READ_COMPLETE);
+ if (bytes > 0) {
+
+ if (bytes == ID3v2_HEADER_SIZE - *len)
+ /* no EOF yet, so fill the caller buffer again after
+ * we have stripped the ID3 tags */
+ fill_buf = 1;
+
+ *len += bytes;
+
+ } else if (*len <= 0) {
+ /* error/EOF */
+ *len = bytes;
+ fill_buf = 0;
+ }
+ }
+
+ if (*len < ID3v2_HEADER_SIZE)
+ break;
+
+ if (ff_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) {
+ struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no];
+ int64_t maxsize = seg->size >= 0 ? seg->size : 1024*1024;
+ int taglen = ff_id3v2_tag_len(buf);
+ int tag_got_bytes = FFMIN(taglen, *len);
+ int remaining = taglen - tag_got_bytes;
+
+ if (taglen > maxsize) {
+ av_log(pls->ctx, AV_LOG_ERROR, "Too large HLS ID3 tag (%d > %"PRId64" bytes)\n",
+ taglen, maxsize);
+ break;
+ }
+
+ /*
+ * Copy the id3 tag to our temporary id3 buffer.
+ * We could read a small id3 tag directly without memcpy, but
+ * we would still need to copy the large tags, and handling
+ * both of those cases together with the possibility for multiple
+ * tags would make the handling a bit complex.
+ */
+ pls->id3_buf = av_fast_realloc(pls->id3_buf, &pls->id3_buf_size, id3_buf_pos + taglen);
+ if (!pls->id3_buf)
+ break;
+ memcpy(pls->id3_buf + id3_buf_pos, buf, tag_got_bytes);
+ id3_buf_pos += tag_got_bytes;
+
+ /* strip the intercepted bytes */
+ *len -= tag_got_bytes;
+ memmove(buf, buf + tag_got_bytes, *len);
+ av_log(pls->ctx, AV_LOG_DEBUG, "Stripped %d HLS ID3 bytes\n", tag_got_bytes);
+
+ if (remaining > 0) {
+ /* read the rest of the tag in */
+ if (read_from_url(pls, pls->id3_buf + id3_buf_pos, remaining, READ_COMPLETE) != remaining)
+ break;
+ id3_buf_pos += remaining;
+ av_log(pls->ctx, AV_LOG_DEBUG, "Stripped additional %d HLS ID3 bytes\n", remaining);
+ }
+
+ } else {
+ /* no more ID3 tags */
+ break;
+ }
+ }
+
+ /* re-fill buffer for the caller unless EOF */
+ if (*len >= 0 && (fill_buf || *len == 0)) {
+ bytes = read_from_url(pls, buf + *len, buf_size - *len, READ_NORMAL);
+
+ /* ignore error if we already had some data */
+ if (bytes >= 0)
+ *len += bytes;
+ else if (*len == 0)
+ *len = bytes;
+ }
+
+ if (pls->id3_buf) {
+ /* Now parse all the ID3 tags */
+ AVIOContext id3ioctx;
+ ffio_init_context(&id3ioctx, pls->id3_buf, id3_buf_pos, 0, NULL, NULL, NULL, NULL);
+ handle_id3(&id3ioctx, pls);
+ }
+
+ if (pls->is_id3_timestamped == -1)
+ pls->is_id3_timestamped = (pls->id3_mpegts_timestamp != AV_NOPTS_VALUE);
+}
+
+static int open_input(HLSContext *c, struct playlist *pls)
{
AVDictionary *opts = NULL;
+ AVDictionary *opts2 = NULL;
int ret;
- struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
+ struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no];
// broker prior HTTP options that should be consistent across requests
av_dict_set(&opts, "user-agent", c->user_agent, 0);
@@ -357,18 +913,37 @@ static int open_input(HLSContext *c, struct variant *var)
av_dict_set(&opts, "headers", c->headers, 0);
av_dict_set(&opts, "seekable", "0", 0);
+ // Same opts for key request (ffurl_open mutilates the opts so it cannot be used twice)
+ av_dict_copy(&opts2, opts, 0);
+
+ if (seg->size >= 0) {
+ /* try to restrict the HTTP request to the part we want
+ * (if this is in fact a HTTP request) */
+ char offset[24] = { 0 };
+ char end_offset[24] = { 0 };
+ snprintf(offset, sizeof(offset) - 1, "%"PRId64,
+ seg->url_offset);
+ snprintf(end_offset, sizeof(end_offset) - 1, "%"PRId64,
+ seg->url_offset + seg->size);
+ av_dict_set(&opts, "offset", offset, 0);
+ av_dict_set(&opts, "end_offset", end_offset, 0);
+ }
+
+ av_log(pls->parent, AV_LOG_VERBOSE, "HLS request for url '%s', offset %"PRId64", playlist %d\n",
+ seg->url, seg->url_offset, pls->index);
+
if (seg->key_type == KEY_NONE) {
- ret = ffurl_open(&var->input, seg->url, AVIO_FLAG_READ,
- &var->parent->interrupt_callback, &opts);
- goto cleanup;
+ ret = ffurl_open(&pls->input, seg->url, AVIO_FLAG_READ,
+ &pls->parent->interrupt_callback, &opts);
+
} else if (seg->key_type == KEY_AES_128) {
char iv[33], key[33], url[MAX_URL_SIZE];
- if (strcmp(seg->key, var->key_url)) {
+ if (strcmp(seg->key, pls->key_url)) {
URLContext *uc;
if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ,
- &var->parent->interrupt_callback, &opts) == 0) {
- if (ffurl_read_complete(uc, var->key, sizeof(var->key))
- != sizeof(var->key)) {
+ &pls->parent->interrupt_callback, &opts2) == 0) {
+ if (ffurl_read_complete(uc, pls->key, sizeof(pls->key))
+ != sizeof(pls->key)) {
av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
seg->key);
}
@@ -377,26 +952,24 @@ static int open_input(HLSContext *c, struct variant *var)
av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n",
seg->key);
}
- av_strlcpy(var->key_url, seg->key, sizeof(var->key_url));
+ av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url));
}
ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
- ff_data_to_hex(key, var->key, sizeof(var->key), 0);
+ ff_data_to_hex(key, pls->key, sizeof(pls->key), 0);
iv[32] = key[32] = '\0';
if (strstr(seg->url, "://"))
snprintf(url, sizeof(url), "crypto+%s", seg->url);
else
snprintf(url, sizeof(url), "crypto:%s", seg->url);
- if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ,
- &var->parent->interrupt_callback)) < 0)
+ if ((ret = ffurl_alloc(&pls->input, url, AVIO_FLAG_READ,
+ &pls->parent->interrupt_callback)) < 0)
goto cleanup;
- av_opt_set(var->input->priv_data, "key", key, 0);
- av_opt_set(var->input->priv_data, "iv", iv, 0);
- /* Need to repopulate options */
- av_dict_free(&opts);
- av_dict_set(&opts, "seekable", "0", 0);
- if ((ret = ffurl_connect(var->input, &opts)) < 0) {
- ffurl_close(var->input);
- var->input = NULL;
+ av_opt_set(pls->input->priv_data, "key", key, 0);
+ av_opt_set(pls->input->priv_data, "iv", iv, 0);
+
+ if ((ret = ffurl_connect(pls->input, &opts)) < 0) {
+ ffurl_close(pls->input);
+ pls->input = NULL;
goto cleanup;
}
ret = 0;
@@ -404,30 +977,76 @@ static int open_input(HLSContext *c, struct variant *var)
else
ret = AVERROR(ENOSYS);
+ /* Seek to the requested position. If this was a HTTP request, the offset
+ * should already be where want it to, but this allows e.g. local testing
+ * without a HTTP server. */
+ if (ret == 0 && seg->key_type == KEY_NONE) {
+ int seekret = ffurl_seek(pls->input, seg->url_offset, SEEK_SET);
+ if (seekret < 0) {
+ av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url);
+ ret = seekret;
+ ffurl_close(pls->input);
+ pls->input = NULL;
+ }
+ }
+
cleanup:
av_dict_free(&opts);
+ av_dict_free(&opts2);
+ pls->cur_seg_offset = 0;
return ret;
}
+static int64_t default_reload_interval(struct playlist *pls)
+{
+ return pls->n_segments > 0 ?
+ pls->segments[pls->n_segments - 1]->duration :
+ pls->target_duration;
+}
+
static int read_data(void *opaque, uint8_t *buf, int buf_size)
{
- struct variant *v = opaque;
+ struct playlist *v = opaque;
HLSContext *c = v->parent->priv_data;
int ret, i;
+ int just_opened = 0;
restart:
+ if (!v->needed)
+ return AVERROR_EOF;
+
if (!v->input) {
+ int64_t reload_interval;
+
+ /* Check that the playlist is still needed before opening a new
+ * segment. */
+ if (v->ctx && v->ctx->nb_streams &&
+ v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
+ v->needed = 0;
+ for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
+ i++) {
+ if (v->parent->streams[i]->discard < AVDISCARD_ALL)
+ v->needed = 1;
+ }
+ }
+ if (!v->needed) {
+ av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n",
+ v->index);
+ return AVERROR_EOF;
+ }
+
/* If this is a live stream and the reload interval has elapsed since
- * the last playlist reload, reload the variant playlists now. */
- int64_t reload_interval = v->n_segments > 0 ?
- v->segments[v->n_segments - 1]->duration :
- v->target_duration;
+ * the last playlist reload, reload the playlists now. */
+ reload_interval = default_reload_interval(v);
reload:
if (!v->finished &&
av_gettime() - v->last_load_time >= reload_interval) {
- if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
+ if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) {
+ av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n",
+ v->index);
return ret;
+ }
/* If we need to reload the playlist again below (if
* there's still no more segments), switch to a reload
* interval of half the target duration. */
@@ -452,34 +1071,169 @@ reload:
}
ret = open_input(c, v);
- if (ret < 0)
+ if (ret < 0) {
+ av_log(v->parent, AV_LOG_WARNING, "Failed to open segment of playlist %d\n",
+ v->index);
return ret;
+ }
+ just_opened = 1;
}
- ret = ffurl_read(v->input, buf, buf_size);
- if (ret > 0)
+
+ ret = read_from_url(v, buf, buf_size, READ_NORMAL);
+ if (ret > 0) {
+ if (just_opened && v->is_id3_timestamped != 0) {
+ /* Intercept ID3 tags here, elementary audio streams are required
+ * to convey timestamps using them in the beginning of each segment. */
+ intercept_id3(v, buf, buf_size, &ret);
+ }
+
return ret;
+ }
ffurl_close(v->input);
v->input = NULL;
v->cur_seq_no++;
- c->end_of_segment = 1;
c->cur_seq_no = v->cur_seq_no;
- if (v->ctx && v->ctx->nb_streams &&
- v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
- v->needed = 0;
- for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
- i++) {
- if (v->parent->streams[i]->discard < AVDISCARD_ALL)
- v->needed = 1;
+ goto restart;
+}
+
+static int playlist_in_multiple_variants(HLSContext *c, struct playlist *pls)
+{
+ int variant_count = 0;
+ int i, j;
+
+ for (i = 0; i < c->n_variants && variant_count < 2; i++) {
+ struct variant *v = c->variants[i];
+
+ for (j = 0; j < v->n_playlists; j++) {
+ if (v->playlists[j] == pls) {
+ variant_count++;
+ break;
+ }
}
}
- if (!v->needed) {
- av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n",
- v->index);
- return AVERROR_EOF;
+
+ return variant_count >= 2;
+}
+
+static void add_renditions_to_variant(HLSContext *c, struct variant *var,
+ enum AVMediaType type, const char *group_id)
+{
+ int i;
+
+ for (i = 0; i < c->n_renditions; i++) {
+ struct rendition *rend = c->renditions[i];
+
+ if (rend->type == type && !strcmp(rend->group_id, group_id)) {
+
+ if (rend->playlist)
+ /* rendition is an external playlist
+ * => add the playlist to the variant */
+ dynarray_add(&var->playlists, &var->n_playlists, rend->playlist);
+ else
+ /* rendition is part of the variant main Media Playlist
+ * => add the rendition to the main Media Playlist */
+ dynarray_add(&var->playlists[0]->renditions,
+ &var->playlists[0]->n_renditions,
+ rend);
+ }
+ }
+}
+
+static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pls,
+ enum AVMediaType type)
+{
+ int rend_idx = 0;
+ int i;
+
+ for (i = 0; i < pls->ctx->nb_streams; i++) {
+ AVStream *st = s->streams[pls->stream_offset + i];
+
+ if (st->codec->codec_type != type)
+ continue;
+
+ for (; rend_idx < pls->n_renditions; rend_idx++) {
+ struct rendition *rend = pls->renditions[rend_idx];
+
+ if (rend->type != type)
+ continue;
+
+ if (rend->language[0])
+ av_dict_set(&st->metadata, "language", rend->language, 0);
+ if (rend->name[0])
+ av_dict_set(&st->metadata, "comment", rend->name, 0);
+
+ st->disposition |= rend->disposition;
+ }
+ if (rend_idx >=pls->n_renditions)
+ break;
}
- goto restart;
+}
+
+/* if timestamp was in valid range: returns 1 and sets seq_no
+ * if not: returns 0 and sets seq_no to closest segment */
+static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
+ int64_t timestamp, int *seq_no)
+{
+ int i;
+ int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
+ 0 : c->first_timestamp;
+
+ if (timestamp < pos) {
+ *seq_no = pls->start_seq_no;
+ return 0;
+ }
+
+ for (i = 0; i < pls->n_segments; i++) {
+ int64_t diff = pos + pls->segments[i]->duration - timestamp;
+ if (diff > 0) {
+ *seq_no = pls->start_seq_no + i;
+ return 1;
+ }
+ pos += pls->segments[i]->duration;
+ }
+
+ *seq_no = pls->start_seq_no + pls->n_segments - 1;
+
+ return 0;
+}
+
+static int select_cur_seq_no(HLSContext *c, struct playlist *pls)
+{
+ int seq_no;
+
+ if (!pls->finished && !c->first_packet &&
+ av_gettime() - pls->last_load_time >= default_reload_interval(pls))
+ /* reload the playlist since it was suspended */
+ parse_playlist(c, pls->url, pls, NULL);
+
+ /* If playback is already in progress (we are just selecting a new
+ * playlist) and this is a complete file, find the matching segment
+ * by counting durations. */
+ if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) {
+ find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no);
+ return seq_no;
+ }
+
+ if (!pls->finished) {
+ if (!c->first_packet && /* we are doing a segment selection during playback */
+ c->cur_seq_no >= pls->start_seq_no &&
+ c->cur_seq_no < pls->start_seq_no + pls->n_segments)
+ /* While spec 3.4.3 says that we cannot assume anything about the
+ * content at the same sequence number on different playlists,
+ * in practice this seems to work and doing it otherwise would
+ * require us to download a segment to inspect its timestamps. */
+ return c->cur_seq_no;
+
+ /* If this is a live stream with more than 3 segments, start at the
+ * third last segment. */
+ if (pls->n_segments > 3)
+ return pls->start_seq_no + pls->n_segments - 3;
+ }
+
+ /* Otherwise just start on the first segment. */
+ return pls->start_seq_no;
}
static int hls_read_header(AVFormatContext *s)
@@ -490,6 +1244,10 @@ static int hls_read_header(AVFormatContext *s)
c->interrupt_callback = &s->interrupt_callback;
+ c->first_packet = 1;
+ c->first_timestamp = AV_NOPTS_VALUE;
+ c->cur_timestamp = AV_NOPTS_VALUE;
+
// if the URL context is good, read important options we must broker later
if (u && u->prot->priv_data_class) {
// get the previous user agent & set back to null if string size is zero
@@ -519,17 +1277,17 @@ static int hls_read_header(AVFormatContext *s)
ret = AVERROR_EOF;
goto fail;
}
- /* If the playlist only contained variants, parse each individual
- * variant playlist. */
- if (c->n_variants > 1 || c->variants[0]->n_segments == 0) {
- for (i = 0; i < c->n_variants; i++) {
- struct variant *v = c->variants[i];
- if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
+ /* If the playlist only contained playlists (Master Playlist),
+ * parse each individual playlist. */
+ if (c->n_playlists > 1 || c->playlists[0]->n_segments == 0) {
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
+ if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0)
goto fail;
}
}
- if (c->variants[0]->n_segments == 0) {
+ if (c->variants[0]->playlists[0]->n_segments == 0) {
av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
ret = AVERROR_EOF;
goto fail;
@@ -537,97 +1295,140 @@ static int hls_read_header(AVFormatContext *s)
/* If this isn't a live stream, calculate the total duration of the
* stream. */
- if (c->variants[0]->finished) {
+ if (c->variants[0]->playlists[0]->finished) {
int64_t duration = 0;
- for (i = 0; i < c->variants[0]->n_segments; i++)
- duration += c->variants[0]->segments[i]->duration;
+ for (i = 0; i < c->variants[0]->playlists[0]->n_segments; i++)
+ duration += c->variants[0]->playlists[0]->segments[i]->duration;
s->duration = duration;
}
- /* Open the demuxer for each variant */
+ /* Associate renditions with variants */
for (i = 0; i < c->n_variants; i++) {
- struct variant *v = c->variants[i];
+ struct variant *var = c->variants[i];
+
+ if (var->audio_group[0])
+ add_renditions_to_variant(c, var, AVMEDIA_TYPE_AUDIO, var->audio_group);
+ if (var->video_group[0])
+ add_renditions_to_variant(c, var, AVMEDIA_TYPE_VIDEO, var->video_group);
+ if (var->subtitles_group[0])
+ add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group);
+ }
+
+ /* Open the demuxer for each playlist */
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
AVInputFormat *in_fmt = NULL;
- char bitrate_str[20];
- AVProgram *program;
- if (v->n_segments == 0)
+ if (pls->n_segments == 0)
continue;
- if (!(v->ctx = avformat_alloc_context())) {
+ if (!(pls->ctx = avformat_alloc_context())) {
ret = AVERROR(ENOMEM);
goto fail;
}
- v->index = i;
- v->needed = 1;
- v->parent = s;
-
- /* If this is a live stream with more than 3 segments, start at the
- * third last segment. */
- v->cur_seq_no = v->start_seq_no;
- if (!v->finished && v->n_segments > 3)
- v->cur_seq_no = v->start_seq_no + v->n_segments - 3;
+ pls->index = i;
+ pls->needed = 1;
+ pls->parent = s;
+ pls->cur_seq_no = select_cur_seq_no(c, pls);
- v->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
- ffio_init_context(&v->pb, v->read_buffer, INITIAL_BUFFER_SIZE, 0, v,
+ pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
+ ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls,
read_data, NULL, NULL);
- v->pb.seekable = 0;
- ret = av_probe_input_buffer(&v->pb, &in_fmt, v->segments[0]->url,
+ pls->pb.seekable = 0;
+ ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url,
NULL, 0, 0);
if (ret < 0) {
/* Free the ctx - it isn't initialized properly at this point,
* so avformat_close_input shouldn't be called. If
* avformat_open_input fails below, it frees and zeros the
* context, so it doesn't need any special treatment like this. */
- av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", v->segments[0]->url);
- avformat_free_context(v->ctx);
- v->ctx = NULL;
+ av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url);
+ avformat_free_context(pls->ctx);
+ pls->ctx = NULL;
goto fail;
}
- v->ctx->pb = &v->pb;
- v->stream_offset = stream_offset;
- ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL);
+ pls->ctx->pb = &pls->pb;
+ pls->stream_offset = stream_offset;
+ ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
if (ret < 0)
goto fail;
- v->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER;
- ret = avformat_find_stream_info(v->ctx, NULL);
+ if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) {
+ ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra);
+ avformat_queue_attached_pictures(pls->ctx);
+ ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
+ pls->id3_deferred_extra = NULL;
+ }
+
+ pls->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER;
+ ret = avformat_find_stream_info(pls->ctx, NULL);
if (ret < 0)
goto fail;
- snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth);
- program = av_new_program(s, i);
- if (!program)
- goto fail;
- av_dict_set(&program->metadata, "variant_bitrate", bitrate_str, 0);
+ if (pls->is_id3_timestamped == -1)
+ av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n");
- /* Create new AVStreams for each stream in this variant */
- for (j = 0; j < v->ctx->nb_streams; j++) {
+ /* Create new AVStreams for each stream in this playlist */
+ for (j = 0; j < pls->ctx->nb_streams; j++) {
AVStream *st = avformat_new_stream(s, NULL);
- AVStream *ist = v->ctx->streams[j];
+ AVStream *ist = pls->ctx->streams[j];
if (!st) {
ret = AVERROR(ENOMEM);
goto fail;
}
- ff_program_add_stream_index(s, i, stream_offset + j);
st->id = i;
- avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
- avcodec_copy_context(st->codec, v->ctx->streams[j]->codec);
- if (v->bandwidth)
- av_dict_set(&st->metadata, "variant_bitrate", bitrate_str,
- 0);
+
+ avcodec_copy_context(st->codec, pls->ctx->streams[j]->codec);
+
+ if (pls->is_id3_timestamped) /* custom timestamps via id3 */
+ avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
+ else
+ avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
}
- stream_offset += v->ctx->nb_streams;
+
+ add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
+ add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
+ add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
+
+ stream_offset += pls->ctx->nb_streams;
}
- c->first_packet = 1;
- c->first_timestamp = AV_NOPTS_VALUE;
- c->seek_timestamp = AV_NOPTS_VALUE;
+ /* Create a program for each variant */
+ for (i = 0; i < c->n_variants; i++) {
+ struct variant *v = c->variants[i];
+ char bitrate_str[20];
+ AVProgram *program;
+
+ snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth);
+
+ program = av_new_program(s, i);
+ if (!program)
+ goto fail;
+ av_dict_set(&program->metadata, "variant_bitrate", bitrate_str, 0);
+
+ for (j = 0; j < v->n_playlists; j++) {
+ struct playlist *pls = v->playlists[j];
+ int is_shared = playlist_in_multiple_variants(c, pls);
+ int k;
+
+ for (k = 0; k < pls->ctx->nb_streams; k++) {
+ struct AVStream *st = s->streams[pls->stream_offset + k];
+
+ ff_program_add_stream_index(s, i, pls->stream_offset + k);
+
+ /* Set variant_bitrate for streams unique to this variant */
+ if (!is_shared && v->bandwidth)
+ av_dict_set(&st->metadata, "variant_bitrate", bitrate_str, 0);
+ }
+ }
+ }
return 0;
fail:
+ free_playlist_list(c);
free_variant_list(c);
+ free_rendition_list(c);
return ret;
}
@@ -637,127 +1438,171 @@ static int recheck_discard_flags(AVFormatContext *s, int first)
int i, changed = 0;
/* Check if any new streams are needed */
- for (i = 0; i < c->n_variants; i++)
- c->variants[i]->cur_needed = 0;
+ for (i = 0; i < c->n_playlists; i++)
+ c->playlists[i]->cur_needed = 0;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- struct variant *var = c->variants[s->streams[i]->id];
+ struct playlist *pls = c->playlists[s->streams[i]->id];
if (st->discard < AVDISCARD_ALL)
- var->cur_needed = 1;
+ pls->cur_needed = 1;
}
- for (i = 0; i < c->n_variants; i++) {
- struct variant *v = c->variants[i];
- if (v->cur_needed && !v->needed) {
- v->needed = 1;
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
+ if (pls->cur_needed && !pls->needed) {
+ pls->needed = 1;
changed = 1;
- v->cur_seq_no = c->cur_seq_no;
- v->pb.eof_reached = 0;
- av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i);
- } else if (first && !v->cur_needed && v->needed) {
- if (v->input)
- ffurl_close(v->input);
- v->input = NULL;
- v->needed = 0;
+ pls->cur_seq_no = select_cur_seq_no(c, pls);
+ pls->pb.eof_reached = 0;
+ if (c->cur_timestamp != AV_NOPTS_VALUE) {
+ /* catch up */
+ pls->seek_timestamp = c->cur_timestamp;
+ pls->seek_flags = AVSEEK_FLAG_ANY;
+ pls->seek_stream_index = -1;
+ }
+ av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no);
+ } else if (first && !pls->cur_needed && pls->needed) {
+ if (pls->input)
+ ffurl_close(pls->input);
+ pls->input = NULL;
+ pls->needed = 0;
changed = 1;
- av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i);
+ av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i);
}
}
return changed;
}
+static void fill_timing_for_id3_timestamped_stream(struct playlist *pls)
+{
+ if (pls->id3_offset >= 0) {
+ pls->pkt.dts = pls->id3_mpegts_timestamp +
+ av_rescale_q(pls->id3_offset,
+ pls->ctx->streams[pls->pkt.stream_index]->time_base,
+ MPEG_TIME_BASE_Q);
+ if (pls->pkt.duration)
+ pls->id3_offset += pls->pkt.duration;
+ else
+ pls->id3_offset = -1;
+ } else {
+ /* there have been packets with unknown duration
+ * since the last id3 tag, should not normally happen */
+ pls->pkt.dts = AV_NOPTS_VALUE;
+ }
+
+ if (pls->pkt.duration)
+ pls->pkt.duration = av_rescale_q(pls->pkt.duration,
+ pls->ctx->streams[pls->pkt.stream_index]->time_base,
+ MPEG_TIME_BASE_Q);
+
+ pls->pkt.pts = AV_NOPTS_VALUE;
+}
+
+static AVRational get_timebase(struct playlist *pls)
+{
+ if (pls->is_id3_timestamped)
+ return MPEG_TIME_BASE_Q;
+
+ return pls->ctx->streams[pls->pkt.stream_index]->time_base;
+}
+
+static int compare_ts_with_wrapdetect(int64_t ts_a, struct playlist *pls_a,
+ int64_t ts_b, struct playlist *pls_b)
+{
+ int64_t scaled_ts_a = av_rescale_q(ts_a, get_timebase(pls_a), MPEG_TIME_BASE_Q);
+ int64_t scaled_ts_b = av_rescale_q(ts_b, get_timebase(pls_b), MPEG_TIME_BASE_Q);
+
+ return av_compare_mod(scaled_ts_a, scaled_ts_b, 1LL << 33);
+}
+
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
{
HLSContext *c = s->priv_data;
- int ret, i, minvariant = -1;
+ int ret, i, minplaylist = -1;
- if (c->first_packet) {
- recheck_discard_flags(s, 1);
- c->first_packet = 0;
- }
+ recheck_discard_flags(s, c->first_packet);
-start:
- c->end_of_segment = 0;
- for (i = 0; i < c->n_variants; i++) {
- struct variant *var = c->variants[i];
- /* Make sure we've got one buffered packet from each open variant
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
+ /* Make sure we've got one buffered packet from each open playlist
* stream */
- if (var->needed && !var->pkt.data) {
+ if (pls->needed && !pls->pkt.data) {
while (1) {
int64_t ts_diff;
- AVStream *st;
- ret = av_read_frame(var->ctx, &var->pkt);
+ AVRational tb;
+ ret = av_read_frame(pls->ctx, &pls->pkt);
if (ret < 0) {
- if (!url_feof(&var->pb) && ret != AVERROR_EOF)
+ if (!url_feof(&pls->pb) && ret != AVERROR_EOF)
return ret;
- reset_packet(&var->pkt);
+ reset_packet(&pls->pkt);
break;
} else {
+ /* stream_index check prevents matching picture attachments etc. */
+ if (pls->is_id3_timestamped && pls->pkt.stream_index == 0) {
+ /* audio elementary streams are id3 timestamped */
+ fill_timing_for_id3_timestamped_stream(pls);
+ }
+
if (c->first_timestamp == AV_NOPTS_VALUE &&
- var->pkt.dts != AV_NOPTS_VALUE)
- c->first_timestamp = av_rescale_q(var->pkt.dts,
- var->ctx->streams[var->pkt.stream_index]->time_base,
- AV_TIME_BASE_Q);
+ pls->pkt.dts != AV_NOPTS_VALUE)
+ c->first_timestamp = av_rescale_q(pls->pkt.dts,
+ get_timebase(pls), AV_TIME_BASE_Q);
}
- if (c->seek_timestamp == AV_NOPTS_VALUE)
+ if (pls->seek_timestamp == AV_NOPTS_VALUE)
break;
- if (var->pkt.dts == AV_NOPTS_VALUE) {
- c->seek_timestamp = AV_NOPTS_VALUE;
- break;
- }
+ if (pls->seek_stream_index < 0 ||
+ pls->seek_stream_index == pls->pkt.stream_index) {
- st = var->ctx->streams[var->pkt.stream_index];
- ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE,
- st->time_base.den, AV_ROUND_DOWN) -
- c->seek_timestamp;
- if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY ||
- var->pkt.flags & AV_PKT_FLAG_KEY)) {
- c->seek_timestamp = AV_NOPTS_VALUE;
- break;
+ if (pls->pkt.dts == AV_NOPTS_VALUE) {
+ pls->seek_timestamp = AV_NOPTS_VALUE;
+ break;
+ }
+
+ tb = get_timebase(pls);
+ ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE,
+ tb.den, AV_ROUND_DOWN) -
+ pls->seek_timestamp;
+ if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY ||
+ pls->pkt.flags & AV_PKT_FLAG_KEY)) {
+ pls->seek_timestamp = AV_NOPTS_VALUE;
+ break;
+ }
}
- av_free_packet(&var->pkt);
- reset_packet(&var->pkt);
+ av_free_packet(&pls->pkt);
+ reset_packet(&pls->pkt);
}
}
- /* Check if this stream still is on an earlier segment number, or
- * has the packet with the lowest dts */
- if (var->pkt.data) {
- struct variant *minvar = minvariant < 0 ?
- NULL : c->variants[minvariant];
- if (minvariant < 0 || var->cur_seq_no < minvar->cur_seq_no) {
- minvariant = i;
- } else if (var->cur_seq_no == minvar->cur_seq_no) {
- int64_t dts = var->pkt.dts;
- int64_t mindts = minvar->pkt.dts;
- AVStream *st = var->ctx->streams[var->pkt.stream_index];
- AVStream *minst = minvar->ctx->streams[minvar->pkt.stream_index];
-
- if (dts == AV_NOPTS_VALUE) {
- minvariant = i;
- } else if (mindts != AV_NOPTS_VALUE) {
- if (st->start_time != AV_NOPTS_VALUE)
- dts -= st->start_time;
- if (minst->start_time != AV_NOPTS_VALUE)
- mindts -= minst->start_time;
-
- if (av_compare_ts(dts, st->time_base,
- mindts, minst->time_base) < 0)
- minvariant = i;
- }
+ /* Check if this stream has the packet with the lowest dts */
+ if (pls->pkt.data) {
+ struct playlist *minpls = minplaylist < 0 ?
+ NULL : c->playlists[minplaylist];
+ if (minplaylist < 0) {
+ minplaylist = i;
+ } else {
+ int64_t dts = pls->pkt.dts;
+ int64_t mindts = minpls->pkt.dts;
+
+ if (dts == AV_NOPTS_VALUE ||
+ (mindts != AV_NOPTS_VALUE && compare_ts_with_wrapdetect(dts, pls, mindts, minpls) < 0))
+ minplaylist = i;
}
}
}
- if (c->end_of_segment) {
- if (recheck_discard_flags(s, 0))
- goto start;
- }
+
/* If we got a packet, return it */
- if (minvariant >= 0) {
- *pkt = c->variants[minvariant]->pkt;
- pkt->stream_index += c->variants[minvariant]->stream_offset;
- reset_packet(&c->variants[minvariant]->pkt);
+ if (minplaylist >= 0) {
+ struct playlist *pls = c->playlists[minplaylist];
+ *pkt = pls->pkt;
+ pkt->stream_index += pls->stream_offset;
+ reset_packet(&c->playlists[minplaylist]->pkt);
+
+ if (pkt->dts != AV_NOPTS_VALUE)
+ c->cur_timestamp = av_rescale_q(pkt->dts,
+ pls->ctx->streams[pls->pkt.stream_index]->time_base,
+ AV_TIME_BASE_Q);
+
return 0;
}
return AVERROR_EOF;
@@ -767,7 +1612,9 @@ static int hls_close(AVFormatContext *s)
{
HLSContext *c = s->priv_data;
+ free_playlist_list(c);
free_variant_list(c);
+ free_rendition_list(c);
return 0;
}
@@ -775,58 +1622,80 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
HLSContext *c = s->priv_data;
- int i, j, ret;
+ struct playlist *seek_pls = NULL;
+ int i, seq_no;
+ int64_t first_timestamp, seek_timestamp, duration;
- if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
+ if ((flags & AVSEEK_FLAG_BYTE) ||
+ !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT))
return AVERROR(ENOSYS);
- c->seek_flags = flags;
- c->seek_timestamp = stream_index < 0 ? timestamp :
- av_rescale_rnd(timestamp, AV_TIME_BASE,
- s->streams[stream_index]->time_base.den,
- flags & AVSEEK_FLAG_BACKWARD ?
- AV_ROUND_DOWN : AV_ROUND_UP);
- timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ?
- s->streams[stream_index]->time_base.den :
- AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
- AV_ROUND_DOWN : AV_ROUND_UP);
- if (s->duration < c->seek_timestamp) {
- c->seek_timestamp = AV_NOPTS_VALUE;
+ first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ?
+ 0 : c->first_timestamp;
+
+ seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE,
+ s->streams[stream_index]->time_base.den,
+ flags & AVSEEK_FLAG_BACKWARD ?
+ AV_ROUND_DOWN : AV_ROUND_UP);
+
+ duration = s->duration == AV_NOPTS_VALUE ?
+ 0 : s->duration;
+
+ if (0 < duration && duration < seek_timestamp - first_timestamp)
return AVERROR(EIO);
+
+ /* find the playlist with the specified stream */
+ for (i = 0; i < c->n_playlists; i++) {
+ struct playlist *pls = c->playlists[i];
+ if (stream_index >= pls->stream_offset &&
+ stream_index - pls->stream_offset < pls->ctx->nb_streams) {
+ seek_pls = pls;
+ break;
+ }
}
+ /* check if the timestamp is valid for the playlist with the
+ * specified stream index */
+ if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no))
+ return AVERROR(EIO);
- ret = AVERROR(EIO);
- for (i = 0; i < c->n_variants; i++) {
+ /* set segment now so we do not need to search again below */
+ seek_pls->cur_seq_no = seq_no;
+ seek_pls->seek_stream_index = stream_index - seek_pls->stream_offset;
+
+ for (i = 0; i < c->n_playlists; i++) {
/* Reset reading */
- struct variant *var = c->variants[i];
- int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
- 0 : c->first_timestamp;
- if (var->input) {
- ffurl_close(var->input);
- var->input = NULL;
+ struct playlist *pls = c->playlists[i];
+ if (pls->input) {
+ ffurl_close(pls->input);
+ pls->input = NULL;
}
- av_free_packet(&var->pkt);
- reset_packet(&var->pkt);
- var->pb.eof_reached = 0;
+ av_free_packet(&pls->pkt);
+ reset_packet(&pls->pkt);
+ pls->pb.eof_reached = 0;
/* Clear any buffered data */
- var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer;
+ pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer;
/* Reset the pos, to let the mpegts demuxer know we've seeked. */
- var->pb.pos = 0;
-
- /* Locate the segment that contains the target timestamp */
- for (j = 0; j < var->n_segments; j++) {
- if (timestamp >= pos &&
- timestamp < pos + var->segments[j]->duration) {
- var->cur_seq_no = var->start_seq_no + j;
- ret = 0;
- break;
- }
- pos += var->segments[j]->duration;
+ pls->pb.pos = 0;
+ /* Flush the packet queue of the subdemuxer. */
+ ff_read_frame_flush(pls->ctx);
+
+ pls->seek_timestamp = seek_timestamp;
+ pls->seek_flags = flags;
+
+ if (pls != seek_pls) {
+ /* set closest segment seq_no for playlists not handled above */
+ find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no);
+ /* seek the playlist to the given position without taking
+ * keyframes into account since this playlist does not have the
+ * specified stream where we should look for the keyframes */
+ pls->seek_stream_index = -1;
+ pls->seek_flags |= AVSEEK_FLAG_ANY;
}
- if (ret)
- c->seek_timestamp = AV_NOPTS_VALUE;
}
- return ret;
+
+ c->cur_timestamp = seek_timestamp;
+
+ return 0;
}
static int hls_probe(AVProbeData *p)
diff --git a/chromium/third_party/ffmpeg/libavformat/hlsenc.c b/chromium/third_party/ffmpeg/libavformat/hlsenc.c
index b9bf60543fa..12bd07b2d43 100644
--- a/chromium/third_party/ffmpeg/libavformat/hlsenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/hlsenc.c
@@ -33,7 +33,7 @@
typedef struct ListEntry {
char name[1024];
- int duration;
+ double duration;
struct ListEntry *next;
} ListEntry;
@@ -41,6 +41,7 @@ typedef struct HLSContext {
const AVClass *class; // Class for private options.
unsigned number;
int64_t sequence;
+ int64_t start_sequence;
AVOutputFormat *oformat;
AVFormatContext *avf;
float time; // Set by a private option.
@@ -50,11 +51,12 @@ typedef struct HLSContext {
int has_video;
int64_t start_pts;
int64_t end_pts;
- int64_t duration; // last segment duration computed so far, in seconds
+ double duration; // last segment duration computed so far, in seconds
int nb_entries;
ListEntry *list;
ListEntry *end_list;
char *basename;
+ char *baseurl;
AVIOContext *pb;
} HLSContext;
@@ -70,6 +72,7 @@ static int hls_mux_init(AVFormatContext *s)
oc->oformat = hls->oformat;
oc->interrupt_callback = s->interrupt_callback;
+ av_dict_copy(&oc->metadata, s->metadata, 0);
for (i = 0; i < s->nb_streams; i++) {
AVStream *st;
@@ -82,7 +85,7 @@ static int hls_mux_init(AVFormatContext *s)
return 0;
}
-static int append_entry(HLSContext *hls, uint64_t duration)
+static int append_entry(HLSContext *hls, double duration)
{
ListEntry *en = av_malloc(sizeof(*en));
@@ -101,7 +104,7 @@ static int append_entry(HLSContext *hls, uint64_t duration)
hls->end_list = en;
- if (hls->nb_entries >= hls->size) {
+ if (hls->size && hls->nb_entries >= hls->size) {
en = hls->list;
hls->list = en->next;
av_free(en);
@@ -130,6 +133,7 @@ static int hls_window(AVFormatContext *s, int last)
ListEntry *en;
int target_duration = 0;
int ret = 0;
+ int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries);
if ((ret = avio_open2(&hls->pb, s->filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL)) < 0)
@@ -137,17 +141,21 @@ static int hls_window(AVFormatContext *s, int last)
for (en = hls->list; en; en = en->next) {
if (target_duration < en->duration)
- target_duration = en->duration;
+ target_duration = (int) floor(en->duration + 0.5);
}
avio_printf(hls->pb, "#EXTM3U\n");
avio_printf(hls->pb, "#EXT-X-VERSION:3\n");
avio_printf(hls->pb, "#EXT-X-TARGETDURATION:%d\n", target_duration);
- avio_printf(hls->pb, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
- FFMAX(0, hls->sequence - hls->size));
+ avio_printf(hls->pb, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+
+ av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
+ sequence);
for (en = hls->list; en; en = en->next) {
- avio_printf(hls->pb, "#EXTINF:%d,\n", en->duration);
+ avio_printf(hls->pb, "#EXTINF:%f,\n", en->duration);
+ if (hls->baseurl)
+ avio_printf(hls->pb, "%s", hls->baseurl);
avio_printf(hls->pb, "%s\n", en->name);
}
@@ -166,7 +174,7 @@ static int hls_start(AVFormatContext *s)
int err = 0;
if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
- c->basename, c->wrap ? c->number % c->wrap : c->number) < 0) {
+ c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename);
return AVERROR(EINVAL);
}
@@ -190,8 +198,7 @@ static int hls_write_header(AVFormatContext *s)
const char *pattern = "%d.ts";
int basename_size = strlen(s->filename) + strlen(pattern) + 1;
- hls->number = 0;
-
+ hls->sequence = hls->start_sequence;
hls->recording_time = hls->time * AV_TIME_BASE;
hls->start_pts = AV_NOPTS_VALUE;
@@ -269,8 +276,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
is_ref_pkt = can_split = 0;
if (is_ref_pkt)
- hls->duration = av_rescale(pkt->pts - hls->end_pts,
- st->time_base.num, st->time_base.den);
+ hls->duration = (double)(pkt->pts - hls->end_pts)
+ * st->time_base.num / st->time_base.den;
if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base,
end_pts, AV_TIME_BASE_Q) >= 0) {
@@ -320,10 +327,11 @@ static int hls_write_trailer(struct AVFormatContext *s)
#define OFFSET(x) offsetof(HLSContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
- {"start_number", "set first number in the sequence", OFFSET(sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
+ {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
{"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E},
{"hls_list_size", "set maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
{"hls_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
+ {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
{ NULL },
};
diff --git a/chromium/third_party/ffmpeg/libavformat/hnm.c b/chromium/third_party/ffmpeg/libavformat/hnm.c
index 47a1808afba..1320fa52062 100644
--- a/chromium/third_party/ffmpeg/libavformat/hnm.c
+++ b/chromium/third_party/ffmpeg/libavformat/hnm.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
@@ -90,7 +92,7 @@ static int hnm_read_header(AVFormatContext *s)
hnm->currentframe = 0;
- if (hnm->width < 320 || hnm->width > 640 ||
+ if (hnm->width < 256 || hnm->width > 640 ||
hnm->height < 150 || hnm->height > 480) {
av_log(s, AV_LOG_ERROR,
"invalid resolution: %ux%u\n", hnm->width, hnm->height);
@@ -149,8 +151,9 @@ static int hnm_read_packet(AVFormatContext *s, AVPacket *pkt)
avio_skip(pb, 2);
if (chunk_size > hnm->superchunk_remaining || !chunk_size) {
- av_log(s, AV_LOG_ERROR, "invalid chunk size: %u, offset: %u\n",
- chunk_size, (int) avio_tell(pb));
+ av_log(s, AV_LOG_ERROR,
+ "invalid chunk size: %"PRIu32", offset: %"PRId64"\n",
+ chunk_size, avio_tell(pb));
avio_skip(pb, hnm->superchunk_remaining - 8);
hnm->superchunk_remaining = 0;
}
@@ -172,8 +175,8 @@ static int hnm_read_packet(AVFormatContext *s, AVPacket *pkt)
break;
default:
- av_log(s, AV_LOG_WARNING, "unknown chunk found: %d, offset: %d\n",
- chunk_id, (int) avio_tell(pb));
+ av_log(s, AV_LOG_WARNING, "unknown chunk found: %"PRIu16", offset: %"PRId64"\n",
+ chunk_id, avio_tell(pb));
avio_skip(pb, chunk_size - 8);
hnm->superchunk_remaining -= chunk_size;
break;
diff --git a/chromium/third_party/ffmpeg/libavformat/http.c b/chromium/third_party/ffmpeg/libavformat/http.c
index 0619e2a06cf..3e172e36455 100644
--- a/chromium/third_party/ffmpeg/libavformat/http.c
+++ b/chromium/third_party/ffmpeg/libavformat/http.c
@@ -49,29 +49,37 @@ typedef struct {
unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
int line_count;
int http_code;
- int64_t chunksize; /**< Used if "Transfer-Encoding: chunked" otherwise -1. */
- char *content_type;
- char *user_agent;
- int64_t off, filesize;
- int icy_data_read; ///< how much data was read since last ICY metadata packet
- int icy_metaint; ///< after how many bytes of read data a new metadata packet will be found
+ /* Used if "Transfer-Encoding: chunked" otherwise -1. */
+ int64_t chunksize;
+ int64_t off, end_off, filesize;
char *location;
HTTPAuthState auth_state;
HTTPAuthState proxy_auth_state;
char *headers;
- int willclose; /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */
+ char *mime_type;
+ char *user_agent;
+ char *content_type;
+ /* Set if the server correctly handles Connection: close and will close
+ * the connection after feeding us the content. */
+ int willclose;
int seekable; /**< Control seekability, 0 = disable, 1 = enable, -1 = probe. */
int chunked_post;
- int end_chunked_post; /**< A flag which indicates if the end of chunked encoding has been sent. */
- int end_header; /**< A flag which indicates we have finished to read POST reply. */
- int multiple_requests; /**< A flag which indicates if we use persistent connections. */
+ /* A flag which indicates if the end of chunked encoding has been sent. */
+ int end_chunked_post;
+ /* A flag which indicates we have finished to read POST reply. */
+ int end_header;
+ /* A flag which indicates if we use persistent connections. */
+ int multiple_requests;
uint8_t *post_data;
int post_datalen;
int is_akamai;
int is_mediagateway;
- char *mime_type;
char *cookies; ///< holds newline (\n) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
int icy;
+ /* how much data was read since the last ICY metadata packet */
+ int icy_data_read;
+ /* after how many bytes of read data a new metadata packet will be found */
+ int icy_metaint;
char *icy_metadata_headers;
char *icy_metadata_packet;
#if CONFIG_ZLIB
@@ -91,20 +99,23 @@ static const AVOption options[] = {
{"seekable", "control seekability of connection", OFFSET(seekable), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, D },
{"chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
{"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
-{"content_type", "force a content type", OFFSET(content_type), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
+{"content_type", "set a specific content type for the POST messages", OFFSET(content_type), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
+{"user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = DEFAULT_USER_AGENT}, 0, 0, D },
{"user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = DEFAULT_USER_AGENT}, 0, 0, D },
{"multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
{"post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D|E },
-{"mime_type", "set MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
+{"mime_type", "export the MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {0}, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
{"cookies", "set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax", OFFSET(cookies), AV_OPT_TYPE_STRING, {0}, 0, 0, D },
{"icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D },
-{"icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
-{"icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 },
+{"icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, {0}, 0, 0, AV_OPT_FLAG_EXPORT },
+{"icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, {0}, 0, 0, AV_OPT_FLAG_EXPORT },
{"auth_type", "HTTP authentication type", OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, {.i64 = HTTP_AUTH_NONE}, HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D|E, "auth_type" },
{"none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, {.i64 = HTTP_AUTH_NONE}, 0, 0, D|E, "auth_type" },
{"basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, {.i64 = HTTP_AUTH_BASIC}, 0, 0, D|E, "auth_type" },
{"send_expect_100", "Force sending an Expect: 100-continue header for POST", OFFSET(send_expect_100), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
{"location", "The actual location of the data received", OFFSET(location), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
+{"offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D },
+{"end_offset", "try to limit the request to bytes preceding this offset", OFFSET(end_off), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D },
{NULL}
};
#define HTTP_CLASS(flavor)\
@@ -285,7 +296,7 @@ static int http_getc(HTTPContext *s)
if (len < 0) {
return len;
} else if (len == 0) {
- return -1;
+ return AVERROR_EOF;
} else {
s->buf_ptr = s->buffer;
s->buf_end = s->buffer + len;
@@ -318,11 +329,110 @@ static int http_get_line(HTTPContext *s, char *line, int line_size)
}
}
+static int check_http_code(URLContext *h, int http_code, const char *end)
+{
+ HTTPContext *s = h->priv_data;
+ /* error codes are 4xx and 5xx, but regard 401 as a success, so we
+ * don't abort until all headers have been parsed. */
+ if (http_code >= 400 && http_code < 600 &&
+ (http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
+ (http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
+ end += strspn(end, SPACE_CHARS);
+ av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", http_code, end);
+ return AVERROR(EIO);
+ }
+ return 0;
+}
+
+static int parse_location(HTTPContext *s, const char *p)
+{
+ char redirected_location[MAX_URL_SIZE], *new_loc;
+ ff_make_absolute_url(redirected_location, sizeof(redirected_location),
+ s->location, p);
+ new_loc = av_strdup(redirected_location);
+ if (!new_loc)
+ return AVERROR(ENOMEM);
+ av_free(s->location);
+ s->location = new_loc;
+ return 0;
+}
+
+/* "bytes $from-$to/$document_size" */
+static void parse_content_range(URLContext *h, const char *p)
+{
+ HTTPContext *s = h->priv_data;
+ const char *slash;
+
+ if (!strncmp(p, "bytes ", 6)) {
+ p += 6;
+ s->off = strtoll(p, NULL, 10);
+ if ((slash = strchr(p, '/')) && strlen(slash) > 0)
+ s->filesize = strtoll(slash+1, NULL, 10);
+ }
+ if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
+ h->is_streamed = 0; /* we _can_ in fact seek */
+}
+
+static int parse_content_encoding(URLContext *h, const char *p)
+{
+ HTTPContext *s = h->priv_data;
+
+ if (!av_strncasecmp(p, "gzip", 4) ||
+ !av_strncasecmp(p, "deflate", 7)) {
+#if CONFIG_ZLIB
+ s->compressed = 1;
+ inflateEnd(&s->inflate_stream);
+ if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
+ av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
+ s->inflate_stream.msg);
+ return AVERROR(ENOSYS);
+ }
+ if (zlibCompileFlags() & (1 << 17)) {
+ av_log(h, AV_LOG_WARNING,
+ "Your zlib was compiled without gzip support.\n");
+ return AVERROR(ENOSYS);
+ }
+#else
+ av_log(h, AV_LOG_WARNING,
+ "Compressed (%s) content, need zlib with gzip support\n", p);
+ return AVERROR(ENOSYS);
+#endif
+ } else if (!av_strncasecmp(p, "identity", 8)) {
+ // The normal, no-encoding case (although servers shouldn't include
+ // the header at all if this is the case).
+ } else {
+ av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
+ }
+ return 0;
+}
+
+// Concat all Icy- header lines
+static int parse_icy(HTTPContext *s, const char *tag, const char *p)
+{
+ int len = 4 + strlen(p) + strlen(tag);
+ int is_first = !s->icy_metadata_headers;
+ int ret;
+
+ if (s->icy_metadata_headers)
+ len += strlen(s->icy_metadata_headers);
+
+ if ((ret = av_reallocp(&s->icy_metadata_headers, len)) < 0)
+ return ret;
+
+ if (is_first)
+ *s->icy_metadata_headers = '\0';
+
+ av_strlcatf(s->icy_metadata_headers, len, "%s: %s\n", tag, p);
+
+ return 0;
+}
+
static int process_line(URLContext *h, char *line, int line_count,
int *new_location)
{
HTTPContext *s = h->priv_data;
char *tag, *p, *end;
+ int ret;
/* end of header */
if (line[0] == '\0') {
@@ -340,16 +450,8 @@ static int process_line(URLContext *h, char *line, int line_count,
av_log(h, AV_LOG_DEBUG, "http_code=%d\n", s->http_code);
- /* error codes are 4xx and 5xx, but regard 401 as a success, so we
- * don't abort until all headers have been parsed. */
- if (s->http_code >= 400 && s->http_code < 600 && (s->http_code != 401
- || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
- (s->http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
- end += strspn(end, SPACE_CHARS);
- av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n",
- s->http_code, end);
- return -1;
- }
+ if ((ret = check_http_code(h, s->http_code, end)) < 0)
+ return ret;
} else {
while (*p != '\0' && *p != ':')
p++;
@@ -362,40 +464,28 @@ static int process_line(URLContext *h, char *line, int line_count,
while (av_isspace(*p))
p++;
if (!av_strcasecmp(tag, "Location")) {
- char redirected_location[MAX_URL_SIZE], *new_loc;
- ff_make_absolute_url(redirected_location, sizeof(redirected_location),
- s->location, p);
- new_loc = av_strdup(redirected_location);
- if (!new_loc)
- return AVERROR(ENOMEM);
- av_free(s->location);
- s->location = new_loc;
+ if ((ret = parse_location(s, p)) < 0)
+ return ret;
*new_location = 1;
- } else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) {
+ } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == -1) {
s->filesize = strtoll(p, NULL, 10);
- } else if (!av_strcasecmp (tag, "Content-Range")) {
- /* "bytes $from-$to/$document_size" */
- const char *slash;
- if (!strncmp (p, "bytes ", 6)) {
- p += 6;
- s->off = strtoll(p, NULL, 10);
- if ((slash = strchr(p, '/')) && strlen(slash) > 0)
- s->filesize = strtoll(slash+1, NULL, 10);
- }
- if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
- h->is_streamed = 0; /* we _can_ in fact seek */
- } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5) && s->seekable == -1) {
+ } else if (!av_strcasecmp(tag, "Content-Range")) {
+ parse_content_range(h, p);
+ } else if (!av_strcasecmp(tag, "Accept-Ranges") &&
+ !strncmp(p, "bytes", 5) &&
+ s->seekable == -1) {
h->is_streamed = 0;
- } else if (!av_strcasecmp (tag, "Transfer-Encoding") && !av_strncasecmp(p, "chunked", 7)) {
+ } else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
+ !av_strncasecmp(p, "chunked", 7)) {
s->filesize = -1;
s->chunksize = 0;
- } else if (!av_strcasecmp (tag, "WWW-Authenticate")) {
+ } else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
ff_http_auth_handle_header(&s->auth_state, tag, p);
- } else if (!av_strcasecmp (tag, "Authentication-Info")) {
+ } else if (!av_strcasecmp(tag, "Authentication-Info")) {
ff_http_auth_handle_header(&s->auth_state, tag, p);
- } else if (!av_strcasecmp (tag, "Proxy-Authenticate")) {
+ } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) {
ff_http_auth_handle_header(&s->proxy_auth_state, tag, p);
- } else if (!av_strcasecmp (tag, "Connection")) {
+ } else if (!av_strcasecmp(tag, "Connection")) {
if (!strcmp(p, "close"))
s->willclose = 1;
} else if (!av_strcasecmp (tag, "Server")) {
@@ -405,7 +495,8 @@ static int process_line(URLContext *h, char *line, int line_count,
s->is_mediagateway = 1;
}
} else if (!av_strcasecmp (tag, "Content-Type")) {
- av_free(s->mime_type); s->mime_type = av_strdup(p);
+ av_free(s->mime_type);
+ s->mime_type = av_strdup(p);
} else if (!av_strcasecmp (tag, "Set-Cookie")) {
if (!s->cookies) {
if (!(s->cookies = av_strdup(p)))
@@ -423,37 +514,11 @@ static int process_line(URLContext *h, char *line, int line_count,
} else if (!av_strcasecmp (tag, "Icy-MetaInt")) {
s->icy_metaint = strtoll(p, NULL, 10);
} else if (!av_strncasecmp(tag, "Icy-", 4)) {
- // Concat all Icy- header lines
- char *buf = av_asprintf("%s%s: %s\n",
- s->icy_metadata_headers ? s->icy_metadata_headers : "", tag, p);
- if (!buf)
- return AVERROR(ENOMEM);
- av_freep(&s->icy_metadata_headers);
- s->icy_metadata_headers = buf;
- } else if (!av_strcasecmp (tag, "Content-Encoding")) {
- if (!av_strncasecmp(p, "gzip", 4) || !av_strncasecmp(p, "deflate", 7)) {
-#if CONFIG_ZLIB
- s->compressed = 1;
- inflateEnd(&s->inflate_stream);
- if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
- av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
- s->inflate_stream.msg);
- return AVERROR(ENOSYS);
- }
- if (zlibCompileFlags() & (1 << 17)) {
- av_log(h, AV_LOG_WARNING, "Your zlib was compiled without gzip support.\n");
- return AVERROR(ENOSYS);
- }
-#else
- av_log(h, AV_LOG_WARNING, "Compressed (%s) content, need zlib with gzip support\n", p);
- return AVERROR(ENOSYS);
-#endif
- } else if (!av_strncasecmp(p, "identity", 8)) {
- // The normal, no-encoding case (although servers shouldn't include
- // the header at all if this is the case).
- } else {
- av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
- }
+ if ((ret = parse_icy(s, tag, p)) < 0)
+ return ret;
+ } else if (!av_strcasecmp(tag, "Content-Encoding")) {
+ if ((ret = parse_content_encoding(h, p)) < 0)
+ return ret;
}
}
return 1;
@@ -488,8 +553,11 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
av_free(cpath);
cpath = av_strdup(&param[5]);
} else if (!av_strncasecmp("domain=", param, 7)) {
+ // if the cookie specifies a sub-domain, skip the leading dot thereby
+ // supporting URLs that point to sub-domains and the master domain
+ int leading_dot = (param[7] == '.');
av_free(cdomain);
- cdomain = av_strdup(&param[7]);
+ cdomain = av_strdup(&param[7+leading_dot]);
} else if (!av_strncasecmp("secure", param, 6) ||
!av_strncasecmp("comment", param, 7) ||
!av_strncasecmp("max-age", param, 7) ||
@@ -643,9 +711,15 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
// Note: we send this on purpose even when s->off is 0 when we're probing,
// since it allows us to detect more reliably if a (non-conforming)
// server supports seeking by analysing the reply headers.
- if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->seekable == -1))
+ if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) {
len += av_strlcatf(headers + len, sizeof(headers) - len,
- "Range: bytes=%"PRId64"-\r\n", s->off);
+ "Range: bytes=%"PRId64"-", s->off);
+ if (s->end_off)
+ len += av_strlcatf(headers + len, sizeof(headers) - len,
+ "%"PRId64, s->end_off - 1);
+ len += av_strlcpy(headers + len, "\r\n",
+ sizeof(headers) - len);
+ }
if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
len += av_strlcatf(headers + len, sizeof(headers) - len,
"Expect: 100-continue\r\n");
@@ -666,12 +740,13 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
len += av_strlcatf(headers + len, sizeof(headers) - len,
"Content-Length: %d\r\n", s->post_datalen);
+
if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
len += av_strlcatf(headers + len, sizeof(headers) - len,
"Content-Type: %s\r\n", s->content_type);
if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
char *cookies = NULL;
- if (!get_cookies(s, &cookies, path, hoststr)) {
+ if (!get_cookies(s, &cookies, path, hoststr) && cookies) {
len += av_strlcatf(headers + len, sizeof(headers) - len,
"Cookie: %s\r\n", cookies);
av_free(cookies);
@@ -700,17 +775,14 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
authstr ? authstr : "",
proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : "");
- av_freep(&authstr);
- av_freep(&proxyauthstr);
-
av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer);
if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
- return err;
+ goto done;
if (s->post_data)
if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
- return err;
+ goto done;
/* init input buffer */
s->buf_ptr = s->buffer;
@@ -727,15 +799,20 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
* we've still to send the POST data, but the code calling this
* function will check http_code after we return. */
s->http_code = 200;
- return 0;
+ err = 0;
+ goto done;
}
/* wait for header */
err = http_read_header(h, new_location);
if (err < 0)
- return err;
+ goto done;
- return (off == s->off) ? 0 : -1;
+ err = (off == s->off) ? 0 : -1;
+done:
+ av_freep(&authstr);
+ av_freep(&proxyauthstr);
+ return err;
}
@@ -757,7 +834,6 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size)
}
if (len > 0) {
s->off += len;
- s->icy_data_read += len;
if (s->chunksize > 0)
s->chunksize -= len;
}
@@ -796,7 +872,7 @@ static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
}
#endif
-static int http_read(URLContext *h, uint8_t *buf, int size)
+static int http_read_stream(URLContext *h, uint8_t *buf, int size)
{
HTTPContext *s = h->priv_data;
int err, new_location;
@@ -814,7 +890,6 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
if (!s->chunksize) {
char line[32];
- for(;;) {
do {
if ((err = http_get_line(s, line, sizeof(line))) < 0)
return err;
@@ -826,37 +901,9 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
if (!s->chunksize)
return 0;
- break;
- }
}
size = FFMIN(size, s->chunksize);
}
- if (s->icy_metaint > 0) {
- int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */
- if (!remaining) {
- // The metadata packet is variable sized. It has a 1 byte header
- // which sets the length of the packet (divided by 16). If it's 0,
- // the metadata doesn't change. After the packet, icy_metaint bytes
- // of normal data follow.
- int ch = http_getc(s);
- if (ch < 0)
- return ch;
- if (ch > 0) {
- char data[255 * 16 + 1];
- int n;
- int ret;
- ch *= 16;
- for (n = 0; n < ch; n++)
- data[n] = http_getc(s);
- data[ch + 1] = 0;
- if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
- return ret;
- }
- s->icy_data_read = 0;
- remaining = s->icy_metaint;
- }
- size = FFMIN(size, remaining);
- }
#if CONFIG_ZLIB
if (s->compressed)
return http_buf_read_compressed(h, buf, size);
@@ -864,6 +911,72 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
return http_buf_read(h, buf, size);
}
+// Like http_read_stream(), but no short reads.
+// Assumes partial reads are an error.
+static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
+{
+ int pos = 0;
+ while (pos < size) {
+ int len = http_read_stream(h, buf + pos, size - pos);
+ if (len < 0)
+ return len;
+ pos += len;
+ }
+ return pos;
+}
+
+static int store_icy(URLContext *h, int size)
+{
+ HTTPContext *s = h->priv_data;
+ /* until next metadata packet */
+ int remaining = s->icy_metaint - s->icy_data_read;
+
+ if (remaining < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (!remaining) {
+ // The metadata packet is variable sized. It has a 1 byte header
+ // which sets the length of the packet (divided by 16). If it's 0,
+ // the metadata doesn't change. After the packet, icy_metaint bytes
+ // of normal data follow.
+ uint8_t ch;
+ int len = http_read_stream_all(h, &ch, 1);
+ if (len < 0)
+ return len;
+ if (ch > 0) {
+ char data[255 * 16 + 1];
+ int ret;
+ len = ch * 16;
+ ret = http_read_stream_all(h, data, len);
+ if (ret < 0)
+ return ret;
+ data[len + 1] = 0;
+ if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
+ return ret;
+ }
+ s->icy_data_read = 0;
+ remaining = s->icy_metaint;
+ }
+
+ return FFMIN(size, remaining);
+}
+
+static int http_read(URLContext *h, uint8_t *buf, int size)
+{
+ HTTPContext *s = h->priv_data;
+
+ if (s->icy_metaint > 0) {
+ size = store_icy(h, size);
+ if (size < 0)
+ return size;
+ }
+
+ size = http_read_stream(h, buf, size);
+ if (size > 0)
+ s->icy_data_read += size;
+ return size;
+}
+
/* used only when posting data */
static int http_write(URLContext *h, const uint8_t *buf, int size)
{
@@ -934,34 +1047,42 @@ static int64_t http_seek(URLContext *h, int64_t off, int whence)
URLContext *old_hd = s->hd;
int64_t old_off = s->off;
uint8_t old_buf[BUFFER_SIZE];
- int old_buf_size;
+ int old_buf_size, ret;
AVDictionary *options = NULL;
if (whence == AVSEEK_SIZE)
return s->filesize;
+ else if ((whence == SEEK_CUR && off == 0) ||
+ (whence == SEEK_SET && off == s->off))
+ return s->off;
else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed)
- return -1;
+ return AVERROR(ENOSYS);
- /* we save the old context in case the seek fails */
- old_buf_size = s->buf_end - s->buf_ptr;
- memcpy(old_buf, s->buf_ptr, old_buf_size);
- s->hd = NULL;
if (whence == SEEK_CUR)
off += s->off;
else if (whence == SEEK_END)
off += s->filesize;
+ else if (whence != SEEK_SET)
+ return AVERROR(EINVAL);
+ if (off < 0)
+ return AVERROR(EINVAL);
s->off = off;
+ /* we save the old context in case the seek fails */
+ old_buf_size = s->buf_end - s->buf_ptr;
+ memcpy(old_buf, s->buf_ptr, old_buf_size);
+ s->hd = NULL;
+
/* if it fails, continue on old connection */
av_dict_copy(&options, s->chained_options, 0);
- if (http_open_cnx(h, &options) < 0) {
+ if ((ret = http_open_cnx(h, &options)) < 0) {
av_dict_free(&options);
memcpy(s->buffer, old_buf, old_buf_size);
s->buf_ptr = s->buffer;
s->buf_end = s->buffer + old_buf_size;
s->hd = old_hd;
s->off = old_off;
- return -1;
+ return ret;
}
av_dict_free(&options);
ffurl_close(old_hd);
diff --git a/chromium/third_party/ffmpeg/libavformat/httpauth.c b/chromium/third_party/ffmpeg/libavformat/httpauth.c
index 5ca48b9c1de..dbe3eff48f5 100644
--- a/chromium/third_party/ffmpeg/libavformat/httpauth.c
+++ b/chromium/third_party/ffmpeg/libavformat/httpauth.c
@@ -224,8 +224,11 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username,
av_strlcatf(authstr, len, ",nonce=\"%s\"", digest->nonce);
av_strlcatf(authstr, len, ",uri=\"%s\"", uri);
av_strlcatf(authstr, len, ",response=\"%s\"", response);
+
+ // we are violating the RFC and use "" because all others seem to do that too.
if (digest->algorithm[0])
- av_strlcatf(authstr, len, ",algorithm=%s", digest->algorithm);
+ av_strlcatf(authstr, len, ",algorithm=\"%s\"", digest->algorithm);
+
if (digest->opaque[0])
av_strlcatf(authstr, len, ",opaque=\"%s\"", digest->opaque);
if (digest->qop[0]) {
diff --git a/chromium/third_party/ffmpeg/libavformat/icodec.c b/chromium/third_party/ffmpeg/libavformat/icodec.c
index 4c038e96146..847f0eea2f0 100644
--- a/chromium/third_party/ffmpeg/libavformat/icodec.c
+++ b/chromium/third_party/ffmpeg/libavformat/icodec.c
@@ -58,7 +58,7 @@ static int read_header(AVFormatContext *s)
avio_skip(pb, 4);
ico->nb_images = avio_rl16(pb);
- ico->images = av_malloc(ico->nb_images * sizeof(IcoImage));
+ ico->images = av_malloc_array(ico->nb_images, sizeof(IcoImage));
if (!ico->images)
return AVERROR(ENOMEM);
diff --git a/chromium/third_party/ffmpeg/libavformat/icoenc.c b/chromium/third_party/ffmpeg/libavformat/icoenc.c
index 561c6cadcc9..dcf906513af 100644
--- a/chromium/third_party/ffmpeg/libavformat/icoenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/icoenc.c
@@ -101,7 +101,7 @@ static int ico_write_header(AVFormatContext *s)
avio_skip(pb, 16);
}
- ico->images = av_mallocz(ico->nb_images * sizeof(IcoMuxContext));
+ ico->images = av_mallocz_array(ico->nb_images, sizeof(IcoMuxContext));
if (!ico->images)
return AVERROR(ENOMEM);
diff --git a/chromium/third_party/ffmpeg/libavformat/id3v2.c b/chromium/third_party/ffmpeg/libavformat/id3v2.c
index 4bc76a321ca..fb89e83944b 100644
--- a/chromium/third_party/ffmpeg/libavformat/id3v2.c
+++ b/chromium/third_party/ffmpeg/libavformat/id3v2.c
@@ -59,6 +59,7 @@ const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
};
const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
+ { "TCMP", "compilation" },
{ "TDRL", "date" },
{ "TDRC", "date" },
{ "TDEN", "creation_time" },
@@ -71,6 +72,7 @@ const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
static const AVMetadataConv id3v2_2_metadata_conv[] = {
{ "TAL", "album" },
{ "TCO", "genre" },
+ { "TCP", "compilation" },
{ "TT2", "title" },
{ "TEN", "encoded_by" },
{ "TP1", "artist" },
@@ -313,7 +315,7 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen,
* Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
*/
static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen,
- char *tag, ID3v2ExtraMeta **extra_meta)
+ char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
{
ID3v2ExtraMetaGEOB *geob_data = NULL;
ID3v2ExtraMeta *new_extra = NULL;
@@ -325,14 +327,14 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen,
geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB));
if (!geob_data) {
- av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n",
+ av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n",
sizeof(ID3v2ExtraMetaGEOB));
return;
}
new_extra = av_mallocz(sizeof(ID3v2ExtraMeta));
if (!new_extra) {
- av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n",
+ av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n",
sizeof(ID3v2ExtraMeta));
goto fail;
}
@@ -445,7 +447,7 @@ static void free_apic(void *obj)
}
static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen,
- char *tag, ID3v2ExtraMeta **extra_meta)
+ char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
{
int enc, pic_type;
char mimetype[64];
@@ -467,7 +469,12 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen,
taglen--;
/* mimetype */
+ if (isv34) {
taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
+ } else {
+ avio_read(pb, mimetype, 3);
+ mimetype[3] = 0;
+ }
while (mime->id != AV_CODEC_ID_NONE) {
if (!av_strncasecmp(mime->str, mimetype, sizeof(mimetype))) {
id = mime->id;
@@ -518,7 +525,7 @@ fail:
avio_seek(pb, end, SEEK_SET);
}
-static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *ttag, ID3v2ExtraMeta **extra_meta)
+static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *ttag, ID3v2ExtraMeta **extra_meta, int isv34)
{
AVRational time_base = {1, 1000};
uint32_t start, end;
@@ -527,6 +534,14 @@ static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *tta
int taglen;
char tag[5];
+ if (!s) {
+ /* We should probably just put the chapter data to extra_meta here
+ * and do the AVFormatContext-needing part in a separate
+ * ff_id3v2_parse_apic()-like function. */
+ av_log(NULL, AV_LOG_DEBUG, "No AVFormatContext, skipped ID3 chapter data\n");
+ return;
+ }
+
if (decode_str(s, pb, 0, &dst, &len) < 0)
return;
if (len < 16)
@@ -544,15 +559,14 @@ static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *tta
len -= 16;
while (len > 10) {
- avio_read(pb, tag, 4);
+ if (avio_read(pb, tag, 4) < 4)
+ goto end;
tag[4] = 0;
taglen = avio_rb32(pb);
avio_skip(pb, 2);
len -= 10;
- if (taglen < 0 || taglen > len) {
- av_free(dst);
- return;
- }
+ if (taglen < 0 || taglen > len)
+ goto end;
if (tag[0] == 'T')
read_ttag(s, pb, taglen, &chapter->metadata, tag);
else
@@ -562,14 +576,60 @@ static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *tta
ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_34_metadata_conv);
ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_4_metadata_conv);
+end:
av_free(dst);
}
+static void free_priv(void *obj)
+{
+ ID3v2ExtraMetaPRIV *priv = obj;
+ av_freep(&priv->owner);
+ av_freep(&priv->data);
+ av_freep(&priv);
+}
+
+static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen,
+ char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
+{
+ ID3v2ExtraMeta *meta;
+ ID3v2ExtraMetaPRIV *priv;
+
+ meta = av_mallocz(sizeof(*meta));
+ priv = av_mallocz(sizeof(*priv));
+
+ if (!meta || !priv)
+ goto fail;
+
+ if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &priv->owner, &taglen) < 0)
+ goto fail;
+
+ priv->data = av_malloc(taglen);
+ if (!priv->data)
+ goto fail;
+
+ priv->datasize = taglen;
+
+ if (avio_read(pb, priv->data, priv->datasize) != priv->datasize)
+ goto fail;
+
+ meta->tag = "PRIV";
+ meta->data = priv;
+ meta->next = *extra_meta;
+ *extra_meta = meta;
+
+ return;
+
+fail:
+ if (priv)
+ free_priv(priv);
+ av_freep(&meta);
+}
+
typedef struct ID3v2EMFunc {
const char *tag3;
const char *tag4;
void (*read)(AVFormatContext *, AVIOContext *, int, char *,
- ID3v2ExtraMeta **);
+ ID3v2ExtraMeta **, int isv34);
void (*free)(void *obj);
} ID3v2EMFunc;
@@ -577,6 +637,7 @@ static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
{ "GEO", "GEOB", read_geobtag, free_geobtag },
{ "PIC", "APIC", read_apic, free_apic },
{ "CHAP","CHAP", read_chapter, NULL },
+ { "PRIV","PRIV", read_priv, free_priv },
{ NULL }
};
@@ -599,16 +660,17 @@ static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34)
return NULL;
}
-static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
+static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
+ AVFormatContext *s, int len, uint8_t version,
uint8_t flags, ID3v2ExtraMeta **extra_meta)
{
int isv34, unsync;
unsigned tlen;
char tag[5];
- int64_t next, end = avio_tell(s->pb) + len;
+ int64_t next, end = avio_tell(pb) + len;
int taghdrlen;
const char *reason = NULL;
- AVIOContext pb;
+ AVIOContext pb_local;
AVIOContext *pbx;
unsigned char *buffer = NULL;
int buffer_size = 0;
@@ -642,7 +704,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
unsync = flags & 0x80;
if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */
- int extlen = get_size(s->pb, 4);
+ int extlen = get_size(pb, 4);
if (version == 4)
/* In v2.4 the length includes the length field we just read. */
extlen -= 4;
@@ -651,7 +713,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
reason = "invalid extended header length";
goto error;
}
- avio_skip(s->pb, extlen);
+ avio_skip(pb, extlen);
len -= extlen + 4;
if (len < 0) {
reason = "extended header too long.";
@@ -667,18 +729,20 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
unsigned long dlen;
if (isv34) {
- avio_read(s->pb, tag, 4);
+ if (avio_read(pb, tag, 4) < 4)
+ break;
tag[4] = 0;
if (version == 3) {
- tlen = avio_rb32(s->pb);
+ tlen = avio_rb32(pb);
} else
- tlen = get_size(s->pb, 4);
- tflags = avio_rb16(s->pb);
+ tlen = get_size(pb, 4);
+ tflags = avio_rb16(pb);
tunsync = tflags & ID3v2_FLAG_UNSYNCH;
} else {
- avio_read(s->pb, tag, 3);
+ if (avio_read(pb, tag, 3) < 3)
+ break;
tag[3] = 0;
- tlen = avio_rb24(s->pb);
+ tlen = avio_rb24(pb);
}
if (tlen > (1<<28))
break;
@@ -687,7 +751,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
if (len < 0)
break;
- next = avio_tell(s->pb) + tlen;
+ next = avio_tell(pb) + tlen;
if (!tlen) {
if (tag[0])
@@ -699,7 +763,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
if (tflags & ID3v2_FLAG_DATALEN) {
if (tlen < 4)
break;
- dlen = avio_rb32(s->pb);
+ dlen = avio_rb32(pb);
tlen -= 4;
} else
dlen = tlen;
@@ -718,12 +782,12 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
type = "encrypted and compressed";
av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag);
- avio_skip(s->pb, tlen);
+ avio_skip(pb, tlen);
/* check for text tag or supported special meta tag */
} else if (tag[0] == 'T' ||
(extra_meta &&
(extra_func = get_extra_meta_func(tag, isv34)))) {
- pbx = s->pb;
+ pbx = pb;
if (unsync || tunsync || tcomp) {
av_fast_malloc(&buffer, &buffer_size, tlen);
@@ -733,23 +797,23 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
}
}
if (unsync || tunsync) {
- int64_t end = avio_tell(s->pb) + tlen;
+ int64_t end = avio_tell(pb) + tlen;
uint8_t *b;
b = buffer;
- while (avio_tell(s->pb) < end && b - buffer < tlen && !s->pb->eof_reached) {
- *b++ = avio_r8(s->pb);
- if (*(b - 1) == 0xff && avio_tell(s->pb) < end - 1 &&
+ while (avio_tell(pb) < end && b - buffer < tlen && !pb->eof_reached) {
+ *b++ = avio_r8(pb);
+ if (*(b - 1) == 0xff && avio_tell(pb) < end - 1 &&
b - buffer < tlen &&
- !s->pb->eof_reached ) {
- uint8_t val = avio_r8(s->pb);
- *b++ = val ? val : avio_r8(s->pb);
+ !pb->eof_reached ) {
+ uint8_t val = avio_r8(pb);
+ *b++ = val ? val : avio_r8(pb);
}
}
- ffio_init_context(&pb, buffer, b - buffer, 0, NULL, NULL, NULL,
+ ffio_init_context(&pb_local, buffer, b - buffer, 0, NULL, NULL, NULL,
NULL);
tlen = b - buffer;
- pbx = &pb; // read from sync buffer
+ pbx = &pb_local; // read from sync buffer
}
#if CONFIG_ZLIB
@@ -765,7 +829,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
}
if (!(unsync || tunsync)) {
- err = avio_read(s->pb, buffer, tlen);
+ err = avio_read(pb, buffer, tlen);
if (err < 0) {
av_log(s, AV_LOG_ERROR, "Failed to read compressed tag\n");
goto seek;
@@ -778,26 +842,26 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version,
av_log(s, AV_LOG_ERROR, "Failed to uncompress tag: %d\n", err);
goto seek;
}
- ffio_init_context(&pb, uncompressed_buffer, dlen, 0, NULL, NULL, NULL, NULL);
+ ffio_init_context(&pb_local, uncompressed_buffer, dlen, 0, NULL, NULL, NULL, NULL);
tlen = dlen;
- pbx = &pb; // read from sync buffer
+ pbx = &pb_local; // read from sync buffer
}
#endif
if (tag[0] == 'T')
/* parse text tag */
- read_ttag(s, pbx, tlen, &s->metadata, tag);
+ read_ttag(s, pbx, tlen, metadata, tag);
else
/* parse special meta tag */
- extra_func->read(s, pbx, tlen, tag, extra_meta);
+ extra_func->read(s, pbx, tlen, tag, extra_meta, isv34);
} else if (!tag[0]) {
if (tag[1])
av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding\n");
- avio_skip(s->pb, tlen);
+ avio_skip(pb, tlen);
break;
}
/* Skip to end of tag */
seek:
- avio_seek(s->pb, next, SEEK_SET);
+ avio_seek(pb, next, SEEK_SET);
}
/* Footer preset, always 10 bytes, skip over it */
@@ -808,26 +872,36 @@ error:
if (reason)
av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n",
version, reason);
- avio_seek(s->pb, end, SEEK_SET);
+ avio_seek(pb, end, SEEK_SET);
av_free(buffer);
av_free(uncompressed_buffer);
return;
}
-void ff_id3v2_read(AVFormatContext *s, const char *magic,
- ID3v2ExtraMeta **extra_meta)
+static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata,
+ AVFormatContext *s, const char *magic,
+ ID3v2ExtraMeta **extra_meta, int64_t max_search_size)
{
int len, ret;
uint8_t buf[ID3v2_HEADER_SIZE];
int found_header;
- int64_t off;
+ int64_t start, off;
+
+ if (max_search_size && max_search_size < ID3v2_HEADER_SIZE)
+ return;
+ start = avio_tell(pb);
do {
/* save the current offset in case there's nothing to read/skip */
- off = avio_tell(s->pb);
- ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
+ off = avio_tell(pb);
+ if (max_search_size && off - start >= max_search_size - ID3v2_HEADER_SIZE) {
+ avio_seek(pb, off, SEEK_SET);
+ break;
+ }
+
+ ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
if (ret != ID3v2_HEADER_SIZE) {
- avio_seek(s->pb, off, SEEK_SET);
+ avio_seek(pb, off, SEEK_SET);
break;
}
found_header = ff_id3v2_match(buf, magic);
@@ -837,15 +911,27 @@ void ff_id3v2_read(AVFormatContext *s, const char *magic,
((buf[7] & 0x7f) << 14) |
((buf[8] & 0x7f) << 7) |
(buf[9] & 0x7f);
- id3v2_parse(s, len, buf[3], buf[5], extra_meta);
+ id3v2_parse(pb, metadata, s, len, buf[3], buf[5], extra_meta);
} else {
- avio_seek(s->pb, off, SEEK_SET);
+ avio_seek(pb, off, SEEK_SET);
}
} while (found_header);
- ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
- ff_metadata_conv(&s->metadata, NULL, id3v2_2_metadata_conv);
- ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
- merge_date(&s->metadata);
+ ff_metadata_conv(metadata, NULL, ff_id3v2_34_metadata_conv);
+ ff_metadata_conv(metadata, NULL, id3v2_2_metadata_conv);
+ ff_metadata_conv(metadata, NULL, ff_id3v2_4_metadata_conv);
+ merge_date(metadata);
+}
+
+void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata,
+ const char *magic, ID3v2ExtraMeta **extra_meta)
+{
+ id3v2_read_internal(pb, metadata, NULL, magic, extra_meta, 0);
+}
+
+void ff_id3v2_read(AVFormatContext *s, const char *magic,
+ ID3v2ExtraMeta **extra_meta, unsigned int max_search_size)
+{
+ id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta, max_search_size);
}
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
@@ -860,6 +946,8 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
av_freep(&current);
current = next;
}
+
+ *extra_meta = NULL;
}
int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
diff --git a/chromium/third_party/ffmpeg/libavformat/id3v2.h b/chromium/third_party/ffmpeg/libavformat/id3v2.h
index e893922133e..9d7bf1c03c1 100644
--- a/chromium/third_party/ffmpeg/libavformat/id3v2.h
+++ b/chromium/third_party/ffmpeg/libavformat/id3v2.h
@@ -73,6 +73,12 @@ typedef struct ID3v2ExtraMetaAPIC {
enum AVCodecID id;
} ID3v2ExtraMetaAPIC;
+typedef struct ID3v2ExtraMetaPRIV {
+ uint8_t *owner;
+ uint8_t *data;
+ uint32_t datasize;
+} ID3v2ExtraMetaPRIV;
+
/**
* Detect ID3v2 Header.
* @param buf must be ID3v2_HEADER_SIZE byte long
@@ -89,11 +95,27 @@ int ff_id3v2_match(const uint8_t *buf, const char *magic);
int ff_id3v2_tag_len(const uint8_t *buf);
/**
- * Read an ID3v2 tag, including supported extra metadata
+ * Read an ID3v2 tag into specified dictionary and retrieve supported extra metadata.
+ *
+ * Chapters are not currently read by this variant.
+ *
+ * @param metadata Parsed metadata is stored here
+ * @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_dict(AVIOContext *pb, AVDictionary **metadata, const char *magic, ID3v2ExtraMeta **extra_meta);
+
+/**
+ * Read an ID3v2 tag, including supported extra metadata and chapters.
+ *
+ * Data is read from and stored to AVFormatContext.
+ *
* @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
+ * @param[opt] max_search_search restrict ID3 magic number search (bytes from start)
*/
-void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta);
+void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta,
+ unsigned int max_search_size);
/**
* Initialize an ID3v2 tag.
@@ -114,7 +136,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
/**
* Finalize an opened ID3v2 tag.
*/
-void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb);
+void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes);
/**
* Write an ID3v2 tag containing all global metadata from s.
diff --git a/chromium/third_party/ffmpeg/libavformat/id3v2enc.c b/chromium/third_party/ffmpeg/libavformat/id3v2enc.c
index 60522444fc6..4d555b3d241 100644
--- a/chromium/third_party/ffmpeg/libavformat/id3v2enc.c
+++ b/chromium/third_party/ffmpeg/libavformat/id3v2enc.c
@@ -29,8 +29,6 @@
#include "avio_internal.h"
#include "id3v2.h"
-#define PADDING_BYTES 10
-
static void id3v2_put_size(AVIOContext *pb, int size)
{
avio_w8(pb, size >> 21 & 0x7f);
@@ -324,15 +322,23 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
return 0;
}
-void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb)
+void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb,
+ int padding_bytes)
{
int64_t cur_pos;
- /* adding an arbitrary amount of padding bytes at the end of the
- * ID3 metadata fixes cover art display for some software (iTunes,
- * Traktor, Serato, Torq) */
- ffio_fill(pb, 0, PADDING_BYTES);
- id3->len += PADDING_BYTES;
+ if (padding_bytes < 0)
+ padding_bytes = 10;
+
+ /* The ID3v2.3 specification states that 28 bits are used to represent the
+ * size of the whole tag. Therefore the current size of the tag needs to be
+ * subtracted from the upper limit of 2^28-1 to clip the value correctly. */
+ /* The minimum of 10 is an arbitrary amount of padding at the end of the tag
+ * to fix cover art display with some software such as iTunes, Traktor,
+ * Serato, Torq. */
+ padding_bytes = av_clip(padding_bytes, 10, 268435455 - id3->len);
+ ffio_fill(pb, 0, padding_bytes);
+ id3->len += padding_bytes;
cur_pos = avio_tell(pb);
avio_seek(pb, id3->size_pos, SEEK_SET);
@@ -349,7 +355,7 @@ int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version,
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);
+ ff_id3v2_finish(&id3, s->pb, s->metadata_header_padding);
return 0;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/idcin.c b/chromium/third_party/ffmpeg/libavformat/idcin.c
index f2d5548a4f1..cc25fb0e38d 100644
--- a/chromium/third_party/ffmpeg/libavformat/idcin.c
+++ b/chromium/third_party/ffmpeg/libavformat/idcin.c
@@ -205,15 +205,8 @@ static int idcin_read_header(AVFormatContext *s)
st->codec->height = height;
/* load up the Huffman tables into extradata */
- if (ff_alloc_extradata(st->codec, HUFFMAN_TABLE_SIZE))
- return AVERROR(ENOMEM);
- ret = avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE);
- if (ret < 0) {
+ if ((ret = ff_get_extradata(st->codec, pb, HUFFMAN_TABLE_SIZE)) < 0)
return ret;
- } else if (ret != HUFFMAN_TABLE_SIZE) {
- av_log(s, AV_LOG_ERROR, "incomplete header\n");
- return AVERROR(EIO);
- }
if (idcin->audio_present) {
idcin->audio_present = 1;
diff --git a/chromium/third_party/ffmpeg/libavformat/idroqenc.c b/chromium/third_party/ffmpeg/libavformat/idroqenc.c
index 50c428046ba..28a3aba9d43 100644
--- a/chromium/third_party/ffmpeg/libavformat/idroqenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/idroqenc.c
@@ -25,9 +25,35 @@
static int roq_write_header(struct AVFormatContext *s)
{
- static const uint8_t header[] = {
- 0x84, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x00
+ uint8_t header[] = {
+ 0x84, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, /* fps: */ 0x1E, 0x00
};
+ int n;
+ AVCodecContext *avctx;
+
+// set the actual fps
+ for(n=0;n<s->nb_streams;n++) {
+ if ((avctx=s->streams[n]->codec)->codec_type == AVMEDIA_TYPE_VIDEO) {
+ unsigned int fps;
+
+ if (avctx->time_base.num != 1) {
+ av_log(avctx, AV_LOG_ERROR, "Frame rate must be integer\n");
+ return AVERROR(EINVAL);
+ }
+
+ if ((fps=avctx->time_base.den) > 255) {
+ av_log(avctx, AV_LOG_ERROR, "Frame rate may not exceed 255fps\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (fps != 30) {
+ av_log(avctx, AV_LOG_WARNING, "For vintage compatibility fps must be 30\n");
+ }
+
+ header[6] = fps;
+ break;
+ }
+ }
avio_write(s->pb, header, 8);
avio_flush(s->pb);
diff --git a/chromium/third_party/ffmpeg/libavformat/iff.c b/chromium/third_party/ffmpeg/libavformat/iff.c
index edf308b1355..62f0b8387c2 100644
--- a/chromium/third_party/ffmpeg/libavformat/iff.c
+++ b/chromium/third_party/ffmpeg/libavformat/iff.c
@@ -28,12 +28,15 @@
* http://wiki.multimedia.cx/index.php?title=IFF
*/
+#include <inttypes.h>
+
#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
+#include "id3v2.h"
#include "internal.h"
#define ID_8SVX MKTAG('8','S','V','X')
@@ -55,8 +58,10 @@
#define ID_DEEP MKTAG('D','E','E','P')
#define ID_RGB8 MKTAG('R','G','B','8')
#define ID_RGBN MKTAG('R','G','B','N')
+#define ID_DSD MKTAG('D','S','D',' ')
#define ID_FORM MKTAG('F','O','R','M')
+#define ID_FRM8 MKTAG('F','R','M','8')
#define ID_ANNO MKTAG('A','N','N','O')
#define ID_AUTH MKTAG('A','U','T','H')
#define ID_CHRS MKTAG('C','H','R','S')
@@ -93,6 +98,7 @@ typedef enum {
} svx8_compression_type;
typedef struct {
+ int is_64bit; ///< chunk size is 64-bit
int64_t body_pos;
int64_t body_end;
uint32_t body_size;
@@ -118,7 +124,7 @@ static int get_metadata(AVFormatContext *s,
if (!buf)
return AVERROR(ENOMEM);
- if (avio_read(s->pb, buf, data_size) < 0) {
+ if (avio_read(s->pb, buf, data_size) != data_size) {
av_free(buf);
return AVERROR(EIO);
}
@@ -131,7 +137,7 @@ static int iff_probe(AVProbeData *p)
{
const uint8_t *d = p->buf;
- if ( AV_RL32(d) == ID_FORM &&
+ if ( (AV_RL32(d) == ID_FORM &&
(AV_RL32(d+8) == ID_8SVX ||
AV_RL32(d+8) == ID_16SV ||
AV_RL32(d+8) == ID_MAUD ||
@@ -140,11 +146,188 @@ static int iff_probe(AVProbeData *p)
AV_RL32(d+8) == ID_DEEP ||
AV_RL32(d+8) == ID_ILBM ||
AV_RL32(d+8) == ID_RGB8 ||
- AV_RL32(d+8) == ID_RGBN) )
+ AV_RL32(d+8) == ID_RGB8 ||
+ AV_RL32(d+8) == ID_RGBN)) ||
+ (AV_RL32(d) == ID_FRM8 && AV_RL32(d+12) == ID_DSD))
return AVPROBE_SCORE_MAX;
return 0;
}
+static const AVCodecTag dsd_codec_tags[] = {
+ { AV_CODEC_ID_DSD_MSBF, ID_DSD },
+ { AV_CODEC_ID_NONE, 0 },
+};
+
+
+#define DSD_SLFT MKTAG('S','L','F','T')
+#define DSD_SRGT MKTAG('S','R','G','T')
+#define DSD_MLFT MKTAG('M','L','F','T')
+#define DSD_MRGT MKTAG('M','R','G','T')
+#define DSD_C MKTAG('C',' ',' ',' ')
+#define DSD_LS MKTAG('L','S',' ',' ')
+#define DSD_RS MKTAG('R','S',' ',' ')
+#define DSD_LFE MKTAG('L','F','E',' ')
+
+static const uint32_t dsd_stereo[] = { DSD_SLFT, DSD_SRGT };
+static const uint32_t dsd_5point0[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LS, DSD_RS };
+static const uint32_t dsd_5point1[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LFE, DSD_LS, DSD_RS };
+
+typedef struct {
+ uint64_t layout;
+ const uint32_t * dsd_layout;
+} DSDLayoutDesc;
+
+static const DSDLayoutDesc dsd_channel_layout[] = {
+ { AV_CH_LAYOUT_STEREO, dsd_stereo },
+ { AV_CH_LAYOUT_5POINT0, dsd_5point0 },
+ { AV_CH_LAYOUT_5POINT1, dsd_5point1 },
+};
+
+static const uint64_t dsd_loudspeaker_config[] = {
+ AV_CH_LAYOUT_STEREO,
+ 0, 0,
+ AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1,
+};
+
+static const char * dsd_source_comment[] = {
+ "dsd_source_comment",
+ "analogue_source_comment",
+ "pcm_source_comment",
+};
+
+static const char * dsd_history_comment[] = {
+ "general_remark",
+ "operator_name",
+ "creating_machine",
+ "timezone",
+ "file_revision"
+};
+
+static int parse_dsd_diin(AVFormatContext *s, AVStream *st, uint64_t eof)
+{
+ AVIOContext *pb = s->pb;
+
+ while (avio_tell(pb) + 12 <= eof) {
+ uint32_t tag = avio_rl32(pb);
+ uint64_t size = avio_rb64(pb);
+ uint64_t orig_pos = avio_tell(pb);
+ const char * metadata_tag = NULL;
+
+ switch(tag) {
+ case MKTAG('D','I','A','R'): metadata_tag = "artist"; break;
+ case MKTAG('D','I','T','I'): metadata_tag = "title"; break;
+ }
+
+ if (metadata_tag && size > 4) {
+ unsigned int tag_size = avio_rb32(pb);
+ int ret = get_metadata(s, metadata_tag, FFMIN(tag_size, size - 4));
+ if (ret < 0) {
+ av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag);
+ return ret;
+ }
+ }
+
+ avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1));
+ }
+
+ return 0;
+}
+
+static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
+{
+ AVIOContext *pb = s->pb;
+ char abss[24];
+ int hour, min, sec, i, ret, config;
+ int dsd_layout[6];
+ ID3v2ExtraMeta *id3v2_extra_meta;
+
+ while (avio_tell(pb) + 12 <= eof) {
+ uint32_t tag = avio_rl32(pb);
+ uint64_t size = avio_rb64(pb);
+ uint64_t orig_pos = avio_tell(pb);
+
+ switch(tag) {
+ case MKTAG('A','B','S','S'):
+ if (size < 8)
+ return AVERROR_INVALIDDATA;
+ hour = avio_rb16(pb);
+ min = avio_r8(pb);
+ sec = avio_r8(pb);
+ snprintf(abss, sizeof(abss), "%02dh:%02dm:%02ds:%d", hour, min, sec, avio_rb32(pb));
+ av_dict_set(&st->metadata, "absolute_start_time", abss, 0);
+ break;
+
+ case MKTAG('C','H','N','L'):
+ if (size < 2)
+ return AVERROR_INVALIDDATA;
+ st->codec->channels = avio_rb16(pb);
+ if (size < 2 + st->codec->channels * 4)
+ return AVERROR_INVALIDDATA;
+ st->codec->channel_layout = 0;
+ if (st->codec->channels > FF_ARRAY_ELEMS(dsd_layout)) {
+ avpriv_request_sample(s, "channel layout");
+ break;
+ }
+ for (i = 0; i < st->codec->channels; i++)
+ dsd_layout[i] = avio_rl32(pb);
+ for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) {
+ const DSDLayoutDesc * d = &dsd_channel_layout[i];
+ if (av_get_channel_layout_nb_channels(d->layout) == st->codec->channels &&
+ !memcmp(d->dsd_layout, dsd_layout, st->codec->channels * sizeof(uint32_t))) {
+ st->codec->channel_layout = d->layout;
+ break;
+ }
+ }
+ break;
+
+ case MKTAG('C','M','P','R'):
+ if (size < 4)
+ return AVERROR_INVALIDDATA;
+ st->codec->codec_id = ff_codec_get_id(dsd_codec_tags, avio_rl32(pb));
+ break;
+
+ case MKTAG('F','S',' ',' '):
+ if (size < 4)
+ return AVERROR_INVALIDDATA;
+ st->codec->sample_rate = avio_rb32(pb) / 8;
+ break;
+
+ case MKTAG('I','D','3',' '):
+ id3v2_extra_meta = NULL;
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size);
+ if (id3v2_extra_meta) {
+ if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) {
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
+ return ret;
+ }
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
+ }
+
+ if (size < avio_tell(pb) - orig_pos) {
+ av_log(s, AV_LOG_ERROR, "id3 exceeds chunk size\n");
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+
+ case MKTAG('L','S','C','O'):
+ if (size < 2)
+ return AVERROR_INVALIDDATA;
+ config = avio_rb16(pb);
+ if (config != 0xFFFF) {
+ if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config))
+ st->codec->channel_layout = dsd_loudspeaker_config[config];
+ if (!st->codec->channel_layout)
+ avpriv_request_sample(s, "loudspeaker configuration %d", config);
+ }
+ break;
+ }
+
+ avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1));
+ }
+
+ return 0;
+}
+
static const uint8_t deep_rgb24[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
static const uint8_t deep_rgba[] = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
static const uint8_t deep_bgra[] = {0, 0, 0, 4, 0, 3, 0, 8, 0, 2, 0, 8, 0, 1, 0, 8};
@@ -157,7 +340,8 @@ static int iff_read_header(AVFormatContext *s)
AVIOContext *pb = s->pb;
AVStream *st;
uint8_t *buf;
- uint32_t chunk_id, data_size;
+ uint32_t chunk_id;
+ uint64_t data_size;
uint32_t screenmode = 0, num, den;
unsigned transparency = 0;
unsigned masking = 0; // no mask
@@ -170,7 +354,8 @@ static int iff_read_header(AVFormatContext *s)
st->codec->channels = 1;
st->codec->channel_layout = AV_CH_LAYOUT_MONO;
- avio_skip(pb, 8);
+ iff->is_64bit = avio_rl32(pb) == ID_FRM8;
+ avio_skip(pb, iff->is_64bit ? 8 : 4);
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
st->codec->codec_tag = avio_rl32(pb);
iff->bitmap_compression = -1;
@@ -182,8 +367,9 @@ static int iff_read_header(AVFormatContext *s)
uint64_t orig_pos;
int res;
const char *metadata_tag = NULL;
+ int version, nb_comments, i;
chunk_id = avio_rl32(pb);
- data_size = avio_rb32(pb);
+ data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb);
orig_pos = avio_tell(pb);
switch(chunk_id) {
@@ -225,6 +411,7 @@ static int iff_read_header(AVFormatContext *s)
case ID_ABIT:
case ID_BODY:
case ID_DBOD:
+ case ID_DSD:
case ID_MDAT:
iff->body_pos = avio_tell(pb);
iff->body_end = iff->body_pos + data_size;
@@ -251,7 +438,7 @@ static int iff_read_header(AVFormatContext *s)
case ID_CMAP:
if (data_size < 3 || data_size > 768 || data_size % 3) {
- av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %d\n",
+ av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %"PRIu64"\n",
data_size);
return AVERROR_INVALIDDATA;
}
@@ -338,6 +525,84 @@ static int iff_read_header(AVFormatContext *s)
case ID_AUTH: metadata_tag = "artist"; break;
case ID_COPYRIGHT: metadata_tag = "copyright"; break;
case ID_NAME: metadata_tag = "title"; break;
+
+ /* DSD tags */
+
+ case MKTAG('F','V','E','R'):
+ if (data_size < 4)
+ return AVERROR_INVALIDDATA;
+ version = avio_rb32(pb);
+ av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ break;
+
+ case MKTAG('D','I','I','N'):
+ res = parse_dsd_diin(s, st, orig_pos + data_size);
+ if (res < 0)
+ return res;
+ break;
+
+ case MKTAG('P','R','O','P'):
+ if (data_size < 4)
+ return AVERROR_INVALIDDATA;
+ if (avio_rl32(pb) != MKTAG('S','N','D',' ')) {
+ avpriv_request_sample(s, "unknown property type");
+ break;
+ }
+ res = parse_dsd_prop(s, st, orig_pos + data_size);
+ if (res < 0)
+ return res;
+ break;
+
+ case MKTAG('C','O','M','T'):
+ if (data_size < 2)
+ return AVERROR_INVALIDDATA;
+ nb_comments = avio_rb16(pb);
+ for (i = 0; i < nb_comments; i++) {
+ int year, mon, day, hour, min, type, ref;
+ char tmp[24];
+ const char *tag;
+ int metadata_size;
+
+ year = avio_rb16(pb);
+ mon = avio_r8(pb);
+ day = avio_r8(pb);
+ hour = avio_r8(pb);
+ min = avio_r8(pb);
+ snprintf(tmp, sizeof(tmp), "%04d-%02d-%02d %02d:%02d", year, mon, day, hour, min);
+ av_dict_set(&st->metadata, "comment_time", tmp, 0);
+
+ type = avio_rb16(pb);
+ ref = avio_rb16(pb);
+ switch (type) {
+ case 1:
+ if (!i)
+ tag = "channel_comment";
+ else {
+ snprintf(tmp, sizeof(tmp), "channel%d_comment", ref);
+ tag = tmp;
+ }
+ break;
+ case 2:
+ tag = ref < FF_ARRAY_ELEMS(dsd_source_comment) ? dsd_history_comment[ref] : "source_comment";
+ break;
+ case 3:
+ tag = ref < FF_ARRAY_ELEMS(dsd_history_comment) ? dsd_history_comment[ref] : "file_history";
+ break;
+ default:
+ tag = "comment";
+ }
+
+ metadata_size = avio_rb32(pb);
+ if ((res = get_metadata(s, tag, metadata_size)) < 0) {
+ av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", tag);
+ return res;
+ }
+
+ if (metadata_size & 1)
+ avio_skip(pb, 1);
+ }
+ break;
}
if (metadata_tag) {
@@ -370,28 +635,22 @@ static int iff_read_header(AVFormatContext *s)
avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits);
return AVERROR_PATCHWELCOME;
}
-
- st->codec->bits_per_coded_sample =
- av_get_bits_per_sample(st->codec->codec_id);
-
- st->codec->block_align =
- st->codec->bits_per_coded_sample * st->codec->channels / 8;
- } else {
- switch (iff->svx8_compression) {
- case COMP_NONE:
- st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
- break;
- case COMP_FIB:
- st->codec->codec_id = AV_CODEC_ID_8SVX_FIB;
- break;
- case COMP_EXP:
- st->codec->codec_id = AV_CODEC_ID_8SVX_EXP;
- break;
- default:
- av_log(s, AV_LOG_ERROR,
- "Unknown SVX8 compression method '%d'\n", iff->svx8_compression);
- return -1;
- }
+ } else if (st->codec->codec_tag != ID_DSD) {
+ switch (iff->svx8_compression) {
+ case COMP_NONE:
+ st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
+ break;
+ case COMP_FIB:
+ st->codec->codec_id = AV_CODEC_ID_8SVX_FIB;
+ break;
+ case COMP_EXP:
+ st->codec->codec_id = AV_CODEC_ID_8SVX_EXP;
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR,
+ "Unknown SVX8 compression method '%d'\n", iff->svx8_compression);
+ return -1;
+ }
}
st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
@@ -447,7 +706,7 @@ static int iff_read_packet(AVFormatContext *s,
return AVERROR_EOF;
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- if (st->codec->codec_tag == ID_MAUD) {
+ if (st->codec->codec_tag == ID_DSD || st->codec->codec_tag == ID_MAUD) {
ret = av_get_packet(pb, pkt, FFMIN(iff->body_end - pos, 1024 * st->codec->block_align));
} else {
ret = av_get_packet(pb, pkt, iff->body_size);
@@ -462,6 +721,10 @@ static int iff_read_packet(AVFormatContext *s,
buf = pkt->data;
bytestream_put_be16(&buf, 2);
ret = avio_read(pb, buf, iff->body_size);
+ if (ret<0) {
+ av_free_packet(pkt);
+ } else if (ret < iff->body_size)
+ av_shrink_packet(pkt, ret + 2);
} else {
av_assert0(0);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/img2.c b/chromium/third_party/ffmpeg/libavformat/img2.c
index 7539359540e..80020549f63 100644
--- a/chromium/third_party/ffmpeg/libavformat/img2.c
+++ b/chromium/third_party/ffmpeg/libavformat/img2.c
@@ -32,6 +32,7 @@ static const IdStrMap img_tags[] = {
{ AV_CODEC_ID_MJPEG, "jpeg" },
{ AV_CODEC_ID_MJPEG, "jpg" },
{ AV_CODEC_ID_MJPEG, "jps" },
+ { AV_CODEC_ID_MJPEG, "mpo" },
{ AV_CODEC_ID_LJPEG, "ljpg" },
{ AV_CODEC_ID_JPEGLS, "jls" },
{ AV_CODEC_ID_PNG, "png" },
@@ -43,6 +44,7 @@ static const IdStrMap img_tags[] = {
{ AV_CODEC_ID_PGMYUV, "pgmyuv" },
{ AV_CODEC_ID_PBM, "pbm" },
{ AV_CODEC_ID_PAM, "pam" },
+ { AV_CODEC_ID_ALIAS_PIX, "pix" },
{ AV_CODEC_ID_MPEG1VIDEO, "mpg1-img" },
{ AV_CODEC_ID_MPEG2VIDEO, "mpg2-img" },
{ AV_CODEC_ID_MPEG4, "mpg4-img" },
@@ -55,8 +57,8 @@ static const IdStrMap img_tags[] = {
{ AV_CODEC_ID_TIFF, "tif" },
{ AV_CODEC_ID_SGI, "sgi" },
{ AV_CODEC_ID_PTX, "ptx" },
+ { AV_CODEC_ID_BRENDER_PIX,"pix" },
{ AV_CODEC_ID_PCX, "pcx" },
- { AV_CODEC_ID_BRENDER_PIX, "pix" },
{ AV_CODEC_ID_SUNRAST, "sun" },
{ AV_CODEC_ID_SUNRAST, "ras" },
{ AV_CODEC_ID_SUNRAST, "rs" },
diff --git a/chromium/third_party/ffmpeg/libavformat/img2.h b/chromium/third_party/ffmpeg/libavformat/img2.h
new file mode 100644
index 00000000000..dc53c5cc510
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/img2.h
@@ -0,0 +1,61 @@
+/*
+ * Image format
+ * Copyright (c) 2014 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_IMG2_H
+#define AVFORMAT_IMG2_H
+
+#include <stdint.h>
+#include "avformat.h"
+
+#if HAVE_GLOB
+#include <glob.h>
+#endif
+
+typedef struct {
+ const AVClass *class; /**< Class for private options. */
+ int img_first;
+ int img_last;
+ int img_number;
+ int64_t pts;
+ int img_count;
+ int is_pipe;
+ int split_planes; /**< use independent file for each Y, U, V plane */
+ char path[1024];
+ char *pixel_format; /**< Set by a private option. */
+ int width, height; /**< Set by a private option. */
+ AVRational framerate; /**< Set by a private option. */
+ int loop;
+ enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type;
+ int use_glob;
+#if HAVE_GLOB
+ glob_t globstate;
+#endif
+ int start_number;
+ int start_number_range;
+ int frame_size;
+ int ts_from_file;
+} VideoDemuxData;
+
+int ff_img_read_header(AVFormatContext *s1);
+
+int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt);
+
+#endif
diff --git a/chromium/third_party/ffmpeg/libavformat/img2_alias_pix.c b/chromium/third_party/ffmpeg/libavformat/img2_alias_pix.c
new file mode 100644
index 00000000000..a3d5cfa0c4b
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/img2_alias_pix.c
@@ -0,0 +1,65 @@
+/*
+ * Alias PIX image demuxer
+ * Copyright (c) 2014 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "img2.h"
+#include "libavcodec/bytestream.h"
+
+static int brender_read_probe(AVProbeData *p)
+{
+ const uint8_t *b = p->buf;
+ const uint8_t *end = b + p->buf_size;
+ int width = bytestream_get_be16(&b);
+ int height = bytestream_get_be16(&b);
+ av_unused int ox = bytestream_get_be16(&b);
+ av_unused int oy = bytestream_get_be16(&b);
+ int bpp = bytestream_get_be16(&b);
+ int x, y;
+
+ if (!width || !height)
+ return 0;
+
+ if (bpp != 24 && bpp != 8)
+ return 0;
+
+ for (y=0; y<2 && y<height; y++) {
+ for (x=0; x<width; ) {
+ int count = *b++;
+ if (count == 0 || x + count > width)
+ return 0;
+ if (b > end)
+ return AVPROBE_SCORE_MAX / 8;
+ b += bpp / 8;
+ x += count;
+ }
+ }
+
+ return AVPROBE_SCORE_EXTENSION + 1;
+}
+
+AVInputFormat ff_image2_alias_pix_demuxer = {
+ .name = "alias_pix",
+ .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"),
+ .priv_data_size = sizeof(VideoDemuxData),
+ .read_probe = brender_read_probe,
+ .read_header = ff_img_read_header,
+ .read_packet = ff_img_read_packet,
+ .raw_codec_id = AV_CODEC_ID_ALIAS_PIX,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/img2_brender_pix.c b/chromium/third_party/ffmpeg/libavformat/img2_brender_pix.c
new file mode 100644
index 00000000000..f7306267c4b
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/img2_brender_pix.c
@@ -0,0 +1,49 @@
+/*
+ * BRender PIX image demuxer
+ * Copyright (c) 2014 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "img2.h"
+#include "libavutil/intreadwrite.h"
+
+static int aliaspix_read_probe(AVProbeData *p)
+{
+ static const uint8_t brender_magic[16] = {
+ 0,0,0,0x12,0,0,0,8,0,0,0,2,0,0,0,2
+ };
+
+ if (memcmp(p->buf, brender_magic, sizeof(brender_magic)))
+ return 0;
+
+ if (AV_RB32(p->buf+16) != 0x03 &&
+ AV_RB32(p->buf+16) != 0x3D)
+ return 0;
+
+ return AVPROBE_SCORE_MAX-10;
+}
+
+AVInputFormat ff_image2_brender_pix_demuxer = {
+ .name = "brender_pix",
+ .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"),
+ .priv_data_size = sizeof(VideoDemuxData),
+ .read_probe = aliaspix_read_probe,
+ .read_header = ff_img_read_header,
+ .read_packet = ff_img_read_packet,
+ .raw_codec_id = AV_CODEC_ID_BRENDER_PIX,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/img2dec.c b/chromium/third_party/ffmpeg/libavformat/img2dec.c
index 5163e69f65b..dc962dbb33a 100644
--- a/chromium/third_party/ffmpeg/libavformat/img2dec.c
+++ b/chromium/third_party/ffmpeg/libavformat/img2dec.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _BSD_SOURCE
#include <sys/stat.h>
#include "libavutil/avstring.h"
#include "libavutil/log.h"
@@ -28,9 +29,9 @@
#include "libavutil/parseutils.h"
#include "avformat.h"
#include "internal.h"
-#if HAVE_GLOB
-#include <glob.h>
+#include "img2.h"
+#if HAVE_GLOB
/* Locally define as 0 (bitwise-OR no-op) any missing glob options that
are non-posix glibc/bsd extensions. */
#ifndef GLOB_NOMAGIC
@@ -42,31 +43,6 @@
#endif /* HAVE_GLOB */
-typedef struct {
- const AVClass *class; /**< Class for private options. */
- int img_first;
- int img_last;
- int img_number;
- int64_t pts;
- int img_count;
- int is_pipe;
- int split_planes; /**< use independent file for each Y, U, V plane */
- char path[1024];
- char *pixel_format; /**< Set by a private option. */
- int width, height; /**< Set by a private option. */
- AVRational framerate; /**< Set by a private option. */
- int loop;
- enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type;
- int use_glob;
-#if HAVE_GLOB
- glob_t globstate;
-#endif
- int start_number;
- int start_number_range;
- int frame_size;
- int ts_from_file;
-} VideoDemuxData;
-
static const int sizes[][2] = {
{ 640, 480 },
{ 720, 480 },
@@ -192,7 +168,7 @@ static int img_read_probe(AVProbeData *p)
return 0;
}
-static int img_read_header(AVFormatContext *s1)
+int ff_img_read_header(AVFormatContext *s1)
{
VideoDemuxData *s = s1->priv_data;
int first_index, last_index;
@@ -225,7 +201,13 @@ static int img_read_header(AVFormatContext *s1)
st->need_parsing = AVSTREAM_PARSE_FULL;
}
- if (s->ts_from_file)
+ if (s->ts_from_file == 2) {
+#if !HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ av_log(s1, AV_LOG_ERROR, "POSIX.1-2008 not supported, nanosecond file timestamps unavailable\n");
+ return AVERROR(ENOSYS);
+#endif
+ avpriv_set_pts_info(st, 64, 1, 1000000000);
+ } else if (s->ts_from_file)
avpriv_set_pts_info(st, 64, 1, 1);
else
avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
@@ -313,6 +295,9 @@ static int img_read_header(AVFormatContext *s1)
} else if (s1->audio_codec_id) {
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->codec_id = s1->audio_codec_id;
+ } else if (s1->iformat->raw_codec_id) {
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = s1->iformat->raw_codec_id;
} else {
const char *str = strrchr(s->path, '.');
s->split_planes = str && !av_strcasecmp(str + 1, "y");
@@ -320,6 +305,8 @@ static int img_read_header(AVFormatContext *s1)
st->codec->codec_id = ff_guess_image2_codec(s->path);
if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
st->codec->codec_id = AV_CODEC_ID_MJPEG;
+ if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX
+ st->codec->codec_id = AV_CODEC_ID_NONE;
}
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
pix_fmt != AV_PIX_FMT_NONE)
@@ -328,7 +315,7 @@ static int img_read_header(AVFormatContext *s1)
return 0;
}
-static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
+int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
VideoDemuxData *s = s1->priv_data;
char filename_bytes[1024];
@@ -371,6 +358,27 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
filename[strlen(filename) - 1] = 'U' + i;
}
+ if (codec->codec_id == AV_CODEC_ID_NONE) {
+ AVProbeData pd;
+ AVInputFormat *ifmt;
+ uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE];
+ int ret;
+ int score = 0;
+
+ ret = avio_read(f[0], header, PROBE_BUF_MIN);
+ if (ret < 0)
+ return ret;
+ memset(header + ret, 0, sizeof(header) - ret);
+ avio_skip(f[0], -ret);
+ pd.buf = header;
+ pd.buf_size = ret;
+ pd.filename = filename;
+
+ ifmt = av_probe_input_format3(&pd, 1, &score);
+ if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id)
+ codec->codec_id = ifmt->raw_codec_id;
+ }
+
if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
infer_size(&codec->width, &codec->height, size[0]);
} else {
@@ -393,6 +401,10 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
if (stat(filename, &img_stat))
return AVERROR(EIO);
pkt->pts = (int64_t)img_stat.st_mtime;
+#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ if (s->ts_from_file == 2)
+ pkt->pts = 1000000000*pkt->pts + img_stat.st_mtim.tv_nsec;
+#endif
av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME);
} else if (!s->is_pipe) {
pkt->pts = s->pts;
@@ -467,7 +479,10 @@ static const AVOption options[] = {
{ "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC },
{ "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
{ "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC },
- { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC },
+ { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
+ { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
+ { "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" },
+ { "ns", "nano second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 2, DEC, "ts_type" },
{ NULL },
};
@@ -483,8 +498,8 @@ AVInputFormat ff_image2_demuxer = {
.long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
.priv_data_size = sizeof(VideoDemuxData),
.read_probe = img_read_probe,
- .read_header = img_read_header,
- .read_packet = img_read_packet,
+ .read_header = ff_img_read_header,
+ .read_packet = ff_img_read_packet,
.read_close = img_read_close,
.read_seek = img_read_seek,
.flags = AVFMT_NOFILE,
@@ -502,8 +517,8 @@ AVInputFormat ff_image2pipe_demuxer = {
.name = "image2pipe",
.long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
.priv_data_size = sizeof(VideoDemuxData),
- .read_header = img_read_header,
- .read_packet = img_read_packet,
+ .read_header = ff_img_read_header,
+ .read_packet = ff_img_read_packet,
.priv_class = &img2pipe_class,
};
#endif
diff --git a/chromium/third_party/ffmpeg/libavformat/img2enc.c b/chromium/third_party/ffmpeg/libavformat/img2enc.c
index 3529e12c55b..37dfbecce31 100644
--- a/chromium/third_party/ffmpeg/libavformat/img2enc.c
+++ b/chromium/third_party/ffmpeg/libavformat/img2enc.c
@@ -194,7 +194,7 @@ AVOutputFormat ff_image2_muxer = {
.long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
.extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
"ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24,"
- "sunras,xbm,xface",
+ "sunras,webp,xbm,xface,pix,y",
.priv_data_size = sizeof(VideoMuxData),
.video_codec = AV_CODEC_ID_MJPEG,
.write_header = write_header,
diff --git a/chromium/third_party/ffmpeg/libavformat/internal.h b/chromium/third_party/ffmpeg/libavformat/internal.h
index edc6a11685c..66fb5d64af2 100644
--- a/chromium/third_party/ffmpeg/libavformat/internal.h
+++ b/chromium/third_party/ffmpeg/libavformat/internal.h
@@ -28,7 +28,7 @@
/** size of probe buffer, for guessing file type from file contents */
#define PROBE_BUF_MIN 2048
-#define PROBE_BUF_MAX (1<<20)
+#define PROBE_BUF_MAX (1 << 20)
#ifdef DEBUG
# define hex_dump_debug(class, buf, size) av_hex_dump_log(class, AV_LOG_DEBUG, buf, size)
@@ -46,6 +46,16 @@ typedef struct CodecMime{
enum AVCodecID id;
} CodecMime;
+struct AVFormatInternal {
+ /**
+ * Number of streams relevant for interleaving.
+ * Muxing only.
+ */
+ int nb_interleaved_streams;
+
+ int inject_global_side_data;
+};
+
#ifdef __GNUC__
#define dynarray_add(tab, nb_ptr, elem)\
do {\
@@ -350,11 +360,11 @@ enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags);
/**
* Chooses a timebase for muxing the specified stream.
*
- * The choosen timebase allows sample accurate timestamps based
+ * The chosen timebase allows sample accurate timestamps based
* on the framerate or sample rate for audio streams. It also is
- * at least as precisse as 1/min_precission would be.
+ * at least as precise as 1/min_precision would be.
*/
-AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precission);
+AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision);
/**
* Generate standard extradata for AVC-Intra based on width/height and field
@@ -372,6 +382,15 @@ int ff_generate_avci_extradata(AVStream *st);
int ff_alloc_extradata(AVCodecContext *avctx, int size);
/**
+ * Allocate extradata with additional FF_INPUT_BUFFER_PADDING_SIZE at end
+ * which is always set to 0 and fill it from pb.
+ *
+ * @param size size of extradata
+ * @return >= 0 if OK, AVERROR_xxx on error
+ */
+int ff_get_extradata(AVCodecContext *avctx, AVIOContext *pb, int size);
+
+/**
* add frame for rfps calculation.
*
* @param dts timestamp of the i-th frame
@@ -381,4 +400,18 @@ int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts);
void ff_rfps_calculate(AVFormatContext *ic);
+/**
+ * Flags for AVFormatContext.write_uncoded_frame()
+ */
+enum AVWriteUncodedFrameFlags {
+
+ /**
+ * Query whether the feature is possible on this stream.
+ * The frame argument is ignored.
+ */
+ AV_WRITE_UNCODED_FRAME_QUERY = 0x0001,
+
+};
+
+
#endif /* AVFORMAT_INTERNAL_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/ipmovie.c b/chromium/third_party/ffmpeg/libavformat/ipmovie.c
index 368c05922da..4a766ef3bac 100644
--- a/chromium/third_party/ffmpeg/libavformat/ipmovie.c
+++ b/chromium/third_party/ffmpeg/libavformat/ipmovie.c
@@ -321,7 +321,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
case OPCODE_CREATE_TIMER:
av_dlog(NULL, "create timer\n");
- if ((opcode_version > 0) || (opcode_size > 6)) {
+ if ((opcode_version > 0) || (opcode_size != 6)) {
av_dlog(NULL, "bad create_timer opcode\n");
chunk_type = CHUNK_BAD;
break;
@@ -339,7 +339,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
case OPCODE_INIT_AUDIO_BUFFERS:
av_dlog(NULL, "initialize audio buffers\n");
- if ((opcode_version > 1) || (opcode_size > 10)) {
+ if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
av_dlog(NULL, "bad init_audio_buffers opcode\n");
chunk_type = CHUNK_BAD;
break;
@@ -376,7 +376,9 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
case OPCODE_INIT_VIDEO_BUFFERS:
av_dlog(NULL, "initialize video buffers\n");
- if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4) {
+ if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
+ || opcode_version == 2 && opcode_size < 8
+ ) {
av_dlog(NULL, "bad init_video_buffers opcode\n");
chunk_type = CHUNK_BAD;
break;
@@ -449,8 +451,8 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
av_dlog(NULL, "set palette\n");
/* check for the logical maximum palette size
* (3 * 256 + 4 bytes) */
- if (opcode_size > 0x304) {
- av_dlog(NULL, "demux_ipmovie: set_palette opcode too large\n");
+ if (opcode_size > 0x304 || opcode_size < 4) {
+ av_dlog(NULL, "demux_ipmovie: set_palette opcode with invalid size\n");
chunk_type = CHUNK_BAD;
break;
}
@@ -463,7 +465,8 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
first_color = AV_RL16(&scratch[0]);
last_color = first_color + AV_RL16(&scratch[2]) - 1;
/* sanity check (since they are 16 bit values) */
- if ((first_color > 0xFF) || (last_color > 0xFF)) {
+ if ( (first_color > 0xFF) || (last_color > 0xFF)
+ || (last_color - first_color + 1)*3 + 4 > opcode_size) {
av_dlog(NULL, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
first_color, last_color);
chunk_type = CHUNK_BAD;
diff --git a/chromium/third_party/ffmpeg/libavformat/isom.c b/chromium/third_party/ffmpeg/libavformat/isom.c
index de9d20ccab2..b34398b4f3c 100644
--- a/chromium/third_party/ffmpeg/libavformat/isom.c
+++ b/chromium/third_party/ffmpeg/libavformat/isom.c
@@ -26,6 +26,8 @@
#include "isom.h"
#include "libavcodec/mpeg4audio.h"
#include "libavcodec/mpegaudiodata.h"
+#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
/* http://www.mp4ra.org */
/* ordered by muxing preference */
@@ -33,6 +35,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
{ AV_CODEC_ID_MOV_TEXT , 0x08 },
{ AV_CODEC_ID_MPEG4 , 0x20 },
{ AV_CODEC_ID_H264 , 0x21 },
+ { AV_CODEC_ID_HEVC , 0x23 },
{ AV_CODEC_ID_AAC , 0x40 },
{ AV_CODEC_ID_MP4ALS , 0x40 }, /* 14496-3 ALS */
{ AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG2 Main */
@@ -80,7 +83,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('b', '1', '6', 'g') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('b', '4', '8', 'r') },
- { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') }, /* BOXX */
{ AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'r', 'g') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'y', 'v') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('N', 'O', '1', '6') },
@@ -151,8 +154,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_RAWVIDEO, MKTAG('W', 'R', 'A', 'W') },
- { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */
{ AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, /* HEVC/H.265 which indicates parameter sets may be in ES */
+ { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */
{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
{ AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'p') }, /* AVC-Intra 50M 720p24/30/60 */
@@ -167,12 +170,12 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '3') }, /* AVC-Intra 100M 1080p24/30/60 */
{ AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '5') }, /* AVC-Intra 100M 1080i50 */
{ AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '6') }, /* AVC-Intra 100M 1080i60 */
- { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 4:2:2 10bit */
{ AV_CODEC_ID_H264, MKTAG('A', 'V', 'i', 'n') }, /* AVC-Intra with implicit SPS/PPS */
+ { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 4:2:2 10bit */
+ { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') },
{ AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple MPEG-1 Camcorder */
{ AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
- { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') },
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', '2', 'v', '1') }, /* Apple MPEG-2 Camcorder */
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG2 HDV 720p30 */
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 HDV 1080i60 */
@@ -218,6 +221,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', 'd') }, /* XDCAM HD 540p */
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', '2') }, /* XDCAM HD422 540p */
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('A', 'V', 'm', 'p') }, /* AVID IMX PAL */
+ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '2', 'v') }, /* FCP5 */
{ AV_CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
@@ -299,7 +303,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = {
{ AV_CODEC_ID_QDM2, MKTAG('Q', 'D', 'M', '2') },
{ AV_CODEC_ID_QDMC, MKTAG('Q', 'D', 'M', 'C') },
{ AV_CODEC_ID_SPEEX, MKTAG('s', 'p', 'e', 'x') }, /* Flash Media Server */
- { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') },
+ { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') }, /* ZygoAudio (quality 10 mode) */
{ AV_CODEC_ID_WMAV2, MKTAG('W', 'M', 'A', '2') },
{ AV_CODEC_ID_EVRC, MKTAG('s', 'e', 'v', 'c') }, /* 3GPP2 */
{ AV_CODEC_ID_SMV, MKTAG('s', 's', 'm', 'v') }, /* 3GPP2 */
@@ -438,6 +442,7 @@ static const AVCodecTag mp4_audio_types[] = {
int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb)
{
int len, tag;
+ int ret;
int object_type_id = avio_r8(pb);
avio_r8(pb); /* stream type */
avio_rb24(pb); /* buffer size db */
@@ -457,11 +462,10 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext
if (!len || (uint64_t)len > (1<<30))
return -1;
av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, len))
- return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, len);
+ if ((ret = ff_get_extradata(st->codec, pb, len)) < 0)
+ return ret;
if (st->codec->codec_id == AV_CODEC_ID_AAC) {
- MPEG4AudioConfig cfg;
+ MPEG4AudioConfig cfg = {0};
avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
st->codec->extradata_size * 8, 1);
st->codec->channels = cfg.channels;
@@ -574,3 +578,12 @@ void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout)
avio_wb32(pb, 0); // mNumberChannelDescriptions
}
+const struct AVCodecTag *avformat_get_mov_video_tags(void)
+{
+ return ff_codec_movvideo_tags;
+}
+
+const struct AVCodecTag *avformat_get_mov_audio_tags(void)
+{
+ return ff_codec_movaudio_tags;
+}
diff --git a/chromium/third_party/ffmpeg/libavformat/isom.h b/chromium/third_party/ffmpeg/libavformat/isom.h
index 2834b11b3e8..a929ebf05ef 100644
--- a/chromium/third_party/ffmpeg/libavformat/isom.h
+++ b/chromium/third_party/ffmpeg/libavformat/isom.h
@@ -142,6 +142,9 @@ typedef struct MOVStreamContext {
int start_pad; ///< amount of samples to skip due to enc-dec delay
unsigned int rap_group_count;
MOVSbgp *rap_group;
+
+ int nb_frames_for_fps;
+ int64_t duration_for_fps;
} MOVStreamContext;
typedef struct MOVContext {
diff --git a/chromium/third_party/ffmpeg/libavformat/iss.c b/chromium/third_party/ffmpeg/libavformat/iss.c
index e4335b4cbfb..e9945313d69 100644
--- a/chromium/third_party/ffmpeg/libavformat/iss.c
+++ b/chromium/third_party/ffmpeg/libavformat/iss.c
@@ -76,14 +76,23 @@ static av_cold int iss_read_header(AVFormatContext *s)
get_token(pb, token, sizeof(token)); //"IMA_ADPCM_Sound"
get_token(pb, token, sizeof(token)); //packet size
- sscanf(token, "%d", &iss->packet_size);
+ if (sscanf(token, "%d", &iss->packet_size) != 1) {
+ av_log(s, AV_LOG_ERROR, "Failed parsing packet size\n");
+ return AVERROR_INVALIDDATA;
+ }
get_token(pb, token, sizeof(token)); //File ID
get_token(pb, token, sizeof(token)); //out size
get_token(pb, token, sizeof(token)); //stereo
- sscanf(token, "%d", &stereo);
+ if (sscanf(token, "%d", &stereo) != 1) {
+ av_log(s, AV_LOG_ERROR, "Failed parsing stereo flag\n");
+ return AVERROR_INVALIDDATA;
+ }
get_token(pb, token, sizeof(token)); //Unknown1
get_token(pb, token, sizeof(token)); //RateDivisor
- sscanf(token, "%d", &rate_divisor);
+ if (sscanf(token, "%d", &rate_divisor) != 1) {
+ av_log(s, AV_LOG_ERROR, "Failed parsing rate_divisor\n");
+ return AVERROR_INVALIDDATA;
+ }
get_token(pb, token, sizeof(token)); //Unknown2
get_token(pb, token, sizeof(token)); //Version ID
get_token(pb, token, sizeof(token)); //Size
diff --git a/chromium/third_party/ffmpeg/libavformat/jvdec.c b/chromium/third_party/ffmpeg/libavformat/jvdec.c
index 69ac8f27fd3..eab450d862b 100644
--- a/chromium/third_party/ffmpeg/libavformat/jvdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/jvdec.c
@@ -27,6 +27,7 @@
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
+
#include "avformat.h"
#include "internal.h"
@@ -59,6 +60,15 @@ static int read_probe(AVProbeData *pd)
return 0;
}
+static int read_close(AVFormatContext *s)
+{
+ JVDemuxContext *jv = s->priv_data;
+
+ av_freep(&jv->frames);
+
+ return 0;
+}
+
static int read_header(AVFormatContext *s)
{
JVDemuxContext *jv = s->priv_data;
@@ -87,17 +97,18 @@ static int read_header(AVFormatContext *s)
avio_skip(pb, 4);
- ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
- ast->codec->codec_tag = 0; /* no fourcc */
- ast->codec->sample_rate = avio_rl16(pb);
- ast->codec->channels = 1;
+ ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
+ ast->codec->codec_tag = 0; /* no fourcc */
+ ast->codec->sample_rate = avio_rl16(pb);
+ ast->codec->channels = 1;
ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
avio_skip(pb, 10);
- ast->index_entries = av_malloc(ast->nb_index_entries * sizeof(*ast->index_entries));
+ ast->index_entries = av_malloc(ast->nb_index_entries *
+ sizeof(*ast->index_entries));
if (!ast->index_entries)
return AVERROR(ENOMEM);
@@ -106,28 +117,41 @@ static int read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
offset = 0x68 + ast->nb_index_entries * 16;
- for(i = 0; i < ast->nb_index_entries; i++) {
+ for (i = 0; i < ast->nb_index_entries; i++) {
AVIndexEntry *e = ast->index_entries + i;
JVFrame *jvf = jv->frames + i;
/* total frame size including audio, video, palette data and padding */
- e->size = avio_rl32(pb);
- e->timestamp = i;
- e->pos = offset;
- offset += e->size;
+ e->size = avio_rl32(pb);
+ e->timestamp = i;
+ e->pos = offset;
+ offset += e->size;
- jvf->audio_size = avio_rl32(pb);
- jvf->video_size = avio_rl32(pb);
+ jvf->audio_size = avio_rl32(pb);
+ jvf->video_size = avio_rl32(pb);
jvf->palette_size = avio_r8(pb) ? 768 : 0;
- jvf->video_size = FFMIN(FFMAX(jvf->video_size, 0),
- INT_MAX - JV_PREAMBLE_SIZE - jvf->palette_size);
+
+ if ((jvf->video_size | jvf->audio_size) & ~0xFFFFFF ||
+ e->size - jvf->audio_size
+ - jvf->video_size
+ - jvf->palette_size < 0) {
+ if (s->error_recognition & AV_EF_EXPLODE) {
+ read_close(s);
+ return AVERROR_INVALIDDATA;
+ }
+ jvf->audio_size =
+ jvf->video_size =
+ jvf->palette_size = 0;
+ }
+
if (avio_r8(pb))
- av_log(s, AV_LOG_WARNING, "unsupported audio codec\n");
+ av_log(s, AV_LOG_WARNING, "unsupported audio codec\n");
+
jvf->video_type = avio_r8(pb);
avio_skip(pb, 1);
e->timestamp = jvf->audio_size ? audio_pts : AV_NOPTS_VALUE;
- audio_pts += jvf->audio_size;
+ audio_pts += jvf->audio_size;
e->flags = jvf->video_type != 1 ? AVINDEX_KEYFRAME : 0;
}
@@ -146,10 +170,10 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
const AVIndexEntry *e = ast->index_entries + jv->pts;
const JVFrame *jvf = jv->frames + jv->pts;
- switch(jv->state) {
+ switch (jv->state) {
case JV_AUDIO:
jv->state++;
- if (jvf->audio_size ) {
+ if (jvf->audio_size) {
if (av_get_packet(s->pb, pkt, jvf->audio_size) < 0)
return AVERROR(ENOMEM);
pkt->stream_index = 0;
@@ -160,16 +184,22 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
case JV_VIDEO:
jv->state++;
if (jvf->video_size || jvf->palette_size) {
+ int ret;
int size = jvf->video_size + jvf->palette_size;
if (av_new_packet(pkt, size + JV_PREAMBLE_SIZE))
return AVERROR(ENOMEM);
AV_WL32(pkt->data, jvf->video_size);
- pkt->data[4] = jvf->video_type;
- if ((size = avio_read(pb, pkt->data + JV_PREAMBLE_SIZE, size)) < 0)
- return AVERROR(EIO);
-
- pkt->size = size + JV_PREAMBLE_SIZE;
+ pkt->data[4] = jvf->video_type;
+ ret = avio_read(pb, pkt->data + JV_PREAMBLE_SIZE, size);
+ if (ret < 0)
+ return ret;
+ if (ret < size) {
+ memset(pkt->data + JV_PREAMBLE_SIZE + ret, 0,
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ pkt->flags |= AV_PKT_FLAG_CORRUPT;
+ }
+ pkt->size = ret + JV_PREAMBLE_SIZE;
pkt->stream_index = 1;
pkt->pts = jv->pts;
if (jvf->video_type != 1)
@@ -184,6 +214,9 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
}
}
+ if (s->pb->eof_reached)
+ return AVERROR_EOF;
+
return AVERROR(EIO);
}
@@ -194,10 +227,10 @@ static int read_seek(AVFormatContext *s, int stream_index,
AVStream *ast = s->streams[0];
int i;
- if (flags & (AVSEEK_FLAG_BYTE|AVSEEK_FLAG_FRAME))
+ if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))
return AVERROR(ENOSYS);
- switch(stream_index) {
+ switch (stream_index) {
case 0:
i = av_index_search_timestamp(ast, ts, flags);
break;
@@ -218,15 +251,6 @@ static int read_seek(AVFormatContext *s, int stream_index,
return 0;
}
-static int read_close(AVFormatContext *s)
-{
- JVDemuxContext *jv = s->priv_data;
-
- av_freep(&jv->frames);
-
- return 0;
-}
-
AVInputFormat ff_jv_demuxer = {
.name = "jv",
.long_name = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV"),
diff --git a/chromium/third_party/ffmpeg/libavformat/libmodplug.c b/chromium/third_party/ffmpeg/libavformat/libmodplug.c
index 836b7c2ec06..3f00dbf2a42 100644
--- a/chromium/third_party/ffmpeg/libavformat/libmodplug.c
+++ b/chromium/third_party/ffmpeg/libavformat/libmodplug.c
@@ -22,6 +22,7 @@
* @todo better probing than extensions matching
*/
+#define MODPLUG_STATIC
#include <libmodplug/modplug.h>
#include "libavutil/avstring.h"
#include "libavutil/eval.h"
diff --git a/chromium/third_party/ffmpeg/libavformat/libnut.c b/chromium/third_party/ffmpeg/libavformat/libnut.c
index be8f3cb283e..4a9a21a7668 100644
--- a/chromium/third_party/ffmpeg/libavformat/libnut.c
+++ b/chromium/third_party/ffmpeg/libavformat/libnut.c
@@ -70,7 +70,7 @@ static int nut_write_header(AVFormatContext * avf) {
nut_stream_header_tt * s;
int i;
- priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s);
+ priv->s = s = av_mallocz_array(avf->nb_streams + 1, sizeof*s);
if(!s)
return AVERROR(ENOMEM);
diff --git a/chromium/third_party/ffmpeg/libavformat/librtmp.c b/chromium/third_party/ffmpeg/libavformat/librtmp.c
index 5b4c39dde5c..5172c5148ab 100644
--- a/chromium/third_party/ffmpeg/libavformat/librtmp.c
+++ b/chromium/third_party/ffmpeg/libavformat/librtmp.c
@@ -37,7 +37,16 @@ typedef struct LibRTMPContext {
const AVClass *class;
RTMP rtmp;
char *app;
+ char *conn;
+ char *subscribe;
char *playpath;
+ char *tcurl;
+ char *flashver;
+ char *swfurl;
+ char *swfverify;
+ char *pageurl;
+ char *client_buffer_time;
+ int live;
} LibRTMPContext;
static void rtmp_log(int level, const char *fmt, va_list args)
@@ -83,6 +92,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
RTMP *r = &ctx->rtmp;
int rc = 0, level;
char *filename = s->filename;
+ int len = strlen(s->filename) + 1;
switch (av_log_get_level()) {
default:
@@ -96,22 +106,111 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
RTMP_LogSetLevel(level);
RTMP_LogSetCallback(rtmp_log);
- if (ctx->app || ctx->playpath) {
- int len = strlen(s->filename) + 1;
- if (ctx->app) len += strlen(ctx->app) + sizeof(" app=");
- if (ctx->playpath) len += strlen(ctx->playpath) + sizeof(" playpath=");
+ if (ctx->app) len += strlen(ctx->app) + sizeof(" app=");
+ if (ctx->tcurl) len += strlen(ctx->tcurl) + sizeof(" tcUrl=");
+ if (ctx->pageurl) len += strlen(ctx->pageurl) + sizeof(" pageUrl=");
+ if (ctx->flashver) len += strlen(ctx->flashver) + sizeof(" flashver=");
+
+ if (ctx->conn) {
+ char *sep, *p = ctx->conn;
+ int options = 0;
+
+ while (p) {
+ options++;
+ p += strspn(p, " ");
+ if (!*p)
+ break;
+ sep = strchr(p, ' ');
+ if (sep)
+ p = sep + 1;
+ else
+ break;
+ }
+ len += options * sizeof(" conn=");
+ len += strlen(ctx->conn);
+ }
+
+ if (ctx->playpath)
+ len += strlen(ctx->playpath) + sizeof(" playpath=");
+ if (ctx->live)
+ len += sizeof(" live=1");
+ if (ctx->subscribe)
+ len += strlen(ctx->subscribe) + sizeof(" subscribe=");
- if (!(filename = av_malloc(len)))
- return AVERROR(ENOMEM);
+ if (ctx->client_buffer_time)
+ len += strlen(ctx->client_buffer_time) + sizeof(" buffer=");
- av_strlcpy(filename, s->filename, len);
- if (ctx->app) {
- av_strlcat(filename, " app=", len);
- av_strlcat(filename, ctx->app, len);
+ if (ctx->swfurl || ctx->swfverify) {
+ len += sizeof(" swfUrl=");
+
+ if (ctx->swfverify)
+ len += strlen(ctx->swfverify) + sizeof(" swfVfy=1");
+ else
+ len += strlen(ctx->swfurl);
+ }
+
+ if (!(filename = av_malloc(len)))
+ return AVERROR(ENOMEM);
+
+ av_strlcpy(filename, s->filename, len);
+ if (ctx->app) {
+ av_strlcat(filename, " app=", len);
+ av_strlcat(filename, ctx->app, len);
+ }
+ if (ctx->tcurl) {
+ av_strlcat(filename, " tcUrl=", len);
+ av_strlcat(filename, ctx->tcurl, len);
+ }
+ if (ctx->pageurl) {
+ av_strlcat(filename, " pageUrl=", len);
+ av_strlcat(filename, ctx->pageurl, len);
+ }
+ if (ctx->swfurl) {
+ av_strlcat(filename, " swfUrl=", len);
+ av_strlcat(filename, ctx->pageurl, len);
+ }
+ if (ctx->flashver) {
+ av_strlcat(filename, " flashVer=", len);
+ av_strlcat(filename, ctx->flashver, len);
+ }
+ if (ctx->conn) {
+ char *sep, *p = ctx->conn;
+ while (p) {
+ av_strlcat(filename, " conn=", len);
+ p += strspn(p, " ");
+ if (!*p)
+ break;
+ sep = strchr(p, ' ');
+ if (sep)
+ *sep = '\0';
+ av_strlcat(filename, p, len);
+
+ if (sep)
+ p = sep + 1;
}
- if (ctx->playpath) {
- av_strlcat(filename, " playpath=", len);
- av_strlcat(filename, ctx->playpath, len);
+ }
+ if (ctx->playpath) {
+ av_strlcat(filename, " playpath=", len);
+ av_strlcat(filename, ctx->playpath, len);
+ }
+ if (ctx->live)
+ av_strlcat(filename, " live=1", len);
+ if (ctx->subscribe) {
+ av_strlcat(filename, " subscribe=", len);
+ av_strlcat(filename, ctx->subscribe, len);
+ }
+ if (ctx->client_buffer_time) {
+ av_strlcat(filename, " buffer=", len);
+ av_strlcat(filename, ctx->client_buffer_time, len);
+ }
+ if (ctx->swfurl || ctx->swfverify) {
+ av_strlcat(filename, " swfUrl=", len);
+
+ if (ctx->swfverify) {
+ av_strlcat(filename, ctx->swfverify, len);
+ av_strlcat(filename, " swfVfy=1", len);
+ } else {
+ av_strlcat(filename, ctx->swfurl, len);
}
}
@@ -134,6 +233,9 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
fail:
if (filename != s->filename)
av_freep(&filename);
+ if (rc)
+ RTMP_Close(r);
+
return rc;
}
@@ -194,8 +296,20 @@ static int rtmp_get_file_handle(URLContext *s)
#define DEC AV_OPT_FLAG_DECODING_PARAM
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
- {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
- {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_STRING, {.str = "3000"}, 0, 0, DEC|ENC},
+ {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
+ {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
+ {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
+ {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
+ {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
+ {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
+ {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically. (unimplemented)", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
+ {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{ NULL },
};
diff --git a/chromium/third_party/ffmpeg/libavformat/libssh.c b/chromium/third_party/ffmpeg/libavformat/libssh.c
index 4a9b8674cf4..b20e93bbab9 100644
--- a/chromium/third_party/ffmpeg/libavformat/libssh.c
+++ b/chromium/third_party/ffmpeg/libavformat/libssh.c
@@ -19,9 +19,11 @@
*/
#include <fcntl.h>
+#define LIBSSH_STATIC
#include <libssh/sftp.h>
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
+#include "libavutil/attributes.h"
#include "avformat.h"
#include "internal.h"
#include "url.h"
@@ -34,106 +36,179 @@ typedef struct {
int64_t filesize;
int rw_timeout;
int trunc;
+ char *priv_key;
} LIBSSHContext;
-static int libssh_close(URLContext *h)
+static av_cold int libssh_create_ssh_session(LIBSSHContext *libssh, const char* hostname, unsigned int port)
{
- LIBSSHContext *s = h->priv_data;
- if (s->file)
- sftp_close(s->file);
- if (s->sftp)
- sftp_free(s->sftp);
- if (s->session) {
- ssh_disconnect(s->session);
- ssh_free(s->session);
+ static const int verbosity = SSH_LOG_NOLOG;
+
+ if (!(libssh->session = ssh_new())) {
+ av_log(libssh, AV_LOG_ERROR, "SSH session creation failed: %s\n", ssh_get_error(libssh->session));
+ return AVERROR(ENOMEM);
+ }
+ ssh_options_set(libssh->session, SSH_OPTIONS_HOST, hostname);
+ ssh_options_set(libssh->session, SSH_OPTIONS_PORT, &port);
+ ssh_options_set(libssh->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+ if (libssh->rw_timeout > 0) {
+ long timeout = libssh->rw_timeout * 1000;
+ ssh_options_set(libssh->session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
+ }
+
+ if (ssh_connect(libssh->session) != SSH_OK) {
+ av_log(libssh, AV_LOG_ERROR, "Connection failed: %s\n", ssh_get_error(libssh->session));
+ return AVERROR(EIO);
}
+
return 0;
}
-static int libssh_open(URLContext *h, const char *url, int flags)
+static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user, const char *password)
{
- static const int verbosity = SSH_LOG_NOLOG;
- LIBSSHContext *s = h->priv_data;
- char proto[10], path[MAX_URL_SIZE], hostname[1024], credencials[1024];
- int port = 22, access, ret;
- long timeout = s->rw_timeout * 1000;
- const char *user = NULL, *pass = NULL;
- char *end = NULL;
- sftp_attributes stat;
+ int authorized = 0;
+ int auth_methods;
- av_url_split(proto, sizeof(proto),
- credencials, sizeof(credencials),
- hostname, sizeof(hostname),
- &port,
- path, sizeof(path),
- url);
+ if (user)
+ ssh_options_set(libssh->session, SSH_OPTIONS_USER, user);
- if (port <= 0 || port > 65535)
- port = 22;
+ auth_methods = ssh_userauth_list(libssh->session, NULL);
- if (!(s->session = ssh_new())) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
+ if (libssh->priv_key) {
+ ssh_string pub_key;
+ ssh_private_key priv_key;
+ int type;
+ if (!ssh_try_publickey_from_file(libssh->session, libssh->priv_key, &pub_key, &type)) {
+ priv_key = privatekey_from_file(libssh->session, libssh->priv_key, type, password);
+ if (ssh_userauth_pubkey(libssh->session, NULL, pub_key, priv_key) == SSH_AUTH_SUCCESS) {
+ av_log(libssh, AV_LOG_DEBUG, "Authentication successful with selected private key.\n");
+ authorized = 1;
+ }
+ } else {
+ av_log(libssh, AV_LOG_DEBUG, "Invalid key is provided.\n");
+ return AVERROR(EACCES);
+ }
+ } else if (ssh_userauth_autopubkey(libssh->session, password) == SSH_AUTH_SUCCESS) {
+ av_log(libssh, AV_LOG_DEBUG, "Authentication successful with auto selected key.\n");
+ authorized = 1;
+ }
}
- user = av_strtok(credencials, ":", &end);
- pass = av_strtok(end, ":", &end);
- ssh_options_set(s->session, SSH_OPTIONS_HOST, hostname);
- ssh_options_set(s->session, SSH_OPTIONS_PORT, &port);
- ssh_options_set(s->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
- if (timeout > 0)
- ssh_options_set(s->session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
- if (user)
- ssh_options_set(s->session, SSH_OPTIONS_USER, user);
- if (ssh_connect(s->session) != SSH_OK) {
- av_log(h, AV_LOG_ERROR, "Connection failed. %s\n", ssh_get_error(s->session));
- ret = AVERROR(EIO);
- goto fail;
+ if (!authorized && (auth_methods & SSH_AUTH_METHOD_PASSWORD)) {
+ if (ssh_userauth_password(libssh->session, NULL, password) == SSH_AUTH_SUCCESS) {
+ av_log(libssh, AV_LOG_DEBUG, "Authentication successful with password.\n");
+ authorized = 1;
+ }
}
- if (pass && ssh_userauth_password(s->session, NULL, pass) != SSH_AUTH_SUCCESS) {
- av_log(h, AV_LOG_ERROR, "Error authenticating with password: %s\n", ssh_get_error(s->session));
- ret = AVERROR(EACCES);
- goto fail;
+ if (!authorized) {
+ av_log(libssh, AV_LOG_ERROR, "Authentication failed.\n");
+ return AVERROR(EACCES);
}
- if (!(s->sftp = sftp_new(s->session))) {
- av_log(h, AV_LOG_ERROR, "SFTP session creation failed: %s\n", ssh_get_error(s->session));
- ret = AVERROR(ENOMEM);
- goto fail;
+ return 0;
+}
+
+static av_cold int libssh_create_sftp_session(LIBSSHContext *libssh)
+{
+ if (!(libssh->sftp = sftp_new(libssh->session))) {
+ av_log(libssh, AV_LOG_ERROR, "SFTP session creation failed: %s\n", ssh_get_error(libssh->session));
+ return AVERROR(ENOMEM);
}
- if (sftp_init(s->sftp) != SSH_OK) {
- av_log(h, AV_LOG_ERROR, "Error initializing sftp session: %s\n", ssh_get_error(s->session));
- ret = AVERROR(EIO);
- goto fail;
+ if (sftp_init(libssh->sftp) != SSH_OK) {
+ av_log(libssh, AV_LOG_ERROR, "Error initializing sftp session: %s\n", ssh_get_error(libssh->session));
+ return AVERROR(EIO);
}
+ return 0;
+}
+
+static av_cold int libssh_open_file(LIBSSHContext *libssh, int flags, const char *file)
+{
+ int access;
+
if ((flags & AVIO_FLAG_WRITE) && (flags & AVIO_FLAG_READ)) {
access = O_CREAT | O_RDWR;
- if (s->trunc)
+ if (libssh->trunc)
access |= O_TRUNC;
} else if (flags & AVIO_FLAG_WRITE) {
access = O_CREAT | O_WRONLY;
- if (s->trunc)
+ if (libssh->trunc)
access |= O_TRUNC;
- } else {
+ } else
access = O_RDONLY;
- }
- if (!(s->file = sftp_open(s->sftp, path, access, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH))) {
- av_log(h, AV_LOG_ERROR, "Error opening sftp file: %s\n", ssh_get_error(s->session));
- ret = AVERROR(EIO);
- goto fail;
+ /* 0666 = -rw-rw-rw- = read+write for everyone, minus umask */
+ if (!(libssh->file = sftp_open(libssh->sftp, file, access, 0666))) {
+ av_log(libssh, AV_LOG_ERROR, "Error opening sftp file: %s\n", ssh_get_error(libssh->session));
+ return AVERROR(EIO);
}
- if (!(stat = sftp_fstat(s->file))) {
- av_log(h, AV_LOG_WARNING, "Cannot stat remote file %s.\n", path);
- s->filesize = -1;
+ return 0;
+}
+
+static av_cold void libssh_stat_file(LIBSSHContext *libssh)
+{
+ sftp_attributes stat;
+
+ if (!(stat = sftp_fstat(libssh->file))) {
+ av_log(libssh, AV_LOG_WARNING, "Cannot stat remote file.\n");
+ libssh->filesize = -1;
} else {
- s->filesize = stat->size;
+ libssh->filesize = stat->size;
sftp_attributes_free(stat);
}
+}
+
+static av_cold int libssh_close(URLContext *h)
+{
+ LIBSSHContext *libssh = h->priv_data;
+ if (libssh->file)
+ sftp_close(libssh->file);
+ if (libssh->sftp)
+ sftp_free(libssh->sftp);
+ if (libssh->session) {
+ ssh_disconnect(libssh->session);
+ ssh_free(libssh->session);
+ }
+ return 0;
+}
+
+static av_cold int libssh_open(URLContext *h, const char *url, int flags)
+{
+ LIBSSHContext *libssh = h->priv_data;
+ char proto[10], path[MAX_URL_SIZE], hostname[1024], credencials[1024];
+ int port = 22, ret;
+ const char *user = NULL, *pass = NULL;
+ char *end = NULL;
+
+ av_url_split(proto, sizeof(proto),
+ credencials, sizeof(credencials),
+ hostname, sizeof(hostname),
+ &port,
+ path, sizeof(path),
+ url);
+
+ if (port <= 0 || port > 65535)
+ port = 22;
+
+ if ((ret = libssh_create_ssh_session(libssh, hostname, port)) < 0)
+ goto fail;
+
+ user = av_strtok(credencials, ":", &end);
+ pass = av_strtok(end, ":", &end);
+
+ if ((ret = libssh_authentication(libssh, user, pass)) < 0)
+ goto fail;
+
+ if ((ret = libssh_create_sftp_session(libssh)) < 0)
+ goto fail;
+
+ if ((ret = libssh_open_file(libssh, flags, path)) < 0)
+ goto fail;
+
+ libssh_stat_file(libssh);
return 0;
@@ -144,31 +219,36 @@ static int libssh_open(URLContext *h, const char *url, int flags)
static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
{
- LIBSSHContext *s = h->priv_data;
+ LIBSSHContext *libssh = h->priv_data;
int64_t newpos;
- if (s->filesize == -1 && (whence == AVSEEK_SIZE || whence == SEEK_END)) {
+ if (libssh->filesize == -1 && (whence == AVSEEK_SIZE || whence == SEEK_END)) {
av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
return AVERROR(EIO);
}
switch(whence) {
case AVSEEK_SIZE:
- return s->filesize;
+ return libssh->filesize;
case SEEK_SET:
newpos = pos;
break;
case SEEK_CUR:
- newpos = sftp_tell64(s->file);
+ newpos = sftp_tell64(libssh->file) + pos;
break;
case SEEK_END:
- newpos = s->filesize + pos;
+ newpos = libssh->filesize + pos;
break;
default:
return AVERROR(EINVAL);
}
- if (sftp_seek64(s->file, newpos)) {
+ if (newpos < 0) {
+ av_log(h, AV_LOG_ERROR, "Seeking to nagative position.\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (sftp_seek64(libssh->file, newpos)) {
av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
return AVERROR(EIO);
}
@@ -178,11 +258,11 @@ static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
static int libssh_read(URLContext *h, unsigned char *buf, int size)
{
- LIBSSHContext *s = h->priv_data;
+ LIBSSHContext *libssh = h->priv_data;
int bytes_read;
- if ((bytes_read = sftp_read(s->file, buf, size)) < 0) {
- av_log(h, AV_LOG_ERROR, "Read error.\n");
+ if ((bytes_read = sftp_read(libssh->file, buf, size)) < 0) {
+ av_log(libssh, AV_LOG_ERROR, "Read error.\n");
return AVERROR(EIO);
}
return bytes_read;
@@ -190,11 +270,11 @@ static int libssh_read(URLContext *h, unsigned char *buf, int size)
static int libssh_write(URLContext *h, const unsigned char *buf, int size)
{
- LIBSSHContext *s = h->priv_data;
+ LIBSSHContext *libssh = h->priv_data;
int bytes_written;
- if ((bytes_written = sftp_write(s->file, buf, size)) < 0) {
- av_log(h, AV_LOG_ERROR, "Write error.\n");
+ if ((bytes_written = sftp_write(libssh->file, buf, size)) < 0) {
+ av_log(libssh, AV_LOG_ERROR, "Write error.\n");
return AVERROR(EIO);
}
return bytes_written;
@@ -206,6 +286,7 @@ static int libssh_write(URLContext *h, const unsigned char *buf, int size)
static const AVOption options[] = {
{"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
{"truncate", "Truncate existing files on write", OFFSET(trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
+ {"private_key", "set path to private key", OFFSET(priv_key), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D|E },
{NULL}
};
diff --git a/chromium/third_party/ffmpeg/libavformat/loasdec.c b/chromium/third_party/ffmpeg/libavformat/loasdec.c
index 05ef0fe3ad5..c41809be006 100644
--- a/chromium/third_party/ffmpeg/libavformat/loasdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/loasdec.c
@@ -25,6 +25,8 @@
#include "internal.h"
#include "rawdec.h"
+#define LOAS_SYNC_WORD 0x2b7
+
static int loas_probe(AVProbeData *p)
{
int max_frames = 0, first_frames = 0;
@@ -35,27 +37,32 @@ static int loas_probe(AVProbeData *p)
const uint8_t *end = buf0 + p->buf_size - 3;
buf = buf0;
- for(; buf < end; buf= buf2+1) {
+ for (; buf < end; buf = buf2 + 1) {
buf2 = buf;
- for(frames = 0; buf2 < end; frames++) {
+ for (frames = 0; buf2 < end; frames++) {
uint32_t header = AV_RB24(buf2);
- if((header >> 13) != 0x2B7)
+ if ((header >> 13) != LOAS_SYNC_WORD)
break;
fsize = (header & 0x1FFF) + 3;
- if(fsize < 7)
+ if (fsize < 7)
break;
fsize = FFMIN(fsize, end - buf2);
buf2 += fsize;
}
max_frames = FFMAX(max_frames, frames);
- if(buf == buf0)
- first_frames= frames;
+ if (buf == buf0)
+ first_frames = frames;
}
- if (first_frames>=3) return AVPROBE_SCORE_EXTENSION+1;
- else if(max_frames>100)return AVPROBE_SCORE_EXTENSION;
- else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2;
- else return 0;
+
+ if (first_frames >= 3)
+ return AVPROBE_SCORE_EXTENSION + 1;
+ else if (max_frames > 100)
+ return AVPROBE_SCORE_EXTENSION;
+ else if (max_frames >= 3)
+ return AVPROBE_SCORE_EXTENSION / 2;
+ else
+ return 0;
}
static int loas_read_header(AVFormatContext *s)
diff --git a/chromium/third_party/ffmpeg/libavformat/lxfdec.c b/chromium/third_party/ffmpeg/libavformat/lxfdec.c
index f0a96396b46..19f7f27385a 100644
--- a/chromium/third_party/ffmpeg/libavformat/lxfdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/lxfdec.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/intreadwrite.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
@@ -128,12 +130,12 @@ static int get_packet_header(AVFormatContext *s)
version = bytestream_get_le32(&p);
header_size = bytestream_get_le32(&p);
if (version > 1)
- avpriv_request_sample(s, "Unknown format version %i\n", version);
+ avpriv_request_sample(s, "Unknown format version %"PRIu32"\n", version);
if (header_size < (version ? 72 : 60) ||
header_size > LXF_MAX_PACKET_HEADER_SIZE ||
(header_size & 3)) {
- av_log(s, AV_LOG_ERROR, "Invalid header size 0x%x\n", header_size);
+ av_log(s, AV_LOG_ERROR, "Invalid header size 0x%"PRIx32"\n", header_size);
return AVERROR_INVALIDDATA;
}
@@ -301,7 +303,8 @@ static int lxf_read_packet(AVFormatContext *s, AVPacket *pkt)
stream = lxf->packet_type;
if (stream > 1) {
- av_log(s, AV_LOG_WARNING, "got packet with illegal stream index %u\n", stream);
+ av_log(s, AV_LOG_WARNING,
+ "got packet with illegal stream index %"PRIu32"\n", stream);
return AVERROR(EAGAIN);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/matroska.c b/chromium/third_party/ffmpeg/libavformat/matroska.c
index 77a88a8756c..d281ef4fd53 100644
--- a/chromium/third_party/ffmpeg/libavformat/matroska.c
+++ b/chromium/third_party/ffmpeg/libavformat/matroska.c
@@ -35,7 +35,7 @@ const CodecTags ff_mkv_codec_tags[]={
{"A_MPEG/L2" , AV_CODEC_ID_MP2},
{"A_MPEG/L1" , AV_CODEC_ID_MP2},
{"A_MPEG/L3" , AV_CODEC_ID_MP3},
- {"A_OPUS", AV_CODEC_ID_OPUS},
+ {"A_OPUS" , AV_CODEC_ID_OPUS},
{"A_OPUS/EXPERIMENTAL",AV_CODEC_ID_OPUS},
{"A_PCM/FLOAT/IEEE" , AV_CODEC_ID_PCM_F32LE},
{"A_PCM/FLOAT/IEEE" , AV_CODEC_ID_PCM_F64LE},
@@ -113,6 +113,7 @@ const CodecMime ff_mkv_mime_tags[] = {
{"application/x-truetype-font", AV_CODEC_ID_TTF},
{"application/x-font" , AV_CODEC_ID_TTF},
{"application/vnd.ms-opentype", AV_CODEC_ID_OTF},
+ {"binary" , AV_CODEC_ID_BIN_DATA},
{"" , AV_CODEC_ID_NONE}
};
diff --git a/chromium/third_party/ffmpeg/libavformat/matroskadec.c b/chromium/third_party/ffmpeg/libavformat/matroskadec.c
index cedb3452a51..dcbdd2f5246 100644
--- a/chromium/third_party/ffmpeg/libavformat/matroskadec.c
+++ b/chromium/third_party/ffmpeg/libavformat/matroskadec.c
@@ -28,33 +28,38 @@
* @see specs available on the Matroska project page: http://www.matroska.org/
*/
+#include "config.h"
+
+#include <inttypes.h>
#include <stdio.h>
+#if CONFIG_BZLIB
+#include <bzlib.h>
+#endif
+#if CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+#include "libavutil/avstring.h"
+#include "libavutil/base64.h"
+#include "libavutil/dict.h"
+#include "libavutil/intfloat.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/lzo.h"
+#include "libavutil/mathematics.h"
+
+#include "libavcodec/bytestream.h"
+#include "libavcodec/mpeg4audio.h"
+
#include "avformat.h"
-#include "internal.h"
#include "avio_internal.h"
+#include "internal.h"
+#include "isom.h"
+#include "matroska.h"
/* For ff_codec_get_id(). */
#include "riff.h"
-#include "isom.h"
#if CONFIG_SIPR_DECODER
#include "rmsipr.h"
#endif
-#include "matroska.h"
-#include "libavcodec/bytestream.h"
-#include "libavcodec/mpeg4audio.h"
-#include "libavutil/base64.h"
-#include "libavutil/intfloat.h"
-#include "libavutil/intreadwrite.h"
-#include "libavutil/avstring.h"
-#if CONFIG_LZO
-#include "libavutil/lzo.h"
-#endif
-#include "libavutil/dict.h"
-#if CONFIG_ZLIB
-#include <zlib.h>
-#endif
-#if CONFIG_BZLIB
-#include <bzlib.h>
-#endif
static int matroska_read_close(AVFormatContext *s);
@@ -170,12 +175,12 @@ typedef struct {
uint64_t default_duration;
uint64_t flag_default;
uint64_t flag_forced;
- uint64_t codec_delay;
uint64_t seek_preroll;
MatroskaTrackVideo video;
MatroskaTrackAudio audio;
MatroskaTrackOperation operation;
EbmlList encodings;
+ uint64_t codec_delay;
AVStream *stream;
int64_t end_timecode;
@@ -190,7 +195,7 @@ typedef struct {
EbmlBin bin;
AVStream *stream;
-} MatroskaAttachement;
+} MatroskaAttachment;
typedef struct {
uint64_t start;
@@ -259,6 +264,7 @@ typedef struct {
uint64_t time_scale;
double duration;
char *title;
+ char *muxingapp;
EbmlBin date_utc;
EbmlList tracks;
EbmlList attachments;
@@ -303,67 +309,67 @@ typedef struct {
} MatroskaBlock;
static EbmlSyntax ebml_header[] = {
- { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} },
- { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} },
- { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml,id_length), {.u=4} },
- { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml,doctype), {.s="(none)"} },
- { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml,doctype_version), {.u=1} },
- { EBML_ID_EBMLVERSION, EBML_NONE },
- { EBML_ID_DOCTYPEVERSION, EBML_NONE },
+ { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml, version), { .u = EBML_VERSION } },
+ { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml, max_size), { .u = 8 } },
+ { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml, id_length), { .u = 4 } },
+ { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml, doctype), { .s = "(none)" } },
+ { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml, doctype_version), { .u = 1 } },
+ { EBML_ID_EBMLVERSION, EBML_NONE },
+ { EBML_ID_DOCTYPEVERSION, EBML_NONE },
{ 0 }
};
static EbmlSyntax ebml_syntax[] = {
- { EBML_ID_HEADER, EBML_NEST, 0, 0, {.n=ebml_header} },
+ { EBML_ID_HEADER, EBML_NEST, 0, 0, { .n = ebml_header } },
{ 0 }
};
static EbmlSyntax matroska_info[] = {
- { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, offsetof(MatroskaDemuxContext,time_scale), {.u=1000000} },
- { MATROSKA_ID_DURATION, EBML_FLOAT, 0, offsetof(MatroskaDemuxContext,duration) },
- { MATROSKA_ID_TITLE, EBML_UTF8, 0, offsetof(MatroskaDemuxContext,title) },
- { MATROSKA_ID_WRITINGAPP, EBML_NONE },
- { MATROSKA_ID_MUXINGAPP, EBML_NONE },
- { MATROSKA_ID_DATEUTC, EBML_BIN, 0, offsetof(MatroskaDemuxContext,date_utc) },
- { MATROSKA_ID_SEGMENTUID, EBML_NONE },
+ { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } },
+ { MATROSKA_ID_DURATION, EBML_FLOAT, 0, offsetof(MatroskaDemuxContext, duration) },
+ { MATROSKA_ID_TITLE, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, title) },
+ { MATROSKA_ID_WRITINGAPP, EBML_NONE },
+ { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, muxingapp) },
+ { MATROSKA_ID_DATEUTC, EBML_BIN, 0, offsetof(MatroskaDemuxContext, date_utc) },
+ { MATROSKA_ID_SEGMENTUID, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_track_video[] = {
- { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT,0, offsetof(MatroskaTrackVideo,frame_rate) },
- { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_width), {.u=-1} },
- { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_height), {.u=-1} },
- { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) },
- { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) },
- { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo,color_space) },
- { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,stereo_mode) },
- { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,alpha_mode) },
- { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE },
- { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE },
- { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE },
- { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE },
- { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE },
- { MATROSKA_ID_VIDEOFLAGINTERLACED,EBML_NONE },
- { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE },
+ { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) },
+ { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } },
+ { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } },
+ { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_width) },
+ { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_height) },
+ { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo, color_space) },
+ { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode) },
+ { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, alpha_mode) },
+ { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE },
+ { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE },
+ { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE },
+ { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE },
+ { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE },
+ { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE },
+ { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_track_audio[] = {
- { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT,0, offsetof(MatroskaTrackAudio,samplerate), {.f=8000.0} },
- { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ,EBML_FLOAT,0,offsetof(MatroskaTrackAudio,out_samplerate) },
- { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio,bitdepth) },
- { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio,channels), {.u=1} },
+ { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } },
+ { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, out_samplerate) },
+ { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio, bitdepth) },
+ { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } },
{ 0 }
};
static EbmlSyntax matroska_track_encoding_compression[] = {
- { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression,algo), {.u=0} },
- { MATROSKA_ID_ENCODINGCOMPSETTINGS,EBML_BIN, 0, offsetof(MatroskaTrackCompression,settings) },
+ { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression, algo), { .u = 0 } },
+ { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, offsetof(MatroskaTrackCompression, settings) },
{ 0 }
};
static EbmlSyntax matroska_track_encoding_encryption[] = {
- { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u=0} },
+ { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u = 0} },
{ MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, offsetof(MatroskaTrackEncryption,key_id) },
{ MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE },
{ MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE },
@@ -373,16 +379,16 @@ static EbmlSyntax matroska_track_encoding_encryption[] = {
{ 0 }
};
static EbmlSyntax matroska_track_encoding[] = {
- { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,scope), {.u=1} },
- { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding,type), {.u=0} },
- { MATROSKA_ID_ENCODINGCOMPRESSION,EBML_NEST, 0, offsetof(MatroskaTrackEncoding,compression), {.n=matroska_track_encoding_compression} },
- { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding,encryption), {.n=matroska_track_encoding_encryption} },
- { MATROSKA_ID_ENCODINGORDER, EBML_NONE },
+ { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } },
+ { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, type), { .u = 0 } },
+ { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } },
+ { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } },
+ { MATROSKA_ID_ENCODINGORDER, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_track_encodings[] = {
- { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack,encodings), {.n=matroska_track_encoding} },
+ { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } },
{ 0 }
};
@@ -393,75 +399,75 @@ static EbmlSyntax matroska_track_plane[] = {
};
static EbmlSyntax matroska_track_combine_planes[] = {
- { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n=matroska_track_plane} },
+ { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} },
{ 0 }
};
static EbmlSyntax matroska_track_operation[] = {
- { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n=matroska_track_combine_planes} },
+ { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n = matroska_track_combine_planes} },
{ 0 }
};
static EbmlSyntax matroska_track[] = {
- { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) },
- { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack,name) },
- { MATROSKA_ID_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTrack,uid) },
- { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack,type) },
- { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack,codec_id) },
- { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack,codec_priv) },
- { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack,language), {.s="eng"} },
- { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack,default_duration) },
- { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT,0, offsetof(MatroskaTrack,time_scale), {.f=1.0} },
- { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack,flag_default), {.u=1} },
- { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack,flag_forced), {.u=0} },
- { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack,video), {.n=matroska_track_video} },
- { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack,audio), {.n=matroska_track_audio} },
- { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack,operation), {.n=matroska_track_operation} },
- { MATROSKA_ID_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} },
- { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack,max_block_additional_id) },
- { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, offsetof(MatroskaTrack,codec_delay) },
- { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack,seek_preroll) },
- { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE },
- { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE },
- { MATROSKA_ID_CODECNAME, EBML_NONE },
- { MATROSKA_ID_CODECDECODEALL, EBML_NONE },
- { MATROSKA_ID_CODECINFOURL, EBML_NONE },
- { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE },
- { MATROSKA_ID_TRACKMINCACHE, EBML_NONE },
- { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE },
+ { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack, num) },
+ { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack, name) },
+ { MATROSKA_ID_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTrack, uid) },
+ { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack, type) },
+ { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack, codec_id) },
+ { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack, codec_priv) },
+ { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, offsetof(MatroskaTrack, codec_delay) },
+ { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack, language), { .s = "eng" } },
+ { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack, default_duration) },
+ { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } },
+ { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } },
+ { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack, flag_forced), { .u = 0 } },
+ { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } },
+ { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } },
+ { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } },
+ { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, { .n = matroska_track_encodings } },
+ { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack, max_block_additional_id) },
+ { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack, seek_preroll) },
+ { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE },
+ { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE },
+ { MATROSKA_ID_CODECNAME, EBML_NONE },
+ { MATROSKA_ID_CODECDECODEALL, EBML_NONE },
+ { MATROSKA_ID_CODECINFOURL, EBML_NONE },
+ { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE },
+ { MATROSKA_ID_TRACKMINCACHE, EBML_NONE },
+ { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_tracks[] = {
- { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext,tracks), {.n=matroska_track} },
+ { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } },
{ 0 }
};
static EbmlSyntax matroska_attachment[] = {
- { MATROSKA_ID_FILEUID, EBML_UINT, 0, offsetof(MatroskaAttachement,uid) },
- { MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachement,filename) },
- { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachement,mime) },
- { MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachement,bin) },
- { MATROSKA_ID_FILEDESC, EBML_NONE },
+ { MATROSKA_ID_FILEUID, EBML_UINT, 0, offsetof(MatroskaAttachment, uid) },
+ { MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachment, filename) },
+ { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachment, mime) },
+ { MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachment, bin) },
+ { MATROSKA_ID_FILEDESC, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_attachments[] = {
- { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachement), offsetof(MatroskaDemuxContext,attachments), {.n=matroska_attachment} },
+ { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } },
{ 0 }
};
static EbmlSyntax matroska_chapter_display[] = {
- { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter,title) },
- { MATROSKA_ID_CHAPLANG, EBML_NONE },
+ { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter, title) },
+ { MATROSKA_ID_CHAPLANG, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_chapter_entry[] = {
- { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, offsetof(MatroskaChapter,start), {.u=AV_NOPTS_VALUE} },
- { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, offsetof(MatroskaChapter,end), {.u=AV_NOPTS_VALUE} },
- { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaChapter,uid) },
- { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, {.n=matroska_chapter_display} },
+ { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } },
+ { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } },
+ { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaChapter, uid) },
+ { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, { .n = matroska_chapter_display } },
{ MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE },
{ MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE },
{ MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE },
@@ -470,7 +476,7 @@ static EbmlSyntax matroska_chapter_entry[] = {
};
static EbmlSyntax matroska_chapter[] = {
- { MATROSKA_ID_CHAPTERATOM, EBML_NEST, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext,chapters), {.n=matroska_chapter_entry} },
+ { MATROSKA_ID_CHAPTERATOM, EBML_NEST, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } },
{ MATROSKA_ID_EDITIONUID, EBML_NONE },
{ MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE },
{ MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE },
@@ -479,13 +485,13 @@ static EbmlSyntax matroska_chapter[] = {
};
static EbmlSyntax matroska_chapters[] = {
- { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, {.n=matroska_chapter} },
+ { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, { .n = matroska_chapter } },
{ 0 }
};
static EbmlSyntax matroska_index_pos[] = {
- { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos,track) },
- { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos,pos) },
+ { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos, track) },
+ { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos, pos) },
{ MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE },
{ MATROSKA_ID_CUEDURATION, EBML_NONE },
{ MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE },
@@ -493,71 +499,71 @@ static EbmlSyntax matroska_index_pos[] = {
};
static EbmlSyntax matroska_index_entry[] = {
- { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex,time) },
- { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex,pos), {.n=matroska_index_pos} },
+ { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex, time) },
+ { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } },
{ 0 }
};
static EbmlSyntax matroska_index[] = {
- { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext,index), {.n=matroska_index_entry} },
+ { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } },
{ 0 }
};
static EbmlSyntax matroska_simpletag[] = {
- { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag,name) },
- { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag,string) },
- { MATROSKA_ID_TAGLANG, EBML_STR, 0, offsetof(MatroskaTag,lang), {.s="und"} },
- { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTag,def) },
- { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, offsetof(MatroskaTag,def) },
- { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag,sub), {.n=matroska_simpletag} },
+ { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag, name) },
+ { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag, string) },
+ { MATROSKA_ID_TAGLANG, EBML_STR, 0, offsetof(MatroskaTag, lang), { .s = "und" } },
+ { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTag, def) },
+ { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, offsetof(MatroskaTag, def) },
+ { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } },
{ 0 }
};
static EbmlSyntax matroska_tagtargets[] = {
- { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget,type) },
- { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget,typevalue), {.u=50} },
- { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,trackuid) },
- { MATROSKA_ID_TAGTARGETS_CHAPTERUID,EBML_UINT, 0, offsetof(MatroskaTagTarget,chapteruid) },
- { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,attachuid) },
+ { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget, type) },
+ { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } },
+ { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, trackuid) },
+ { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, chapteruid) },
+ { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, attachuid) },
{ 0 }
};
static EbmlSyntax matroska_tag[] = {
- { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags,tag), {.n=matroska_simpletag} },
- { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags,target), {.n=matroska_tagtargets} },
+ { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } },
+ { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } },
{ 0 }
};
static EbmlSyntax matroska_tags[] = {
- { MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} },
+ { MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } },
{ 0 }
};
static EbmlSyntax matroska_seekhead_entry[] = {
- { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead,id) },
- { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead,pos), {.u=-1} },
+ { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead, id) },
+ { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } },
{ 0 }
};
static EbmlSyntax matroska_seekhead[] = {
- { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext,seekhead), {.n=matroska_seekhead_entry} },
+ { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } },
{ 0 }
};
static EbmlSyntax matroska_segment[] = {
- { MATROSKA_ID_INFO, EBML_NEST, 0, 0, {.n=matroska_info } },
- { MATROSKA_ID_TRACKS, EBML_NEST, 0, 0, {.n=matroska_tracks } },
- { MATROSKA_ID_ATTACHMENTS, EBML_NEST, 0, 0, {.n=matroska_attachments} },
- { MATROSKA_ID_CHAPTERS, EBML_NEST, 0, 0, {.n=matroska_chapters } },
- { MATROSKA_ID_CUES, EBML_NEST, 0, 0, {.n=matroska_index } },
- { MATROSKA_ID_TAGS, EBML_NEST, 0, 0, {.n=matroska_tags } },
- { MATROSKA_ID_SEEKHEAD, EBML_NEST, 0, 0, {.n=matroska_seekhead } },
- { MATROSKA_ID_CLUSTER, EBML_STOP },
+ { MATROSKA_ID_INFO, EBML_NEST, 0, 0, { .n = matroska_info } },
+ { MATROSKA_ID_TRACKS, EBML_NEST, 0, 0, { .n = matroska_tracks } },
+ { MATROSKA_ID_ATTACHMENTS, EBML_NEST, 0, 0, { .n = matroska_attachments } },
+ { MATROSKA_ID_CHAPTERS, EBML_NEST, 0, 0, { .n = matroska_chapters } },
+ { MATROSKA_ID_CUES, EBML_NEST, 0, 0, { .n = matroska_index } },
+ { MATROSKA_ID_TAGS, EBML_NEST, 0, 0, { .n = matroska_tags } },
+ { MATROSKA_ID_SEEKHEAD, EBML_NEST, 0, 0, { .n = matroska_seekhead } },
+ { MATROSKA_ID_CLUSTER, EBML_STOP },
{ 0 }
};
static EbmlSyntax matroska_segments[] = {
- { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, {.n=matroska_segment } },
+ { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, { .n = matroska_segment } },
{ 0 }
};
@@ -568,69 +574,69 @@ static EbmlSyntax matroska_blockmore[] = {
};
static EbmlSyntax matroska_blockadditions[] = {
- { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, {.n=matroska_blockmore} },
+ { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, {.n = matroska_blockmore} },
{ 0 }
};
static EbmlSyntax matroska_blockgroup[] = {
- { MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) },
- { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, {.n=matroska_blockadditions} },
- { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) },
- { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock,duration) },
- { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock,discard_padding) },
- { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock,reference) },
+ { MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) },
+ { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, { .n = matroska_blockadditions} },
+ { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) },
+ { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock, duration) },
+ { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock, discard_padding) },
+ { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference) },
{ MATROSKA_ID_CODECSTATE, EBML_NONE },
- { 1, EBML_UINT, 0, offsetof(MatroskaBlock,non_simple), {.u=1} },
+ { 1, EBML_UINT, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } },
{ 0 }
};
static EbmlSyntax matroska_cluster[] = {
- { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) },
- { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} },
- { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} },
- { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE },
- { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE },
+ { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) },
+ { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
+ { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
+ { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE },
+ { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_clusters[] = {
- { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster} },
- { MATROSKA_ID_INFO, EBML_NONE },
- { MATROSKA_ID_CUES, EBML_NONE },
- { MATROSKA_ID_TAGS, EBML_NONE },
- { MATROSKA_ID_SEEKHEAD, EBML_NONE },
+ { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = matroska_cluster } },
+ { MATROSKA_ID_INFO, EBML_NONE },
+ { MATROSKA_ID_CUES, EBML_NONE },
+ { MATROSKA_ID_TAGS, EBML_NONE },
+ { MATROSKA_ID_SEEKHEAD, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_cluster_incremental_parsing[] = {
- { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) },
- { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} },
- { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} },
- { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE },
- { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE },
- { MATROSKA_ID_INFO, EBML_NONE },
- { MATROSKA_ID_CUES, EBML_NONE },
- { MATROSKA_ID_TAGS, EBML_NONE },
- { MATROSKA_ID_SEEKHEAD, EBML_NONE },
- { MATROSKA_ID_CLUSTER, EBML_STOP },
+ { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) },
+ { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
+ { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
+ { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE },
+ { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE },
+ { MATROSKA_ID_INFO, EBML_NONE },
+ { MATROSKA_ID_CUES, EBML_NONE },
+ { MATROSKA_ID_TAGS, EBML_NONE },
+ { MATROSKA_ID_SEEKHEAD, EBML_NONE },
+ { MATROSKA_ID_CLUSTER, EBML_STOP },
{ 0 }
};
static EbmlSyntax matroska_cluster_incremental[] = {
- { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) },
- { MATROSKA_ID_BLOCKGROUP, EBML_STOP },
- { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP },
- { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE },
- { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE },
+ { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) },
+ { MATROSKA_ID_BLOCKGROUP, EBML_STOP },
+ { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP },
+ { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE },
+ { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_clusters_incremental[] = {
- { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster_incremental} },
- { MATROSKA_ID_INFO, EBML_NONE },
- { MATROSKA_ID_CUES, EBML_NONE },
- { MATROSKA_ID_TAGS, EBML_NONE },
- { MATROSKA_ID_SEEKHEAD, EBML_NONE },
+ { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = matroska_cluster_incremental } },
+ { MATROSKA_ID_INFO, EBML_NONE },
+ { MATROSKA_ID_CUES, EBML_NONE },
+ { MATROSKA_ID_TAGS, EBML_NONE },
+ { MATROSKA_ID_SEEKHEAD, EBML_NONE },
{ 0 }
};
@@ -655,11 +661,12 @@ static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos)
id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS ||
id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS ||
id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) {
- matroska->current_id = id;
- return 0;
+ matroska->current_id = id;
+ return 0;
}
id = (id << 8) | avio_r8(pb);
}
+
eof:
matroska->done = 1;
return AVERROR_EOF;
@@ -795,13 +802,13 @@ static int ebml_read_sint(AVIOContext *pb, int size, int64_t *num)
*/
static int ebml_read_float(AVIOContext *pb, int size, double *num)
{
- if (size == 0) {
+ if (size == 0)
*num = 0;
- } else if (size == 4) {
+ else if (size == 4)
*num = av_int2float(avio_rb32(pb));
- } else if (size == 8){
+ else if (size == 8)
*num = av_int2double(avio_rb64(pb));
- } else
+ else
return AVERROR_INVALIDDATA;
return 0;
@@ -867,8 +874,8 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, uint64_t length)
return AVERROR(ENOSYS);
}
- level = &matroska->levels[matroska->num_levels++];
- level->start = avio_tell(pb);
+ level = &matroska->levels[matroska->num_levels++];
+ level->start = avio_tell(pb);
level->length = length;
return 0;
@@ -900,7 +907,7 @@ static int matroska_ebmlnum_sint(MatroskaDemuxContext *matroska,
return res;
/* make signed (weird way) */
- *num = unum - ((1LL << (7*res - 1)) - 1);
+ *num = unum - ((1LL << (7 * res - 1)) - 1);
return res;
}
@@ -912,15 +919,15 @@ static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
uint32_t id, void *data)
{
int i;
- for (i=0; syntax[i].id; i++)
+ for (i = 0; syntax[i].id; i++)
if (id == syntax[i].id)
break;
if (!syntax[i].id && id == MATROSKA_ID_CLUSTER &&
- matroska->num_levels > 0 &&
- matroska->levels[matroska->num_levels-1].length == 0xffffffffffffff)
+ matroska->num_levels > 0 &&
+ matroska->levels[matroska->num_levels - 1].length == 0xffffffffffffff)
return 0; // we reached the end of an unknown size cluster
if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) {
- av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id);
+ av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%"PRIX32"\n", id);
if (matroska->ctx->error_recognition & AV_EF_EXPLODE)
return AVERROR_INVALIDDATA;
}
@@ -935,7 +942,7 @@ static int ebml_parse(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
int res = ebml_read_num(matroska, matroska->ctx->pb, 4, &id);
if (res < 0)
return res;
- matroska->current_id = id | 1 << 7*res;
+ matroska->current_id = id | 1 << 7 * res;
}
return ebml_parse_id(matroska, syntax, matroska->current_id, data);
}
@@ -945,19 +952,19 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
{
int i, res = 0;
- for (i=0; syntax[i].id; i++)
+ for (i = 0; syntax[i].id; i++)
switch (syntax[i].type) {
case EBML_UINT:
- *(uint64_t *)((char *)data+syntax[i].data_offset) = syntax[i].def.u;
+ *(uint64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.u;
break;
case EBML_FLOAT:
- *(double *)((char *)data+syntax[i].data_offset) = syntax[i].def.f;
+ *(double *) ((char *) data + syntax[i].data_offset) = syntax[i].def.f;
break;
case EBML_STR:
case EBML_UTF8:
// the default may be NULL
if (syntax[i].def.s) {
- uint8_t **dst = (uint8_t**)((uint8_t*)data + syntax[i].data_offset);
+ uint8_t **dst = (uint8_t **) ((uint8_t *) data + syntax[i].data_offset);
*dst = av_strdup(syntax[i].def.s);
if (!*dst)
return AVERROR(ENOMEM);
@@ -990,14 +997,14 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
int res;
void *newelem;
- data = (char *)data + syntax->data_offset;
+ data = (char *) data + syntax->data_offset;
if (syntax->list_elem_size) {
EbmlList *list = data;
- newelem = av_realloc_array(list->elem, list->nb_elem+1, syntax->list_elem_size);
+ newelem = av_realloc_array(list->elem, list->nb_elem + 1, syntax->list_elem_size);
if (!newelem)
return AVERROR(ENOMEM);
list->elem = newelem;
- data = (char*)list->elem + list->nb_elem*syntax->list_elem_size;
+ data = (char *) list->elem + list->nb_elem * syntax->list_elem_size;
memset(data, 0, syntax->list_elem_size);
list->nb_elem++;
}
@@ -1015,23 +1022,36 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
}
switch (syntax->type) {
- case EBML_UINT: res = ebml_read_uint (pb, length, data); break;
- case EBML_SINT: res = ebml_read_sint (pb, length, data); break;
- case EBML_FLOAT: res = ebml_read_float (pb, length, data); break;
+ case EBML_UINT:
+ res = ebml_read_uint(pb, length, data);
+ break;
+ case EBML_SINT:
+ res = ebml_read_sint(pb, length, data);
+ break;
+ case EBML_FLOAT:
+ res = ebml_read_float(pb, length, data);
+ break;
case EBML_STR:
- case EBML_UTF8: res = ebml_read_ascii (pb, length, data); break;
- case EBML_BIN: res = ebml_read_binary(pb, length, data); break;
- case EBML_NEST: if ((res=ebml_read_master(matroska, length)) < 0)
- return res;
- if (id == MATROSKA_ID_SEGMENT)
- matroska->segment_start = avio_tell(matroska->ctx->pb);
- return ebml_parse_nest(matroska, syntax->def.n, data);
- case EBML_PASS: return ebml_parse_id(matroska, syntax->def.n, id, data);
- case EBML_STOP: return 1;
+ case EBML_UTF8:
+ res = ebml_read_ascii(pb, length, data);
+ break;
+ case EBML_BIN:
+ res = ebml_read_binary(pb, length, data);
+ break;
+ case EBML_NEST:
+ if ((res = ebml_read_master(matroska, length)) < 0)
+ return res;
+ if (id == MATROSKA_ID_SEGMENT)
+ matroska->segment_start = avio_tell(matroska->ctx->pb);
+ return ebml_parse_nest(matroska, syntax->def.n, data);
+ case EBML_PASS:
+ return ebml_parse_id(matroska, syntax->def.n, id, data);
+ case EBML_STOP:
+ return 1;
default:
- if(ffio_limit(pb, length) != length)
+ if (ffio_limit(pb, length) != length)
return AVERROR(EIO);
- return avio_skip(pb,length)<0 ? AVERROR(EIO) : 0;
+ return avio_skip(pb, length) < 0 ? AVERROR(EIO) : 0;
}
if (res == AVERROR_INVALIDDATA)
av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n");
@@ -1043,27 +1063,32 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
static void ebml_free(EbmlSyntax *syntax, void *data)
{
int i, j;
- for (i=0; syntax[i].id; i++) {
- void *data_off = (char *)data + syntax[i].data_offset;
+ for (i = 0; syntax[i].id; i++) {
+ void *data_off = (char *) data + syntax[i].data_offset;
switch (syntax[i].type) {
case EBML_STR:
- case EBML_UTF8: av_freep(data_off); break;
- case EBML_BIN: av_freep(&((EbmlBin *)data_off)->data); break;
+ case EBML_UTF8:
+ av_freep(data_off);
+ break;
+ case EBML_BIN:
+ av_freep(&((EbmlBin *) data_off)->data);
+ break;
case EBML_NEST:
if (syntax[i].list_elem_size) {
EbmlList *list = data_off;
char *ptr = list->elem;
- for (j=0; j<list->nb_elem; j++, ptr+=syntax[i].list_elem_size)
+ for (j = 0; j < list->nb_elem;
+ j++, ptr += syntax[i].list_elem_size)
ebml_free(syntax[i].def.n, ptr);
av_free(list->elem);
} else
ebml_free(syntax[i].def.n, data_off);
- default: break;
+ default:
+ break;
}
}
}
-
/*
* Autodetecting...
*/
@@ -1083,14 +1108,14 @@ static int matroska_probe(AVProbeData *p)
len_mask >>= 1;
}
if (size > 8)
- return 0;
+ return 0;
total &= (len_mask - 1);
while (n < size)
total = (total << 8) | p->buf[4 + n++];
/* Does the probe data contain the whole header? */
if (p->buf_size < 4 + size + total)
- return 0;
+ return 0;
/* The header should contain a known document type. For now,
* we don't parse the whole header but simply check for the
@@ -1100,8 +1125,8 @@ static int matroska_probe(AVProbeData *p)
int probelen = strlen(matroska_doctypes[i]);
if (total < probelen)
continue;
- for (n = 4+size; n <= 4+size+total-probelen; n++)
- if (!memcmp(p->buf+n, matroska_doctypes[i], probelen))
+ for (n = 4 + size; n <= 4 + size + total - probelen; n++)
+ if (!memcmp(p->buf + n, matroska_doctypes[i], probelen))
return AVPROBE_SCORE_MAX;
}
@@ -1115,7 +1140,7 @@ static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska,
MatroskaTrack *tracks = matroska->tracks.elem;
int i;
- for (i=0; i < matroska->tracks.nb_elem; i++)
+ for (i = 0; i < matroska->tracks.nb_elem; i++)
if (tracks[i].num == num)
return &tracks[i];
@@ -1123,13 +1148,13 @@ static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska,
return NULL;
}
-static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
+static int matroska_decode_buffer(uint8_t **buf, int *buf_size,
MatroskaTrack *track)
{
MatroskaTrackEncoding *encodings = track->encodings.elem;
- uint8_t* data = *buf;
+ uint8_t *data = *buf;
int isize = *buf_size;
- uint8_t* pkt_data = NULL;
+ uint8_t *pkt_data = NULL;
uint8_t av_unused *newpktdata;
int pkt_size = isize;
int result = 0;
@@ -1139,7 +1164,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
return AVERROR_INVALIDDATA;
switch (encodings[0].compression.algo) {
- case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: {
+ case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP:
+ {
int header_size = encodings[0].compression.settings.size;
uint8_t *header = encodings[0].compression.settings.data;
@@ -1163,15 +1189,15 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
#if CONFIG_LZO
case MATROSKA_TRACK_ENCODING_COMP_LZO:
do {
- olen = pkt_size *= 3;
+ olen = pkt_size *= 3;
newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING);
if (!newpktdata) {
result = AVERROR(ENOMEM);
goto failed;
}
pkt_data = newpktdata;
- result = av_lzo1x_decode(pkt_data, &olen, data, &isize);
- } while (result==AV_LZO_OUTPUT_FULL && pkt_size<10000000);
+ result = av_lzo1x_decode(pkt_data, &olen, data, &isize);
+ } while (result == AV_LZO_OUTPUT_FULL && pkt_size < 10000000);
if (result) {
result = AVERROR_INVALIDDATA;
goto failed;
@@ -1180,27 +1206,28 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
break;
#endif
#if CONFIG_ZLIB
- case MATROSKA_TRACK_ENCODING_COMP_ZLIB: {
- z_stream zstream = {0};
+ case MATROSKA_TRACK_ENCODING_COMP_ZLIB:
+ {
+ z_stream zstream = { 0 };
if (inflateInit(&zstream) != Z_OK)
return -1;
- zstream.next_in = data;
+ zstream.next_in = data;
zstream.avail_in = isize;
do {
- pkt_size *= 3;
+ pkt_size *= 3;
newpktdata = av_realloc(pkt_data, pkt_size);
if (!newpktdata) {
inflateEnd(&zstream);
goto failed;
}
- pkt_data = newpktdata;
+ pkt_data = newpktdata;
zstream.avail_out = pkt_size - zstream.total_out;
- zstream.next_out = pkt_data + zstream.total_out;
+ zstream.next_out = pkt_data + zstream.total_out;
if (pkt_data) {
result = inflate(&zstream, Z_NO_FLUSH);
} else
result = Z_MEM_ERROR;
- } while (result==Z_OK && pkt_size<10000000);
+ } while (result == Z_OK && pkt_size < 10000000);
pkt_size = zstream.total_out;
inflateEnd(&zstream);
if (result != Z_STREAM_END) {
@@ -1214,27 +1241,28 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
}
#endif
#if CONFIG_BZLIB
- case MATROSKA_TRACK_ENCODING_COMP_BZLIB: {
- bz_stream bzstream = {0};
+ case MATROSKA_TRACK_ENCODING_COMP_BZLIB:
+ {
+ bz_stream bzstream = { 0 };
if (BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK)
return -1;
- bzstream.next_in = data;
+ bzstream.next_in = data;
bzstream.avail_in = isize;
do {
- pkt_size *= 3;
+ pkt_size *= 3;
newpktdata = av_realloc(pkt_data, pkt_size);
if (!newpktdata) {
BZ2_bzDecompressEnd(&bzstream);
goto failed;
}
- pkt_data = newpktdata;
+ pkt_data = newpktdata;
bzstream.avail_out = pkt_size - bzstream.total_out_lo32;
- bzstream.next_out = pkt_data + bzstream.total_out_lo32;
+ bzstream.next_out = pkt_data + bzstream.total_out_lo32;
if (pkt_data) {
result = BZ2_bzDecompress(&bzstream);
} else
result = BZ_MEM_ERROR;
- } while (result==BZ_OK && pkt_size<10000000);
+ } while (result == BZ_OK && pkt_size < 10000000);
pkt_size = bzstream.total_out_lo32;
BZ2_bzDecompressEnd(&bzstream);
if (result != BZ_STREAM_END) {
@@ -1251,10 +1279,11 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
return AVERROR_INVALIDDATA;
}
- *buf = pkt_data;
+ *buf = pkt_data;
*buf_size = pkt_size;
return 0;
- failed:
+
+failed:
av_free(pkt_data);
return result;
}
@@ -1264,28 +1293,38 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska,
AVPacket *pkt, uint64_t display_duration)
{
AVBufferRef *line;
- char *layer, *ptr = pkt->data, *end = ptr+pkt->size;
- for (; *ptr!=',' && ptr<end-1; ptr++);
+ char *layer, *ptr = pkt->data, *end = ptr + pkt->size;
+
+ for (; *ptr != ',' && ptr < end - 1; ptr++)
+ ;
if (*ptr == ',')
ptr++;
layer = ptr;
- for (; *ptr!=',' && ptr<end-1; ptr++);
+ for (; *ptr != ',' && ptr < end - 1; ptr++)
+ ;
if (*ptr == ',') {
int64_t end_pts = pkt->pts + display_duration;
int sc = matroska->time_scale * pkt->pts / 10000000;
int ec = matroska->time_scale * end_pts / 10000000;
int sh, sm, ss, eh, em, es, len;
- sh = sc/360000; sc -= 360000*sh;
- sm = sc/ 6000; sc -= 6000*sm;
- ss = sc/ 100; sc -= 100*ss;
- eh = ec/360000; ec -= 360000*eh;
- em = ec/ 6000; ec -= 6000*em;
- es = ec/ 100; ec -= 100*es;
+ sh = sc / 360000;
+ sc -= 360000 * sh;
+ sm = sc / 6000;
+ sc -= 6000 * sm;
+ ss = sc / 100;
+ sc -= 100 * ss;
+ eh = ec / 360000;
+ ec -= 360000 * eh;
+ em = ec / 6000;
+ ec -= 6000 * em;
+ es = ec / 100;
+ ec -= 100 * es;
*ptr++ = '\0';
- len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE;
+ len = 50 + end - ptr + FF_INPUT_BUFFER_PADDING_SIZE;
if (!(line = av_buffer_alloc(len)))
return;
- snprintf(line->data, len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n",
+ snprintf(line->data, len,
+ "Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n",
layer, sh, sm, ss, sc, eh, em, es, ec, ptr);
av_buffer_unref(&pkt->buf);
pkt->buf = line;
@@ -1315,20 +1354,22 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
char key[1024];
int i;
- for (i=0; i < list->nb_elem; i++) {
- const char *lang = tags[i].lang && strcmp(tags[i].lang, "und") ?
- tags[i].lang : NULL;
+ for (i = 0; i < list->nb_elem; i++) {
+ const char *lang = tags[i].lang &&
+ strcmp(tags[i].lang, "und") ? tags[i].lang : NULL;
if (!tags[i].name) {
av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no TagName.\n");
continue;
}
- if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
- else av_strlcpy(key, tags[i].name, sizeof(key));
+ if (prefix)
+ snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
+ else
+ av_strlcpy(key, tags[i].name, sizeof(key));
if (tags[i].def || !lang) {
- av_dict_set(metadata, key, tags[i].string, 0);
- if (tags[i].sub.nb_elem)
- matroska_convert_tag(s, &tags[i].sub, metadata, key);
+ av_dict_set(metadata, key, tags[i].string, 0);
+ if (tags[i].sub.nb_elem)
+ matroska_convert_tag(s, &tags[i].sub, metadata, key);
}
if (lang) {
av_strlcat(key, "-", sizeof(key));
@@ -1347,24 +1388,24 @@ static void matroska_convert_tags(AVFormatContext *s)
MatroskaTags *tags = matroska->tags.elem;
int i, j;
- for (i=0; i < matroska->tags.nb_elem; i++) {
+ for (i = 0; i < matroska->tags.nb_elem; i++) {
if (tags[i].target.attachuid) {
- MatroskaAttachement *attachment = matroska->attachments.elem;
- for (j=0; j<matroska->attachments.nb_elem; j++)
- if (attachment[j].uid == tags[i].target.attachuid
- && attachment[j].stream)
+ MatroskaAttachment *attachment = matroska->attachments.elem;
+ for (j = 0; j < matroska->attachments.nb_elem; j++)
+ if (attachment[j].uid == tags[i].target.attachuid &&
+ attachment[j].stream)
matroska_convert_tag(s, &tags[i].tag,
&attachment[j].stream->metadata, NULL);
} else if (tags[i].target.chapteruid) {
MatroskaChapter *chapter = matroska->chapters.elem;
- for (j=0; j<matroska->chapters.nb_elem; j++)
- if (chapter[j].uid == tags[i].target.chapteruid
- && chapter[j].chapter)
+ for (j = 0; j < matroska->chapters.nb_elem; j++)
+ if (chapter[j].uid == tags[i].target.chapteruid &&
+ chapter[j].chapter)
matroska_convert_tag(s, &tags[i].tag,
&chapter[j].chapter->metadata, NULL);
} else if (tags[i].target.trackuid) {
MatroskaTrack *track = matroska->tracks.elem;
- for (j=0; j<matroska->tracks.nb_elem; j++)
+ for (j = 0; j < matroska->tracks.nb_elem; j++)
if (track[j].uid == tags[i].target.trackuid && track[j].stream)
matroska_convert_tag(s, &tags[i].tag,
&track[j].stream->metadata, NULL);
@@ -1375,20 +1416,21 @@ static void matroska_convert_tags(AVFormatContext *s)
}
}
-static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, int idx)
+static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska,
+ int idx)
{
EbmlList *seekhead_list = &matroska->seekhead;
+ uint32_t level_up = matroska->level_up;
+ uint32_t saved_id = matroska->current_id;
MatroskaSeekhead *seekhead = seekhead_list->elem;
- uint32_t level_up = matroska->level_up;
int64_t before_pos = avio_tell(matroska->ctx->pb);
- uint32_t saved_id = matroska->current_id;
MatroskaLevel level;
int64_t offset;
int ret = 0;
- if (idx >= seekhead_list->nb_elem
- || seekhead[idx].id == MATROSKA_ID_SEEKHEAD
- || seekhead[idx].id == MATROSKA_ID_CLUSTER)
+ if (idx >= seekhead_list->nb_elem ||
+ seekhead[idx].id == MATROSKA_ID_SEEKHEAD ||
+ seekhead[idx].id == MATROSKA_ID_CLUSTER)
return 0;
/* seek */
@@ -1402,25 +1444,25 @@ static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, int idx
"cannot parse further.\n", EBML_MAX_DEPTH);
ret = AVERROR_INVALIDDATA;
} else {
- level.start = 0;
- level.length = (uint64_t)-1;
+ level.start = 0;
+ level.length = (uint64_t) -1;
matroska->levels[matroska->num_levels] = level;
matroska->num_levels++;
- matroska->current_id = 0;
+ matroska->current_id = 0;
ret = ebml_parse(matroska, matroska_segment, matroska);
/* remove dummy level */
while (matroska->num_levels) {
uint64_t length = matroska->levels[--matroska->num_levels].length;
- if (length == (uint64_t)-1)
+ if (length == (uint64_t) -1)
break;
}
}
}
/* seek back */
avio_seek(matroska->ctx->pb, before_pos, SEEK_SET);
- matroska->level_up = level_up;
+ matroska->level_up = level_up;
matroska->current_id = saved_id;
return ret;
@@ -1456,28 +1498,30 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska)
}
}
-static void matroska_add_index_entries(MatroskaDemuxContext *matroska) {
+static void matroska_add_index_entries(MatroskaDemuxContext *matroska)
+{
EbmlList *index_list;
MatroskaIndex *index;
int index_scale = 1;
int i, j;
index_list = &matroska->index;
- index = index_list->elem;
- if (index_list->nb_elem
- && index[0].time > 1E14/matroska->time_scale) {
+ index = index_list->elem;
+ if (index_list->nb_elem &&
+ index[0].time > 1E14 / matroska->time_scale) {
av_log(matroska->ctx, AV_LOG_WARNING, "Working around broken index.\n");
index_scale = matroska->time_scale;
}
for (i = 0; i < index_list->nb_elem; i++) {
- EbmlList *pos_list = &index[i].pos;
+ EbmlList *pos_list = &index[i].pos;
MatroskaIndexPos *pos = pos_list->elem;
for (j = 0; j < pos_list->nb_elem; j++) {
- MatroskaTrack *track = matroska_find_track_by_num(matroska, pos[j].track);
+ MatroskaTrack *track = matroska_find_track_by_num(matroska,
+ pos[j].track);
if (track && track->stream)
av_add_index_entry(track->stream,
pos[j].pos + matroska->segment_start,
- index[i].time/index_scale, 0, 0,
+ index[i].time / index_scale, 0, 0,
AVINDEX_KEYFRAME);
}
}
@@ -1500,10 +1544,10 @@ static void matroska_parse_cues(MatroskaDemuxContext *matroska) {
static int matroska_aac_profile(char *codec_id)
{
- static const char * const aac_profiles[] = { "MAIN", "LC", "SSR" };
+ static const char *const aac_profiles[] = { "MAIN", "LC", "SSR" };
int profile;
- for (profile=0; profile<FF_ARRAY_ELEMS(aac_profiles); profile++)
+ for (profile = 0; profile < FF_ARRAY_ELEMS(aac_profiles); profile++)
if (strstr(codec_id, aac_profiles[profile]))
break;
return profile + 1;
@@ -1513,7 +1557,7 @@ static int matroska_aac_sri(int samplerate)
{
int sri;
- for (sri=0; sri<FF_ARRAY_ELEMS(avpriv_mpeg4audio_sample_rates); sri++)
+ for (sri = 0; sri < FF_ARRAY_ELEMS(avpriv_mpeg4audio_sample_rates); sri++)
if (avpriv_mpeg4audio_sample_rates[sri] == samplerate)
break;
return sri;
@@ -1533,9 +1577,9 @@ static void matroska_metadata_creation_time(AVDictionary **metadata, int64_t dat
static int matroska_read_header(AVFormatContext *s)
{
MatroskaDemuxContext *matroska = s->priv_data;
- EbmlList *attachements_list = &matroska->attachments;
- MatroskaAttachement *attachements;
- EbmlList *chapters_list = &matroska->chapters;
+ EbmlList *attachments_list = &matroska->attachments;
+ EbmlList *chapters_list = &matroska->chapters;
+ MatroskaAttachment *attachments;
MatroskaChapter *chapters;
MatroskaTrack *tracks;
uint64_t max_start = 0;
@@ -1547,9 +1591,12 @@ static int matroska_read_header(AVFormatContext *s)
matroska->ctx = s;
/* First read the EBML header. */
- if (ebml_parse(matroska, ebml_syntax, &ebml)
- || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t)
- || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 3 || !ebml.doctype) {
+ if (ebml_parse(matroska, ebml_syntax, &ebml) ||
+ ebml.version > EBML_VERSION ||
+ ebml.max_size > sizeof(uint64_t) ||
+ ebml.id_length > sizeof(uint32_t) ||
+ ebml.doctype_version > 3 ||
+ !ebml.doctype) {
av_log(matroska->ctx, AV_LOG_ERROR,
"EBML header using unsupported features\n"
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
@@ -1590,15 +1637,16 @@ static int matroska_read_header(AVFormatContext *s)
if (!matroska->time_scale)
matroska->time_scale = 1000000;
if (matroska->duration)
- matroska->ctx->duration = matroska->duration * matroska->time_scale
- * 1000 / AV_TIME_BASE;
+ matroska->ctx->duration = matroska->duration * matroska->time_scale *
+ 1000 / AV_TIME_BASE;
av_dict_set(&s->metadata, "title", matroska->title, 0);
+ av_dict_set(&s->metadata, "encoder", matroska->muxingapp, 0);
if (matroska->date_utc.size == 8)
matroska_metadata_creation_time(&s->metadata, AV_RB64(matroska->date_utc.data));
tracks = matroska->tracks.elem;
- for (i=0; i < matroska->tracks.nb_elem; i++) {
+ for (i = 0; i < matroska->tracks.nb_elem; i++) {
MatroskaTrack *track = &tracks[i];
enum AVCodecID codec_id = AV_CODEC_ID_NONE;
EbmlList *encodings_list = &track->encodings;
@@ -1609,6 +1657,7 @@ static int matroska_read_header(AVFormatContext *s)
uint32_t fourcc = 0;
AVIOContext b;
char* key_id_base64 = NULL;
+ int bit_depth = -1;
/* Apply some sanity checks. */
if (track->type != MATROSKA_TRACK_TYPE_VIDEO &&
@@ -1625,7 +1674,7 @@ static int matroska_read_header(AVFormatContext *s)
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
if (!track->default_duration && track->video.frame_rate > 0)
- track->default_duration = 1000000000/track->video.frame_rate;
+ track->default_duration = 1000000000 / track->video.frame_rate;
if (track->video.display_width == -1)
track->video.display_width = track->video.pixel_width;
if (track->video.display_height == -1)
@@ -1659,19 +1708,19 @@ static int matroska_read_header(AVFormatContext *s)
}
} else if (
#if CONFIG_ZLIB
- encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
+ encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
#endif
#if CONFIG_BZLIB
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&
#endif
#if CONFIG_LZO
- encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO &&
+ encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO &&
#endif
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) {
encodings[0].scope = 0;
av_log(matroska->ctx, AV_LOG_ERROR,
"Unsupported encoding type");
- } else if (track->codec_priv.size && encodings[0].scope&2) {
+ } else if (track->codec_priv.size && encodings[0].scope & 2) {
uint8_t *codec_priv = track->codec_priv.data;
int ret = matroska_decode_buffer(&track->codec_priv.data,
&track->codec_priv.size,
@@ -1688,10 +1737,10 @@ static int matroska_read_header(AVFormatContext *s)
}
}
- for(j=0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++){
- if(!strncmp(ff_mkv_codec_tags[j].str, track->codec_id,
- strlen(ff_mkv_codec_tags[j].str))){
- codec_id= ff_mkv_codec_tags[j].id;
+ for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
+ if (!strncmp(ff_mkv_codec_tags[j].str, track->codec_id,
+ strlen(ff_mkv_codec_tags[j].str))) {
+ codec_id = ff_mkv_codec_tags[j].id;
break;
}
}
@@ -1708,79 +1757,114 @@ static int matroska_read_header(AVFormatContext *s)
av_freep(&key_id_base64);
}
- if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC")
- && track->codec_priv.size >= 40
- && track->codec_priv.data != NULL) {
- track->ms_compat = 1;
- fourcc = AV_RL32(track->codec_priv.data + 16);
- codec_id = ff_codec_get_id(ff_codec_bmp_tags, fourcc);
- extradata_offset = 40;
- } else if (!strcmp(track->codec_id, "A_MS/ACM")
- && track->codec_priv.size >= 14
- && track->codec_priv.data != NULL) {
+ if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&
+ track->codec_priv.size >= 40 &&
+ track->codec_priv.data != NULL) {
+ track->ms_compat = 1;
+ bit_depth = AV_RL16(track->codec_priv.data + 14);
+ fourcc = AV_RL32(track->codec_priv.data + 16);
+ codec_id = ff_codec_get_id(ff_codec_bmp_tags,
+ fourcc);
+ if (!codec_id)
+ codec_id = ff_codec_get_id(ff_codec_movvideo_tags,
+ fourcc);
+ extradata_offset = 40;
+ } else if (!strcmp(track->codec_id, "A_MS/ACM") &&
+ track->codec_priv.size >= 14 &&
+ track->codec_priv.data != NULL) {
int ret;
- ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size,
+ ffio_init_context(&b, track->codec_priv.data,
+ track->codec_priv.size,
0, NULL, NULL, NULL, NULL);
ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size);
if (ret < 0)
return ret;
- codec_id = st->codec->codec_id;
+ codec_id = st->codec->codec_id;
extradata_offset = FFMIN(track->codec_priv.size, 18);
- } else if (!strcmp(track->codec_id, "V_QUICKTIME")
+ } else if (!strcmp(track->codec_id, "A_QUICKTIME")
&& (track->codec_priv.size >= 86)
&& (track->codec_priv.data != NULL)) {
- fourcc = AV_RL32(track->codec_priv.data);
+ fourcc = AV_RL32(track->codec_priv.data + 4);
+ codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
+ if (ff_codec_get_id(ff_codec_movaudio_tags, AV_RL32(track->codec_priv.data))) {
+ fourcc = AV_RL32(track->codec_priv.data);
+ codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
+ }
+ } else if (!strcmp(track->codec_id, "V_QUICKTIME") &&
+ (track->codec_priv.size >= 21) &&
+ (track->codec_priv.data != NULL)) {
+ fourcc = AV_RL32(track->codec_priv.data + 4);
codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
+ if (ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(track->codec_priv.data))) {
+ fourcc = AV_RL32(track->codec_priv.data);
+ codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
+ }
+ if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI "))
+ codec_id = AV_CODEC_ID_SVQ3;
} else if (codec_id == AV_CODEC_ID_PCM_S16BE) {
switch (track->audio.bitdepth) {
- case 8: codec_id = AV_CODEC_ID_PCM_U8; break;
- case 24: codec_id = AV_CODEC_ID_PCM_S24BE; break;
- case 32: codec_id = AV_CODEC_ID_PCM_S32BE; break;
+ case 8:
+ codec_id = AV_CODEC_ID_PCM_U8;
+ break;
+ case 24:
+ codec_id = AV_CODEC_ID_PCM_S24BE;
+ break;
+ case 32:
+ codec_id = AV_CODEC_ID_PCM_S32BE;
+ break;
}
} else if (codec_id == AV_CODEC_ID_PCM_S16LE) {
switch (track->audio.bitdepth) {
- case 8: codec_id = AV_CODEC_ID_PCM_U8; break;
- case 24: codec_id = AV_CODEC_ID_PCM_S24LE; break;
- case 32: codec_id = AV_CODEC_ID_PCM_S32LE; break;
+ case 8:
+ codec_id = AV_CODEC_ID_PCM_U8;
+ break;
+ case 24:
+ codec_id = AV_CODEC_ID_PCM_S24LE;
+ break;
+ case 32:
+ codec_id = AV_CODEC_ID_PCM_S32LE;
+ break;
}
- } else if (codec_id==AV_CODEC_ID_PCM_F32LE && track->audio.bitdepth==64) {
+ } else if (codec_id == AV_CODEC_ID_PCM_F32LE &&
+ track->audio.bitdepth == 64) {
codec_id = AV_CODEC_ID_PCM_F64LE;
} else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) {
int profile = matroska_aac_profile(track->codec_id);
- int sri = matroska_aac_sri(track->audio.samplerate);
- extradata = av_mallocz(5 + FF_INPUT_BUFFER_PADDING_SIZE);
+ int sri = matroska_aac_sri(track->audio.samplerate);
+ extradata = av_mallocz(5 + FF_INPUT_BUFFER_PADDING_SIZE);
if (extradata == NULL)
return AVERROR(ENOMEM);
- extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
- extradata[1] = ((sri&0x01) << 7) | (track->audio.channels<<3);
+ extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1);
+ extradata[1] = ((sri & 0x01) << 7) | (track->audio.channels << 3);
if (strstr(track->codec_id, "SBR")) {
- sri = matroska_aac_sri(track->audio.out_samplerate);
- extradata[2] = 0x56;
- extradata[3] = 0xE5;
- extradata[4] = 0x80 | (sri<<3);
+ sri = matroska_aac_sri(track->audio.out_samplerate);
+ extradata[2] = 0x56;
+ extradata[3] = 0xE5;
+ extradata[4] = 0x80 | (sri << 3);
extradata_size = 5;
} else
extradata_size = 2;
} else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - FF_INPUT_BUFFER_PADDING_SIZE) {
/* Only ALAC's magic cookie is stored in Matroska's track headers.
- Create the "atom size", "tag", and "tag version" fields the
- decoder expects manually. */
+ * Create the "atom size", "tag", and "tag version" fields the
+ * decoder expects manually. */
extradata_size = 12 + track->codec_priv.size;
- extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ extradata = av_mallocz(extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
if (extradata == NULL)
return AVERROR(ENOMEM);
AV_WB32(extradata, extradata_size);
memcpy(&extradata[4], "alac", 4);
AV_WB32(&extradata[8], 0);
memcpy(&extradata[12], track->codec_priv.data,
- track->codec_priv.size);
+ track->codec_priv.size);
} else if (codec_id == AV_CODEC_ID_TTA) {
extradata_size = 30;
- extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
if (extradata == NULL)
return AVERROR(ENOMEM);
ffio_init_context(&b, extradata, extradata_size, 1,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
avio_write(&b, "TTA1", 4);
avio_wl16(&b, 1);
avio_wl16(&b, track->audio.channels);
@@ -1788,21 +1872,28 @@ static int matroska_read_header(AVFormatContext *s)
if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX)
return AVERROR_INVALIDDATA;
avio_wl32(&b, track->audio.out_samplerate);
- avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale), track->audio.out_samplerate, AV_TIME_BASE * 1000));
- } else if (codec_id == AV_CODEC_ID_RV10 || codec_id == AV_CODEC_ID_RV20 ||
- codec_id == AV_CODEC_ID_RV30 || codec_id == AV_CODEC_ID_RV40) {
+ avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale),
+ track->audio.out_samplerate,
+ AV_TIME_BASE * 1000));
+ } else if (codec_id == AV_CODEC_ID_RV10 ||
+ codec_id == AV_CODEC_ID_RV20 ||
+ codec_id == AV_CODEC_ID_RV30 ||
+ codec_id == AV_CODEC_ID_RV40) {
extradata_offset = 26;
} else if (codec_id == AV_CODEC_ID_RA_144) {
track->audio.out_samplerate = 8000;
- track->audio.channels = 1;
- } else if ((codec_id == AV_CODEC_ID_RA_288 || codec_id == AV_CODEC_ID_COOK ||
- codec_id == AV_CODEC_ID_ATRAC3 || codec_id == AV_CODEC_ID_SIPR)
- && track->codec_priv.data) {
+ track->audio.channels = 1;
+ } else if ((codec_id == AV_CODEC_ID_RA_288 ||
+ codec_id == AV_CODEC_ID_COOK ||
+ codec_id == AV_CODEC_ID_ATRAC3 ||
+ codec_id == AV_CODEC_ID_SIPR)
+ && track->codec_priv.data) {
#if CONFIG_RA_288_DECODER || CONFIG_COOK_DECODER || CONFIG_ATRAC3_DECODER || CONFIG_SIPR_DECODER
int flavor;
- ffio_init_context(&b, track->codec_priv.data,track->codec_priv.size,
- 0, NULL, NULL, NULL, NULL);
+ ffio_init_context(&b, track->codec_priv.data,
+ track->codec_priv.size,
+ 0, NULL, NULL, NULL, NULL);
avio_skip(&b, 22);
flavor = avio_rb16(&b);
track->audio.coded_framesize = avio_rb32(&b);
@@ -1810,11 +1901,14 @@ static int matroska_read_header(AVFormatContext *s)
track->audio.sub_packet_h = avio_rb16(&b);
track->audio.frame_size = avio_rb16(&b);
track->audio.sub_packet_size = avio_rb16(&b);
- if (flavor <= 0 || track->audio.coded_framesize <= 0 ||
- track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 ||
+ if (flavor < 0 ||
+ track->audio.coded_framesize <= 0 ||
+ track->audio.sub_packet_h <= 0 ||
+ track->audio.frame_size <= 0 ||
track->audio.sub_packet_size <= 0)
return AVERROR_INVALIDDATA;
- track->audio.buf = av_malloc_array(track->audio.sub_packet_h, track->audio.frame_size);
+ track->audio.buf = av_malloc_array(track->audio.sub_packet_h,
+ track->audio.frame_size);
if (!track->audio.buf)
return AVERROR(ENOMEM);
if (codec_id == AV_CODEC_ID_RA_288) {
@@ -1824,16 +1918,18 @@ static int matroska_read_header(AVFormatContext *s)
if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) {
static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 };
track->audio.sub_packet_size = ff_sipr_subpk_size[flavor];
- st->codec->bit_rate = sipr_bit_rate[flavor];
+ st->codec->bit_rate = sipr_bit_rate[flavor];
}
st->codec->block_align = track->audio.sub_packet_size;
- extradata_offset = 78;
+ extradata_offset = 78;
}
#else
/* Returning without closing would cause leaks with some files */
matroska_read_close(s);
return AVERROR_INVALIDDATA;
#endif
+ } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) {
+ fourcc = AV_RL32(track->codec_priv.data);
}
track->codec_priv.size -= extradata_offset;
@@ -1843,10 +1939,16 @@ static int matroska_read_header(AVFormatContext *s)
if (track->time_scale < 0.01)
track->time_scale = 1.0;
- avpriv_set_pts_info(st, 64, matroska->time_scale*track->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
+ avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale,
+ 1000 * 1000 * 1000); /* 64 bit pts in ns */
+
+ /* convert the delay from ns to the track timebase */
+ track->codec_delay = av_rescale_q(track->codec_delay,
+ (AVRational){ 1, 1000000000 },
+ st->time_base);
st->codec->codec_id = codec_id;
- st->start_time = 0;
+
if (strcmp(track->language, "und"))
av_dict_set(&st->metadata, "language", track->language, 0);
av_dict_set(&st->metadata, "title", track->name, 0);
@@ -1857,10 +1959,10 @@ static int matroska_read_header(AVFormatContext *s)
st->disposition |= AV_DISPOSITION_FORCED;
if (!st->codec->extradata) {
- if(extradata){
- st->codec->extradata = extradata;
+ if (extradata) {
+ st->codec->extradata = extradata;
st->codec->extradata_size = extradata_size;
- } else if(track->codec_priv.data && track->codec_priv.size > 0){
+ } else if (track->codec_priv.data && track->codec_priv.size > 0) {
if (ff_alloc_extradata(st->codec, track->codec_priv.size))
return AVERROR(ENOMEM);
memcpy(st->codec->extradata,
@@ -1874,12 +1976,14 @@ static int matroska_read_header(AVFormatContext *s)
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_tag = fourcc;
- st->codec->width = track->video.pixel_width;
- st->codec->height = track->video.pixel_height;
+ if (bit_depth >= 0)
+ st->codec->bits_per_coded_sample = bit_depth;
+ st->codec->width = track->video.pixel_width;
+ st->codec->height = track->video.pixel_height;
av_reduce(&st->sample_aspect_ratio.num,
&st->sample_aspect_ratio.den,
st->codec->height * track->video.display_width,
- st->codec-> width * track->video.display_height,
+ st->codec->width * track->video.display_height,
255);
if (st->codec->codec_id != AV_CODEC_ID_HEVC)
st->need_parsing = AVSTREAM_PARSE_HEADERS;
@@ -1916,15 +2020,16 @@ static int matroska_read_header(AVFormatContext *s)
}
}
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
- st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->sample_rate = track->audio.out_samplerate;
- st->codec->channels = track->audio.channels;
- st->codec->bits_per_coded_sample = track->audio.bitdepth;
+ st->codec->channels = track->audio.channels;
+ if (!st->codec->bits_per_coded_sample)
+ st->codec->bits_per_coded_sample = track->audio.bitdepth;
if (st->codec->codec_id != AV_CODEC_ID_AAC)
- st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
if (track->codec_delay > 0) {
st->codec->delay = av_rescale_q(track->codec_delay,
- (AVRational){1, 1000000000},
+ st->time_base,
(AVRational){1, st->codec->sample_rate});
}
if (track->seek_preroll > 0) {
@@ -1955,44 +2060,46 @@ static int matroska_read_header(AVFormatContext *s)
}
}
- attachements = attachements_list->elem;
- for (j=0; j<attachements_list->nb_elem; j++) {
- if (!(attachements[j].filename && attachements[j].mime &&
- attachements[j].bin.data && attachements[j].bin.size > 0)) {
+ attachments = attachments_list->elem;
+ for (j = 0; j < attachments_list->nb_elem; j++) {
+ if (!(attachments[j].filename && attachments[j].mime &&
+ attachments[j].bin.data && attachments[j].bin.size > 0)) {
av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
} else {
AVStream *st = avformat_new_stream(s, NULL);
if (st == NULL)
break;
- av_dict_set(&st->metadata, "filename",attachements[j].filename, 0);
- av_dict_set(&st->metadata, "mimetype", attachements[j].mime, 0);
- st->codec->codec_id = AV_CODEC_ID_NONE;
+ av_dict_set(&st->metadata, "filename", attachments[j].filename, 0);
+ av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0);
+ st->codec->codec_id = AV_CODEC_ID_NONE;
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
- if (ff_alloc_extradata(st->codec, attachements[j].bin.size))
+ if (ff_alloc_extradata(st->codec, attachments[j].bin.size))
break;
- memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size);
+ memcpy(st->codec->extradata, attachments[j].bin.data,
+ attachments[j].bin.size);
- for (i=0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
- if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime,
+ for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
+ if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime,
strlen(ff_mkv_mime_tags[i].str))) {
st->codec->codec_id = ff_mkv_mime_tags[i].id;
break;
}
}
- attachements[j].stream = st;
+ attachments[j].stream = st;
}
}
chapters = chapters_list->elem;
- for (i=0; i<chapters_list->nb_elem; i++)
- if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid
- && (max_start==0 || chapters[i].start > max_start)) {
+ for (i = 0; i < chapters_list->nb_elem; i++)
+ if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid &&
+ (max_start == 0 || chapters[i].start > max_start)) {
chapters[i].chapter =
- avpriv_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000},
- chapters[i].start, chapters[i].end,
- chapters[i].title);
+ avpriv_new_chapter(s, chapters[i].uid,
+ (AVRational) { 1, 1000000000 },
+ chapters[i].start, chapters[i].end,
+ chapters[i].title);
av_dict_set(&chapters[i].chapter->metadata,
- "title", chapters[i].title, 0);
+ "title", chapters[i].title, 0);
max_start = chapters[i].start;
}
@@ -2018,7 +2125,8 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
memmove(&matroska->packets[0], &matroska->packets[1],
(matroska->num_packets - 1) * sizeof(AVPacket *));
newpackets = av_realloc(matroska->packets,
- (matroska->num_packets - 1) * sizeof(AVPacket *));
+ (matroska->num_packets - 1) *
+ sizeof(AVPacket *));
if (newpackets)
matroska->packets = newpackets;
} else {
@@ -2050,7 +2158,7 @@ static void matroska_clear_queue(MatroskaDemuxContext *matroska)
}
static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
- int* buf_size, int type,
+ int *buf_size, int type,
uint32_t **lace_buf, int *laces)
{
int res = 0, n, size = *buf_size;
@@ -2058,7 +2166,7 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
uint32_t *lace_size;
if (!type) {
- *laces = 1;
+ *laces = 1;
*lace_buf = av_mallocz(sizeof(int));
if (!*lace_buf)
return AVERROR(ENOMEM);
@@ -2068,15 +2176,16 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
}
av_assert0(size > 0);
- *laces = *data + 1;
- data += 1;
- size -= 1;
+ *laces = *data + 1;
+ data += 1;
+ size -= 1;
lace_size = av_mallocz(*laces * sizeof(int));
if (!lace_size)
return AVERROR(ENOMEM);
switch (type) {
- case 0x1: /* Xiph lacing */ {
+ case 0x1: /* Xiph lacing */
+ {
uint8_t temp;
uint32_t total = 0;
for (n = 0; res == 0 && n < *laces - 1; n++) {
@@ -2085,11 +2194,11 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
res = AVERROR_INVALIDDATA;
break;
}
- temp = *data;
- total += temp;
+ temp = *data;
+ total += temp;
lace_size[n] += temp;
- data += 1;
- size -= 1;
+ data += 1;
+ size -= 1;
if (temp != 0xff)
break;
}
@@ -2112,7 +2221,8 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
lace_size[n] = size / *laces;
break;
- case 0x3: /* EBML lacing */ {
+ case 0x3: /* EBML lacing */
+ {
uint64_t num;
uint64_t total;
n = matroska_ebmlnum_uint(matroska, data, size, &num);
@@ -2135,10 +2245,10 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
res = r<0 ? r : AVERROR_INVALIDDATA;
break;
}
- data += r;
- size -= r;
+ data += r;
+ size -= r;
lace_size[n] = lace_size[n - 1] + snum;
- total += lace_size[n];
+ total += lace_size[n];
}
if (size <= total) {
res = AVERROR_INVALIDDATA;
@@ -2157,18 +2267,16 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
}
static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
- MatroskaTrack *track,
- AVStream *st,
- uint8_t *data, int size,
- uint64_t timecode,
+ MatroskaTrack *track, AVStream *st,
+ uint8_t *data, int size, uint64_t timecode,
int64_t pos)
{
int a = st->codec->block_align;
int sps = track->audio.sub_packet_size;
int cfs = track->audio.coded_framesize;
- int h = track->audio.sub_packet_h;
- int y = track->audio.sub_packet_cnt;
- int w = track->audio.frame_size;
+ int h = track->audio.sub_packet_h;
+ int y = track->audio.sub_packet_cnt;
+ int w = track->audio.frame_size;
int x;
if (!track->audio.pkt_cnt) {
@@ -2180,24 +2288,26 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
"Corrupt int4 RM-style audio packet size\n");
return AVERROR_INVALIDDATA;
}
- for (x=0; x<h/2; x++)
- memcpy(track->audio.buf+x*2*w+y*cfs,
- data+x*cfs, cfs);
+ for (x = 0; x < h / 2; x++)
+ memcpy(track->audio.buf + x * 2 * w + y * cfs,
+ data + x * cfs, cfs);
} else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
if (size < w) {
av_log(matroska->ctx, AV_LOG_ERROR,
"Corrupt sipr RM-style audio packet size\n");
return AVERROR_INVALIDDATA;
}
- memcpy(track->audio.buf + y*w, data, w);
+ memcpy(track->audio.buf + y * w, data, w);
} else {
- if (size < sps * w / sps || h<=0) {
+ if (size < sps * w / sps || h<=0 || w%sps) {
av_log(matroska->ctx, AV_LOG_ERROR,
"Corrupt generic RM-style audio packet size\n");
return AVERROR_INVALIDDATA;
}
- for (x=0; x<w/sps; x++)
- memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
+ for (x = 0; x < w / sps; x++)
+ memcpy(track->audio.buf +
+ sps * (h * x + ((h + 1) / 2) * (y & 1) + (y >> 1)),
+ data + x * sps, sps);
}
if (++track->audio.sub_packet_cnt >= h) {
@@ -2209,23 +2319,24 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
#endif
}
track->audio.sub_packet_cnt = 0;
- track->audio.pkt_cnt = h*w / a;
+ track->audio.pkt_cnt = h * w / a;
}
}
while (track->audio.pkt_cnt) {
AVPacket *pkt = NULL;
- if (!(pkt = av_mallocz(sizeof(AVPacket))) || av_new_packet(pkt, a) < 0){
+ if (!(pkt = av_mallocz(sizeof(AVPacket))) || av_new_packet(pkt, a) < 0) {
av_free(pkt);
return AVERROR(ENOMEM);
}
- memcpy(pkt->data, track->audio.buf
- + a * (h*w / a - track->audio.pkt_cnt--), a);
- pkt->pts = track->audio.buf_timecode;
+ memcpy(pkt->data,
+ track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--),
+ a);
+ pkt->pts = track->audio.buf_timecode;
track->audio.buf_timecode = AV_NOPTS_VALUE;
- pkt->pos = pos;
- pkt->stream_index = st->index;
- dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
+ pkt->pos = pos;
+ pkt->stream_index = st->index;
+ dynarray_add(&matroska->packets, &matroska->num_packets, pkt);
}
return 0;
@@ -2268,8 +2379,8 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src,
goto fail;
}
blocksize = AV_RL32(src);
- src += 4;
- srclen -= 4;
+ src += 4;
+ srclen -= 4;
} else
blocksize = srclen;
@@ -2286,16 +2397,16 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src,
dst = tmp;
dstlen += blocksize + 32;
- AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag
- AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8
- AV_WL16(dst + offset + 8, ver); // version
- AV_WL16(dst + offset + 10, 0); // track/index_no
- AV_WL32(dst + offset + 12, 0); // total samples
- AV_WL32(dst + offset + 16, 0); // block index
- AV_WL32(dst + offset + 20, samples); // number of samples
- AV_WL32(dst + offset + 24, flags); // flags
- AV_WL32(dst + offset + 28, crc); // crc
- memcpy (dst + offset + 32, src, blocksize); // block data
+ AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag
+ AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8
+ AV_WL16(dst + offset + 8, ver); // version
+ AV_WL16(dst + offset + 10, 0); // track/index_no
+ AV_WL32(dst + offset + 12, 0); // total samples
+ AV_WL32(dst + offset + 16, 0); // block index
+ AV_WL32(dst + offset + 20, samples); // number of samples
+ AV_WL32(dst + offset + 24, flags); // flags
+ AV_WL32(dst + offset + 28, crc); // crc
+ memcpy(dst + offset + 32, src, blocksize); // block data
src += blocksize;
srclen -= blocksize;
@@ -2427,8 +2538,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska,
}
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
- MatroskaTrack *track,
- AVStream *st,
+ MatroskaTrack *track, AVStream *st,
uint8_t *data, int pkt_size,
uint64_t timecode, uint64_t lace_duration,
int64_t pos, int is_keyframe,
@@ -2450,7 +2560,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
uint8_t *wv_data;
res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size);
if (res < 0) {
- av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n");
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Error parsing a wavpack block.\n");
goto fail;
}
if (pkt_data != data)
@@ -2458,7 +2569,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
pkt_data = wv_data;
}
- if (st->codec->codec_id == AV_CODEC_ID_PRORES)
+ if (st->codec->codec_id == AV_CODEC_ID_PRORES &&
+ AV_RB32(&data[4]) != MKBETAG('i', 'c', 'p', 'f'))
offset = 8;
pkt = av_mallocz(sizeof(AVPacket));
@@ -2469,7 +2581,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
goto fail;
}
- if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
+ if (st->codec->codec_id == AV_CODEC_ID_PRORES && offset == 8) {
uint8_t *buf = pkt->data;
bytestream_put_be32(&buf, pkt_size);
bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
@@ -2480,14 +2592,14 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
if (pkt_data != data)
av_freep(&pkt_data);
- pkt->flags = is_keyframe;
+ pkt->flags = is_keyframe;
pkt->stream_index = st->index;
if (additional_size > 0) {
uint8_t *side_data = av_packet_new_side_data(pkt,
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
additional_size + 8);
- if(side_data == NULL) {
+ if (side_data == NULL) {
av_free_packet(pkt);
av_free(pkt);
return AVERROR(ENOMEM);
@@ -2500,7 +2612,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
uint8_t *side_data = av_packet_new_side_data(pkt,
AV_PKT_DATA_SKIP_SAMPLES,
10);
- if(side_data == NULL) {
+ if (side_data == NULL) {
av_free_packet(pkt);
av_free(pkt);
return AVERROR(ENOMEM);
@@ -2544,14 +2656,14 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
if (st->codec->codec_id == AV_CODEC_ID_SSA)
matroska_fix_ass_packet(matroska, pkt, lace_duration);
- if (matroska->prev_pkt &&
- timecode != AV_NOPTS_VALUE &&
- matroska->prev_pkt->pts == timecode &&
- matroska->prev_pkt->stream_index == st->index &&
+ if (matroska->prev_pkt &&
+ timecode != AV_NOPTS_VALUE &&
+ matroska->prev_pkt->pts == timecode &&
+ matroska->prev_pkt->stream_index == st->index &&
st->codec->codec_id == AV_CODEC_ID_SSA)
matroska_merge_packets(matroska->prev_pkt, pkt);
else {
- dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
+ dynarray_add(&matroska->packets, &matroska->num_packets, pkt);
matroska->prev_pkt = pkt;
}
#else
@@ -2560,6 +2672,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
#endif
return 0;
+
fail:
if (pkt_data != data)
av_freep(&pkt_data);
@@ -2602,23 +2715,25 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
av_assert1(block_duration != AV_NOPTS_VALUE);
block_time = sign_extend(AV_RB16(data), 16);
- data += 2;
- flags = *data++;
- size -= 3;
+ data += 2;
+ flags = *data++;
+ size -= 3;
if (is_keyframe == -1)
is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0;
- if (cluster_time != (uint64_t)-1
- && (block_time >= 0 || cluster_time >= -block_time)) {
- timecode = cluster_time + block_time;
- if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE
- && timecode < track->end_timecode)
+ if (cluster_time != (uint64_t) -1 &&
+ (block_time >= 0 || cluster_time >= -block_time)) {
+ timecode = cluster_time + block_time - track->codec_delay;
+ if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE &&
+ timecode < track->end_timecode)
is_keyframe = 0; /* overlapping subtitles are not key frame */
if (is_keyframe)
- av_add_index_entry(st, cluster_pos, timecode, 0,0,AVINDEX_KEYFRAME);
+ av_add_index_entry(st, cluster_pos, timecode, 0, 0,
+ AVINDEX_KEYFRAME);
}
- if (matroska->skip_to_keyframe && track->type != MATROSKA_TRACK_TYPE_SUBTITLE) {
+ if (matroska->skip_to_keyframe &&
+ track->type != MATROSKA_TRACK_TYPE_SUBTITLE) {
if (timecode < matroska->skip_to_timecode)
return res;
if (is_keyframe)
@@ -2638,7 +2753,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
if (track->audio.samplerate == 8000) {
// If this is needed for more codecs, then add them here
if (st->codec->codec_id == AV_CODEC_ID_AC3) {
- if(track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size)
+ if (track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size)
trust_default_duration = 0;
}
}
@@ -2659,11 +2774,10 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
}
if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
- st->codec->codec_id == AV_CODEC_ID_COOK ||
- st->codec->codec_id == AV_CODEC_ID_SIPR ||
+ st->codec->codec_id == AV_CODEC_ID_COOK ||
+ st->codec->codec_id == AV_CODEC_ID_SIPR ||
st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
- st->codec->block_align && track->audio.sub_packet_size) {
-
+ st->codec->block_align && track->audio.sub_packet_size) {
#if CONFIG_RA_288_DECODER || CONFIG_COOK_DECODER || CONFIG_ATRAC3_DECODER || CONFIG_SIPR_DECODER
res = matroska_parse_rm_audio(matroska, track, st, data,
lace_size[n],
@@ -2681,13 +2795,12 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
pos);
if (res)
goto end;
-
} else {
res = matroska_parse_frame(matroska, track, st, data, lace_size[n],
- timecode, lace_duration,
- pos, !n? is_keyframe : 0,
- additional, additional_id, additional_size,
- discard_padding);
+ timecode, lace_duration, pos,
+ !n ? is_keyframe : 0,
+ additional, additional_id, additional_size,
+ discard_padding);
if (res)
goto end;
}
@@ -2718,8 +2831,8 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska)
ebml_free(matroska_cluster, &matroska->current_cluster);
memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster));
matroska->current_cluster_num_blocks = 0;
- matroska->current_cluster_pos = avio_tell(matroska->ctx->pb);
- matroska->prev_pkt = NULL;
+ matroska->current_cluster_pos = avio_tell(matroska->ctx->pb);
+ matroska->prev_pkt = NULL;
/* sizeof the ID which was already read */
if (matroska->current_id)
matroska->current_cluster_pos -= 4;
@@ -2735,21 +2848,20 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska)
if (!res &&
matroska->current_cluster_num_blocks <
- matroska->current_cluster.blocks.nb_elem) {
+ matroska->current_cluster.blocks.nb_elem) {
blocks_list = &matroska->current_cluster.blocks;
- blocks = blocks_list->elem;
+ blocks = blocks_list->elem;
matroska->current_cluster_num_blocks = blocks_list->nb_elem;
- i = blocks_list->nb_elem - 1;
+ i = blocks_list->nb_elem - 1;
if (blocks[i].bin.size > 0 && blocks[i].bin.data) {
int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
uint8_t* additional = blocks[i].additional.size > 0 ?
blocks[i].additional.data : NULL;
if (!blocks[i].non_simple)
blocks[i].duration = 0;
- res = matroska_parse_block(matroska,
- blocks[i].bin.data, blocks[i].bin.size,
- blocks[i].bin.pos,
+ res = matroska_parse_block(matroska, blocks[i].bin.data,
+ blocks[i].bin.size, blocks[i].bin.pos,
matroska->current_cluster.timecode,
blocks[i].duration, is_keyframe,
additional, blocks[i].additional_id,
@@ -2769,23 +2881,24 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
MatroskaBlock *blocks;
int i, res;
int64_t pos;
+
if (!matroska->contains_ssa)
return matroska_parse_cluster_incremental(matroska);
pos = avio_tell(matroska->ctx->pb);
matroska->prev_pkt = NULL;
if (matroska->current_id)
pos -= 4; /* sizeof the ID which was already read */
- res = ebml_parse(matroska, matroska_clusters, &cluster);
+ res = ebml_parse(matroska, matroska_clusters, &cluster);
blocks_list = &cluster.blocks;
- blocks = blocks_list->elem;
- for (i=0; i<blocks_list->nb_elem; i++)
+ blocks = blocks_list->elem;
+ for (i = 0; i < blocks_list->nb_elem; i++)
if (blocks[i].bin.size > 0 && blocks[i].bin.data) {
int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
- res=matroska_parse_block(matroska,
- blocks[i].bin.data, blocks[i].bin.size,
- blocks[i].bin.pos, cluster.timecode,
- blocks[i].duration, is_keyframe, NULL, 0, 0,
- pos, blocks[i].discard_padding);
+ res = matroska_parse_block(matroska, blocks[i].bin.data,
+ blocks[i].bin.size, blocks[i].bin.pos,
+ cluster.timecode, blocks[i].duration,
+ is_keyframe, NULL, 0, 0, pos,
+ blocks[i].discard_padding);
}
ebml_free(matroska_cluster, &cluster);
return res;
@@ -2825,7 +2938,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
timestamp = FFMAX(timestamp, st->index_entries[0].timestamp);
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
- avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET);
+ avio_seek(s->pb, st->index_entries[st->nb_index_entries - 1].pos,
+ SEEK_SET);
matroska->current_id = 0;
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
matroska_clear_queue(matroska);
@@ -2839,24 +2953,26 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
goto err;
index_min = index;
- for (i=0; i < matroska->tracks.nb_elem; i++) {
- tracks[i].audio.pkt_cnt = 0;
+ for (i = 0; i < matroska->tracks.nb_elem; i++) {
+ tracks[i].audio.pkt_cnt = 0;
tracks[i].audio.sub_packet_cnt = 0;
- tracks[i].audio.buf_timecode = AV_NOPTS_VALUE;
- tracks[i].end_timecode = 0;
- if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE
- && tracks[i].stream->discard != AVDISCARD_ALL) {
- index_sub = av_index_search_timestamp(tracks[i].stream, st->index_entries[index].timestamp, AVSEEK_FLAG_BACKWARD);
- while(index_sub >= 0
- && index_min >= 0
- && tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos
- && st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000/matroska->time_scale)
+ tracks[i].audio.buf_timecode = AV_NOPTS_VALUE;
+ tracks[i].end_timecode = 0;
+ if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE &&
+ tracks[i].stream->discard != AVDISCARD_ALL) {
+ index_sub = av_index_search_timestamp(
+ tracks[i].stream, st->index_entries[index].timestamp,
+ AVSEEK_FLAG_BACKWARD);
+ while (index_sub >= 0 &&
+ index_min > 0 &&
+ tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos &&
+ st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000 / matroska->time_scale)
index_min--;
}
}
avio_seek(s->pb, st->index_entries[index_min].pos, SEEK_SET);
- matroska->current_id = 0;
+ matroska->current_id = 0;
if (flags & AVSEEK_FLAG_ANY) {
st->skip_to_keyframe = 0;
matroska->skip_to_timecode = timestamp;
@@ -2865,8 +2981,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
matroska->skip_to_timecode = st->index_entries[index].timestamp;
}
matroska->skip_to_keyframe = 1;
- matroska->done = 0;
- matroska->num_levels = 0;
+ matroska->done = 0;
+ matroska->num_levels = 0;
ff_update_cur_dts(s, st, st->index_entries[index].timestamp);
return 0;
err:
@@ -2889,7 +3005,7 @@ static int matroska_read_close(AVFormatContext *s)
matroska_clear_queue(matroska);
- for (n=0; n < matroska->tracks.nb_elem; n++)
+ for (n = 0; n < matroska->tracks.nb_elem; n++)
if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO)
av_free(tracks[n].audio.buf);
ebml_free(matroska_cluster, &matroska->current_cluster);
diff --git a/chromium/third_party/ffmpeg/libavformat/matroskaenc.c b/chromium/third_party/ffmpeg/libavformat/matroskaenc.c
index e461c5e60ed..17eb318aadb 100644
--- a/chromium/third_party/ffmpeg/libavformat/matroskaenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/matroskaenc.c
@@ -22,6 +22,7 @@
#include <stdint.h>
#include "avc.h"
+#include "hevc.h"
#include "avformat.h"
#include "avio_internal.h"
#include "avlanguage.h"
@@ -84,6 +85,7 @@ typedef struct {
typedef struct {
int write_dts;
int has_cue;
+ int64_t ts_offset;
} mkv_track;
#define MODE_MATROSKAv2 0x01
@@ -532,6 +534,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
ret = put_wv_codecpriv(dyn_cp, codec);
else if (codec->codec_id == AV_CODEC_ID_H264)
ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size);
+ else if (codec->codec_id == AV_CODEC_ID_HEVC)
+ ret = ff_isom_write_hvcc(dyn_cp, codec->extradata, codec->extradata_size, 0);
else if (codec->codec_id == AV_CODEC_ID_ALAC) {
if (codec->extradata_size < 36) {
av_log(s, AV_LOG_ERROR,
@@ -541,6 +545,9 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
} else
avio_write(dyn_cp, codec->extradata + 12,
codec->extradata_size - 12);
+ } else if (codec->codec_id == AV_CODEC_ID_PRORES &&
+ ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == AV_CODEC_ID_PRORES) {
+ avio_wl32(dyn_cp, codec->codec_tag);
}
else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA)
avio_write(dyn_cp, codec->extradata, codec->extradata_size);
@@ -548,9 +555,23 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
if (qt_id) {
if (!codec->codec_tag)
codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id);
- if (codec->extradata_size)
+ if (codec->extradata_size) {
+ if ( ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == codec->codec_id
+ && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata+4)) != codec->codec_id
+ ) {
+ int i;
+ avio_wb32(dyn_cp, 0x5a + codec->extradata_size);
+ avio_wl32(dyn_cp, codec->codec_tag);
+ for(i=0; i<0x5a-8; i++)
+ avio_w8(dyn_cp, 0);
+ }
avio_write(dyn_cp, codec->extradata, codec->extradata_size);
+ }
} else {
+ if (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id))
+ av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n",
+ avcodec_get_name(codec->codec_id));
+
if (!codec->codec_tag)
codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id);
if (!codec->codec_tag) {
@@ -559,7 +580,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
ret = AVERROR(EINVAL);
}
- ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0);
+ ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0, 0);
}
} else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -573,7 +594,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
if (!codec->codec_tag)
codec->codec_tag = tag;
- ff_put_wav_header(dyn_cp, codec);
+ ff_put_wav_header(dyn_cp, codec, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
}
codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv);
@@ -616,7 +637,7 @@ static int mkv_write_tracks(AVFormatContext *s)
continue;
}
- if (!bit_depth)
+ if (!bit_depth && codec->codec_id != AV_CODEC_ID_ADPCM_G726)
bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3;
if (!bit_depth)
bit_depth = codec->bits_per_coded_sample;
@@ -674,13 +695,17 @@ static int mkv_write_tracks(AVFormatContext *s)
}
}
+ if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->delay && codec->codec_id == AV_CODEC_ID_OPUS) {
+// mkv->tracks[i].ts_offset = av_rescale_q(codec->delay,
+// (AVRational){ 1, codec->sample_rate },
+// st->time_base);
+
+ put_ebml_uint(pb, MATROSKA_ID_CODECDELAY,
+ av_rescale_q(codec->delay, (AVRational){ 1, codec->sample_rate },
+ (AVRational){ 1, 1000000000 }));
+ }
if (codec->codec_id == AV_CODEC_ID_OPUS) {
- uint64_t codec_delay =av_rescale_q(codec->delay,
- (AVRational){1, codec->sample_rate},
- (AVRational){1, 1000000000});
- put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codec_delay);
put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL);
-
}
if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 ||
@@ -928,7 +953,9 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int eleme
end_ebml_master(s->pb, targets);
while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
- if (av_strcasecmp(t->key, "title") && av_strcasecmp(t->key, "stereo_mode"))
+ if (av_strcasecmp(t->key, "title") &&
+ av_strcasecmp(t->key, "stereo_mode") &&
+ av_strcasecmp(t->key, "encoding_tool"))
mkv_write_simpletag(s->pb, t);
end_ebml_master(s->pb, tag);
@@ -1069,7 +1096,7 @@ static int mkv_write_header(AVFormatContext *s)
AVIOContext *pb = s->pb;
ebml_master ebml_header, segment_info;
AVDictionaryEntry *tag;
- int ret, i;
+ int ret, i, version = 2;
if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM;
else mkv->mode = MODE_MATROSKAv2;
@@ -1077,7 +1104,12 @@ static int mkv_write_header(AVFormatContext *s)
if (s->avoid_negative_ts < 0)
s->avoid_negative_ts = 1;
- for (i = 0; i < s->nb_streams; i++)
+ if (mkv->mode != MODE_WEBM ||
+ av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||
+ av_dict_get(s->metadata, "alpha_mode", NULL, 0))
+ version = 4;
+
+ for (i = 0; i < s->nb_streams; i++) {
if (s->streams[i]->codec->codec_id == AV_CODEC_ID_ATRAC3 ||
s->streams[i]->codec->codec_id == AV_CODEC_ID_COOK ||
s->streams[i]->codec->codec_id == AV_CODEC_ID_RA_288 ||
@@ -1089,8 +1121,13 @@ static int mkv_write_header(AVFormatContext *s)
avcodec_get_name(s->streams[i]->codec->codec_id));
return AVERROR_PATCHWELCOME;
}
+ if (s->streams[i]->codec->codec_id == AV_CODEC_ID_OPUS ||
+ av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||
+ av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))
+ version = 4;
+ }
- mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks));
+ mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
if (!mkv->tracks)
return AVERROR(ENOMEM);
@@ -1100,7 +1137,7 @@ static int mkv_write_header(AVFormatContext *s)
put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8);
put_ebml_string (pb, EBML_ID_DOCTYPE , s->oformat->name);
- put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 4);
+ put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , version);
put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2);
end_ebml_master(pb, ebml_header);
@@ -1123,7 +1160,7 @@ static int mkv_write_header(AVFormatContext *s)
put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))
put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);
- if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+ if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
uint32_t segment_uid[4];
AVLFG lfg;
@@ -1133,7 +1170,10 @@ static int mkv_write_header(AVFormatContext *s)
segment_uid[i] = av_lfg_get(&lfg);
put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT);
- put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
+ if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0)))
+ put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);
+ else
+ put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);
} else {
const char *ident = "Lavf";
@@ -1349,6 +1389,10 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
if (codec->codec_id == AV_CODEC_ID_H264 && codec->extradata_size > 0 &&
(AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
+ else if (codec->codec_id == AV_CODEC_ID_HEVC && codec->extradata_size > 6 &&
+ (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
+ /* extradata is Annex B, assume the bitstream is too and convert it */
+ ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL);
else if (codec->codec_id == AV_CODEC_ID_WAVPACK) {
int ret = mkv_strip_wavpack(pkt->data, &data, &size);
if (ret < 0) {
@@ -1520,6 +1564,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
return AVERROR(EINVAL);
}
+ ts += mkv->tracks[pkt->stream_index].ts_offset;
if (!s->pb->seekable) {
if (!mkv->dyn_bc) {
@@ -1585,6 +1630,7 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
cluster_time = pkt->dts - mkv->cluster_pts;
else
cluster_time = pkt->pts - mkv->cluster_pts;
+ cluster_time += mkv->tracks[pkt->stream_index].ts_offset;
// start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
// after 4k and on a keyframe
@@ -1630,9 +1676,9 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM);
} else
ret = av_dup_packet(&mkv->cur_audio_pkt);
- if (mkv->cur_audio_pkt.side_data_elems > 0) {
- ret = av_copy_packet_side_data(&mkv->cur_audio_pkt, &mkv->cur_audio_pkt);
- }
+ if (mkv->cur_audio_pkt.side_data_elems > 0) {
+ ret = av_copy_packet_side_data(&mkv->cur_audio_pkt, &mkv->cur_audio_pkt);
+ }
} else
ret = mkv_write_packet_internal(s, pkt);
return ret;
diff --git a/chromium/third_party/ffmpeg/libavformat/metadata.c b/chromium/third_party/ffmpeg/libavformat/metadata.c
index fc3a9d7d556..b9b6de79725 100644
--- a/chromium/third_party/ffmpeg/libavformat/metadata.c
+++ b/chromium/third_party/ffmpeg/libavformat/metadata.c
@@ -33,7 +33,7 @@ void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv,
AVDictionary *dst = NULL;
const char *key;
- if (d_conv == s_conv)
+ if (d_conv == s_conv || !pm)
return;
while ((mtag = av_dict_get(*pm, "", mtag, AV_DICT_IGNORE_SUFFIX))) {
diff --git a/chromium/third_party/ffmpeg/libavformat/microdvddec.c b/chromium/third_party/ffmpeg/libavformat/microdvddec.c
index 7b49e439765..49d2b681921 100644
--- a/chromium/third_party/ffmpeg/libavformat/microdvddec.c
+++ b/chromium/third_party/ffmpeg/libavformat/microdvddec.c
@@ -24,12 +24,15 @@
#include "internal.h"
#include "subtitles.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
#define MAX_LINESIZE 2048
typedef struct {
+ const AVClass *class;
FFDemuxSubtitlesQueue q;
+ AVRational frame_rate;
} MicroDVDContext;
@@ -71,22 +74,30 @@ static int get_duration(const char *buf)
return -1;
}
+static const char *bom = "\xEF\xBB\xBF";
+
static int microdvd_read_header(AVFormatContext *s)
{
AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */
MicroDVDContext *microdvd = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
int i = 0;
- char line[MAX_LINESIZE];
+ char line_buf[MAX_LINESIZE];
+ int has_real_fps = 0;
if (!st)
return AVERROR(ENOMEM);
while (!url_feof(s->pb)) {
- char *p = line;
+ char *p;
AVPacket *sub;
int64_t pos = avio_tell(s->pb);
- int len = ff_get_line(s->pb, line, sizeof(line));
+ int len = ff_get_line(s->pb, line_buf, sizeof(line_buf));
+ char *line = line_buf;
+
+ if (!strncmp(line, bom, 3))
+ line += 3;
+ p = line;
if (!len)
break;
@@ -98,8 +109,10 @@ static int microdvd_read_header(AVFormatContext *s)
if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 ||
sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2)
- && frame <= 1 && fps > 3 && fps < 100)
+ && frame <= 1 && fps > 3 && fps < 100) {
pts_info = av_d2q(fps, 100000);
+ has_real_fps = 1;
+ }
if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) {
st->codec->extradata = av_strdup(line + 11);
if (!st->codec->extradata)
@@ -128,6 +141,13 @@ static int microdvd_read_header(AVFormatContext *s)
sub->duration = get_duration(line);
}
ff_subtitles_queue_finalize(&microdvd->q);
+ if (has_real_fps) {
+ /* export the FPS info only if set in the file */
+ microdvd->frame_rate = pts_info;
+ } else if (microdvd->frame_rate.num) {
+ /* fallback on user specified frame rate */
+ pts_info = microdvd->frame_rate;
+ }
avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
st->codec->codec_id = AV_CODEC_ID_MICRODVD;
@@ -155,6 +175,21 @@ static int microdvd_read_close(AVFormatContext *s)
return 0;
}
+
+#define OFFSET(x) offsetof(MicroDVDContext, x)
+#define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
+static const AVOption microdvd_options[] = {
+ { "subfps", "set the movie frame rate fallback", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, SD },
+ { NULL }
+};
+
+static const AVClass microdvd_class = {
+ .class_name = "microdvddec",
+ .item_name = av_default_item_name,
+ .option = microdvd_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVInputFormat ff_microdvd_demuxer = {
.name = "microdvd",
.long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
@@ -164,4 +199,5 @@ AVInputFormat ff_microdvd_demuxer = {
.read_packet = microdvd_read_packet,
.read_seek2 = microdvd_read_seek,
.read_close = microdvd_read_close,
+ .priv_class = &microdvd_class,
};
diff --git a/chromium/third_party/ffmpeg/libavformat/mlvdec.c b/chromium/third_party/ffmpeg/libavformat/mlvdec.c
new file mode 100644
index 00000000000..a980ed6218c
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/mlvdec.c
@@ -0,0 +1,471 @@
+/*
+ * Magic Lantern Video (MLV) demuxer
+ * Copyright (c) 2014 Peter Ross
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Magic Lantern Video (MLV) demuxer
+ */
+
+#include "libavutil/eval.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/rational.h"
+#include "avformat.h"
+#include "internal.h"
+#include "riff.h"
+
+#define MLV_VERSION "v2.0"
+
+#define MLV_VIDEO_CLASS_RAW 1
+#define MLV_VIDEO_CLASS_YUV 2
+#define MLV_VIDEO_CLASS_JPEG 3
+#define MLV_VIDEO_CLASS_H264 4
+
+#define MLV_AUDIO_CLASS_WAV 1
+
+#define MLV_CLASS_FLAG_DELTA 0x40
+#define MLV_CLASS_FLAG_LZMA 0x80
+
+typedef struct {
+ AVIOContext *pb[101];
+ int class[2];
+ int stream_index;
+ uint64_t pts;
+} MlvContext;
+
+static int probe(AVProbeData *p)
+{
+ if (AV_RL32(p->buf) == MKTAG('M','L','V','I') &&
+ AV_RL32(p->buf + 4) >= 52 &&
+ !memcmp(p->buf + 8, MLV_VERSION, 5))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+static int check_file_header(AVIOContext *pb, uint64_t guid)
+{
+ unsigned int size;
+ uint8_t version[8];
+
+ avio_skip(pb, 4);
+ size = avio_rl32(pb);
+ if (size < 52)
+ return AVERROR_INVALIDDATA;
+ avio_read(pb, version, 8);
+ if (memcmp(version, MLV_VERSION, 5) || avio_rl64(pb) != guid)
+ return AVERROR_INVALIDDATA;
+ avio_skip(pb, size - 24);
+ return 0;
+}
+
+static void read_string(AVFormatContext *avctx, AVIOContext *pb, const char *tag, int size)
+{
+ char * value = av_malloc(size + 1);
+ if (!value) {
+ avio_skip(pb, size);
+ return;
+ }
+
+ avio_read(pb, value, size);
+ if (!value[0]) {
+ av_free(value);
+ return;
+ }
+
+ value[size] = 0;
+ av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL);
+}
+
+static void read_uint8(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
+{
+ char value[4];
+ snprintf(value, sizeof(value), "%i", avio_r8(pb));
+ av_dict_set(&avctx->metadata, tag, value, 0);
+}
+
+static void read_uint16(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
+{
+ char value[8];
+ snprintf(value, sizeof(value), "%i", avio_rl16(pb));
+ av_dict_set(&avctx->metadata, tag, value, 0);
+}
+
+static void read_uint32(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
+{
+ char value[16];
+ snprintf(value, sizeof(value), fmt, avio_rl32(pb));
+ av_dict_set(&avctx->metadata, tag, value, 0);
+}
+
+static void read_uint64(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
+{
+ char value[32];
+ snprintf(value, sizeof(value), fmt, avio_rl64(pb));
+ av_dict_set(&avctx->metadata, tag, value, 0);
+}
+
+static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int file)
+{
+ MlvContext *mlv = avctx->priv_data;
+ AVIOContext *pb = mlv->pb[file];
+ int ret;
+ while (!url_feof(pb)) {
+ int type;
+ unsigned int size;
+ type = avio_rl32(pb);
+ size = avio_rl32(pb);
+ avio_skip(pb, 8); //timestamp
+ if (size < 16)
+ break;
+ size -= 16;
+ if (vst && type == MKTAG('R','A','W','I') && size >= 164) {
+ vst->codec->width = avio_rl16(pb);
+ vst->codec->height = avio_rl16(pb);
+ if (avio_rl32(pb) != 1)
+ avpriv_request_sample(avctx, "raw api version");
+ avio_skip(pb, 20); // pointer, width, height, pitch, frame_size
+ vst->codec->bits_per_coded_sample = avio_rl32(pb);
+ avio_skip(pb, 8 + 16 + 24); // black_level, white_level, xywh, active_area, exposure_bias
+ if (avio_rl32(pb) != 0x2010100) /* RGGB */
+ avpriv_request_sample(avctx, "cfa_pattern");
+ avio_skip(pb, 80); // calibration_illuminant1, color_matrix1, dynamic_range
+ vst->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE;
+ vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16);
+ size -= 164;
+ } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) {
+ ret = ff_get_wav_header(pb, ast->codec, 16);
+ if (ret < 0)
+ return ret;
+ size -= 16;
+ } else if (type == MKTAG('I','N','F','O')) {
+ if (size > 0)
+ read_string(avctx, pb, "info", size);
+ continue;
+ } else if (type == MKTAG('I','D','N','T') && size >= 36) {
+ read_string(avctx, pb, "cameraName", 32);
+ read_uint32(avctx, pb, "cameraModel", "0x%"PRIx32);
+ size -= 36;
+ if (size >= 32) {
+ read_string(avctx, pb, "cameraSerial", 32);
+ size -= 32;
+ }
+ } else if (type == MKTAG('L','E','N','S') && size >= 48) {
+ read_uint16(avctx, pb, "focalLength", "%i");
+ read_uint16(avctx, pb, "focalDist", "%i");
+ read_uint16(avctx, pb, "aperture", "%i");
+ read_uint8(avctx, pb, "stabilizerMode", "%i");
+ read_uint8(avctx, pb, "autofocusMode", "%i");
+ read_uint32(avctx, pb, "flags", "0x%"PRIx32);
+ read_uint32(avctx, pb, "lensID", "%"PRIi32);
+ read_string(avctx, pb, "lensName", 32);
+ size -= 48;
+ if (size >= 32) {
+ read_string(avctx, pb, "lensSerial", 32);
+ size -= 32;
+ }
+ } else if (vst && type == MKTAG('V', 'I', 'D', 'F') && size >= 4) {
+ uint64_t pts = avio_rl32(pb);
+ ff_add_index_entry(&vst->index_entries, &vst->nb_index_entries, &vst->index_entries_allocated_size,
+ avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
+ size -= 4;
+ } else if (ast && type == MKTAG('A', 'U', 'D', 'F') && size >= 4) {
+ uint64_t pts = avio_rl32(pb);
+ ff_add_index_entry(&ast->index_entries, &ast->nb_index_entries, &ast->index_entries_allocated_size,
+ avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
+ size -= 4;
+ } else if (vst && type == MKTAG('W','B','A','L') && size >= 28) {
+ read_uint32(avctx, pb, "wb_mode", "%"PRIi32);
+ read_uint32(avctx, pb, "kelvin", "%"PRIi32);
+ read_uint32(avctx, pb, "wbgain_r", "%"PRIi32);
+ read_uint32(avctx, pb, "wbgain_g", "%"PRIi32);
+ read_uint32(avctx, pb, "wbgain_b", "%"PRIi32);
+ read_uint32(avctx, pb, "wbs_gm", "%"PRIi32);
+ read_uint32(avctx, pb, "wbs_ba", "%"PRIi32);
+ size -= 28;
+ } else if (type == MKTAG('R','T','C','I') && size >= 20) {
+ char str[32];
+ struct tm time = { 0 };
+ time.tm_sec = avio_rl16(pb);
+ time.tm_min = avio_rl16(pb);
+ time.tm_hour = avio_rl16(pb);
+ time.tm_mday = avio_rl16(pb);
+ time.tm_mon = avio_rl16(pb);
+ time.tm_year = avio_rl16(pb);
+ time.tm_wday = avio_rl16(pb);
+ time.tm_yday = avio_rl16(pb);
+ time.tm_isdst = avio_rl16(pb);
+ avio_skip(pb, 2);
+ strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &time);
+ av_dict_set(&avctx->metadata, "time", str, 0);
+ size -= 20;
+ } else if (type == MKTAG('E','X','P','O') && size >= 16) {
+ av_dict_set(&avctx->metadata, "isoMode", avio_rl32(pb) ? "auto" : "manual", 0);
+ read_uint32(avctx, pb, "isoValue", "%"PRIi32);
+ read_uint32(avctx, pb, "isoAnalog", "%"PRIi32);
+ read_uint32(avctx, pb, "digitalGain", "%"PRIi32);
+ size -= 16;
+ if (size >= 8) {
+ read_uint64(avctx, pb, "shutterValue", "%"PRIi64);
+ size -= 8;
+ }
+ } else if (type == MKTAG('S','T','Y','L') && size >= 36) {
+ read_uint32(avctx, pb, "picStyleId", "%"PRIi32);
+ read_uint32(avctx, pb, "contrast", "%"PRIi32);
+ read_uint32(avctx, pb, "sharpness", "%"PRIi32);
+ read_uint32(avctx, pb, "saturation", "%"PRIi32);
+ read_uint32(avctx, pb, "colortone", "%"PRIi32);
+ read_string(avctx, pb, "picStyleName", 16);
+ size -= 36;
+ } else if (type == MKTAG('M','A','R','K')) {
+ } else if (type == MKTAG('N','U','L','L')) {
+ } else if (type == MKTAG('M','L','V','I')) { /* occurs when MLV and Mnn files are concatenated */
+ } else {
+ av_log(avctx, AV_LOG_INFO, "unsupported tag %c%c%c%c, size %u\n", type&0xFF, (type>>8)&0xFF, (type>>16)&0xFF, (type>>24)&0xFF, size);
+ }
+ avio_skip(pb, size);
+ }
+ return 0;
+}
+
+static int read_header(AVFormatContext *avctx)
+{
+ MlvContext *mlv = avctx->priv_data;
+ AVIOContext *pb = avctx->pb;
+ AVStream *vst = NULL, *ast = NULL;
+ int size, ret;
+ uint64_t guid;
+ char guidstr[32];
+
+ avio_skip(pb, 4);
+ size = avio_rl32(pb);
+ if (size < 52)
+ return AVERROR_INVALIDDATA;
+
+ avio_skip(pb, 8);
+
+ guid = avio_rl64(pb);
+ snprintf(guidstr, sizeof(guidstr), "0x%"PRIx64, guid);
+ av_dict_set(&avctx->metadata, "guid", guidstr, 0);
+
+ avio_skip(pb, 8); //fileNum, fileCount, fileFlags
+
+ mlv->class[0] = avio_rl16(pb);
+ if (mlv->class[0]) {
+ vst = avformat_new_stream(avctx, NULL);
+ if (!vst)
+ return AVERROR(ENOMEM);
+ vst->id = 0;
+ if ((mlv->class[0] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)))
+ avpriv_request_sample(avctx, "compression");
+ vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ switch (mlv->class[0] & ~(MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)) {
+ case MLV_VIDEO_CLASS_RAW:
+ vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+ break;
+ case MLV_VIDEO_CLASS_YUV:
+ vst->codec->pix_fmt = AV_PIX_FMT_YUV420P;
+ vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+ vst->codec->codec_tag = 0;
+ break;
+ case MLV_VIDEO_CLASS_JPEG:
+ vst->codec->codec_id = AV_CODEC_ID_MJPEG;
+ vst->codec->codec_tag = 0;
+ break;
+ case MLV_VIDEO_CLASS_H264:
+ vst->codec->codec_id = AV_CODEC_ID_H264;
+ vst->codec->codec_tag = 0;
+ break;
+ default:
+ avpriv_request_sample(avctx, "unknown video class");
+ }
+ }
+
+ mlv->class[1] = avio_rl16(pb);
+ if (mlv->class[1]) {
+ ast = avformat_new_stream(avctx, NULL);
+ if (!ast)
+ return AVERROR(ENOMEM);
+ ast->id = 1;
+ if ((mlv->class[1] & MLV_CLASS_FLAG_LZMA))
+ avpriv_request_sample(avctx, "compression");
+ if ((mlv->class[1] & ~MLV_CLASS_FLAG_LZMA) != MLV_AUDIO_CLASS_WAV)
+ avpriv_request_sample(avctx, "unknown audio class");
+
+ ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate);
+ }
+
+ if (vst)
+ vst->nb_frames = avio_rl32(pb);
+ else
+ avio_skip(pb, 4);
+
+ if (ast)
+ ast->nb_frames = avio_rl32(pb);
+ else
+ avio_skip(pb, 4);
+
+ if (vst) {
+ AVRational framerate;
+ framerate.num = avio_rl32(pb);
+ framerate.den = avio_rl32(pb);
+ avpriv_set_pts_info(vst, 64, framerate.den, framerate.num);
+ } else
+ avio_skip(pb, 8);
+
+ avio_skip(pb, size - 52);
+
+ /* scan primary file */
+ mlv->pb[100] = avctx->pb;
+ ret = scan_file(avctx, vst, ast, 100);
+ if (ret < 0)
+ return ret;
+
+ /* scan secondary files */
+ if (strlen(avctx->filename) > 2) {
+ int i;
+ char *filename = av_strdup(avctx->filename);
+ if (!filename)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < 100; i++) {
+ snprintf(filename + strlen(filename) - 2, 3, "%02d", i);
+ if (avio_open2(&mlv->pb[i], filename, AVIO_FLAG_READ, &avctx->interrupt_callback, NULL) < 0)
+ break;
+ if (check_file_header(mlv->pb[i], guid) < 0) {
+ av_log(avctx, AV_LOG_WARNING, "ignoring %s; bad format or guid mismatch\n", filename);
+ avio_close(mlv->pb[i]);
+ mlv->pb[i] = NULL;
+ continue;
+ }
+ av_log(avctx, AV_LOG_INFO, "scanning %s\n", filename);
+ ret = scan_file(avctx, vst, ast, i);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_WARNING, "ignoring %s; %s\n", filename, av_err2str(ret));
+ avio_close(mlv->pb[i]);
+ mlv->pb[i] = NULL;
+ continue;
+ }
+ }
+ av_free(filename);
+ }
+
+ if (vst)
+ vst->duration = vst->nb_index_entries;
+ if (ast)
+ ast->duration = ast->nb_index_entries;
+
+ if (vst && ast)
+ avio_seek(pb, FFMIN(vst->index_entries[0].pos, ast->index_entries[0].pos), SEEK_SET);
+ else if (vst)
+ avio_seek(pb, vst->index_entries[0].pos, SEEK_SET);
+ else if (ast)
+ avio_seek(pb, ast->index_entries[0].pos, SEEK_SET);
+
+ return 0;
+}
+
+static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
+{
+ MlvContext *mlv = avctx->priv_data;
+ AVIOContext *pb;
+ AVStream *st = avctx->streams[mlv->stream_index];
+ int index, ret;
+ unsigned int size, space;
+
+ if (mlv->pts >= st->duration)
+ return AVERROR_EOF;
+
+ index = av_index_search_timestamp(st, mlv->pts, AVSEEK_FLAG_ANY);
+ if (index < 0) {
+ av_log(avctx, AV_LOG_ERROR, "could not find index entry for frame %"PRId64"\n", mlv->pts);
+ return AVERROR(EIO);
+ }
+
+ pb = mlv->pb[st->index_entries[index].size];
+ avio_seek(pb, st->index_entries[index].pos, SEEK_SET);
+
+ avio_skip(pb, 4); // blockType
+ size = avio_rl32(pb);
+ if (size < 16)
+ return AVERROR_INVALIDDATA;
+ avio_skip(pb, 12); //timestamp, frameNumber
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ avio_skip(pb, 8); // cropPosX, cropPosY, panPosX, panPosY
+ space = avio_rl32(pb);
+ avio_skip(pb, space);
+
+ if ((mlv->class[st->id] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA))) {
+ ret = AVERROR_PATCHWELCOME;
+ } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ ret = av_get_packet(pb, pkt, (st->codec->width * st->codec->height * st->codec->bits_per_coded_sample + 7) >> 3);
+ } else { // AVMEDIA_TYPE_AUDIO
+ if (space > UINT_MAX - 24 || size < (24 + space))
+ return AVERROR_INVALIDDATA;
+ ret = av_get_packet(pb, pkt, size - (24 + space));
+ }
+
+ if (ret < 0)
+ return ret;
+
+ pkt->stream_index = mlv->stream_index;
+ pkt->pts = mlv->pts;
+
+ mlv->stream_index++;
+ if (mlv->stream_index == avctx->nb_streams) {
+ mlv->stream_index = 0;
+ mlv->pts++;
+ }
+ return 0;
+}
+
+static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
+{
+ MlvContext *mlv = avctx->priv_data;
+
+ if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
+ return AVERROR(ENOSYS);
+
+ if (!avctx->pb->seekable)
+ return AVERROR(EIO);
+
+ mlv->pts = timestamp;
+ return 0;
+}
+
+static int read_close(AVFormatContext *s)
+{
+ MlvContext *mlv = s->priv_data;
+ int i;
+ for (i = 0; i < 100; i++)
+ if (mlv->pb[i])
+ avio_close(mlv->pb[i]);
+ return 0;
+}
+
+AVInputFormat ff_mlv_demuxer = {
+ .name = "mlv",
+ .long_name = NULL_IF_CONFIG_SMALL("Magic Lantern Video (MLV)"),
+ .priv_data_size = sizeof(MlvContext),
+ .read_probe = probe,
+ .read_header = read_header,
+ .read_packet = read_packet,
+ .read_close = read_close,
+ .read_seek = read_seek,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/mms.c b/chromium/third_party/ffmpeg/libavformat/mms.c
index 46fbede90c4..7e60b3bec60 100644
--- a/chromium/third_party/ffmpeg/libavformat/mms.c
+++ b/chromium/third_party/ffmpeg/libavformat/mms.c
@@ -1,7 +1,7 @@
/*
* MMS protocol common definitions.
* Copyright (c) 2006,2007 Ryan Martell
- * Copyright (c) 2007 Björn Axelsson
+ * Copyright (c) 2007 Björn Axelsson
* Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
*
* This file is part of FFmpeg.
diff --git a/chromium/third_party/ffmpeg/libavformat/mmsh.c b/chromium/third_party/ffmpeg/libavformat/mmsh.c
index 482ece40316..dac5d9f6539 100644
--- a/chromium/third_party/ffmpeg/libavformat/mmsh.c
+++ b/chromium/third_party/ffmpeg/libavformat/mmsh.c
@@ -119,7 +119,7 @@ static int read_data_packet(MMSHContext *mmsh, const int len)
int res;
if (len > sizeof(mms->in_buffer)) {
av_log(NULL, AV_LOG_ERROR,
- "Data packet length %d exceeds the in_buffer size %zu\n",
+ "Data packet length %d exceeds the in_buffer size %"SIZE_SPECIFIER"\n",
len, sizeof(mms->in_buffer));
return AVERROR(EIO);
}
@@ -194,7 +194,7 @@ static int get_http_header_data(MMSHContext *mmsh)
if (len) {
if (len > sizeof(mms->in_buffer)) {
av_log(NULL, AV_LOG_ERROR,
- "Other packet len = %d exceed the in_buffer size %zu\n",
+ "Other packet len = %d exceed the in_buffer size %"SIZE_SPECIFIER"\n",
len, sizeof(mms->in_buffer));
return AVERROR(EIO);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mmst.c b/chromium/third_party/ffmpeg/libavformat/mmst.c
index 382895566ee..c851187dafb 100644
--- a/chromium/third_party/ffmpeg/libavformat/mmst.c
+++ b/chromium/third_party/ffmpeg/libavformat/mmst.c
@@ -1,7 +1,7 @@
/*
* MMS protocol over TCP
* Copyright (c) 2006,2007 Ryan Martell
- * Copyright (c) 2007 Björn Axelsson
+ * Copyright (c) 2007 Björn Axelsson
* Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
*
* This file is part of FFmpeg.
@@ -284,7 +284,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
if (length_remaining < 0
|| length_remaining > sizeof(mms->in_buffer) - 12) {
av_log(NULL, AV_LOG_ERROR,
- "Incoming packet length %d exceeds bufsize %zu\n",
+ "Incoming packet length %d exceeds bufsize %"SIZE_SPECIFIER"\n",
length_remaining, sizeof(mms->in_buffer) - 12);
return AVERROR_INVALIDDATA;
}
@@ -320,7 +320,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
if (length_remaining < 0
|| length_remaining > sizeof(mms->in_buffer) - 8) {
av_log(NULL, AV_LOG_ERROR,
- "Data length %d is invalid or too large (max=%zu)\n",
+ "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER")\n",
length_remaining, sizeof(mms->in_buffer));
return AVERROR_INVALIDDATA;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mov.c b/chromium/third_party/ffmpeg/libavformat/mov.c
index 0157a7dc8a9..b0500d9756c 100644
--- a/chromium/third_party/ffmpeg/libavformat/mov.c
+++ b/chromium/third_party/ffmpeg/libavformat/mov.c
@@ -23,6 +23,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
@@ -46,6 +47,7 @@
#include "libavcodec/get_bits.h"
#include "id3v1.h"
#include "mov_chan.h"
+#include "replaygain.h"
#if CONFIG_ZLIB
#include <zlib.h>
@@ -129,74 +131,6 @@ static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
return 0;
}
-static int mov_read_custom_metadata(MOVContext *c, AVIOContext *pb, MOVAtom atom)
-{
- char key[1024]={0}, data[1024]={0};
- int i;
- AVStream *st;
- MOVStreamContext *sc;
-
- if (c->fc->nb_streams < 1)
- return 0;
- st = c->fc->streams[c->fc->nb_streams-1];
- sc = st->priv_data;
-
- if (atom.size <= 8) return 0;
-
- for (i = 0; i < 3; i++) { // Parse up to three sub-atoms looking for name and data.
- int data_size = avio_rb32(pb);
- int tag = avio_rl32(pb);
- int str_size = 0, skip_size = 0;
- char *target = NULL;
-
- switch (tag) {
- case MKTAG('n','a','m','e'):
- avio_rb32(pb); // version/flags
- str_size = skip_size = data_size - 12;
- atom.size -= 12;
- target = key;
- break;
- case MKTAG('d','a','t','a'):
- avio_rb32(pb); // version/flags
- avio_rb32(pb); // reserved (zero)
- str_size = skip_size = data_size - 16;
- atom.size -= 16;
- target = data;
- break;
- default:
- skip_size = data_size - 8;
- str_size = 0;
- break;
- }
-
- if (target) {
- str_size = FFMIN3(sizeof(data)-1, str_size, atom.size);
- avio_read(pb, target, str_size);
- target[str_size] = 0;
- }
- atom.size -= skip_size;
-
- // If we didn't read the full data chunk for the sub-atom, skip to the end of it.
- if (skip_size > str_size) avio_skip(pb, skip_size - str_size);
- }
-
- if (*key && *data) {
- if (strcmp(key, "iTunSMPB") == 0) {
- int priming, remainder, samples;
- if(sscanf(data, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
- if(priming>0 && priming<16384)
- sc->start_pad = priming;
- return 1;
- }
- }
- if (strcmp(key, "cdec") == 0) {
-// av_dict_set(&st->metadata, key, data, 0);
- return 1;
- }
- }
- return 0;
-}
-
static const uint32_t mac_to_unicode[128] = {
0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
@@ -298,15 +232,14 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
uint32_t data_type = 0, str_size;
int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
- if (c->itunes_metadata && atom.type == MKTAG('-','-','-','-'))
- return mov_read_custom_metadata(c, pb, atom);
-
switch (atom.type) {
case MKTAG(0xa9,'n','a','m'): key = "title"; break;
case MKTAG(0xa9,'a','u','t'):
case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
+ case MKTAG( 'c','p','i','l'): key = "compilation";
+ parse = mov_metadata_int8_no_padding; break;
case MKTAG( 'c','p','r','t'):
case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
@@ -362,8 +295,8 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int ret = mov_read_covr(c, pb, data_type, str_size);
if (ret < 0) {
av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
- return ret;
}
+ return ret;
}
} else return 0;
} else if (atom.size > 4 && key && !c->itunes_metadata) {
@@ -394,7 +327,9 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff))) { // MAC Encoded
mov_read_mac_string(c, pb, str_size, str, sizeof(str));
} else {
- avio_read(pb, str, str_size);
+ int ret = avio_read(pb, str, str_size);
+ if (ret != str_size)
+ return ret < 0 ? ret : AVERROR_INVALIDDATA;
str[str_size] = 0;
}
av_dict_set(&c->fc->metadata, key, str, 0);
@@ -537,7 +472,8 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
dref->dir = av_malloc(len+1);
if (!dref->dir)
return AVERROR(ENOMEM);
- avio_read(pb, dref->dir, len);
+ if (avio_read(pb, dref->dir, len) != len)
+ return AVERROR_INVALIDDATA;
dref->dir[len] = 0;
for (j = 0; j < len; j++)
if (dref->dir[j] == ':')
@@ -764,7 +700,7 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
av_dict_set(&c->fc->metadata, "major_brand", type, 0);
minor_ver = avio_rb32(pb); /* minor version */
- snprintf(minor_ver_str, sizeof(minor_ver_str), "%d", minor_ver);
+ snprintf(minor_ver_str, sizeof(minor_ver_str), "%"PRIu32"", minor_ver);
av_dict_set(&c->fc->metadata, "minor_version", minor_ver_str, 0);
comp_brand_size = atom.size - 8;
@@ -1002,7 +938,14 @@ static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE;
AV_WB32( buf , atom.size + 8);
AV_WL32( buf + 4, atom.type);
- avio_read(pb, buf + 8, atom.size);
+ err = avio_read(pb, buf + 8, atom.size);
+ if (err < 0) {
+ return err;
+ } else if (err < atom.size) {
+ av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
+ st->codec->extradata_size -= atom.size - err;
+ }
+ memset(buf + 8 + err, 0, FF_INPUT_BUFFER_PADDING_SIZE);
return 0;
}
@@ -1080,9 +1023,8 @@ static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
st->codec->codec_id == AV_CODEC_ID_SPEEX) {
// pass all frma atom to codec, needed at least for QDMC and QDM2
av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, atom.size))
+ if (ff_get_extradata(st->codec, pb, atom.size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, atom.size);
} else if (atom.size > 8) { /* to read frma, esds atoms */
int ret;
if ((ret = mov_read_default(c, pb, atom)) < 0)
@@ -1117,9 +1059,9 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return mov_read_default(c, pb, atom);
}
av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, atom.size))
+ if (ff_get_extradata(st->codec, pb, atom.size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, atom.size);
+
return 0;
}
@@ -1127,6 +1069,7 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVStream *st;
uint8_t profile_level;
+ int ret;
if (c->fc->nb_streams < 1)
return 0;
@@ -1139,11 +1082,11 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if ((profile_level & 0xf0) != 0xc0)
return 0;
- av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, atom.size - 7))
- return AVERROR(ENOMEM);
avio_seek(pb, 6, SEEK_CUR);
- avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+ av_free(st->codec->extradata);
+ if ((ret = ff_get_extradata(st->codec, pb, atom.size - 7)) < 0)
+ return ret;
+
return 0;
}
@@ -1165,11 +1108,10 @@ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if ((uint64_t)atom.size > (1<<30))
return AVERROR_INVALIDDATA;
+ avio_skip(pb, 40);
av_free(st->codec->extradata);
- if (ff_alloc_extradata(st->codec, atom.size - 40))
+ if (ff_get_extradata(st->codec, pb, atom.size - 40) < 0)
return AVERROR(ENOMEM);
- avio_skip(pb, 40);
- avio_read(pb, st->codec->extradata, atom.size - 40);
return 0;
}
@@ -1266,6 +1208,7 @@ static int mov_codec_id(AVStream *st, uint32_t format)
static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
AVStream *st, MOVStreamContext *sc)
{
+ uint8_t codec_name[32];
unsigned int color_depth, len, j;
int color_greyscale;
int color_table_id;
@@ -1287,18 +1230,22 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
len = avio_r8(pb); /* codec name, pascal string */
if (len > 31)
len = 31;
- mov_read_mac_string(c, pb, len, st->codec->codec_name, 32);
+ mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
if (len < 31)
avio_skip(pb, 31 - len);
+
+ if (codec_name[0])
+ av_dict_set(&st->metadata, "encoder", codec_name, 0);
+
/* codec_tag YV12 triggers an UV swap in rawdec.c */
- if (!memcmp(st->codec->codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
+ if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
st->codec->codec_tag = MKTAG('I', '4', '2', '0');
st->codec->width &= ~1;
st->codec->height &= ~1;
}
/* Flash Media Server uses tag H263 with Sorenson Spark */
if (st->codec->codec_tag == MKTAG('H','2','6','3') &&
- !memcmp(st->codec->codec_name, "Sorenson H263", 13))
+ !memcmp(codec_name, "Sorenson H263", 13))
st->codec->codec_id = AV_CODEC_ID_FLV1;
st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */
@@ -1308,6 +1255,9 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
/* figure out the palette situation */
color_depth = st->codec->bits_per_coded_sample & 0x1F;
color_greyscale = st->codec->bits_per_coded_sample & 0x20;
+ /* Do not create a greyscale palette for cinepak */
+ if (color_greyscale && st->codec->codec_id == AV_CODEC_ID_CINEPAK)
+ return;
/* if the depth is 2, 4, or 8 bpp, file is palettized */
if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) {
@@ -1323,9 +1273,6 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
color_index = 255;
color_dec = 256 / (color_count - 1);
for (j = 0; j < color_count; j++) {
- if (st->codec->codec_id == AV_CODEC_ID_CINEPAK){
- r = g = b = color_count - 1 - color_index;
- } else
r = g = b = color_index;
sc->palette[j] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
color_index -= color_dec;
@@ -1477,14 +1424,64 @@ static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
st->codec->height = sc->height;
}
+static uint32_t yuv_to_rgba(uint32_t ycbcr)
+{
+ uint8_t r, g, b;
+ int y, cb, cr;
+
+ y = (ycbcr >> 16) & 0xFF;
+ cr = (ycbcr >> 8) & 0xFF;
+ cb = ycbcr & 0xFF;
+
+ b = av_clip_uint8(1.164 * (y - 16) + 2.018 * (cb - 128));
+ g = av_clip_uint8(1.164 * (y - 16) - 0.813 * (cr - 128) - 0.391 * (cb - 128));
+ r = av_clip_uint8(1.164 * (y - 16) + 1.596 * (cr - 128));
+
+ return (r << 16) | (g << 8) | b;
+}
+
+static int mov_rewrite_dvd_sub_extradata(AVStream *st)
+{
+ char buf[256] = {0};
+ uint8_t *src = st->codec->extradata;
+ int i;
+
+ if (st->codec->extradata_size != 64)
+ return 0;
+
+ if (st->codec->width > 0 && st->codec->height > 0)
+ snprintf(buf, sizeof(buf), "size: %dx%d\n",
+ st->codec->width, st->codec->height);
+ av_strlcat(buf, "palette: ", sizeof(buf));
+
+ for (i = 0; i < 16; i++) {
+ uint32_t yuv = AV_RB32(src + i * 4);
+ uint32_t rgba = yuv_to_rgba(yuv);
+
+ av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
+ }
+
+ if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
+ return 0;
+
+ av_freep(&st->codec->extradata);
+ st->codec->extradata_size = 0;
+ st->codec->extradata = av_mallocz(strlen(buf) + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
+ st->codec->extradata_size = strlen(buf);
+ memcpy(st->codec->extradata, buf, st->codec->extradata_size);
+
+ return 0;
+}
+
static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
AVStream *st, MOVStreamContext *sc,
int size)
{
if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
- if (ff_alloc_extradata(st->codec, size))
+ if (ff_get_extradata(st->codec, pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, size);
if (size > 16) {
MOVStreamContext *tmcd_ctx = st->priv_data;
int val;
@@ -1529,6 +1526,10 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
// force sample rate for qcelp when not stored in mov
if (st->codec->codec_tag != MKTAG('Q','c','l','p'))
st->codec->sample_rate = 8000;
+ // FIXME: Why is the following needed for some files?
+ sc->samples_per_frame = 160;
+ if (!sc->bytes_per_frame)
+ sc->bytes_per_frame = 35;
break;
case AV_CODEC_ID_AMR_NB:
st->codec->channels = 1;
@@ -1561,11 +1562,7 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
}
break;
case AV_CODEC_ID_AC3:
- st->need_parsing = AVSTREAM_PARSE_FULL;
- break;
case AV_CODEC_ID_MPEG1VIDEO:
- st->need_parsing = AVSTREAM_PARSE_FULL;
- break;
case AV_CODEC_ID_VC1:
st->need_parsing = AVSTREAM_PARSE_FULL;
break;
@@ -1906,6 +1903,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (entries >= UINT_MAX / sizeof(*sc->stts_data))
return -1;
+ av_free(sc->stts_data);
sc->stts_data = av_malloc(entries * sizeof(*sc->stts_data));
if (!sc->stts_data)
return AVERROR(ENOMEM);
@@ -1919,7 +1917,8 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
/* sample_duration < 0 is invalid based on the spec */
if (sample_duration < 0) {
- av_log(c->fc, AV_LOG_ERROR, "Invalid SampleDelta in STTS %d\n", sample_duration);
+ av_log(c->fc, AV_LOG_ERROR, "Invalid SampleDelta %d in STTS, at %d st:%d\n",
+ sample_duration, i, c->fc->nb_streams-1);
sample_duration = 1;
}
if (sample_count < 0) {
@@ -1932,12 +1931,21 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_dlog(c->fc, "sample_count=%d, sample_duration=%d\n",
sample_count, sample_duration);
+ if ( i+1 == entries
+ && i
+ && sample_count == 1
+ && total_sample_count > 100
+ && sample_duration/10 > duration / total_sample_count)
+ sample_duration = duration / total_sample_count;
duration+=(int64_t)sample_duration*sample_count;
total_sample_count+=sample_count;
}
sc->stts_count = i;
+ sc->duration_for_fps += duration;
+ sc->nb_frames_for_fps += total_sample_count;
+
if (pb->eof_reached)
return AVERROR_EOF;
@@ -2145,6 +2153,11 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
rap_group_index++;
}
}
+ if (sc->keyframe_absent
+ && !sc->stps_count
+ && !rap_group_present
+ && st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ keyframe = 1;
if (keyframe)
distance = 0;
sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
@@ -2379,10 +2392,6 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
((double)st->codec->width * sc->height), INT_MAX);
}
- if (st->duration > 0)
- av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
- sc->time_scale*st->nb_frames, st->duration, INT_MAX);
-
#if FF_API_R_FRAME_RATE
if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
@@ -2434,6 +2443,103 @@ static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return ret;
}
+static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
+{
+ int64_t end = avio_tell(pb) + size;
+ uint8_t *key = NULL, *val = NULL;
+ int i;
+ AVStream *st;
+ MOVStreamContext *sc;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+ st = c->fc->streams[c->fc->nb_streams-1];
+ sc = st->priv_data;
+
+ for (i = 0; i < 2; i++) {
+ uint8_t **p;
+ uint32_t len, tag;
+
+ if (end - avio_tell(pb) <= 12)
+ break;
+
+ len = avio_rb32(pb);
+ tag = avio_rl32(pb);
+ avio_skip(pb, 4); // flags
+
+ if (len < 12 || len - 12 > end - avio_tell(pb))
+ break;
+ len -= 12;
+
+ if (tag == MKTAG('n', 'a', 'm', 'e'))
+ p = &key;
+ else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
+ avio_skip(pb, 4);
+ len -= 4;
+ p = &val;
+ } else
+ break;
+
+ *p = av_malloc(len + 1);
+ if (!*p)
+ break;
+ avio_read(pb, *p, len);
+ (*p)[len] = 0;
+ }
+
+ if (key && val) {
+ if (strcmp(key, "iTunSMPB") == 0) {
+ int priming, remainder, samples;
+ if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
+ if(priming>0 && priming<16384)
+ sc->start_pad = priming;
+ }
+ } else if (strcmp(key, "cdec") == 0) {
+ } else {
+ av_dict_set(&c->fc->metadata, key, val,
+ AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+ key = val = NULL;
+ }
+ }
+
+ avio_seek(pb, end, SEEK_SET);
+ av_freep(&key);
+ av_freep(&val);
+ return 0;
+}
+
+static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ int64_t end = avio_tell(pb) + atom.size;
+ uint32_t tag, len;
+
+ if (atom.size < 8)
+ goto fail;
+
+ len = avio_rb32(pb);
+ tag = avio_rl32(pb);
+
+ if (len > atom.size)
+ goto fail;
+
+ if (tag == MKTAG('m', 'e', 'a', 'n') && len > 12) {
+ uint8_t domain[128];
+ int domain_len;
+
+ avio_skip(pb, 4); // flags
+ len -= 12;
+
+ domain_len = avio_get_str(pb, len, domain, sizeof(domain));
+ avio_skip(pb, len - domain_len);
+ return mov_read_custom_2plus(c, pb, end - avio_tell(pb));
+ }
+
+fail:
+ av_log(c->fc, AV_LOG_VERBOSE,
+ "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
+ return 0;
+}
+
static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
while (atom.size > 8) {
@@ -2701,6 +2807,8 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
dts += sample_duration;
offset += sample_size;
sc->data_size += sample_size;
+ sc->duration_for_fps += sample_duration;
+ sc->nb_frames_for_fps ++;
}
if (pb->eof_reached)
@@ -2975,6 +3083,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('h','v','c','C'), mov_read_glbl },
{ MKTAG('u','u','i','d'), mov_read_uuid },
{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
+{ MKTAG('-','-','-','-'), mov_read_custom },
{ 0, NULL }
};
@@ -3272,15 +3381,20 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&sc->drefs[j].dir);
}
av_freep(&sc->drefs);
+
+ sc->drefs_count = 0;
+
if (!sc->pb_is_copied)
avio_close(sc->pb);
+
sc->pb = NULL;
av_freep(&sc->chunk_offsets);
- av_freep(&sc->keyframes);
- av_freep(&sc->sample_sizes);
- av_freep(&sc->stps_data);
av_freep(&sc->stsc_data);
+ av_freep(&sc->sample_sizes);
+ av_freep(&sc->keyframes);
av_freep(&sc->stts_data);
+ av_freep(&sc->stps_data);
+ av_freep(&sc->rap_group);
}
if (mov->dv_demux) {
@@ -3336,8 +3450,9 @@ static int mov_read_header(AVFormatContext *s)
{
MOVContext *mov = s->priv_data;
AVIOContext *pb = s->pb;
- int i, j, err;
+ int j, err;
MOVAtom atom = { AV_RL32("root") };
+ int i;
mov->fc = s;
/* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
@@ -3395,6 +3510,19 @@ static int mov_read_header(AVFormatContext *s)
if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->codec_id == AV_CODEC_ID_AAC) {
st->skip_samples = sc->start_pad;
}
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
+ av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
+ sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
+ if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ if (st->codec->width <= 0 && st->codec->height <= 0) {
+ st->codec->width = sc->width;
+ st->codec->height = sc->height;
+ }
+ if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
+ if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
+ return err;
+ }
+ }
}
if (mov->trex_data) {
@@ -3414,6 +3542,19 @@ static int mov_read_header(AVFormatContext *s)
ff_rfps_calculate(s);
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+
+ if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+ continue;
+
+ err = ff_replaygain_export(st, s->metadata);
+ if (err < 0) {
+ mov_read_close(s);
+ return err;
+ }
+ }
+
return 0;
}
@@ -3617,6 +3758,7 @@ AVInputFormat ff_mov_demuxer = {
.name = "mov,mp4,m4a,3gp,3g2,mj2",
.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
.priv_data_size = sizeof(MOVContext),
+ .extensions = "mov,mp4,m4a,3gp,3g2,mj2",
.read_probe = mov_probe,
.read_header = mov_read_header,
.read_packet = mov_read_packet,
diff --git a/chromium/third_party/ffmpeg/libavformat/movenc.c b/chromium/third_party/ffmpeg/libavformat/movenc.c
index 7315417ca2a..adcbcf2c0f8 100644
--- a/chromium/third_party/ffmpeg/libavformat/movenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/movenc.c
@@ -22,6 +22,7 @@
*/
#include <stdint.h>
+#include <inttypes.h>
#include "movenc.h"
#include "avformat.h"
@@ -33,12 +34,15 @@
#include "libavcodec/get_bits.h"
#include "libavcodec/put_bits.h"
#include "libavcodec/vc1.h"
+#include "libavcodec/raw.h"
#include "internal.h"
#include "libavutil/avstring.h"
#include "libavutil/intfloat.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
+#include "libavutil/pixdesc.h"
+#include "hevc.h"
#include "rtpenc.h"
#include "mov_chan.h"
@@ -66,6 +70,7 @@ static const AVOption options[] = {
{ "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
{ "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
+ { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
{ NULL },
};
@@ -348,7 +353,9 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
// the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
// plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
- if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
+ if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+ avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
+ else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
avio_w8(pb, 0x15); // flags (= Audiostream)
else
avio_w8(pb, 0x11); // flags (= Visualstream)
@@ -390,20 +397,24 @@ static int mov_pcm_be_gt16(enum AVCodecID codec_id)
static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
{
+ int ret;
int64_t pos = avio_tell(pb);
avio_wb32(pb, 0);
avio_wl32(pb, track->tag); // store it byteswapped
track->enc->codec_tag = av_bswap16(track->tag >> 16);
- ff_put_wav_header(pb, track->enc);
+ if ((ret = ff_put_wav_header(pb, track->enc, 0)) < 0)
+ return ret;
return update_size(pb, pos);
}
static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track)
{
+ int ret;
int64_t pos = avio_tell(pb);
avio_wb32(pb, 0);
ffio_wfourcc(pb, "wfex");
- ff_put_wav_header(pb, track->enc);
+ if ((ret = ff_put_wav_header(pb, track->enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
+ return ret;
return update_size(pb, pos);
}
@@ -614,7 +625,12 @@ static int get_cluster_duration(MOVTrack *track, int cluster_idx)
else
next_dts = track->cluster[cluster_idx + 1].dts;
- return next_dts - track->cluster[cluster_idx].dts;
+ next_dts -= track->cluster[cluster_idx].dts;
+
+ av_assert0(next_dts >= 0);
+ av_assert0(next_dts <= INT_MAX);
+
+ return next_dts;
}
static int get_samples_per_packet(MOVTrack *track)
@@ -767,6 +783,16 @@ static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
return update_size(pb, pos);
}
+static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
+{
+ int64_t pos = avio_tell(pb);
+
+ avio_wb32(pb, 0);
+ ffio_wfourcc(pb, "hvcC");
+ ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
+ return update_size(pb, pos);
+}
+
/* also used by all avid codecs (dv, imx, meridien) and their variants */
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
{
@@ -823,12 +849,14 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
return 0;
if (track->enc->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1');
+ else if (track->enc->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1');
else if (track->enc->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3');
else if (track->enc->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c');
else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g');
else if (track->enc->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1');
else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
+ else if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s');
return tag;
}
@@ -901,11 +929,14 @@ static AVRational find_fps(AVFormatContext *s, AVStream *st)
static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
{
- int tag = MKTAG('m', '2', 'v', '1'); //fallback tag
+ int tag = track->enc->codec_tag;
int interlaced = track->enc->field_order > AV_FIELD_PROGRESSIVE;
AVStream *st = track->st;
int rate = av_q2d(find_fps(s, st));
+ if (!tag)
+ tag = MKTAG('m', '2', 'v', '1'); //fallback tag
+
if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) {
if (track->enc->width == 1280 && track->enc->height == 720) {
if (!interlaced) {
@@ -984,6 +1015,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
{
int tag = track->enc->codec_tag;
int i;
+ enum AVPixelFormat pix_fmt;
for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
@@ -994,6 +1026,13 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
}
}
+ pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov,
+ track->enc->bits_per_coded_sample);
+ if (tag == MKTAG('r','a','w',' ') &&
+ track->enc->pix_fmt != pix_fmt &&
+ track->enc->pix_fmt != AV_PIX_FMT_NONE)
+ av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
+ av_get_pix_fmt_name(track->enc->pix_fmt));
return tag;
}
@@ -1122,7 +1161,9 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
avio_wb16(pb, 0); /* Reserved */
avio_wb16(pb, 1); /* Data-reference index */
- if (track->enc->extradata_size)
+ if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+ mov_write_esds_tag(pb, track);
+ else if (track->enc->extradata_size)
avio_write(pb, track->enc->extradata, track->enc->extradata_size);
return update_size(pb, pos);
@@ -1221,6 +1262,8 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
avio_wb32(pb, 0);
} else if (track->enc->codec_id == AV_CODEC_ID_DNXHD)
mov_write_avid_tag(pb, track);
+ else if (track->enc->codec_id == AV_CODEC_ID_HEVC)
+ mov_write_hvcc_tag(pb, track);
else if (track->enc->codec_id == AV_CODEC_ID_H264) {
mov_write_avcc_tag(pb, track);
if (track->mode == MODE_IPOD)
@@ -1539,6 +1582,12 @@ static int mov_write_vmhd_tag(AVIOContext *pb)
return 0x14;
}
+static int is_clcp_track(MOVTrack *track)
+{
+ return track->tag == MKTAG('c','7','0','8') ||
+ track->tag == MKTAG('c','6','0','8');
+}
+
static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
{
const char *hdlr, *descr = NULL, *hdlr_type = NULL;
@@ -1557,12 +1606,17 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
hdlr_type = "soun";
descr = "SoundHandler";
} else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- if (track->tag == MKTAG('c','6','0','8')) {
+ if (is_clcp_track(track)) {
hdlr_type = "clcp";
descr = "ClosedCaptionHandler";
} else {
- if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
- else hdlr_type = "text";
+ if (track->tag == MKTAG('t','x','3','g')) {
+ hdlr_type = "sbtl";
+ } else if (track->tag == MKTAG('m','p','4','s')) {
+ hdlr_type = "subp";
+ } else {
+ hdlr_type = "text";
+ }
descr = "SubtitleHandler";
}
} else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
@@ -1623,7 +1677,7 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
mov_write_smhd_tag(pb);
else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- if (track->tag == MKTAG('t','e','x','t') || track->tag == MKTAG('c','6','0','8')) {
+ if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
mov_write_gmhd_tag(pb, track);
} else {
mov_write_nmhd_tag(pb);
@@ -1929,10 +1983,16 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
if (track->tag == MKTAG('r','t','p',' '))
mov_write_udta_sdp(pb, track);
- if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
- double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
- if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio)
+ if (track->mode == MODE_MOV) {
+ if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
+ if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
+ mov_write_tapt_tag(pb, track);
+ }
+ }
+ if (is_clcp_track(track) && st->sample_aspect_ratio.num) {
mov_write_tapt_tag(pb, track);
+ }
}
return update_size(pb, pos);
}
@@ -2203,7 +2263,9 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
mov_write_string_metadata(s, pb, "\251alb", "album" , 1);
mov_write_string_metadata(s, pb, "\251day", "date" , 1);
- mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
+ if (!mov->exact &&
+ !mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1))
+ mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1);
mov_write_string_metadata(s, pb, "\251gen", "genre" , 1);
mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);
@@ -2219,6 +2281,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
mov_write_int8_metadata (s, pb, "stik", "media_type",1);
mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1);
mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1);
+ mov_write_int8_metadata (s, pb, "cpil", "compilation", 1);
mov_write_trkn_tag(pb, mov, s, 0); // track number
mov_write_trkn_tag(pb, mov, s, 1); // disc number
mov_write_tmpo_tag(pb, s);
@@ -2321,14 +2384,9 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
AVFormatContext *s)
{
AVIOContext *pb_buf;
- int i, ret, size;
+ int ret, size;
uint8_t *buf;
- for (i = 0; i < s->nb_streams; i++)
- if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
- return 0;
- }
-
ret = avio_open_dyn_buf(&pb_buf);
if (ret < 0)
return ret;
@@ -2388,6 +2446,7 @@ static void mov_write_psp_udta_tag(AVIOContext *pb,
static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
{
+ MOVMuxContext *mov = s->priv_data;
AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
int64_t pos, pos2;
@@ -2412,7 +2471,8 @@ static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s)
avio_wb16(pb, 0x0); /* ? */
avio_wb16(pb, 0x021C); /* data */
- mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04);
+ if (!mov->exact)
+ mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04);
mov_write_psp_udta_tag(pb, title->value, "eng", 0x01);
mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03);
@@ -2482,7 +2542,10 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
int src_trk = mov->tracks[i].src_track;
mov->tracks[src_trk].tref_tag = mov->tracks[i].tag;
mov->tracks[src_trk].tref_id = mov->tracks[i].track_id;
- mov->tracks[i].track_duration = mov->tracks[src_trk].track_duration;
+ //src_trk may have a different timescale than the tmcd track
+ mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration,
+ mov->tracks[i].timescale,
+ mov->tracks[src_trk].timescale);
}
}
@@ -2541,7 +2604,8 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
avio_printf(pb, "<head>\n");
- avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
+ if (!mov->exact)
+ avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n",
LIBAVFORMAT_IDENT);
avio_printf(pb, "</head>\n");
avio_printf(pb, "<body>\n");
@@ -2937,7 +3001,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
avio_wb32(pb, 0); /* size */
ffio_wfourcc(pb, "ftyp");
- if (mov->mode == MODE_3GP) {
+ if (mov->major_brand && strlen(mov->major_brand) >= 4)
+ ffio_wfourcc(pb, mov->major_brand);
+ else if (mov->mode == MODE_3GP) {
ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4");
minor = has_h264 ? 0x100 : 0x200;
} else if (mov->mode & MODE_3G2) {
@@ -3255,6 +3321,17 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
int size = pkt->size;
uint8_t *reformatted_data = NULL;
+ if (trk->entry) {
+ int64_t duration = pkt->dts - trk->cluster[trk->entry - 1].dts;
+ if (duration < 0 || duration > INT_MAX) {
+ av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range for mov/mp4 format\n",
+ duration, pkt->dts
+ );
+
+ pkt->dts = trk->cluster[trk->entry - 1].dts + 1;
+ pkt->pts = AV_NOPTS_VALUE;
+ }
+ }
if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
int ret;
if (mov->fragments > 0) {
@@ -3321,6 +3398,15 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
} else {
size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
}
+ } else if (enc->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
+ (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
+ /* extradata is Annex B, assume the bitstream is too and convert it */
+ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
+ ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL);
+ avio_write(pb, reformatted_data, size);
+ } else {
+ size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
+ }
} else {
avio_write(pb, pkt->data, size);
}
@@ -3558,7 +3644,7 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
track->enc->extradata = buf;
track->enc->extradata_size = size;
} else {
- av_free(&buf);
+ av_freep(&buf);
}
}
#endif
@@ -3700,12 +3786,77 @@ static void mov_free(AVFormatContext *s)
av_freep(&mov->tracks);
}
+static uint32_t rgb_to_yuv(uint32_t rgb)
+{
+ uint8_t r, g, b;
+ int y, cb, cr;
+
+ r = (rgb >> 16) & 0xFF;
+ g = (rgb >> 8) & 0xFF;
+ b = (rgb ) & 0xFF;
+
+ y = av_clip_uint8( 16. + 0.257 * r + 0.504 * g + 0.098 * b);
+ cb = av_clip_uint8(128. - 0.148 * r - 0.291 * g + 0.439 * b);
+ cr = av_clip_uint8(128. + 0.439 * r - 0.368 * g - 0.071 * b);
+
+ return (y << 16) | (cr << 8) | cb;
+}
+
+static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
+ AVStream *st)
+{
+ int i, width = 720, height = 480;
+ int have_palette = 0, have_size = 0;
+ uint32_t palette[16];
+ char *cur = st->codec->extradata;
+
+ while (cur && *cur) {
+ if (strncmp("palette:", cur, 8) == 0) {
+ int i, count;
+ count = sscanf(cur + 8,
+ "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
+ "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
+ "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", "
+ "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"",
+ &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3],
+ &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7],
+ &palette[ 8], &palette[ 9], &palette[10], &palette[11],
+ &palette[12], &palette[13], &palette[14], &palette[15]);
+
+ for (i = 0; i < count; i++) {
+ palette[i] = rgb_to_yuv(palette[i]);
+ }
+ have_palette = 1;
+ } else if (!strncmp("size:", cur, 5)) {
+ sscanf(cur + 5, "%dx%d", &width, &height);
+ have_size = 1;
+ }
+ if (have_palette && have_size)
+ break;
+ cur += strcspn(cur, "\n\r");
+ cur += strspn(cur, "\n\r");
+ }
+ if (have_palette) {
+ track->vos_data = av_malloc(16*4);
+ if (!track->vos_data)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < 16; i++) {
+ AV_WB32(track->vos_data + i * 4, palette[i]);
+ }
+ track->vos_len = 16 * 4;
+ }
+ st->codec->width = width;
+ st->codec->height = track->height = height;
+
+ return 0;
+}
+
static int mov_write_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
MOVMuxContext *mov = s->priv_data;
AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
- int i, hint_track = 0, tmcd_track = 0;
+ int i, ret, hint_track = 0, tmcd_track = 0;
/* Default mode == MP4 */
mov->mode = MODE_MP4;
@@ -3720,6 +3871,10 @@ static int mov_write_header(AVFormatContext *s)
else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V;
}
+ for (i = 0; i < s->nb_streams; i++)
+ if (s->flags & AVFMT_FLAG_BITEXACT)
+ mov->exact = 1;
+
/* Set the FRAGMENT flag if any of the fragmentation methods are
* enabled. */
if (mov->max_fragment_duration || mov->max_fragment_size ||
@@ -3745,7 +3900,7 @@ static int mov_write_header(AVFormatContext *s)
}
if (!supports_edts(mov) && s->avoid_negative_ts < 0) {
- s->avoid_negative_ts = 1;
+ s->avoid_negative_ts = 2;
}
/* Non-seekable output is ok if using fragmentation. If ism_lookahead
@@ -3837,8 +3992,10 @@ static int mov_write_header(AVFormatContext *s)
track->mode = mov->mode;
track->tag = mov_find_codec_tag(s, track);
if (!track->tag) {
- av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
- "codec not currently supported in container\n", i);
+ av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
+ "codec not currently supported in container\n",
+ avcodec_get_name(st->codec->codec_id), i);
+ ret = AVERROR(EINVAL);
goto error;
}
/* If hinting of this track is enabled by a later hint track,
@@ -3851,6 +4008,7 @@ static int mov_write_header(AVFormatContext *s)
track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
+ ret = AVERROR(EINVAL);
goto error;
}
track->height = track->tag >> 24 == 'n' ? 486 : 576;
@@ -3877,6 +4035,7 @@ static int mov_write_header(AVFormatContext *s)
st->codec->codec_id == AV_CODEC_ID_ILBC){
if (!st->codec->block_align) {
av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
+ ret = AVERROR(EINVAL);
goto error;
}
track->sample_size = st->codec->block_align;
@@ -3893,6 +4052,7 @@ static int mov_write_header(AVFormatContext *s)
track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
i, track->enc->sample_rate);
+ ret = AVERROR(EINVAL);
goto error;
}
} else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
@@ -3913,21 +4073,18 @@ static int mov_write_header(AVFormatContext *s)
/* copy extradata if it exists */
if (st->codec->extradata_size) {
- track->vos_len = st->codec->extradata_size;
- track->vos_data = av_malloc(track->vos_len);
- memcpy(track->vos_data, st->codec->extradata, track->vos_len);
+ if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+ mov_create_dvd_sub_decoder_specific_info(track, st);
+ else {
+ track->vos_len = st->codec->extradata_size;
+ track->vos_data = av_malloc(track->vos_len);
+ memcpy(track->vos_data, st->codec->extradata, track->vos_len);
+ }
}
}
enable_tracks(s);
- if (mov->mode == MODE_ISM) {
- /* If no fragmentation options have been set, set a default. */
- if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
- FF_MOV_FLAG_FRAG_CUSTOM)) &&
- !mov->max_fragment_duration && !mov->max_fragment_size)
- mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
- }
if (mov->reserved_moov_size){
mov->reserved_moov_pos= avio_tell(pb);
@@ -3935,7 +4092,13 @@ static int mov_write_header(AVFormatContext *s)
avio_skip(pb, mov->reserved_moov_size);
}
- if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
+ if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
+ /* If no fragmentation options have been set, set a default. */
+ if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME |
+ FF_MOV_FLAG_FRAG_CUSTOM)) &&
+ !mov->max_fragment_duration && !mov->max_fragment_size)
+ mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME;
+ } else {
if (mov->flags & FF_MOV_FLAG_FASTSTART)
mov->reserved_moov_pos = avio_tell(pb);
mov_write_mdat_tag(pb, mov);
@@ -3947,7 +4110,7 @@ static int mov_write_header(AVFormatContext *s)
mov->time += 0x7C25B080; // 1970 based -> 1904 based
if (mov->chapter_track)
- if (mov_create_chapter_track(s, mov->chapter_track) < 0)
+ if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0)
goto error;
if (mov->flags & FF_MOV_FLAG_RTP_HINT) {
@@ -3956,7 +4119,7 @@ static int mov_write_header(AVFormatContext *s)
AVStream *st = s->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- if (ff_mov_init_hinting(s, hint_track, i) < 0)
+ if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
goto error;
hint_track++;
}
@@ -3974,7 +4137,7 @@ static int mov_write_header(AVFormatContext *s)
t = av_dict_get(st->metadata, "timecode", NULL, 0);
if (!t)
continue;
- if (mov_create_timecode_track(s, tmcd_track, i, t->value) < 0)
+ if ((ret = mov_create_timecode_track(s, tmcd_track, i, t->value)) < 0)
goto error;
tmcd_track++;
}
@@ -3994,7 +4157,7 @@ static int mov_write_header(AVFormatContext *s)
return 0;
error:
mov_free(s);
- return -1;
+ return ret;
}
static int get_moov_size(AVFormatContext *s)
diff --git a/chromium/third_party/ffmpeg/libavformat/movenc.h b/chromium/third_party/ffmpeg/libavformat/movenc.h
index 09f3ea772c8..fce2d3c9329 100644
--- a/chromium/third_party/ffmpeg/libavformat/movenc.h
+++ b/chromium/third_party/ffmpeg/libavformat/movenc.h
@@ -156,6 +156,7 @@ typedef struct MOVMuxContext {
int flags;
int rtp_flags;
+ int exact;
int iods_skip;
int iods_video_profile;
@@ -173,6 +174,8 @@ typedef struct MOVMuxContext {
int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise
int64_t reserved_moov_pos;
+
+ char *major_brand;
} MOVMuxContext;
#define FF_MOV_FLAG_RTP_HINT 1
diff --git a/chromium/third_party/ffmpeg/libavformat/mp3dec.c b/chromium/third_party/ffmpeg/libavformat/mp3dec.c
index 5d484e9090d..00142c5163c 100644
--- a/chromium/third_party/ffmpeg/libavformat/mp3dec.c
+++ b/chromium/third_party/ffmpeg/libavformat/mp3dec.c
@@ -22,12 +22,16 @@
#include "libavutil/opt.h"
#include "libavutil/avstring.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/crc.h"
#include "libavutil/dict.h"
#include "libavutil/mathematics.h"
#include "avformat.h"
#include "internal.h"
+#include "avio_internal.h"
#include "id3v2.h"
#include "id3v1.h"
+#include "replaygain.h"
+
#include "libavcodec/mpegaudiodecheader.h"
#define XING_FLAG_FRAMES 0x01
@@ -39,11 +43,12 @@
typedef struct {
AVClass *class;
int64_t filesize;
- int64_t header_filesize;
int xing_toc;
int start_pad;
int end_pad;
int usetoc;
+ unsigned frames; /* Total number of frames in file */
+ unsigned header_filesize; /* Total number of bytes in the stream */
int is_cbr;
} MP3DecContext;
@@ -85,10 +90,10 @@ static int mp3_read_probe(AVProbeData *p)
// issues with MPEG-files!
if (first_frames>=4) return AVPROBE_SCORE_EXTENSION + 1;
else if(max_frames>200)return AVPROBE_SCORE_EXTENSION;
- else if(max_frames>=4) return AVPROBE_SCORE_EXTENSION / 2;
+ else if(max_frames>=4 && max_frames >= p->buf_size/10000) return AVPROBE_SCORE_EXTENSION / 2;
else if(ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size)
return p->buf_size < PROBE_BUF_MAX ? AVPROBE_SCORE_EXTENSION / 4 : AVPROBE_SCORE_EXTENSION - 2;
- else if(max_frames>=1) return 1;
+ else if(max_frames>=1 && max_frames >= p->buf_size/10000) return 1;
else return 0;
//mpegps_mp3_unrecognized_format.mpg has max_frames=3
}
@@ -117,19 +122,149 @@ static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration
mp3->xing_toc = 1;
}
+static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st,
+ MPADecodeHeader *c, uint32_t spf)
+{
+#define LAST_BITS(k, n) ((k) & ((1 << (n)) - 1))
+#define MIDDLE_BITS(k, m, n) LAST_BITS((k) >> (m), ((n) - (m)))
+
+ uint16_t crc;
+ uint32_t v;
+
+ char version[10];
+
+ uint32_t peak = 0;
+ int32_t r_gain = INT32_MIN, a_gain = INT32_MIN;
+
+ MP3DecContext *mp3 = s->priv_data;
+ static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
+
+ /* Check for Xing / Info tag */
+ avio_skip(s->pb, xing_offtbl[c->lsf == 1][c->nb_channels == 1]);
+ v = avio_rb32(s->pb);
+ mp3->is_cbr = v == MKBETAG('I', 'n', 'f', 'o');
+ if (v != MKBETAG('X', 'i', 'n', 'g') && !mp3->is_cbr)
+ return;
+
+ v = avio_rb32(s->pb);
+ if (v & XING_FLAG_FRAMES)
+ mp3->frames = avio_rb32(s->pb);
+ if (v & XING_FLAG_SIZE)
+ mp3->header_filesize = avio_rb32(s->pb);
+ if (v & XING_FLAG_TOC)
+ read_xing_toc(s, mp3->header_filesize, av_rescale_q(mp3->frames,
+ (AVRational){spf, c->sample_rate},
+ st->time_base));
+ /* VBR quality */
+ if(v & 8)
+ avio_skip(s->pb, 4);
+
+ /* Encoder short version string */
+ memset(version, 0, sizeof(version));
+ avio_read(s->pb, version, 9);
+
+ /* Info Tag revision + VBR method */
+ avio_r8(s->pb);
+
+ /* Lowpass filter value */
+ avio_r8(s->pb);
+
+ /* ReplayGain peak */
+ v = avio_rb32(s->pb);
+ peak = av_rescale(v, 100000, 1 << 23);
+
+ /* Radio ReplayGain */
+ v = avio_rb16(s->pb);
+
+ if (MIDDLE_BITS(v, 13, 15) == 1) {
+ r_gain = MIDDLE_BITS(v, 0, 8) * 10000;
+
+ if (v & (1 << 9))
+ r_gain *= -1;
+ }
+
+ /* Audiophile ReplayGain */
+ v = avio_rb16(s->pb);
+
+ if (MIDDLE_BITS(v, 13, 15) == 2) {
+ a_gain = MIDDLE_BITS(v, 0, 8) * 10000;
+
+ if (v & (1 << 9))
+ a_gain *= -1;
+ }
+
+ /* Encoding flags + ATH Type */
+ avio_r8(s->pb);
+
+ /* if ABR {specified bitrate} else {minimal bitrate} */
+ avio_r8(s->pb);
+
+ /* Encoder delays */
+ v= avio_rb24(s->pb);
+ if(AV_RB32(version) == MKBETAG('L', 'A', 'M', 'E')
+ || AV_RB32(version) == MKBETAG('L', 'a', 'v', 'f')) {
+
+ mp3->start_pad = v>>12;
+ mp3-> end_pad = v&4095;
+ st->skip_samples = mp3->start_pad + 528 + 1;
+ av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad);
+ }
+
+ /* Misc */
+ avio_r8(s->pb);
+
+ /* MP3 gain */
+ avio_r8(s->pb);
+
+ /* Preset and surround info */
+ avio_rb16(s->pb);
+
+ /* Music length */
+ avio_rb32(s->pb);
+
+ /* Music CRC */
+ avio_rb16(s->pb);
+
+ /* Info Tag CRC */
+ crc = ffio_get_checksum(s->pb);
+ v = avio_rb16(s->pb);
+
+ if (v == crc) {
+ ff_replaygain_export_raw(st, r_gain, peak, a_gain, 0);
+ av_dict_set(&st->metadata, "encoder", version, 0);
+ }
+}
+
+static void mp3_parse_vbri_tag(AVFormatContext *s, AVStream *st, int64_t base)
+{
+ uint32_t v;
+ MP3DecContext *mp3 = s->priv_data;
+
+ /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
+ avio_seek(s->pb, base + 4 + 32, SEEK_SET);
+ v = avio_rb32(s->pb);
+ if (v == MKBETAG('V', 'B', 'R', 'I')) {
+ /* Check tag version */
+ if (avio_rb16(s->pb) == 1) {
+ /* skip delay and quality */
+ avio_skip(s->pb, 4);
+ mp3->header_filesize = avio_rb32(s->pb);
+ mp3->frames = avio_rb32(s->pb);
+ }
+ }
+}
+
/**
* Try to find Xing/Info/VBRI tags and compute duration from info therein
*/
static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
{
- MP3DecContext *mp3 = s->priv_data;
uint32_t v, spf;
- unsigned frames = 0; /* Total number of frames in file */
- unsigned size = 0; /* Total number of bytes in the stream */
- static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
MPADecodeHeader c;
int vbrtag_size = 0;
- int is_cbr;
+ MP3DecContext *mp3 = s->priv_data;
+
+ ffio_init_checksum(s->pb, ff_crcA001_update, 0);
v = avio_rb32(s->pb);
if(ff_mpa_check_header(v) < 0)
@@ -142,60 +277,23 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */
- /* Check for Xing / Info tag */
- avio_skip(s->pb, xing_offtbl[c.lsf == 1][c.nb_channels == 1]);
- v = avio_rb32(s->pb);
- is_cbr = v == MKBETAG('I', 'n', 'f', 'o');
- if (v == MKBETAG('X', 'i', 'n', 'g') || is_cbr) {
- v = avio_rb32(s->pb);
- if(v & XING_FLAG_FRAMES)
- frames = avio_rb32(s->pb);
- if(v & XING_FLAG_SIZE)
- size = avio_rb32(s->pb);
- if (v & XING_FLAG_TOC)
- read_xing_toc(s, size, av_rescale_q(frames, (AVRational){spf, c.sample_rate},
- st->time_base));
- if(v & 8)
- avio_skip(s->pb, 4);
-
- v = avio_rb32(s->pb);
- if(v == MKBETAG('L', 'A', 'M', 'E') || v == MKBETAG('L', 'a', 'v', 'f')) {
- avio_skip(s->pb, 21-4);
- v= avio_rb24(s->pb);
- mp3->start_pad = v>>12;
- mp3-> end_pad = v&4095;
- st->skip_samples = mp3->start_pad + 528 + 1;
- av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad);
- }
- }
+ mp3->frames = 0;
+ mp3->header_filesize = 0;
- /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
- avio_seek(s->pb, base + 4 + 32, SEEK_SET);
- v = avio_rb32(s->pb);
- if(v == MKBETAG('V', 'B', 'R', 'I')) {
- /* Check tag version */
- if(avio_rb16(s->pb) == 1) {
- /* skip delay and quality */
- avio_skip(s->pb, 4);
- size = avio_rb32(s->pb);
- frames = avio_rb32(s->pb);
- }
- }
+ mp3_parse_info_tag(s, st, &c, spf);
+ mp3_parse_vbri_tag(s, st, base);
- if(!frames && !size)
+ if (!mp3->frames && !mp3->header_filesize)
return -1;
/* Skip the vbr tag frame */
avio_seek(s->pb, base + vbrtag_size, SEEK_SET);
- if(frames)
- st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},
+ if (mp3->frames)
+ st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate},
st->time_base);
- if (size && frames && !is_cbr)
- st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf);
-
- mp3->is_cbr = is_cbr;
- mp3->header_filesize = size;
+ if (mp3->header_filesize && mp3->frames && !mp3->is_cbr)
+ st->codec->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
return 0;
}
@@ -205,6 +303,7 @@ static int mp3_read_header(AVFormatContext *s)
MP3DecContext *mp3 = s->priv_data;
AVStream *st;
int64_t off;
+ int ret;
st = avformat_new_stream(s, NULL);
if (!st)
@@ -230,6 +329,10 @@ static int mp3_read_header(AVFormatContext *s)
if (mp3_parse_vbr_tags(s, st, off) < 0)
avio_seek(s->pb, off, SEEK_SET);
+ ret = ff_replaygain_export(st, s->metadata);
+ if (ret < 0)
+ return ret;
+
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -314,6 +417,8 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp,
return -1;
}
+ if (dir < 0)
+ avio_seek(s->pb, FFMAX(ie->pos - 4096, 0), SEEK_SET);
ret = avio_seek(s->pb, ie->pos, SEEK_SET);
if (ret < 0)
return ret;
diff --git a/chromium/third_party/ffmpeg/libavformat/mp3enc.c b/chromium/third_party/ffmpeg/libavformat/mp3enc.c
index a5f672b2577..9c9bd5e8626 100644
--- a/chromium/third_party/ffmpeg/libavformat/mp3enc.c
+++ b/chromium/third_party/ffmpeg/libavformat/mp3enc.c
@@ -85,6 +85,7 @@ typedef struct MP3Context {
ID3v2EncContext id3;
int id3v2_version;
int write_id3v1;
+ int write_xing;
/* xing header */
int64_t xing_offset;
@@ -115,17 +116,18 @@ static int mp3_write_xing(AVFormatContext *s)
{
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;
- int xing_offset;
- int32_t header, mask;
- MPADecodeHeader c;
- int srate_idx, ver = 0, i, channels;
- int needed;
- const char *vendor = (codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT;
-
- if (!s->pb->seekable)
+ int32_t header;
+ MPADecodeHeader mpah;
+ int srate_idx, i, channels;
+ int bitrate_idx;
+ int best_bitrate_idx = -1;
+ int best_bitrate_error = INT_MAX;
+ int xing_offset;
+ int ver = 0;
+ int bytes_needed;
+ const char *vendor = (codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT;
+
+ if (!s->pb->seekable || !mp3->write_xing)
return 0;
for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) {
@@ -155,28 +157,29 @@ static int mp3_write_xing(AVFormatContext *s)
/* dummy MPEG audio header */
header = 0xffU << 24; // sync
header |= (0x7 << 5 | ver << 3 | 0x1 << 1 | 0x1) << 16; // sync/audio-version/layer 3/no crc*/
- header |= (srate_idx << 2) << 8;
+ header |= (srate_idx << 2) << 8;
header |= channels << 6;
- for (bitrate_idx=1; bitrate_idx<15; bitrate_idx++) {
- int error;
- avpriv_mpegaudio_decode_header(&c, header | (bitrate_idx << (4+8)));
- error= FFABS(c.bit_rate - codec->bit_rate);
- if(error < best_bitrate_error){
- best_bitrate_error= error;
- best_bitrate_idx = bitrate_idx;
+ for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) {
+ int bit_rate = 1000 * avpriv_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx];
+ int error = FFABS(bit_rate - codec->bit_rate);
+
+ if (error < best_bitrate_error) {
+ best_bitrate_error = error;
+ best_bitrate_idx = bitrate_idx;
}
}
av_assert0(best_bitrate_idx >= 0);
- for (bitrate_idx= best_bitrate_idx;; bitrate_idx++) {
+ for (bitrate_idx = best_bitrate_idx; ; bitrate_idx++) {
+ int32_t mask = bitrate_idx << (4 + 8);
if (15 == bitrate_idx)
return -1;
- mask = bitrate_idx << (4+8);
header |= mask;
- avpriv_mpegaudio_decode_header(&c, header);
- xing_offset=xing_offtbl[c.lsf == 1][c.nb_channels == 1];
- needed = 4 // header
+
+ avpriv_mpegaudio_decode_header(&mpah, header);
+ xing_offset=xing_offtbl[mpah.lsf == 1][mpah.nb_channels == 1];
+ bytes_needed = 4 // header
+ xing_offset
+ 4 // xing tag
+ 4 // frames/size/toc flags
@@ -186,8 +189,9 @@ static int mp3_write_xing(AVFormatContext *s)
+ 24
;
- if (needed <= c.frame_size)
+ if (bytes_needed <= mpah.frame_size)
break;
+
header &= ~mask;
}
@@ -198,7 +202,7 @@ static int mp3_write_xing(AVFormatContext *s)
ffio_wfourcc(s->pb, "Xing");
avio_wb32(s->pb, 0x01 | 0x02 | 0x04); // frames / size / TOC
- mp3->size = c.frame_size;
+ mp3->size = mpah.frame_size;
mp3->want=1;
mp3->seen=0;
mp3->pos=0;
@@ -216,7 +220,7 @@ static int mp3_write_xing(AVFormatContext *s)
avio_w8(s->pb, 0);
avio_wb24(s->pb, FFMAX(codec->delay - 528 - 1, 0)<<12);
- ffio_fill(s->pb, 0, c.frame_size - needed);
+ ffio_fill(s->pb, 0, mpah.frame_size - bytes_needed);
return 0;
}
@@ -256,7 +260,7 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt)
MP3Context *mp3 = s->priv_data;
if (pkt->data && pkt->size >= 4) {
- MPADecodeHeader c;
+ MPADecodeHeader mpah;
int av_unused base;
uint32_t head = AV_RB32(pkt->data);
@@ -265,16 +269,16 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt)
"is invalid, writing it anyway.\n", pkt->size, head);
return ff_raw_write_packet(s, pkt);
}
- avpriv_mpegaudio_decode_header(&c, head);
+ avpriv_mpegaudio_decode_header(&mpah, head);
if (!mp3->initial_bitrate)
- mp3->initial_bitrate = c.bit_rate;
- if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate))
+ mp3->initial_bitrate = mpah.bit_rate;
+ if ((mpah.bit_rate == 0) || (mp3->initial_bitrate != mpah.bit_rate))
mp3->has_variable_bitrate = 1;
#ifdef FILTER_VBR_HEADERS
/* filter out XING and INFO headers. */
- base = 4 + xing_offtbl[c.lsf == 1][c.nb_channels == 1];
+ base = 4 + xing_offtbl[mpah.lsf == 1][mpah.nb_channels == 1];
if (base + 4 <= pkt->size) {
uint32_t v = AV_RB32(pkt->data + base);
@@ -303,7 +307,7 @@ static int mp3_queue_flush(AVFormatContext *s)
AVPacketList *pktl;
int ret = 0, write = 1;
- ff_id3v2_finish(&mp3->id3, s->pb);
+ ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding);
mp3_write_xing(s);
while ((pktl = mp3->queue)) {
@@ -393,9 +397,11 @@ AVOutputFormat ff_mp2_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, {.i64 = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM},
+ offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.i64 = 4}, 0, 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, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
+ { "write_xing", "Write the Xing header containing file duration.",
+ offsetof(MP3Context, write_xing), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL },
};
@@ -414,14 +420,14 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
if (mp3->pics_to_write) {
/* buffer audio packets until we get all the pictures */
AVPacketList *pktl = av_mallocz(sizeof(*pktl));
+ int ret;
if (!pktl)
return AVERROR(ENOMEM);
- pktl->pkt = *pkt;
- pktl->pkt.buf = av_buffer_ref(pkt->buf);
- if (!pktl->pkt.buf) {
+ ret = av_copy_packet(&pktl->pkt, pkt);
+ if (ret < 0) {
av_freep(&pktl);
- return AVERROR(ENOMEM);
+ return ret;
}
if (mp3->queue_end)
@@ -464,6 +470,14 @@ static int mp3_write_header(struct AVFormatContext *s)
MP3Context *mp3 = s->priv_data;
int ret, i;
+ if (mp3->id3v2_version &&
+ mp3->id3v2_version != 3 &&
+ mp3->id3v2_version != 4) {
+ av_log(s, AV_LOG_ERROR, "Invalid ID3v2 version requested: %d. Only "
+ "3, 4 or 0 (disabled) are allowed.\n", mp3->id3v2_version);
+ return AVERROR(EINVAL);
+ }
+
/* check the streams -- we want exactly one audio and arbitrary number of
* video (attached pictures) */
mp3->audio_stream_idx = -1;
@@ -487,13 +501,22 @@ static int mp3_write_header(struct AVFormatContext *s)
}
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 && !mp3->id3v2_version) {
+ av_log(s, AV_LOG_ERROR, "Attached pictures were requested, but the "
+ "ID3v2 header is disabled.\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (mp3->id3v2_version) {
+ 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);
+ if (mp3->id3v2_version)
+ ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding);
mp3_write_xing(s);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mpc.c b/chromium/third_party/ffmpeg/libavformat/mpc.c
index 8abc4885536..c3faebe6c07 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpc.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpc.c
@@ -95,9 +95,8 @@ static int mpc_read_header(AVFormatContext *s)
st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
st->codec->bits_per_coded_sample = 16;
- if (ff_alloc_extradata(st->codec, 16))
+ if (ff_get_extradata(st->codec, s->pb, 16) < 0)
return AVERROR(ENOMEM);
- avio_read(s->pb, st->codec->extradata, 16);
st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3];
avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate);
/* scan for seekpoints */
diff --git a/chromium/third_party/ffmpeg/libavformat/mpc8.c b/chromium/third_party/ffmpeg/libavformat/mpc8.c
index 7017c187f77..b32bc9c3546 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpc8.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpc8.c
@@ -136,7 +136,7 @@ static void mpc8_parse_seektable(AVFormatContext *s, int64_t off)
int tag;
int64_t size, pos, ppos[2];
uint8_t *buf;
- int i, t, seekd;
+ int i, t, seekd, ret;
GetBitContext gb;
if (s->nb_streams == 0) {
@@ -156,7 +156,14 @@ static void mpc8_parse_seektable(AVFormatContext *s, int64_t off)
}
if(!(buf = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE)))
return;
- avio_read(s->pb, buf, size);
+ ret = avio_read(s->pb, buf, size);
+ if (ret != size) {
+ av_log(s, AV_LOG_ERROR, "seek table truncated\n");
+ av_free(buf);
+ return;
+ }
+ memset(buf+size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
init_get_bits(&gb, buf, size * 8);
size = gb_get_v(&gb);
if(size > UINT_MAX/4 || size > c->samples/1152){
@@ -241,9 +248,8 @@ static int mpc8_read_header(AVFormatContext *s)
st->codec->codec_id = AV_CODEC_ID_MUSEPACK8;
st->codec->bits_per_coded_sample = 16;
- if (ff_alloc_extradata(st->codec, 2))
+ if (ff_get_extradata(st->codec, pb, 2) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, st->codec->extradata_size);
st->codec->channels = (st->codec->extradata[1] >> 4) + 1;
st->codec->sample_rate = mpc8_rate[st->codec->extradata[0] >> 5];
diff --git a/chromium/third_party/ffmpeg/libavformat/mpeg.c b/chromium/third_party/ffmpeg/libavformat/mpeg.c
index 1777283939c..d70a5ab9beb 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpeg.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpeg.c
@@ -37,74 +37,85 @@
#define MAX_SYNC_SIZE 100000
-static int check_pes(const uint8_t *p, const uint8_t *end){
+static int check_pes(const uint8_t *p, const uint8_t *end)
+{
int pes1;
- int pes2= (p[3] & 0xC0) == 0x80
- && (p[4] & 0xC0) != 0x40
- &&((p[4] & 0xC0) == 0x00 || (p[4]&0xC0)>>2 == (p[6]&0xF0));
-
- for(p+=3; p<end && *p == 0xFF; p++);
- if((*p&0xC0) == 0x40) p+=2;
- if((*p&0xF0) == 0x20){
- pes1= p[0]&p[2]&p[4]&1;
- }else if((*p&0xF0) == 0x30){
- pes1= p[0]&p[2]&p[4]&p[5]&p[7]&p[9]&1;
- }else
+ int pes2 = (p[3] & 0xC0) == 0x80 &&
+ (p[4] & 0xC0) != 0x40 &&
+ ((p[4] & 0xC0) == 0x00 ||
+ (p[4] & 0xC0) >> 2 == (p[6] & 0xF0));
+
+ for (p += 3; p < end && *p == 0xFF; p++) ;
+ if ((*p & 0xC0) == 0x40)
+ p += 2;
+
+ if ((*p & 0xF0) == 0x20)
+ pes1 = p[0] & p[2] & p[4] & 1;
+ else if ((*p & 0xF0) == 0x30)
+ pes1 = p[0] & p[2] & p[4] & p[5] & p[7] & p[9] & 1;
+ else
pes1 = *p == 0x0F;
- return pes1||pes2;
+ return pes1 || pes2;
}
-static int check_pack_header(const uint8_t *buf) {
+static int check_pack_header(const uint8_t *buf)
+{
return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20;
}
static int mpegps_probe(AVProbeData *p)
{
- uint32_t code= -1;
- int sys=0, pspack=0, priv1=0, vid=0, audio=0, invalid=0;
+ uint32_t code = -1;
int i;
- int score=0;
+ int sys = 0, pspack = 0, priv1 = 0, vid = 0;
+ int audio = 0, invalid = 0, score = 0;
- for(i=0; i<p->buf_size; i++){
- code = (code<<8) + p->buf[i];
+ for (i = 0; i < p->buf_size; i++) {
+ code = (code << 8) + p->buf[i];
if ((code & 0xffffff00) == 0x100) {
- int len= p->buf[i+1] << 8 | p->buf[i+2];
- int pes= check_pes(p->buf+i, p->buf+p->buf_size);
- int pack = check_pack_header(p->buf+i);
-
- if(code == SYSTEM_HEADER_START_CODE) sys++;
- else if(code == PACK_START_CODE && pack) pspack++;
- else if((code & 0xf0) == VIDEO_ID && pes) vid++;
+ int len = p->buf[i + 1] << 8 | p->buf[i + 2];
+ int pes = check_pes(p->buf + i, p->buf + p->buf_size);
+ int pack = check_pack_header(p->buf + i);
+
+ if (code == SYSTEM_HEADER_START_CODE)
+ sys++;
+ else if (code == PACK_START_CODE && pack)
+ pspack++;
+ else if ((code & 0xf0) == VIDEO_ID && pes)
+ vid++;
// skip pes payload to avoid start code emulation for private
// and audio streams
- else if((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;}
- else if(code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;}
- else if(code == 0x1fd && pes) vid++; //VC1
+ else if ((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;}
+ else if (code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;}
+ else if (code == 0x1fd && pes) vid++; //VC1
- else if((code & 0xf0) == VIDEO_ID && !pes) invalid++;
- else if((code & 0xe0) == AUDIO_ID && !pes) invalid++;
- else if(code == PRIVATE_STREAM_1 && !pes) invalid++;
+ else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++;
+ else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++;
+ else if (code == PRIVATE_STREAM_1 && !pes) invalid++;
}
}
- if(vid+audio > invalid+1) /* invalid VDR files nd short PES streams */
+ if (vid + audio > invalid + 1) /* invalid VDR files nd short PES streams */
score = AVPROBE_SCORE_EXTENSION / 2;
- if(sys>invalid && sys*9 <= pspack*10)
- return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg
- if(pspack > invalid && (priv1+vid+audio)*10 >= pspack*9)
- return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg
- if((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && !pspack && p->buf_size>2048 && vid + audio > invalid) /* PES stream */
- return (audio > 12 || vid > 3 + 2*invalid) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2;
-
- //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
- //mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6
- //Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618
+ if (sys > invalid && sys * 9 <= pspack * 10)
+ return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2
+ : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg
+ if (pspack > invalid && (priv1 + vid + audio) * 10 >= pspack * 9)
+ return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2
+ : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg
+ if ((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys &&
+ !pspack && p->buf_size > 2048 && vid + audio > invalid) /* PES stream */
+ return (audio > 12 || vid > 3 + 2 * invalid) ? AVPROBE_SCORE_EXTENSION + 2
+ : AVPROBE_SCORE_EXTENSION / 2;
+
+ // 02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
+ // mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6
+ // Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618
return score;
}
-
typedef struct MpegDemuxContext {
int32_t header_state;
unsigned char psm_es_type[256];
@@ -124,7 +135,7 @@ static int mpegps_read_header(AVFormatContext *s)
int64_t last_pos = avio_tell(s->pb);
m->header_state = 0xff;
- s->ctx_flags |= AVFMTCTX_NOHEADER;
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
avio_get_str(s->pb, 6, buffer, sizeof(buffer));
if (!memcmp("IMKH", buffer, 4)) {
@@ -142,8 +153,8 @@ static int64_t get_pts(AVIOContext *pb, int c)
{
uint8_t buf[5];
- buf[0] = c<0 ? avio_r8(pb) : c;
- avio_read(pb, buf+1, 4);
+ buf[0] = c < 0 ? avio_r8(pb) : c;
+ avio_read(pb, buf + 1, 4);
return ff_parse_pes_pts(buf);
}
@@ -155,7 +166,7 @@ static int find_next_start_code(AVIOContext *pb, int *size_ptr,
int val, n;
state = *header_state;
- n = *size_ptr;
+ n = *size_ptr;
while (n > 0) {
if (url_feof(pb))
break;
@@ -163,15 +174,16 @@ static int find_next_start_code(AVIOContext *pb, int *size_ptr,
n--;
if (state == 0x000001) {
state = ((state << 8) | v) & 0xffffff;
- val = state;
+ val = state;
goto found;
}
state = ((state << 8) | v) & 0xffffff;
}
val = -1;
- found:
+
+found:
*header_state = state;
- *size_ptr = n;
+ *size_ptr = n;
return val;
}
@@ -197,10 +209,11 @@ static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb)
es_map_length = psm_length - ps_info_length - 10;
/* at least one es available? */
- while (es_map_length >= 4){
+ while (es_map_length >= 4) {
unsigned char type = avio_r8(pb);
unsigned char es_id = avio_r8(pb);
uint16_t es_info_length = avio_rb16(pb);
+
/* remember mapping from stream id to stream type */
m->psm_es_type[es_id] = type;
/* skip program_stream_info */
@@ -212,7 +225,7 @@ static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb)
}
/* read the next PES header. Return its position in ppos
- (if not NULL), and its start code, pts and dts.
+ * (if not NULL), and its start code, pts and dts.
*/
static int mpegps_read_pes_header(AVFormatContext *s,
int64_t *ppos, int *pstart_code,
@@ -222,20 +235,20 @@ static int mpegps_read_pes_header(AVFormatContext *s,
int len, size, startcode, c, flags, header_len;
int pes_ext, ext2_len, id_ext, skip;
int64_t pts, dts;
- int64_t last_sync= avio_tell(s->pb);
-
- error_redo:
- avio_seek(s->pb, last_sync, SEEK_SET);
- redo:
- /* next start code (should be immediately after) */
- m->header_state = 0xff;
- size = MAX_SYNC_SIZE;
- startcode = find_next_start_code(s->pb, &size, &m->header_state);
- last_sync = avio_tell(s->pb);
- if (startcode < 0){
- if(url_feof(s->pb))
+ int64_t last_sync = avio_tell(s->pb);
+
+error_redo:
+ avio_seek(s->pb, last_sync, SEEK_SET);
+redo:
+ /* next start code (should be immediately after) */
+ m->header_state = 0xff;
+ size = MAX_SYNC_SIZE;
+ startcode = find_next_start_code(s->pb, &size, &m->header_state);
+ last_sync = avio_tell(s->pb);
+ if (startcode < 0) {
+ if (url_feof(s->pb))
return AVERROR_EOF;
- //FIXME we should remember header_state
+ // FIXME we should remember header_state
return AVERROR(EAGAIN);
}
@@ -346,7 +359,7 @@ static int mpegps_read_pes_header(AVFormatContext *s,
if (startcode != PRIVATE_STREAM_2)
{
/* stuffing */
- for(;;) {
+ for (;;) {
if (len < 1)
goto error_redo;
c = avio_r8(s->pb);
@@ -358,45 +371,47 @@ static int mpegps_read_pes_header(AVFormatContext *s,
if ((c & 0xc0) == 0x40) {
/* buffer scale & size */
avio_r8(s->pb);
- c = avio_r8(s->pb);
+ c = avio_r8(s->pb);
len -= 2;
}
if ((c & 0xe0) == 0x20) {
- dts = pts = get_pts(s->pb, c);
+ dts =
+ pts = get_pts(s->pb, c);
len -= 4;
- if (c & 0x10){
- dts = get_pts(s->pb, -1);
+ if (c & 0x10) {
+ dts = get_pts(s->pb, -1);
len -= 5;
}
} else if ((c & 0xc0) == 0x80) {
/* mpeg 2 PES */
- flags = avio_r8(s->pb);
+ flags = avio_r8(s->pb);
header_len = avio_r8(s->pb);
- len -= 2;
+ len -= 2;
if (header_len > len)
goto error_redo;
len -= header_len;
if (flags & 0x80) {
- dts = pts = get_pts(s->pb, -1);
+ dts = pts = get_pts(s->pb, -1);
header_len -= 5;
if (flags & 0x40) {
- dts = get_pts(s->pb, -1);
+ dts = get_pts(s->pb, -1);
header_len -= 5;
}
}
- if (flags & 0x3f && header_len == 0){
+ if (flags & 0x3f && header_len == 0) {
flags &= 0xC0;
av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n");
}
if (flags & 0x01) { /* PES extension */
pes_ext = avio_r8(s->pb);
header_len--;
- /* Skip PES private data, program packet sequence counter and P-STD buffer */
- skip = (pes_ext >> 4) & 0xb;
+ /* Skip PES private data, program packet sequence counter
+ * and P-STD buffer */
+ skip = (pes_ext >> 4) & 0xb;
skip += skip & 0x9;
- if (pes_ext & 0x40 || skip > header_len){
+ if (pes_ext & 0x40 || skip > header_len) {
av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext);
- pes_ext=skip=0;
+ pes_ext = skip = 0;
}
avio_skip(s->pb, skip);
header_len -= skip;
@@ -412,11 +427,10 @@ static int mpegps_read_pes_header(AVFormatContext *s,
}
}
}
- if(header_len < 0)
+ if (header_len < 0)
goto error_redo;
avio_skip(s->pb, header_len);
- }
- else if( c!= 0xf )
+ } else if (c != 0xf)
goto redo;
}
@@ -424,22 +438,23 @@ static int mpegps_read_pes_header(AVFormatContext *s,
startcode = avio_r8(s->pb);
len--;
}
- if(len<0)
+ if (len < 0)
goto error_redo;
- if(dts != AV_NOPTS_VALUE && ppos){
+ if (dts != AV_NOPTS_VALUE && ppos) {
int i;
- for(i=0; i<s->nb_streams; i++){
- if(startcode == s->streams[i]->id &&
- s->pb->seekable /* index useless on streams anyway */) {
+ for (i = 0; i < s->nb_streams; i++) {
+ if (startcode == s->streams[i]->id &&
+ s->pb->seekable /* index useless on streams anyway */) {
ff_reduce_index(s, i);
- av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
+ av_add_index_entry(s->streams[i], *ppos, dts, 0, 0,
+ AVINDEX_KEYFRAME /* FIXME keyframe? */);
}
}
}
*pstart_code = startcode;
- *ppts = pts;
- *pdts = dts;
+ *ppts = pts;
+ *pdts = dts;
return len;
}
@@ -453,15 +468,15 @@ static int mpegps_read_packet(AVFormatContext *s,
int request_probe= 0;
enum AVCodecID codec_id = AV_CODEC_ID_NONE;
enum AVMediaType type;
- int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work
+ int64_t pts, dts, dummy_pos; // dummy_pos is needed for the index building to work
- redo:
+redo:
len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts);
if (len < 0)
return len;
if (startcode >= 0x80 && startcode <= 0xcf) {
- if(len < 4)
+ if (len < 4)
goto skip;
/* audio: skip header */
@@ -476,44 +491,45 @@ static int mpegps_read_packet(AVFormatContext *s,
}
/* now find stream */
- for(i=0;i<s->nb_streams;i++) {
+ for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->id == startcode)
goto found;
}
es_type = m->psm_es_type[startcode & 0xff];
- if(es_type == STREAM_TYPE_VIDEO_MPEG1){
+ if (es_type == STREAM_TYPE_VIDEO_MPEG1) {
codec_id = AV_CODEC_ID_MPEG2VIDEO;
- type = AVMEDIA_TYPE_VIDEO;
- } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){
+ type = AVMEDIA_TYPE_VIDEO;
+ } else if (es_type == STREAM_TYPE_VIDEO_MPEG2) {
codec_id = AV_CODEC_ID_MPEG2VIDEO;
- type = AVMEDIA_TYPE_VIDEO;
- } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 ||
- es_type == STREAM_TYPE_AUDIO_MPEG2){
+ type = AVMEDIA_TYPE_VIDEO;
+ } else if (es_type == STREAM_TYPE_AUDIO_MPEG1 ||
+ es_type == STREAM_TYPE_AUDIO_MPEG2) {
codec_id = AV_CODEC_ID_MP3;
- type = AVMEDIA_TYPE_AUDIO;
- } else if(es_type == STREAM_TYPE_AUDIO_AAC){
+ type = AVMEDIA_TYPE_AUDIO;
+ } else if (es_type == STREAM_TYPE_AUDIO_AAC) {
codec_id = AV_CODEC_ID_AAC;
- type = AVMEDIA_TYPE_AUDIO;
- } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){
+ type = AVMEDIA_TYPE_AUDIO;
+ } else if (es_type == STREAM_TYPE_VIDEO_MPEG4) {
codec_id = AV_CODEC_ID_MPEG4;
- type = AVMEDIA_TYPE_VIDEO;
- } else if(es_type == STREAM_TYPE_VIDEO_H264){
+ type = AVMEDIA_TYPE_VIDEO;
+ } else if (es_type == STREAM_TYPE_VIDEO_H264) {
codec_id = AV_CODEC_ID_H264;
- type = AVMEDIA_TYPE_VIDEO;
- } else if(es_type == STREAM_TYPE_AUDIO_AC3){
+ type = AVMEDIA_TYPE_VIDEO;
+ } else if (es_type == STREAM_TYPE_AUDIO_AC3) {
codec_id = AV_CODEC_ID_AC3;
- type = AVMEDIA_TYPE_AUDIO;
- } else if(m->imkh_cctv && es_type == 0x91){
+ type = AVMEDIA_TYPE_AUDIO;
+ } else if (m->imkh_cctv && es_type == 0x91) {
codec_id = AV_CODEC_ID_PCM_MULAW;
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
} else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 };
unsigned char buf[8];
+
avio_read(s->pb, buf, 8);
avio_seek(s->pb, -8, SEEK_CUR);
- if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
+ if (!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
codec_id = AV_CODEC_ID_CAVS;
else
request_probe= 1;
@@ -522,7 +538,7 @@ static int mpegps_read_packet(AVFormatContext *s,
type = AVMEDIA_TYPE_DATA;
codec_id = AV_CODEC_ID_DVD_NAV;
} else if (startcode >= 0x1c0 && startcode <= 0x1df) {
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
if (m->sofdec > 0) {
codec_id = AV_CODEC_ID_ADPCM_ADX;
// Auto-detect AC-3
@@ -531,35 +547,35 @@ static int mpegps_read_packet(AVFormatContext *s,
codec_id = AV_CODEC_ID_MP2;
}
} else if (startcode >= 0x80 && startcode <= 0x87) {
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
codec_id = AV_CODEC_ID_AC3;
- } else if ( ( startcode >= 0x88 && startcode <= 0x8f)
- ||( startcode >= 0x98 && startcode <= 0x9f)) {
+ } else if ((startcode >= 0x88 && startcode <= 0x8f) ||
+ (startcode >= 0x98 && startcode <= 0x9f)) {
/* 0x90 - 0x97 is reserved for SDDS in DVD specs */
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
codec_id = AV_CODEC_ID_DTS;
} else if (startcode >= 0xa0 && startcode <= 0xaf) {
- type = AVMEDIA_TYPE_AUDIO;
- if(lpcm_header_len == 6) {
+ type = AVMEDIA_TYPE_AUDIO;
+ if (lpcm_header_len == 6) {
codec_id = AV_CODEC_ID_MLP;
} else {
codec_id = AV_CODEC_ID_PCM_DVD;
}
} else if (startcode >= 0xb0 && startcode <= 0xbf) {
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
codec_id = AV_CODEC_ID_TRUEHD;
} else if (startcode >= 0xc0 && startcode <= 0xcf) {
/* Used for both AC-3 and E-AC-3 in EVOB files */
- type = AVMEDIA_TYPE_AUDIO;
+ type = AVMEDIA_TYPE_AUDIO;
codec_id = AV_CODEC_ID_AC3;
} else if (startcode >= 0x20 && startcode <= 0x3f) {
- type = AVMEDIA_TYPE_SUBTITLE;
+ type = AVMEDIA_TYPE_SUBTITLE;
codec_id = AV_CODEC_ID_DVD_SUBTITLE;
} else if (startcode >= 0xfd55 && startcode <= 0xfd5f) {
- type = AVMEDIA_TYPE_VIDEO;
+ type = AVMEDIA_TYPE_VIDEO;
codec_id = AV_CODEC_ID_VC1;
} else {
- skip:
+skip:
/* skip packet */
avio_skip(s->pb, len);
goto redo;
@@ -568,18 +584,19 @@ static int mpegps_read_packet(AVFormatContext *s,
st = avformat_new_stream(s, NULL);
if (!st)
goto skip;
- st->id = startcode;
+ st->id = startcode;
st->codec->codec_type = type;
- st->codec->codec_id = codec_id;
+ st->codec->codec_id = codec_id;
if (st->codec->codec_id == AV_CODEC_ID_PCM_MULAW) {
st->codec->channels = 1;
st->codec->channel_layout = AV_CH_LAYOUT_MONO;
st->codec->sample_rate = 8000;
}
st->request_probe = request_probe;
- st->need_parsing = AVSTREAM_PARSE_FULL;
- found:
- if(st->discard >= AVDISCARD_ALL)
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+
+found:
+ if (st->discard >= AVDISCARD_ALL)
goto skip;
if (startcode >= 0xa0 && startcode <= 0xaf) {
if (lpcm_header_len == 6 && st->codec->codec_id == AV_CODEC_ID_MLP) {
@@ -590,9 +607,10 @@ static int mpegps_read_packet(AVFormatContext *s,
}
}
ret = av_get_packet(s->pb, pkt, len);
- pkt->pts = pts;
- pkt->dts = dts;
- pkt->pos = dummy_pos;
+
+ pkt->pts = pts;
+ pkt->dts = dts;
+ pkt->pos = dummy_pos;
pkt->stream_index = st->index;
av_dlog(s, "%d: pts=%0.3f dts=%0.3f size=%d\n",
pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0,
@@ -611,7 +629,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
if (avio_seek(s->pb, pos, SEEK_SET) < 0)
return AV_NOPTS_VALUE;
- for(;;) {
+ for (;;) {
len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts);
if (len < 0) {
av_dlog(s, "none (ret=%d)\n", len);
@@ -739,7 +757,7 @@ static int vobsub_read_header(AVFormatContext *s)
break;
}
timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay;
- timestamp = av_rescale_q(timestamp, (AVRational){1,1000}, st->time_base);
+ timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base);
sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 0, 0);
if (!sub) {
@@ -810,8 +828,6 @@ end:
return ret;
}
-#define FAIL(r) do { ret = r; goto fail; } while (0)
-
static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MpegDemuxContext *vobsub = s->priv_data;
@@ -860,7 +876,7 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
if (ret < 0) {
if (pkt->size) // raise packet even if incomplete
break;
- FAIL(ret);
+ goto fail;
}
to_read = ret & 0xffff;
new_pos = avio_tell(pb);
@@ -877,7 +893,7 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
ret = av_grow_packet(pkt, to_read);
if (ret < 0)
- FAIL(ret);
+ goto fail;
n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read);
if (n < to_read)
diff --git a/chromium/third_party/ffmpeg/libavformat/mpeg.h b/chromium/third_party/ffmpeg/libavformat/mpeg.h
index cf10d6a4c40..55f9e0cb51b 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpeg.h
+++ b/chromium/third_party/ffmpeg/libavformat/mpeg.h
@@ -57,7 +57,6 @@
#define STREAM_TYPE_VIDEO_CAVS 0x42
#define STREAM_TYPE_AUDIO_AC3 0x81
-#define STREAM_TYPE_AUDIO_DTS 0x8a
static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };
diff --git a/chromium/third_party/ffmpeg/libavformat/mpegenc.c b/chromium/third_party/ffmpeg/libavformat/mpegenc.c
index ccf3ec21f7a..5521f48cee4 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpegenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpegenc.c
@@ -387,7 +387,9 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
if (st->codec->rc_buffer_size)
stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8;
else {
- av_log(ctx, AV_LOG_WARNING, "VBV buffer size not set, muxing may fail\n");
+ av_log(ctx, AV_LOG_WARNING, "VBV buffer size not set, using default size of 130KB\n"
+ "If you want the mpeg file to be compliant to some specification\n"
+ "Like DVD, VCD or others, make sure you set the correct buffer size\n");
stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default
}
if (stream->max_buffer_size > 1024 * 8191) {
@@ -1157,7 +1159,7 @@ static int mpeg_mux_end(AVFormatContext *ctx)
stream = ctx->streams[i]->priv_data;
assert(av_fifo_size(stream->fifo) == 0);
- av_fifo_free(stream->fifo);
+ av_fifo_freep(&stream->fifo);
}
return 0;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mpegts.c b/chromium/third_party/ffmpeg/libavformat/mpegts.c
index d67c63a4de2..0a5ac689614 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpegts.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpegts.c
@@ -29,7 +29,6 @@
#include "libavutil/avassert.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/get_bits.h"
-#include "libavcodec/mathops.h"
#include "avformat.h"
#include "mpegts.h"
#include "internal.h"
@@ -39,37 +38,46 @@
#include "isom.h"
/* maximum size in which we look for synchronisation if
- synchronisation is lost */
+ * synchronisation is lost */
#define MAX_RESYNC_SIZE 65536
-#define MAX_PES_PAYLOAD 200*1024
+#define MAX_PES_PAYLOAD 200 * 1024
#define MAX_MP4_DESCR_COUNT 16
+#define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \
+ do { \
+ if ((prev_dividend) == 0 || (dividend) - (prev_dividend) != (divisor)) \
+ (modulus) = (dividend) % (divisor); \
+ (prev_dividend) = (dividend); \
+ } while (0)
+
enum MpegTSFilterType {
MPEGTS_PES,
MPEGTS_SECTION,
+ MPEGTS_PCR,
};
typedef struct MpegTSFilter MpegTSFilter;
-typedef int PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos, int64_t cur_pcr);
+typedef int PESCallback (MpegTSFilter *f, const uint8_t *buf, int len,
+ int is_start, int64_t pos);
typedef struct MpegTSPESFilter {
PESCallback *pes_cb;
void *opaque;
} MpegTSPESFilter;
-typedef void SectionCallback(MpegTSFilter *f, const uint8_t *buf, int len);
+typedef void SectionCallback (MpegTSFilter *f, const uint8_t *buf, int len);
-typedef void SetServiceCallback(void *opaque, int ret);
+typedef void SetServiceCallback (void *opaque, int ret);
typedef struct MpegTSSectionFilter {
int section_index;
int section_h_size;
uint8_t *section_buf;
- unsigned int check_crc:1;
- unsigned int end_of_section_reached:1;
+ unsigned int check_crc : 1;
+ unsigned int end_of_section_reached : 1;
SectionCallback *section_cb;
void *opaque;
} MpegTSSectionFilter;
@@ -78,6 +86,7 @@ struct MpegTSFilter {
int pid;
int es_id;
int last_cc; /* last cc code (-1 if first packet) */
+ int64_t last_pcr;
enum MpegTSFilterType type;
union {
MpegTSPESFilter pes_filter;
@@ -87,16 +96,19 @@ struct MpegTSFilter {
#define MAX_PIDS_PER_PROGRAM 64
struct Program {
- unsigned int id; //program id/service id
+ unsigned int id; // program id/service id
unsigned int nb_pids;
unsigned int pids[MAX_PIDS_PER_PROGRAM];
+
+ /** have we found pmt for this program */
+ int pmt_found;
};
struct MpegTSContext {
const AVClass *class;
/* user data */
AVFormatContext *stream;
- /** raw packet size, including FEC if present */
+ /** raw packet size, including FEC if present */
int raw_packet_size;
int size_stat[3];
@@ -105,43 +117,47 @@ struct MpegTSContext {
int64_t pos47_full;
- /** if true, all pids are analyzed to find streams */
+ /** if true, all pids are analyzed to find streams */
int auto_guess;
- /** compute exact PCR for each transport stream packet */
+ /** compute exact PCR for each transport stream packet */
int mpeg2ts_compute_pcr;
/** fix dvb teletext pts */
int fix_teletext_pts;
- int64_t cur_pcr; /**< used to estimate the exact PCR */
- int pcr_incr; /**< used to estimate the exact PCR */
+ int64_t cur_pcr; /**< used to estimate the exact PCR */
+ int pcr_incr; /**< used to estimate the exact PCR */
/* data needed to handle file based ts */
- /** stop parsing loop */
+ /** stop parsing loop */
int stop_parse;
- /** packet containing Audio/Video data */
+ /** packet containing Audio/Video data */
AVPacket *pkt;
- /** to detect seek */
+ /** to detect seek */
int64_t last_pos;
/******************************************/
/* private mpegts data */
/* scan context */
- /** structure to keep track of Program->pids mapping */
+ /** structure to keep track of Program->pids mapping */
unsigned int nb_prg;
struct Program *prg;
int8_t crc_validity[NB_PID_MAX];
-
/** filters for various streams specified by PMT + for the PAT and PMT */
MpegTSFilter *pids[NB_PID_MAX];
int current_pid;
};
static const AVOption mpegtsraw_options[] = {
- {"compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT,
- {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
+ { "compute_pcr", "Compute exact PCR for each transport stream packet.",
+ offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT,
+ { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
+ { "ts_packetsize", "Output option carrying the raw packet size.",
+ offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
+ { .i64 = 0 }, 0, 0,
+ AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
{ NULL },
};
@@ -155,6 +171,8 @@ static const AVClass mpegtsraw_class = {
static const AVOption mpegts_options[] = {
{"fix_teletext_pts", "Try to fix pts values of dvb teletext streams.", offsetof(MpegTSContext, fix_teletext_pts), AV_OPT_TYPE_INT,
{.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
+ {"ts_packetsize", "Output option carrying the raw packet size.", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
+ {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
{ NULL },
};
@@ -200,17 +218,27 @@ typedef struct PESContext {
uint8_t header[MAX_PES_HEADER_SIZE];
AVBufferRef *buffer;
SLConfigDescr sl;
- int64_t last_pcr;
} PESContext;
extern AVInputFormat ff_mpegts_demuxer;
+static struct Program * get_program(MpegTSContext *ts, unsigned int programid)
+{
+ int i;
+ for (i = 0; i < ts->nb_prg; i++) {
+ if (ts->prg[i].id == programid) {
+ return &ts->prg[i];
+ }
+ }
+ return NULL;
+}
+
static void clear_avprogram(MpegTSContext *ts, unsigned int programid)
{
AVProgram *prg = NULL;
int i;
- for(i=0; i<ts->stream->nb_programs; i++)
- if(ts->stream->programs[i]->id == programid){
+ for (i = 0; i < ts->stream->nb_programs; i++)
+ if (ts->stream->programs[i]->id == programid) {
prg = ts->stream->programs[i];
break;
}
@@ -224,15 +252,17 @@ static void clear_program(MpegTSContext *ts, unsigned int programid)
int i;
clear_avprogram(ts, programid);
- for(i=0; i<ts->nb_prg; i++)
- if(ts->prg[i].id == programid)
+ for (i = 0; i < ts->nb_prg; i++)
+ if (ts->prg[i].id == programid) {
ts->prg[i].nb_pids = 0;
+ ts->prg[i].pmt_found = 0;
+ }
}
static void clear_programs(MpegTSContext *ts)
{
av_freep(&ts->prg);
- ts->nb_prg=0;
+ ts->nb_prg = 0;
}
static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
@@ -245,32 +275,36 @@ static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
p = &ts->prg[ts->nb_prg];
p->id = programid;
p->nb_pids = 0;
+ p->pmt_found = 0;
ts->nb_prg++;
}
-static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned int pid)
+static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid,
+ unsigned int pid)
{
- int i;
- struct Program *p = NULL;
- for(i=0; i<ts->nb_prg; i++) {
- if(ts->prg[i].id == programid) {
- p = &ts->prg[i];
- break;
- }
- }
- if(!p)
+ struct Program *p = get_program(ts, programid);
+ if (!p)
return;
- if(p->nb_pids >= MAX_PIDS_PER_PROGRAM)
+ if (p->nb_pids >= MAX_PIDS_PER_PROGRAM)
return;
p->pids[p->nb_pids++] = pid;
}
+static void set_pmt_found(MpegTSContext *ts, unsigned int programid)
+{
+ struct Program *p = get_program(ts, programid);
+ if (!p)
+ return;
+
+ p->pmt_found = 1;
+}
+
static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid)
{
int i;
- for(i=0; i<s->nb_programs; i++) {
- if(s->programs[i]->id == programid) {
+ for (i = 0; i < s->nb_programs; i++) {
+ if (s->programs[i]->id == programid) {
s->programs[i]->pcr_pid = pid;
break;
}
@@ -292,24 +326,22 @@ static int discard_pid(MpegTSContext *ts, unsigned int pid)
struct Program *p;
/* If none of the programs have .discard=AVDISCARD_ALL then there's
- * no way we have to discard this packet
- */
- for (k = 0; k < ts->stream->nb_programs; k++) {
+ * no way we have to discard this packet */
+ for (k = 0; k < ts->stream->nb_programs; k++)
if (ts->stream->programs[k]->discard == AVDISCARD_ALL)
break;
- }
if (k == ts->stream->nb_programs)
return 0;
- for(i=0; i<ts->nb_prg; i++) {
+ for (i = 0; i < ts->nb_prg; i++) {
p = &ts->prg[i];
- for(j=0; j<p->nb_pids; j++) {
- if(p->pids[j] != pid)
+ for (j = 0; j < p->nb_pids; j++) {
+ if (p->pids[j] != pid)
continue;
- //is program with id p->id set to be discarded?
- for(k=0; k<ts->stream->nb_programs; k++) {
- if(ts->stream->programs[k]->id == p->id) {
- if(ts->stream->programs[k]->discard == AVDISCARD_ALL)
+ // is program with id p->id set to be discarded?
+ for (k = 0; k < ts->stream->nb_programs; k++) {
+ if (ts->stream->programs[k]->id == p->id) {
+ if (ts->stream->programs[k]->discard == AVDISCARD_ALL)
discarded++;
else
used++;
@@ -355,15 +387,16 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
tss->section_h_size = len;
}
- if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {
+ if (tss->section_h_size != -1 &&
+ tss->section_index >= tss->section_h_size) {
int crc_valid = 1;
tss->end_of_section_reached = 1;
- if (tss->check_crc){
+ if (tss->check_crc) {
crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);
- if (crc_valid){
+ if (crc_valid) {
ts->crc_validity[ tss1->pid ] = 100;
- }else if(ts->crc_validity[ tss1->pid ] > -10){
+ }else if (ts->crc_validity[ tss1->pid ] > -10) {
ts->crc_validity[ tss1->pid ]--;
}else
crc_valid = 2;
@@ -373,13 +406,10 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
}
}
-static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int pid,
- SectionCallback *section_cb, void *opaque,
- int check_crc)
-
+static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid,
+ enum MpegTSFilterType type)
{
MpegTSFilter *filter;
- MpegTSSectionFilter *sec;
av_dlog(ts->stream, "Filter: pid=0x%x\n", pid);
@@ -389,15 +419,32 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int
if (!filter)
return NULL;
ts->pids[pid] = filter;
- filter->type = MPEGTS_SECTION;
- filter->pid = pid;
- filter->es_id = -1;
+
+ filter->type = type;
+ filter->pid = pid;
+ filter->es_id = -1;
filter->last_cc = -1;
+ filter->last_pcr= -1;
+
+ return filter;
+}
+
+static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts,
+ unsigned int pid,
+ SectionCallback *section_cb,
+ void *opaque,
+ int check_crc)
+{
+ MpegTSFilter *filter;
+ MpegTSSectionFilter *sec;
+
+ if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION)))
+ return NULL;
sec = &filter->u.section_filter;
- sec->section_cb = section_cb;
- sec->opaque = opaque;
+ sec->section_cb = section_cb;
+ sec->opaque = opaque;
sec->section_buf = av_malloc(MAX_SECTION_SIZE);
- sec->check_crc = check_crc;
+ sec->check_crc = check_crc;
if (!sec->section_buf) {
av_free(filter);
return NULL;
@@ -406,28 +453,26 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int
}
static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,
- PESCallback *pes_cb,
- void *opaque)
+ PESCallback *pes_cb,
+ void *opaque)
{
MpegTSFilter *filter;
MpegTSPESFilter *pes;
- if (pid >= NB_PID_MAX || ts->pids[pid])
+ if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_PES)))
return NULL;
- filter = av_mallocz(sizeof(MpegTSFilter));
- if (!filter)
- return NULL;
- ts->pids[pid] = filter;
- filter->type = MPEGTS_PES;
- filter->pid = pid;
- filter->es_id = -1;
- filter->last_cc = -1;
+
pes = &filter->u.pes_filter;
pes->pes_cb = pes_cb;
pes->opaque = opaque;
return filter;
}
+static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid)
+{
+ return mpegts_open_filter(ts, pid, MPEGTS_PCR);
+}
+
static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
{
int pid;
@@ -449,20 +494,22 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
ts->pids[pid] = NULL;
}
-static int analyze(const uint8_t *buf, int size, int packet_size, int *index){
+static int analyze(const uint8_t *buf, int size, int packet_size, int *index)
+{
int stat[TS_MAX_PACKET_SIZE];
int i;
- int best_score=0;
+ int best_score = 0;
- memset(stat, 0, packet_size*sizeof(*stat));
+ memset(stat, 0, packet_size * sizeof(*stat));
- for(i=0; i<size-3; i++){
- if(buf[i] == 0x47 && !(buf[i+1] & 0x80) && buf[i+3] != 0x47){
+ for (i = 0; i < size - 3; i++) {
+ if (buf[i] == 0x47 && !(buf[i + 1] & 0x80) && buf[i + 3] != 0x47) {
int x = i % packet_size;
stat[x]++;
- if(stat[x] > best_score){
- best_score= stat[x];
- if(index) *index= x;
+ if (stat[x] > best_score) {
+ best_score = stat[x];
+ if (index)
+ *index = x;
}
}
}
@@ -476,18 +523,22 @@ static int get_packet_size(const uint8_t *buf, int size)
int score, fec_score, dvhs_score;
if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
- return -1;
+ return AVERROR_INVALIDDATA;
- score = analyze(buf, size, TS_PACKET_SIZE, NULL);
- dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL);
- fec_score= analyze(buf, size, TS_FEC_PACKET_SIZE, NULL);
+ score = analyze(buf, size, TS_PACKET_SIZE, NULL);
+ dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL);
+ fec_score = analyze(buf, size, TS_FEC_PACKET_SIZE, NULL);
av_dlog(NULL, "score: %d, dvhs_score: %d, fec_score: %d \n",
score, dvhs_score, fec_score);
- if (score > fec_score && score > dvhs_score) return TS_PACKET_SIZE;
- else if(dvhs_score > score && dvhs_score > fec_score) return TS_DVHS_PACKET_SIZE;
- else if(score < fec_score && dvhs_score < fec_score) return TS_FEC_PACKET_SIZE;
- else return -1;
+ if (score > fec_score && score > dvhs_score)
+ return TS_PACKET_SIZE;
+ else if (dvhs_score > score && dvhs_score > fec_score)
+ return TS_DVHS_PACKET_SIZE;
+ else if (score < fec_score && dvhs_score < fec_score)
+ return TS_FEC_PACKET_SIZE;
+ else
+ return AVERROR_INVALIDDATA;
}
typedef struct SectionHeader {
@@ -505,8 +556,8 @@ static inline int get8(const uint8_t **pp, const uint8_t *p_end)
p = *pp;
if (p >= p_end)
- return -1;
- c = *p++;
+ return AVERROR_INVALIDDATA;
+ c = *p++;
*pp = p;
return c;
}
@@ -518,9 +569,9 @@ static inline int get16(const uint8_t **pp, const uint8_t *p_end)
p = *pp;
if ((p + 1) >= p_end)
- return -1;
- c = AV_RB16(p);
- p += 2;
+ return AVERROR_INVALIDDATA;
+ c = AV_RB16(p);
+ p += 2;
*pp = p;
return c;
}
@@ -532,7 +583,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
const uint8_t *p;
char *str;
- p = *pp;
+ p = *pp;
len = get8(&p, p_end);
if (len < 0)
return NULL;
@@ -543,7 +594,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
return NULL;
memcpy(str, p, len);
str[len] = '\0';
- p += len;
+ p += len;
*pp = p;
return str;
}
@@ -555,24 +606,24 @@ static int parse_section_header(SectionHeader *h,
val = get8(pp, p_end);
if (val < 0)
- return -1;
+ return val;
h->tid = val;
*pp += 2;
- val = get16(pp, p_end);
+ val = get16(pp, p_end);
if (val < 0)
- return -1;
+ return val;
h->id = val;
val = get8(pp, p_end);
if (val < 0)
- return -1;
+ return val;
h->version = (val >> 1) & 0x1f;
val = get8(pp, p_end);
if (val < 0)
- return -1;
+ return val;
h->sec_num = val;
val = get8(pp, p_end);
if (val < 0)
- return -1;
+ return val;
h->last_sec_num = val;
return 0;
}
@@ -586,94 +637,95 @@ typedef struct {
static const StreamType ISO_types[] = {
{ 0x01, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO },
{ 0x02, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO },
- { 0x03, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 },
- { 0x04, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 },
- { 0x0f, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC },
- { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 },
+ { 0x03, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 },
+ { 0x04, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 },
+ { 0x0f, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC },
+ { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 },
/* Makito encoder sets stream type 0x11 for AAC,
* so auto-detect LOAS/LATM instead of hardcoding it. */
#if !CONFIG_LOAS_DEMUXER
- { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */
+ { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */
#endif
- { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
- { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
- { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS },
- { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
- { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 },
+ { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
+ { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
+ { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS },
+ { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
+ { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 },
{ 0 },
};
static const StreamType HDMV_types[] = {
- { 0x80, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_BLURAY },
- { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
- { 0x82, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
- { 0x83, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_TRUEHD },
- { 0x84, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 },
- { 0x85, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD */
- { 0x86, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD MASTER*/
- { 0xa1, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC3 Secondary Audio */
- { 0xa2, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS Express Secondary Audio */
+ { 0x80, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_BLURAY },
+ { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
+ { 0x82, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { 0x83, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_TRUEHD },
+ { 0x84, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 },
+ { 0x85, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD */
+ { 0x86, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS HD MASTER*/
+ { 0xa1, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC3 Secondary Audio */
+ { 0xa2, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, /* DTS Express Secondary Audio */
{ 0x90, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_PGS_SUBTITLE },
{ 0 },
};
/* ATSC ? */
static const StreamType MISC_types[] = {
- { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
- { 0x8a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
+ { 0x8a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
{ 0 },
};
static const StreamType REGD_types[] = {
- { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
- { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
- { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M },
- { MKTAG('D','T','S','1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
- { MKTAG('D','T','S','2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
- { MKTAG('D','T','S','3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
- { MKTAG('H','E','V','C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
- { MKTAG('K','L','V','A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV },
- { MKTAG('V','C','-','1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 },
+ { MKTAG('d', 'r', 'a', 'c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
+ { MKTAG('A', 'C', '-', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
+ { MKTAG('B', 'S', 'S', 'D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M },
+ { MKTAG('D', 'T', 'S', '1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
+ { MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV },
+ { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 },
{ 0 },
};
static const StreamType METADATA_types[] = {
{ MKTAG('K','L','V','A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV },
+ { MKTAG('I','D','3',' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 },
{ 0 },
};
/* descriptor present */
static const StreamType DESC_types[] = {
- { 0x6a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, /* AC-3 descriptor */
- { 0x7a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC-3 descriptor */
- { 0x7b, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
+ { 0x6a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, /* AC-3 descriptor */
+ { 0x7a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, /* E-AC-3 descriptor */
+ { 0x7b, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
{ 0x56, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_TELETEXT },
{ 0x59, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */
{ 0 },
};
static void mpegts_find_stream_type(AVStream *st,
- uint32_t stream_type, const StreamType *types)
+ uint32_t stream_type,
+ const StreamType *types)
{
if (avcodec_is_open(st->codec)) {
av_log(NULL, AV_LOG_DEBUG, "cannot set stream info, codec is open\n");
return;
}
- for (; types->stream_type; types++) {
+ for (; types->stream_type; types++)
if (stream_type == types->stream_type) {
st->codec->codec_type = types->codec_type;
st->codec->codec_id = types->codec_id;
st->request_probe = 0;
return;
}
- }
}
static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
uint32_t stream_type, uint32_t prog_reg_desc)
{
- int old_codec_type= st->codec->codec_type;
+ int old_codec_type = st->codec->codec_type;
int old_codec_id = st->codec->codec_id;
if (avcodec_is_open(st->codec)) {
@@ -682,16 +734,16 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
}
avpriv_set_pts_info(st, 33, 1, 90000);
- st->priv_data = pes;
+ st->priv_data = pes;
st->codec->codec_type = AVMEDIA_TYPE_DATA;
st->codec->codec_id = AV_CODEC_ID_NONE;
- st->need_parsing = AVSTREAM_PARSE_FULL;
- pes->st = st;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ pes->st = st;
pes->stream_type = stream_type;
av_log(pes->stream, AV_LOG_DEBUG,
"stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s\n",
- st->index, pes->stream_type, pes->pid, (char*)&prog_reg_desc);
+ st->index, pes->stream_type, pes->pid, (char *)&prog_reg_desc);
st->codec->codec_tag = pes->stream_type;
@@ -718,23 +770,32 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
sub_st->id = pes->pid;
avpriv_set_pts_info(sub_st, 33, 1, 90000);
- sub_st->priv_data = sub_pes;
+ sub_st->priv_data = sub_pes;
sub_st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
sub_st->codec->codec_id = AV_CODEC_ID_AC3;
- sub_st->need_parsing = AVSTREAM_PARSE_FULL;
- sub_pes->sub_st = pes->sub_st = sub_st;
+ sub_st->need_parsing = AVSTREAM_PARSE_FULL;
+ sub_pes->sub_st = pes->sub_st = sub_st;
}
}
if (st->codec->codec_id == AV_CODEC_ID_NONE)
mpegts_find_stream_type(st, pes->stream_type, MISC_types);
- if (st->codec->codec_id == AV_CODEC_ID_NONE){
+ if (st->codec->codec_id == AV_CODEC_ID_NONE) {
st->codec->codec_id = old_codec_id;
- st->codec->codec_type= old_codec_type;
+ st->codec->codec_type = old_codec_type;
}
return 0;
}
+static void reset_pes_packet_state(PESContext *pes)
+{
+ pes->pts = AV_NOPTS_VALUE;
+ pes->dts = AV_NOPTS_VALUE;
+ pes->data_index = 0;
+ pes->flags = 0;
+ av_buffer_unref(&pes->buffer);
+}
+
static void new_pes_packet(PESContext *pes, AVPacket *pkt)
{
av_init_packet(pkt);
@@ -743,12 +804,13 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pkt->data = pes->buffer->data;
pkt->size = pes->data_index;
- if(pes->total_size != MAX_PES_PAYLOAD &&
- pes->pes_header_size + pes->data_index != pes->total_size + PES_START_SIZE) {
+ if (pes->total_size != MAX_PES_PAYLOAD &&
+ pes->pes_header_size + pes->data_index != pes->total_size +
+ PES_START_SIZE) {
av_log(pes->stream, AV_LOG_WARNING, "PES packet size mismatch\n");
pes->flags |= AV_PKT_FLAG_CORRUPT;
}
- memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76)
@@ -758,15 +820,11 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pkt->pts = pes->pts;
pkt->dts = pes->dts;
/* store position of first TS packet of this PES packet */
- pkt->pos = pes->ts_packet_pos;
+ pkt->pos = pes->ts_packet_pos;
pkt->flags = pes->flags;
- /* reset pts values */
- pes->pts = AV_NOPTS_VALUE;
- pes->dts = AV_NOPTS_VALUE;
pes->buffer = NULL;
- pes->data_index = 0;
- pes->flags = 0;
+ reset_pes_packet_state(pes);
}
static uint64_t get_ts64(GetBitContext *gb, int bits)
@@ -776,7 +834,8 @@ static uint64_t get_ts64(GetBitContext *gb, int bits)
return get_bits64(gb, bits);
}
-static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf, int buf_size)
+static int read_sl_header(PESContext *pes, SLConfigDescr *sl,
+ const uint8_t *buf, int buf_size)
{
GetBitContext gb;
int au_start_flag = 0, au_end_flag = 0, ocr_flag = 0, idle_flag = 0;
@@ -784,7 +843,7 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf
int dts_flag = -1, cts_flag = -1;
int64_t dts = AV_NOPTS_VALUE, cts = AV_NOPTS_VALUE;
- init_get_bits(&gb, buf, buf_size*8);
+ init_get_bits(&gb, buf, buf_size * 8);
if (sl->use_au_start)
au_start_flag = get_bits1(&gb);
@@ -845,31 +904,29 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf
/* return non zero if a packet could be constructed */
static int mpegts_push_data(MpegTSFilter *filter,
const uint8_t *buf, int buf_size, int is_start,
- int64_t pos, int64_t pcr)
+ int64_t pos)
{
- PESContext *pes = filter->u.pes_filter.opaque;
+ PESContext *pes = filter->u.pes_filter.opaque;
MpegTSContext *ts = pes->ts;
const uint8_t *p;
int len, code;
- if(!ts->pkt)
+ if (!ts->pkt)
return 0;
- if (pcr != -1)
- pes->last_pcr = pcr;
-
if (is_start) {
if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
new_pes_packet(pes, ts->pkt);
ts->stop_parse = 1;
+ } else {
+ reset_pes_packet_state(pes);
}
- pes->state = MPEGTS_HEADER;
- pes->data_index = 0;
+ pes->state = MPEGTS_HEADER;
pes->ts_packet_pos = pos;
}
p = buf;
while (buf_size > 0) {
- switch(pes->state) {
+ switch (pes->state) {
case MPEGTS_HEADER:
len = PES_START_SIZE - pes->data_index;
if (len > buf_size)
@@ -880,15 +937,17 @@ static int mpegts_push_data(MpegTSFilter *filter,
buf_size -= len;
if (pes->data_index == PES_START_SIZE) {
/* we got all the PES or section header. We can now
- decide */
+ * decide */
if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
pes->header[2] == 0x01) {
/* it must be an mpeg2 PES stream */
code = pes->header[3] | 0x100;
- av_dlog(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, code);
+ av_dlog(pes->stream, "pid=%x pes_code=%#x\n", pes->pid,
+ code);
if ((pes->st && pes->st->discard == AVDISCARD_ALL &&
- (!pes->sub_st || pes->sub_st->discard == AVDISCARD_ALL)) ||
+ (!pes->sub_st ||
+ pes->sub_st->discard == AVDISCARD_ALL)) ||
code == 0x1be) /* padding_stream */
goto skip;
@@ -903,7 +962,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes->total_size = AV_RB16(pes->header + 4);
/* NOTE: a zero total size means the PES size is
- unbounded */
+ * unbounded */
if (!pes->total_size)
pes->total_size = MAX_PES_PAYLOAD;
@@ -919,29 +978,31 @@ static int mpegts_push_data(MpegTSFilter *filter,
code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */
pes->state = MPEGTS_PESHEADER;
if (pes->st->codec->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) {
- av_dlog(pes->stream, "pid=%x stream_type=%x probing\n",
- pes->pid, pes->stream_type);
- pes->st->request_probe= 1;
+ av_dlog(pes->stream,
+ "pid=%x stream_type=%x probing\n",
+ pes->pid,
+ pes->stream_type);
+ pes->st->request_probe = 1;
}
} else {
- pes->state = MPEGTS_PAYLOAD;
+ pes->state = MPEGTS_PAYLOAD;
pes->data_index = 0;
}
} else {
/* otherwise, it should be a table */
/* skip packet */
- skip:
+skip:
pes->state = MPEGTS_SKIP;
continue;
}
}
break;
- /**********************************************/
- /* PES packing parsing */
+ /**********************************************/
+ /* PES packing parsing */
case MPEGTS_PESHEADER:
len = PES_HEADER_SIZE - pes->data_index;
if (len < 0)
- return -1;
+ return AVERROR_INVALIDDATA;
if (len > buf_size)
len = buf_size;
memcpy(pes->header + pes->data_index, p, len);
@@ -950,13 +1011,13 @@ static int mpegts_push_data(MpegTSFilter *filter,
buf_size -= len;
if (pes->data_index == PES_HEADER_SIZE) {
pes->pes_header_size = pes->header[8] + 9;
- pes->state = MPEGTS_PESHEADER_FILL;
+ pes->state = MPEGTS_PESHEADER_FILL;
}
break;
case MPEGTS_PESHEADER_FILL:
len = pes->pes_header_size - pes->data_index;
if (len < 0)
- return -1;
+ return AVERROR_INVALIDDATA;
if (len > buf_size)
len = buf_size;
memcpy(pes->header + pes->data_index, p, len);
@@ -972,10 +1033,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes->pts = AV_NOPTS_VALUE;
pes->dts = AV_NOPTS_VALUE;
if ((flags & 0xc0) == 0x80) {
- pes->pts = ff_parse_pes_pts(r);
- /* video pts is not monotonic, can't be used for dts */
- if (pes->st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
- pes->dts = pes->pts;
+ pes->dts = pes->pts = ff_parse_pes_pts(r);
r += 5;
} else if ((flags & 0xc0) == 0xc0) {
pes->pts = ff_parse_pes_pts(r);
@@ -987,9 +1045,9 @@ static int mpegts_push_data(MpegTSFilter *filter,
if (flags & 0x01) { /* PES extension */
pes_ext = *r++;
/* Skip PES private data, program packet sequence counter and P-STD buffer */
- skip = (pes_ext >> 4) & 0xb;
+ skip = (pes_ext >> 4) & 0xb;
skip += skip & 0x9;
- r += skip;
+ r += skip;
if ((pes_ext & 0x41) == 0x01 &&
(r + 2) <= (pes->header + pes->pes_header_size)) {
/* PES extension 2 */
@@ -1002,7 +1060,8 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes->state = MPEGTS_PAYLOAD;
pes->data_index = 0;
if (pes->stream_type == 0x12 && buf_size > 0) {
- int sl_header_bytes = read_sl_header(pes, &pes->sl, p, buf_size);
+ int sl_header_bytes = read_sl_header(pes, &pes->sl, p,
+ buf_size);
pes->pes_header_size += sl_header_bytes;
p += sl_header_bytes;
buf_size -= sl_header_bytes;
@@ -1018,16 +1077,28 @@ static int mpegts_push_data(MpegTSFilter *filter,
while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) {
if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) {
MpegTSFilter *f = pes->ts->pids[p->pcr_pid];
- if (f && f->type == MPEGTS_PES) {
- PESContext *pcrpes = f->u.pes_filter.opaque;
- if (pcrpes && pcrpes->last_pcr != -1 && pcrpes->st && pcrpes->st->discard != AVDISCARD_ALL) {
+ if (f) {
+ AVStream *st = NULL;
+ if (f->type == MPEGTS_PES) {
+ PESContext *pcrpes = f->u.pes_filter.opaque;
+ if (pcrpes)
+ st = pcrpes->st;
+ } else if (f->type == MPEGTS_PCR) {
+ int i;
+ for (i = 0; i < p->nb_stream_indexes; i++) {
+ AVStream *pst = pes->stream->streams[p->stream_index[i]];
+ if (pst->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ st = pst;
+ }
+ }
+ if (f->last_pcr != -1 && st && st->discard != AVDISCARD_ALL) {
// teletext packets do not always have correct timestamps,
// the standard says they should be handled after 40.6 ms at most,
// and the pcr error to this packet should be no more than 100 ms.
// TODO: we should interpolate the PCR, not just use the last one
- int64_t pcr = pcrpes->last_pcr / 300;
- pes->st->pts_wrap_reference = pcrpes->st->pts_wrap_reference;
- pes->st->pts_wrap_behavior = pcrpes->st->pts_wrap_behavior;
+ int64_t pcr = f->last_pcr / 300;
+ pes->st->pts_wrap_reference = st->pts_wrap_reference;
+ pes->st->pts_wrap_behavior = st->pts_wrap_behavior;
if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) {
pes->pts = pes->dts = pcr;
} else if (pes->dts > pcr + 3654 + 9000) {
@@ -1042,33 +1113,36 @@ static int mpegts_push_data(MpegTSFilter *filter,
}
break;
case MPEGTS_PAYLOAD:
- if (buf_size > 0 && pes->buffer) {
- if (pes->data_index > 0 && pes->data_index+buf_size > pes->total_size) {
+ if (pes->buffer) {
+ if (pes->data_index > 0 &&
+ pes->data_index + buf_size > pes->total_size) {
new_pes_packet(pes, ts->pkt);
pes->total_size = MAX_PES_PAYLOAD;
- pes->buffer = av_buffer_alloc(pes->total_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ pes->buffer = av_buffer_alloc(pes->total_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
if (!pes->buffer)
return AVERROR(ENOMEM);
ts->stop_parse = 1;
- } else if (pes->data_index == 0 && buf_size > pes->total_size) {
+ } else if (pes->data_index == 0 &&
+ buf_size > pes->total_size) {
// pes packet size is < ts size packet and pes data is padded with 0xff
// not sure if this is legal in ts but see issue #2392
buf_size = pes->total_size;
}
memcpy(pes->buffer->data + pes->data_index, p, buf_size);
pes->data_index += buf_size;
+ /* emit complete packets with known packet size
+ * decreases demuxer delay for infrequent packets like subtitles from
+ * a couple of seconds to milliseconds for properly muxed files.
+ * total_size is the number of bytes following pes_packet_length
+ * in the pes header, i.e. not counting the first PES_START_SIZE bytes */
+ if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
+ pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
+ ts->stop_parse = 1;
+ new_pes_packet(pes, ts->pkt);
+ }
}
buf_size = 0;
- /* emit complete packets with known packet size
- * decreases demuxer delay for infrequent packets like subtitles from
- * a couple of seconds to milliseconds for properly muxed files.
- * total_size is the number of bytes following pes_packet_length
- * in the pes header, i.e. not counting the first PES_START_SIZE bytes */
- if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
- pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
- ts->stop_parse = 1;
- new_pes_packet(pes, ts->pkt);
- }
break;
case MPEGTS_SKIP:
buf_size = 0;
@@ -1088,15 +1162,14 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
pes = av_mallocz(sizeof(PESContext));
if (!pes)
return 0;
- pes->ts = ts;
- pes->stream = ts->stream;
- pes->pid = pid;
+ pes->ts = ts;
+ pes->stream = ts->stream;
+ pes->pid = pid;
pes->pcr_pid = pcr_pid;
- pes->state = MPEGTS_SKIP;
- pes->pts = AV_NOPTS_VALUE;
- pes->dts = AV_NOPTS_VALUE;
- pes->last_pcr = -1;
- tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
+ pes->state = MPEGTS_SKIP;
+ pes->pts = AV_NOPTS_VALUE;
+ pes->dts = AV_NOPTS_VALUE;
+ tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
if (!tss) {
av_free(pes);
return 0;
@@ -1115,32 +1188,33 @@ typedef struct {
int level;
} MP4DescrParseContext;
-static int init_MP4DescrParseContext(
- MP4DescrParseContext *d, AVFormatContext *s, const uint8_t *buf,
- unsigned size, Mp4Descr *descr, int max_descr_count)
+static int init_MP4DescrParseContext(MP4DescrParseContext *d, AVFormatContext *s,
+ const uint8_t *buf, unsigned size,
+ Mp4Descr *descr, int max_descr_count)
{
int ret;
- if (size > (1<<30))
+ if (size > (1 << 30))
return AVERROR_INVALIDDATA;
- if ((ret = ffio_init_context(&d->pb, (unsigned char*)buf, size, 0,
- NULL, NULL, NULL, NULL)) < 0)
+ if ((ret = ffio_init_context(&d->pb, (unsigned char *)buf, size, 0,
+ NULL, NULL, NULL, NULL)) < 0)
return ret;
- d->s = s;
- d->level = 0;
- d->descr_count = 0;
- d->descr = descr;
- d->active_descr = NULL;
+ d->s = s;
+ d->level = 0;
+ d->descr_count = 0;
+ d->descr = descr;
+ d->active_descr = NULL;
d->max_descr_count = max_descr_count;
return 0;
}
-static void update_offsets(AVIOContext *pb, int64_t *off, int *len) {
+static void update_offsets(AVIOContext *pb, int64_t *off, int *len)
+{
int64_t new_off = avio_tell(pb);
(*len) -= new_off - *off;
- *off = new_off;
+ *off = new_off;
}
static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
@@ -1149,8 +1223,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
static int parse_mp4_descr_arr(MP4DescrParseContext *d, int64_t off, int len)
{
while (len > 0) {
- if (parse_mp4_descr(d, off, len, 0) < 0)
- return -1;
+ int ret = parse_mp4_descr(d, off, len, 0);
+ if (ret < 0)
+ return ret;
update_offsets(&d->pb, &off, &len);
}
return 0;
@@ -1174,9 +1249,9 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
if (len < 2)
return 0;
id_flags = avio_rb16(&d->pb);
- if (!(id_flags & 0x0020)) { //URL_Flag
+ if (!(id_flags & 0x0020)) { // URL_Flag
update_offsets(&d->pb, &off, &len);
- return parse_mp4_descr_arr(d, off, len); //ES_Descriptor[]
+ return parse_mp4_descr_arr(d, off, len); // ES_Descriptor[]
} else {
return 0;
}
@@ -1186,7 +1261,7 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
{
int es_id = 0;
if (d->descr_count >= d->max_descr_count)
- return -1;
+ return AVERROR_INVALIDDATA;
ff_mp4_parse_es_descr(&d->pb, &es_id);
d->active_descr = d->descr + (d->descr_count++);
@@ -1200,11 +1275,12 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
return 0;
}
-static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, int len)
+static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off,
+ int len)
{
Mp4Descr *descr = d->active_descr;
if (!descr)
- return -1;
+ return AVERROR_INVALIDDATA;
d->active_descr->dec_config_descr = av_malloc(len);
if (!descr->dec_config_descr)
return AVERROR(ENOMEM);
@@ -1218,21 +1294,26 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
Mp4Descr *descr = d->active_descr;
int predefined;
if (!descr)
- return -1;
+ return AVERROR_INVALIDDATA;
predefined = avio_r8(&d->pb);
if (!predefined) {
int lengths;
int flags = avio_r8(&d->pb);
- descr->sl.use_au_start = !!(flags & 0x80);
- descr->sl.use_au_end = !!(flags & 0x40);
- descr->sl.use_rand_acc_pt = !!(flags & 0x20);
- descr->sl.use_padding = !!(flags & 0x08);
- descr->sl.use_timestamps = !!(flags & 0x04);
- descr->sl.use_idle = !!(flags & 0x02);
- descr->sl.timestamp_res = avio_rb32(&d->pb);
- avio_rb32(&d->pb);
+ descr->sl.use_au_start = !!(flags & 0x80);
+ descr->sl.use_au_end = !!(flags & 0x40);
+ descr->sl.use_rand_acc_pt = !!(flags & 0x20);
+ descr->sl.use_padding = !!(flags & 0x08);
+ descr->sl.use_timestamps = !!(flags & 0x04);
+ descr->sl.use_idle = !!(flags & 0x02);
+ descr->sl.timestamp_res = avio_rb32(&d->pb);
+ avio_rb32(&d->pb);
descr->sl.timestamp_len = avio_r8(&d->pb);
+ if (descr->sl.timestamp_len > 64) {
+ avpriv_request_sample(NULL, "timestamp_len > 64");
+ descr->sl.timestamp_len = 64;
+ return AVERROR_PATCHWELCOME;
+ }
descr->sl.ocr_len = avio_r8(&d->pb);
descr->sl.au_len = avio_r8(&d->pb);
descr->sl.inst_bitrate_len = avio_r8(&d->pb);
@@ -1247,13 +1328,16 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
}
static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
- int target_tag) {
+ int target_tag)
+{
int tag;
int len1 = ff_mp4_read_descr(d->s, &d->pb, &tag);
update_offsets(&d->pb, &off, &len);
if (len < 0 || len1 > len || len1 <= 0) {
- av_log(d->s, AV_LOG_ERROR, "Tag %x length violation new length %d bytes remaining %d\n", tag, len1, len);
- return -1;
+ av_log(d->s, AV_LOG_ERROR,
+ "Tag %x length violation new length %d bytes remaining %d\n",
+ tag, len1, len);
+ return AVERROR_INVALIDDATA;
}
if (d->level++ >= MAX_LEVEL) {
@@ -1262,7 +1346,8 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
}
if (target_tag && tag != target_tag) {
- av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag, target_tag);
+ av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag,
+ target_tag);
goto done;
}
@@ -1284,6 +1369,7 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
break;
}
+
done:
d->level--;
avio_seek(&d->pb, off + len1, SEEK_SET);
@@ -1294,36 +1380,43 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size,
Mp4Descr *descr, int *descr_count, int max_descr_count)
{
MP4DescrParseContext d;
- if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0)
- return -1;
+ int ret;
+
+ ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count);
+ if (ret < 0)
+ return ret;
- parse_mp4_descr(&d, avio_tell(&d.pb), size, MP4IODescrTag);
+ ret = parse_mp4_descr(&d, avio_tell(&d.pb), size, MP4IODescrTag);
*descr_count = d.descr_count;
- return 0;
+ return ret;
}
static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size,
Mp4Descr *descr, int *descr_count, int max_descr_count)
{
MP4DescrParseContext d;
- if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0)
- return -1;
+ int ret;
- parse_mp4_descr_arr(&d, avio_tell(&d.pb), size);
+ ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count);
+ if (ret < 0)
+ return ret;
+
+ ret = parse_mp4_descr_arr(&d, avio_tell(&d.pb), size);
*descr_count = d.descr_count;
- return 0;
+ return ret;
}
-static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
+static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
+ int section_len)
{
MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h;
const uint8_t *p, *p_end;
AVIOContext pb;
- Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }};
int mp4_descr_count = 0;
+ Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } };
int i, pid;
AVFormatContext *s = ts->stream;
@@ -1334,30 +1427,31 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
if (h.tid != M4OD_TID)
return;
- mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT);
+ mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count,
+ MAX_MP4_DESCR_COUNT);
for (pid = 0; pid < NB_PID_MAX; pid++) {
if (!ts->pids[pid])
- continue;
+ continue;
for (i = 0; i < mp4_descr_count; i++) {
PESContext *pes;
AVStream *st;
if (ts->pids[pid]->es_id != mp4_descr[i].es_id)
continue;
- if (!(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES)) {
+ if (ts->pids[pid]->type != MPEGTS_PES) {
av_log(s, AV_LOG_ERROR, "pid %x is not PES\n", pid);
continue;
}
pes = ts->pids[pid]->u.pes_filter.opaque;
- st = pes->st;
- if (!st) {
+ st = pes->st;
+ if (!st)
continue;
- }
pes->sl = mp4_descr[i].sl;
ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
- mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
+ mp4_descr[i].dec_config_descr_len, 0,
+ NULL, NULL, NULL, NULL);
ff_mp4_read_dec_config_descr(s, st, &pb);
if (st->codec->codec_id == AV_CODEC_ID_AAC &&
st->codec->extradata_size > 0)
@@ -1367,13 +1461,13 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
st->need_parsing = 0;
if (st->codec->codec_id <= AV_CODEC_ID_NONE) {
- } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_AUDIO) {
+ // do nothing
+ } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_AUDIO)
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
- } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_SUBTITLE) {
+ else if (st->codec->codec_id < AV_CODEC_ID_FIRST_SUBTITLE)
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_UNKNOWN) {
+ else if (st->codec->codec_id < AV_CODEC_ID_FIRST_UNKNOWN)
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
- }
}
}
for (i = 0; i < mp4_descr_count; i++)
@@ -1392,13 +1486,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
desc_tag = get8(pp, desc_list_end);
if (desc_tag < 0)
- return -1;
+ return AVERROR_INVALIDDATA;
desc_len = get8(pp, desc_list_end);
if (desc_len < 0)
- return -1;
+ return AVERROR_INVALIDDATA;
desc_end = *pp + desc_len;
if (desc_end > desc_list_end)
- return -1;
+ return AVERROR_INVALIDDATA;
av_dlog(fc, "tag: 0x%02x len=%d\n", desc_tag, desc_len);
@@ -1406,73 +1500,149 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
stream_type == STREAM_TYPE_PRIVATE_DATA)
mpegts_find_stream_type(st, desc_tag, DESC_types);
- switch(desc_tag) {
+ switch (desc_tag) {
case 0x1E: /* SL descriptor */
desc_es_id = get16(pp, desc_end);
if (ts && ts->pids[pid])
ts->pids[pid]->es_id = desc_es_id;
for (i = 0; i < mp4_descr_count; i++)
- if (mp4_descr[i].dec_config_descr_len &&
- mp4_descr[i].es_id == desc_es_id) {
- AVIOContext pb;
- ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
- mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
- ff_mp4_read_dec_config_descr(fc, st, &pb);
- if (st->codec->codec_id == AV_CODEC_ID_AAC &&
- st->codec->extradata_size > 0)
- st->need_parsing = 0;
- if (st->codec->codec_id == AV_CODEC_ID_MPEG4SYSTEMS)
- mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1);
- }
+ if (mp4_descr[i].dec_config_descr_len &&
+ mp4_descr[i].es_id == desc_es_id) {
+ AVIOContext pb;
+ ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
+ mp4_descr[i].dec_config_descr_len, 0,
+ NULL, NULL, NULL, NULL);
+ ff_mp4_read_dec_config_descr(fc, st, &pb);
+ if (st->codec->codec_id == AV_CODEC_ID_AAC &&
+ st->codec->extradata_size > 0)
+ st->need_parsing = 0;
+ if (st->codec->codec_id == AV_CODEC_ID_MPEG4SYSTEMS)
+ mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1);
+ }
break;
case 0x1F: /* FMC descriptor */
get16(pp, desc_end);
- if (mp4_descr_count > 0 && (st->codec->codec_id == AV_CODEC_ID_AAC_LATM || st->request_probe>0) &&
+ if (mp4_descr_count > 0 &&
+ (st->codec->codec_id == AV_CODEC_ID_AAC_LATM || st->request_probe > 0) &&
mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) {
AVIOContext pb;
ffio_init_context(&pb, mp4_descr->dec_config_descr,
- mp4_descr->dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
+ mp4_descr->dec_config_descr_len, 0,
+ NULL, NULL, NULL, NULL);
ff_mp4_read_dec_config_descr(fc, st, &pb);
if (st->codec->codec_id == AV_CODEC_ID_AAC &&
- st->codec->extradata_size > 0){
- st->request_probe= st->need_parsing = 0;
- st->codec->codec_type= AVMEDIA_TYPE_AUDIO;
+ st->codec->extradata_size > 0) {
+ st->request_probe = st->need_parsing = 0;
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
}
}
break;
case 0x56: /* DVB teletext descriptor */
- language[0] = get8(pp, desc_end);
- language[1] = get8(pp, desc_end);
- language[2] = get8(pp, desc_end);
- language[3] = 0;
- av_dict_set(&st->metadata, "language", language, 0);
+ {
+ uint8_t *extradata = NULL;
+ int language_count = desc_len / 5;
+
+ if (desc_len > 0 && desc_len % 5 != 0)
+ return AVERROR_INVALIDDATA;
+
+ if (language_count > 0) {
+ /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
+ if (language_count > sizeof(language) / 4) {
+ language_count = sizeof(language) / 4;
+ }
+
+ if (st->codec->extradata == NULL) {
+ if (ff_alloc_extradata(st->codec, language_count * 2)) {
+ return AVERROR(ENOMEM);
+ }
+ }
+
+ if (st->codec->extradata_size < language_count * 2)
+ return AVERROR_INVALIDDATA;
+
+ extradata = st->codec->extradata;
+
+ for (i = 0; i < language_count; i++) {
+ language[i * 4 + 0] = get8(pp, desc_end);
+ language[i * 4 + 1] = get8(pp, desc_end);
+ language[i * 4 + 2] = get8(pp, desc_end);
+ language[i * 4 + 3] = ',';
+
+ memcpy(extradata, *pp, 2);
+ extradata += 2;
+
+ *pp += 2;
+ }
+
+ language[i * 4 - 1] = 0;
+ av_dict_set(&st->metadata, "language", language, 0);
+ }
+ }
break;
case 0x59: /* subtitling descriptor */
- language[0] = get8(pp, desc_end);
- language[1] = get8(pp, desc_end);
- language[2] = get8(pp, desc_end);
- language[3] = 0;
- /* hearing impaired subtitles detection */
- switch(get8(pp, desc_end)) {
- case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */
- case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */
- case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */
- case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */
- case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */
- case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */
- st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
- break;
- }
- if (st->codec->extradata) {
- if (st->codec->extradata_size == 4 && memcmp(st->codec->extradata, *pp, 4))
- avpriv_request_sample(fc, "DVB sub with multiple IDs");
- } else {
- if (!ff_alloc_extradata(st->codec, 4)) {
- memcpy(st->codec->extradata, *pp, 4);
+ {
+ /* 8 bytes per DVB subtitle substream data:
+ * ISO_639_language_code (3 bytes),
+ * subtitling_type (1 byte),
+ * composition_page_id (2 bytes),
+ * ancillary_page_id (2 bytes) */
+ int language_count = desc_len / 8;
+
+ if (desc_len > 0 && desc_len % 8 != 0)
+ return AVERROR_INVALIDDATA;
+
+ if (language_count > 1) {
+ avpriv_request_sample(fc, "DVB subtitles with multiple languages");
+ }
+
+ if (language_count > 0) {
+ uint8_t *extradata;
+
+ /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
+ if (language_count > sizeof(language) / 4) {
+ language_count = sizeof(language) / 4;
+ }
+
+ if (st->codec->extradata == NULL) {
+ if (ff_alloc_extradata(st->codec, language_count * 5)) {
+ return AVERROR(ENOMEM);
+ }
+ }
+
+ if (st->codec->extradata_size < language_count * 5)
+ return AVERROR_INVALIDDATA;
+
+ extradata = st->codec->extradata;
+
+ for (i = 0; i < language_count; i++) {
+ language[i * 4 + 0] = get8(pp, desc_end);
+ language[i * 4 + 1] = get8(pp, desc_end);
+ language[i * 4 + 2] = get8(pp, desc_end);
+ language[i * 4 + 3] = ',';
+
+ /* hearing impaired subtitles detection using subtitling_type */
+ switch (*pp[0]) {
+ case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */
+ case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */
+ case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */
+ case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */
+ case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */
+ case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */
+ st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
+ break;
+ }
+
+ extradata[4] = get8(pp, desc_end); /* subtitling_type */
+ memcpy(extradata, *pp, 4); /* composition_page_id and ancillary_page_id */
+ extradata += 5;
+
+ *pp += 4;
+ }
+
+ language[i * 4 - 1] = 0;
+ av_dict_set(&st->metadata, "language", language, 0);
}
}
- *pp += 4;
- av_dict_set(&st->metadata, "language", language, 0);
break;
case 0x0a: /* ISO 639 language descriptor */
for (i = 0; i + 4 <= desc_len; i += 4) {
@@ -1480,11 +1650,17 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
language[i + 1] = get8(pp, desc_end);
language[i + 2] = get8(pp, desc_end);
language[i + 3] = ',';
- switch (get8(pp, desc_end)) {
- case 0x01: st->disposition |= AV_DISPOSITION_CLEAN_EFFECTS; break;
- case 0x02: st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; break;
- case 0x03: st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; break;
- }
+ switch (get8(pp, desc_end)) {
+ case 0x01:
+ st->disposition |= AV_DISPOSITION_CLEAN_EFFECTS;
+ break;
+ case 0x02:
+ st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
+ break;
+ case 0x03:
+ st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED;
+ break;
+ }
}
if (i) {
language[i - 1] = 0;
@@ -1493,7 +1669,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
break;
case 0x05: /* registration descriptor */
st->codec->codec_tag = bytestream_get_le32(pp);
- av_dlog(fc, "reg_desc=%.4s\n", (char*)&st->codec->codec_tag);
+ av_dlog(fc, "reg_desc=%.4s\n", (char *)&st->codec->codec_tag);
if (st->codec->codec_id == AV_CODEC_ID_NONE)
mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
break;
@@ -1527,8 +1703,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
int desc_list_len;
uint32_t prog_reg_desc = 0; /* registration descriptor */
- Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }};
int mp4_descr_count = 0;
+ Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } };
int i;
av_dlog(ts->stream, "PMT: len %i\n", section_len);
@@ -1540,7 +1716,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
return;
av_dlog(ts->stream, "sid=0x%x sec_num=%d/%d\n",
- h->id, h->sec_num, h->last_sec_num);
+ h->id, h->sec_num, h->last_sec_num);
if (h->tid != PMT_TID)
return;
@@ -1559,15 +1735,15 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (program_info_length < 0)
return;
program_info_length &= 0xfff;
- while(program_info_length >= 2) {
+ while (program_info_length >= 2) {
uint8_t tag, len;
tag = get8(&p, p_end);
len = get8(&p, p_end);
av_dlog(ts->stream, "program tag: 0x%02x len=%d\n", tag, len);
- if(len > program_info_length - 2)
- //something else is broken, exit the program_descriptors_loop
+ if (len > program_info_length - 2)
+ // something else is broken, exit the program_descriptors_loop
break;
program_info_length -= len + 2;
if (tag == 0x1d) { // IOD descriptor
@@ -1590,7 +1766,10 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (!ts->stream->nb_streams)
ts->stop_parse = 2;
- for(;;) {
+ set_pmt_found(ts, h->id);
+
+
+ for (;;) {
st = 0;
pes = NULL;
stream_type = get8(&p, p_end);
@@ -1598,23 +1777,24 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
break;
pid = get16(&p, p_end);
if (pid < 0)
- break;
+ goto out;
pid &= 0x1fff;
if (pid == ts->current_pid)
- break;
+ goto out;
/* now create stream */
if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {
pes = ts->pids[pid]->u.pes_filter.opaque;
if (!pes->st) {
- pes->st = avformat_new_stream(pes->stream, NULL);
+ pes->st = avformat_new_stream(pes->stream, NULL);
if (!pes->st)
goto out;
pes->st->id = pes->pid;
}
st = pes->st;
} else if (stream_type != 0x13) {
- if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); //wrongly added sdt filter probably
+ if (ts->pids[pid])
+ mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably
pes = add_pes_stream(ts, pid, pcr_pid);
if (pes) {
st = avformat_new_stream(pes->stream, NULL);
@@ -1647,25 +1827,31 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
desc_list_len = get16(&p, p_end);
if (desc_list_len < 0)
- break;
+ goto out;
desc_list_len &= 0xfff;
- desc_list_end = p + desc_list_len;
+ desc_list_end = p + desc_list_len;
if (desc_list_end > p_end)
- break;
- for(;;) {
- if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p, desc_list_end,
- mp4_descr, mp4_descr_count, pid, ts) < 0)
+ goto out;
+ for (;;) {
+ if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p,
+ desc_list_end, mp4_descr,
+ mp4_descr_count, pid, ts) < 0)
break;
- if (pes && prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) {
- ff_program_add_stream_index(ts->stream, h->id, pes->sub_st->index);
+ if (pes && prog_reg_desc == AV_RL32("HDMV") &&
+ stream_type == 0x83 && pes->sub_st) {
+ ff_program_add_stream_index(ts->stream, h->id,
+ pes->sub_st->index);
pes->sub_st->codec->codec_tag = st->codec->codec_tag;
}
}
p = desc_list_end;
}
- out:
+ if (!ts->pids[pcr_pid])
+ mpegts_open_pcr_filter(ts, pcr_pid);
+
+out:
for (i = 0; i < mp4_descr_count; i++)
av_free(mp4_descr[i].dec_config_descr);
}
@@ -1682,7 +1868,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
hex_dump_debug(ts->stream, section, section_len);
p_end = section + section_len - 4;
- p = section;
+ p = section;
if (parse_section_header(h, &p, p_end) < 0)
return;
if (h->tid != PAT_TID)
@@ -1691,7 +1877,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
ts->stream->ts_id = h->id;
clear_programs(ts);
- for(;;) {
+ for (;;) {
sid = get16(&p, p_end);
if (sid < 0)
break;
@@ -1721,7 +1907,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (!ts->pids[pmt_pid])
mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
add_pat_entry(ts, sid);
- add_pid_to_pmt(ts, sid, 0); //add pat pid to program
+ add_pid_to_pmt(ts, sid, 0); // add pat pid to program
add_pid_to_pmt(ts, sid, pmt_pid);
}
}
@@ -1729,7 +1915,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (sid < 0) {
int i,j;
for (j=0; j<ts->stream->nb_programs; j++) {
- for (i=0; i<ts->nb_prg; i++)
+ for (i = 0; i < ts->nb_prg; i++)
if (ts->prg[i].id == ts->stream->programs[j]->id)
break;
if (i==ts->nb_prg)
@@ -1750,7 +1936,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
hex_dump_debug(ts->stream, section, section_len);
p_end = section + section_len - 4;
- p = section;
+ p = section;
if (parse_section_header(h, &p, p_end) < 0)
return;
if (h->tid != SDT_TID)
@@ -1761,7 +1947,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
val = get8(&p, p_end);
if (val < 0)
return;
- for(;;) {
+ for (;;) {
sid = get16(&p, p_end);
if (sid < 0)
break;
@@ -1772,10 +1958,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (desc_list_len < 0)
break;
desc_list_len &= 0xfff;
- desc_list_end = p + desc_list_len;
+ desc_list_end = p + desc_list_len;
if (desc_list_end > p_end)
break;
- for(;;) {
+ for (;;) {
desc_tag = get8(&p, desc_list_end);
if (desc_tag < 0)
break;
@@ -1785,9 +1971,9 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
break;
av_dlog(ts->stream, "tag: 0x%02x len=%d\n",
- desc_tag, desc_len);
+ desc_tag, desc_len);
- switch(desc_tag) {
+ switch (desc_tag) {
case 0x48:
service_type = get8(&p, p_end);
if (service_type < 0)
@@ -1798,9 +1984,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
name = getstr8(&p, p_end);
if (name) {
AVProgram *program = av_new_program(ts->stream, sid);
- if(program) {
+ if (program) {
av_dict_set(&program->metadata, "service_name", name, 0);
- av_dict_set(&program->metadata, "service_provider", provider_name, 0);
+ av_dict_set(&program->metadata, "service_provider",
+ provider_name, 0);
}
}
av_free(name);
@@ -1829,7 +2016,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
int64_t pos;
pid = AV_RB16(packet + 1) & 0x1fff;
- if(pid && discard_pid(ts, pid))
+ if (pid && discard_pid(ts, pid))
return 0;
is_start = packet[1] & 0x40;
tss = ts->pids[pid];
@@ -1844,32 +2031,32 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
afc = (packet[3] >> 4) & 3;
if (afc == 0) /* reserved value */
return 0;
- has_adaptation = afc & 2;
- has_payload = afc & 1;
- is_discontinuity = has_adaptation
- && packet[4] != 0 /* with length > 0 */
- && (packet[5] & 0x80); /* and discontinuity indicated */
+ has_adaptation = afc & 2;
+ has_payload = afc & 1;
+ is_discontinuity = has_adaptation &&
+ packet[4] != 0 && /* with length > 0 */
+ (packet[5] & 0x80); /* and discontinuity indicated */
/* continuity check (currently not used) */
cc = (packet[3] & 0xf);
expected_cc = has_payload ? (tss->last_cc + 1) & 0x0f : tss->last_cc;
- cc_ok = pid == 0x1FFF // null packet PID
- || is_discontinuity
- || tss->last_cc < 0
- || expected_cc == cc;
+ cc_ok = pid == 0x1FFF || // null packet PID
+ is_discontinuity ||
+ tss->last_cc < 0 ||
+ expected_cc == cc;
tss->last_cc = cc;
if (!cc_ok) {
av_log(ts->stream, AV_LOG_DEBUG,
"Continuity check failed for pid %d expected %d got %d\n",
pid, expected_cc, cc);
- if(tss->type == MPEGTS_PES) {
+ if (tss->type == MPEGTS_PES) {
PESContext *pc = tss->u.pes_filter.opaque;
pc->flags |= AV_PKT_FLAG_CORRUPT;
}
}
- if (!has_payload)
+ if (!has_payload && tss->type != MPEGTS_PCR)
return 0;
p = packet + 4;
if (has_adaptation) {
@@ -1878,7 +2065,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
}
/* if past the end of packet, ignore */
p_end = packet + TS_PACKET_SIZE;
- if (p >= p_end)
+ if (p > p_end || (p == p_end && tss->type != MPEGTS_PCR))
return 0;
pos = avio_tell(ts->stream->pb);
@@ -1912,17 +2099,35 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
p, p_end - p, 0);
}
}
+
+ // stop find_stream_info from waiting for more streams
+ // when all programs have received a PMT
+ if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER) {
+ int i;
+ for (i = 0; i < ts->nb_prg; i++) {
+ if (!ts->prg[i].pmt_found)
+ break;
+ }
+ if (i == ts->nb_prg && ts->nb_prg > 0) {
+ if (ts->stream->nb_streams > 1 || pos > 100000) {
+ av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n");
+ ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER;
+ }
+ }
+ }
+
} else {
int ret;
- int64_t pcr = -1;
int64_t pcr_h;
int pcr_l;
if (parse_pcr(&pcr_h, &pcr_l, packet) == 0)
- pcr = pcr_h * 300 + pcr_l;
+ tss->last_pcr = pcr_h * 300 + pcr_l;
// Note: The position here points actually behind the current packet.
- if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,
- pos - ts->raw_packet_size, pcr)) < 0)
- return ret;
+ if (tss->type == MPEGTS_PES) {
+ if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,
+ pos - ts->raw_packet_size)) < 0)
+ return ret;
+ }
}
return 0;
@@ -1931,7 +2136,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
static void reanalyze(MpegTSContext *ts) {
AVIOContext *pb = ts->stream->pb;
int64_t pos = avio_tell(pb);
- if(pos < 0)
+ if (pos < 0)
return;
pos -= ts->pos47_full;
if (pos == TS_PACKET_SIZE) {
@@ -1943,7 +2148,7 @@ static void reanalyze(MpegTSContext *ts) {
}
ts->size_stat_count ++;
- if(ts->size_stat_count > SIZE_STAT_THRESHOLD) {
+ if (ts->size_stat_count > SIZE_STAT_THRESHOLD) {
int newsize = 0;
if (ts->size_stat[0] > SIZE_STAT_THRESHOLD) {
newsize = TS_PACKET_SIZE;
@@ -1962,34 +2167,36 @@ static void reanalyze(MpegTSContext *ts) {
}
/* XXX: try to find a better synchro over several packets (use
- get_packet_size() ?) */
+ * get_packet_size() ?) */
static int mpegts_resync(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
int c, i;
- for(i = 0;i < MAX_RESYNC_SIZE; i++) {
+ for (i = 0; i < MAX_RESYNC_SIZE; i++) {
c = avio_r8(pb);
if (url_feof(pb))
- return -1;
+ return AVERROR_EOF;
if (c == 0x47) {
avio_seek(pb, -1, SEEK_CUR);
reanalyze(s->priv_data);
return 0;
}
}
- av_log(s, AV_LOG_ERROR, "max resync size reached, could not find sync byte\n");
+ av_log(s, AV_LOG_ERROR,
+ "max resync size reached, could not find sync byte\n");
/* no sync found */
- return -1;
+ return AVERROR_INVALIDDATA;
}
-/* return -1 if error or EOF. Return 0 if OK. */
-static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size, const uint8_t **data)
+/* return AVERROR_something if error or EOF. Return 0 if OK. */
+static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size,
+ const uint8_t **data)
{
AVIOContext *pb = s->pb;
int len;
- for(;;) {
+ for (;;) {
len = ffio_read_indirect(pb, buf, TS_PACKET_SIZE, data);
if (len != TS_PACKET_SIZE)
return len < 0 ? len : AVERROR_EOF;
@@ -2032,13 +2239,13 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
for (i = 0; i < NB_PID_MAX; i++) {
if (ts->pids[i]) {
if (ts->pids[i]->type == MPEGTS_PES) {
- PESContext *pes = ts->pids[i]->u.pes_filter.opaque;
- av_buffer_unref(&pes->buffer);
- pes->data_index = 0;
- pes->state = MPEGTS_SKIP; /* skip until pes header */
- pes->last_pcr = -1;
+ PESContext *pes = ts->pids[i]->u.pes_filter.opaque;
+ av_buffer_unref(&pes->buffer);
+ pes->data_index = 0;
+ pes->state = MPEGTS_SKIP; /* skip until pes header */
}
ts->pids[i]->last_cc = -1;
+ ts->pids[i]->last_pcr = -1;
}
}
}
@@ -2046,7 +2253,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
ts->stop_parse = 0;
packet_num = 0;
memset(packet + TS_PACKET_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- for(;;) {
+ for (;;) {
packet_num++;
if (nb_packets != 0 && packet_num >= nb_packets ||
ts->stop_parse > 1) {
@@ -2070,41 +2277,41 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
static int mpegts_probe(AVProbeData *p)
{
- const int size= p->buf_size;
- int maxscore=0;
- int sumscore=0;
+ const int size = p->buf_size;
+ int maxscore = 0;
+ int sumscore = 0;
int i;
- int check_count= size / TS_FEC_PACKET_SIZE;
+ int check_count = size / TS_FEC_PACKET_SIZE;
#define CHECK_COUNT 10
#define CHECK_BLOCK 100
if (check_count < CHECK_COUNT)
- return -1;
+ return AVERROR_INVALIDDATA;
- for (i=0; i<check_count; i+=CHECK_BLOCK){
+ for (i = 0; i<check_count; i+=CHECK_BLOCK) {
int left = FFMIN(check_count - i, CHECK_BLOCK);
- int score = analyze(p->buf + TS_PACKET_SIZE *i, TS_PACKET_SIZE *left, TS_PACKET_SIZE , NULL);
- int dvhs_score= analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL);
- int fec_score = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL);
+ int score = analyze(p->buf + TS_PACKET_SIZE *i, TS_PACKET_SIZE *left, TS_PACKET_SIZE , NULL);
+ int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL);
+ int fec_score = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL);
score = FFMAX3(score, dvhs_score, fec_score);
sumscore += score;
maxscore = FFMAX(maxscore, score);
}
- sumscore = sumscore*CHECK_COUNT/check_count;
- maxscore = maxscore*CHECK_COUNT/CHECK_BLOCK;
+ sumscore = sumscore * CHECK_COUNT / check_count;
+ maxscore = maxscore * CHECK_COUNT / CHECK_BLOCK;
av_dlog(0, "TS score: %d %d\n", sumscore, maxscore);
- if (sumscore > 6) return AVPROBE_SCORE_MAX + sumscore - CHECK_COUNT;
- else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
- else return -1;
+ if (sumscore > 6) return AVPROBE_SCORE_MAX + sumscore - CHECK_COUNT;
+ else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
+ else
+ return AVERROR_INVALIDDATA;
}
/* return the 90kHz PCR and the extension for the 27MHz PCR. return
- (-1) if not available */
-static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
- const uint8_t *packet)
+ * (-1) if not available */
+static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet)
{
int afc, len, flags;
const uint8_t *p;
@@ -2112,21 +2319,21 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
afc = (packet[3] >> 4) & 3;
if (afc <= 1)
- return -1;
- p = packet + 4;
+ return AVERROR_INVALIDDATA;
+ p = packet + 4;
len = p[0];
p++;
if (len == 0)
- return -1;
+ return AVERROR_INVALIDDATA;
flags = *p++;
len--;
if (!(flags & 0x10))
- return -1;
+ return AVERROR_INVALIDDATA;
if (len < 6)
- return -1;
- v = AV_RB32(p);
- *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7);
- *ppcr_low = ((p[4] & 1) << 8) | p[5];
+ return AVERROR_INVALIDDATA;
+ v = AV_RB32(p);
+ *ppcr_high = ((int64_t) v << 1) | (p[4] >> 7);
+ *ppcr_low = ((p[4] & 1) << 8) | p[5];
return 0;
}
@@ -2142,8 +2349,8 @@ static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) {
static int mpegts_read_header(AVFormatContext *s)
{
MpegTSContext *ts = s->priv_data;
- AVIOContext *pb = s->pb;
- uint8_t buf[8*1024]={0};
+ AVIOContext *pb = s->pb;
+ uint8_t buf[8 * 1024] = {0};
int len;
int64_t pos;
@@ -2157,7 +2364,7 @@ static int mpegts_read_header(AVFormatContext *s)
av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n");
ts->raw_packet_size = TS_PACKET_SIZE;
}
- ts->stream = s;
+ ts->stream = s;
ts->auto_guess = 0;
if (s->iformat == &ff_mpegts_demuxer) {
@@ -2190,19 +2397,19 @@ static int mpegts_read_header(AVFormatContext *s)
st = avformat_new_stream(s, NULL);
if (!st)
- goto fail;
+ return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 60, 1, 27000000);
st->codec->codec_type = AVMEDIA_TYPE_DATA;
- st->codec->codec_id = AV_CODEC_ID_MPEG2TS;
+ st->codec->codec_id = AV_CODEC_ID_MPEG2TS;
/* we iterate until we find two PCRs to estimate the bitrate */
- pcr_pid = -1;
- nb_pcrs = 0;
+ pcr_pid = -1;
+ nb_pcrs = 0;
nb_packets = 0;
- for(;;) {
+ for (;;) {
ret = read_packet(s, packet, ts->raw_packet_size, &data);
if (ret < 0)
- goto fail;
+ return ret;
pid = AV_RB16(data + 1) & 0x1fff;
if ((pcr_pid == -1 || pcr_pid == pid) &&
parse_pcr(&pcr_h, &pcr_l, data) == 0) {
@@ -2222,24 +2429,21 @@ static int mpegts_read_header(AVFormatContext *s)
/* NOTE1: the bitrate is computed without the FEC */
/* NOTE2: it is only the bitrate of the start of the stream */
ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
- ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0];
- s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr;
+ ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0];
+ s->bit_rate = TS_PACKET_SIZE * 8 * 27e6 / ts->pcr_incr;
st->codec->bit_rate = s->bit_rate;
- st->start_time = ts->cur_pcr;
+ st->start_time = ts->cur_pcr;
av_dlog(ts->stream, "start=%0.3f pcr=%0.3f incr=%d\n",
st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
}
seek_back(s, pb, pos);
return 0;
- fail:
- return -1;
}
#define MAX_PACKET_READAHEAD ((128 * 1024) / 188)
-static int mpegts_raw_read_packet(AVFormatContext *s,
- AVPacket *pkt)
+static int mpegts_raw_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MpegTSContext *ts = s->priv_data;
int ret, i;
@@ -2250,8 +2454,8 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
return AVERROR(ENOMEM);
- pkt->pos= avio_tell(s->pb);
ret = read_packet(s, pkt->data, ts->raw_packet_size, &data);
+ pkt->pos = avio_tell(s->pb);
if (ret < 0) {
av_free_packet(pkt);
return ret;
@@ -2264,12 +2468,13 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
/* we read the next PCR (XXX: optimize it by using a bigger buffer */
pos = avio_tell(s->pb);
- for(i = 0; i < MAX_PACKET_READAHEAD; i++) {
+ for (i = 0; i < MAX_PACKET_READAHEAD; i++) {
avio_seek(s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
avio_read(s->pb, pcr_buf, 12);
if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) {
/* XXX: not precise enough */
- ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /
+ ts->pcr_incr =
+ ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /
(i + 1);
break;
}
@@ -2278,16 +2483,15 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
/* no next PCR found: we use previous increment */
ts->cur_pcr = pcr_h * 300 + pcr_l;
}
- pkt->pts = ts->cur_pcr;
+ pkt->pts = ts->cur_pcr;
pkt->duration = ts->pcr_incr;
- ts->cur_pcr += ts->pcr_incr;
+ ts->cur_pcr += ts->pcr_incr;
}
pkt->stream_index = 0;
return 0;
}
-static int mpegts_read_packet(AVFormatContext *s,
- AVPacket *pkt)
+static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MpegTSContext *ts = s->priv_data;
int ret, i;
@@ -2298,7 +2502,7 @@ static int mpegts_read_packet(AVFormatContext *s,
if (ret < 0) {
av_free_packet(ts->pkt);
/* flush pes data left */
- for (i = 0; i < NB_PID_MAX; i++) {
+ for (i = 0; i < NB_PID_MAX; i++)
if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) {
PESContext *pes = ts->pids[i]->u.pes_filter.opaque;
if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
@@ -2308,7 +2512,6 @@ static int mpegts_read_packet(AVFormatContext *s,
break;
}
}
- }
}
if (!ret && pkt->size < 0)
@@ -2322,8 +2525,9 @@ static void mpegts_free(MpegTSContext *ts)
clear_programs(ts);
- for(i=0;i<NB_PID_MAX;i++)
- if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]);
+ for (i = 0; i < NB_PID_MAX; i++)
+ if (ts->pids[i])
+ mpegts_close_filter(ts, ts->pids[i]);
}
static int mpegts_read_close(AVFormatContext *s)
@@ -2339,9 +2543,12 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
MpegTSContext *ts = s->priv_data;
int64_t pos, timestamp;
uint8_t buf[TS_PACKET_SIZE];
- int pcr_l, pcr_pid = ((PESContext*)s->streams[stream_index]->priv_data)->pcr_pid;
+ int pcr_l, pcr_pid =
+ ((PESContext *)s->streams[stream_index]->priv_data)->pcr_pid;
int pos47 = ts->pos47_full % ts->raw_packet_size;
- pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47;
+ pos =
+ ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) *
+ ts->raw_packet_size + pos47;
while(pos < pos_limit) {
if (avio_seek(s->pb, pos, SEEK_SET) < 0)
return AV_NOPTS_VALUE;
@@ -2379,15 +2586,15 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index,
int ret;
AVPacket pkt;
av_init_packet(&pkt);
- ret= av_read_frame(s, &pkt);
- if(ret < 0)
+ ret = av_read_frame(s, &pkt);
+ if (ret < 0)
return AV_NOPTS_VALUE;
av_free_packet(&pkt);
- if(pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0){
+ if (pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0) {
ff_reduce_index(s, pkt.stream_index);
av_add_index_entry(s->streams[pkt.stream_index], pkt.pos, pkt.dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
- if(pkt.stream_index == stream_index && pkt.pos >= *ppos){
- *ppos= pkt.pos;
+ if (pkt.stream_index == stream_index && pkt.pos >= *ppos) {
+ *ppos = pkt.pos;
return pkt.dts;
}
}
@@ -2418,18 +2625,18 @@ MpegTSContext *ff_mpegts_parse_open(AVFormatContext *s)
}
/* return the consumed length if a packet was output, or -1 if no
- packet is output */
+ * packet is output */
int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
- const uint8_t *buf, int len)
+ const uint8_t *buf, int len)
{
int len1;
len1 = len;
ts->pkt = pkt;
- for(;;) {
+ for (;;) {
ts->stop_parse = 0;
if (len < TS_PACKET_SIZE)
- return -1;
+ return AVERROR_INVALIDDATA;
if (buf[0] != 0x47) {
buf++;
len--;
diff --git a/chromium/third_party/ffmpeg/libavformat/mpegts.h b/chromium/third_party/ffmpeg/libavformat/mpegts.h
index 269c23b9257..7dfe844bdb0 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpegts.h
+++ b/chromium/third_party/ffmpeg/libavformat/mpegts.h
@@ -52,12 +52,14 @@
#define STREAM_TYPE_AUDIO_AAC_LATM 0x11
#define STREAM_TYPE_VIDEO_MPEG4 0x10
#define STREAM_TYPE_VIDEO_H264 0x1b
+#define STREAM_TYPE_VIDEO_HEVC 0x24 //Definition of 0x24 HEVC video MPEG TS stream type
#define STREAM_TYPE_VIDEO_CAVS 0x42
#define STREAM_TYPE_VIDEO_VC1 0xea
#define STREAM_TYPE_VIDEO_DIRAC 0xd1
#define STREAM_TYPE_AUDIO_AC3 0x81
-#define STREAM_TYPE_AUDIO_DTS 0x8a
+#define STREAM_TYPE_AUDIO_DTS 0x82
+#define STREAM_TYPE_AUDIO_TRUEHD 0x83
typedef struct MpegTSContext MpegTSContext;
@@ -104,4 +106,10 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
Mp4Descr *mp4_descr, int mp4_descr_count, int pid,
MpegTSContext *ts);
+/**
+ * Check presence of H264 startcode
+ * @return <0 to stop processing
+ */
+int ff_check_h264_startcode(AVFormatContext *s, const AVStream *st, const AVPacket *pkt);
+
#endif /* AVFORMAT_MPEGTS_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c b/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c
index 1d51b97bdf0..48477614fed 100644
--- a/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c
@@ -86,6 +86,8 @@ typedef struct MpegTSWrite {
int flags;
int copyts;
int tables_version;
+
+ int omit_video_pes_length;
} MpegTSWrite;
/* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
@@ -124,6 +126,8 @@ static const AVOption options[] = {
offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "tables_version", "set PAT, PMT and SDT version",
offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AV_OPT_FLAG_ENCODING_PARAM},
+ { "omit_video_pes_length", "Omit the PES packet length for video packets",
+ offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL },
};
@@ -259,7 +263,7 @@ static void mpegts_write_pat(AVFormatContext *s)
data, q - data);
}
-static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
+static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
{
MpegTSWrite *ts = s->priv_data;
uint8_t data[1012], *q, *desc_length_ptr, *program_info_length_ptr;
@@ -292,6 +296,9 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
case AV_CODEC_ID_H264:
stream_type = STREAM_TYPE_VIDEO_H264;
break;
+ case AV_CODEC_ID_HEVC:
+ stream_type = STREAM_TYPE_VIDEO_HEVC;
+ break;
case AV_CODEC_ID_CAVS:
stream_type = STREAM_TYPE_VIDEO_CAVS;
break;
@@ -311,10 +318,20 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
case AV_CODEC_ID_AC3:
stream_type = STREAM_TYPE_AUDIO_AC3;
break;
+ case AV_CODEC_ID_DTS:
+ stream_type = STREAM_TYPE_AUDIO_DTS;
+ break;
+ case AV_CODEC_ID_TRUEHD:
+ stream_type = STREAM_TYPE_AUDIO_TRUEHD;
+ break;
default:
stream_type = STREAM_TYPE_PRIVATE_DATA;
break;
}
+
+ if (q - data > sizeof(data) - 32)
+ return AVERROR(EINVAL);
+
*q++ = stream_type;
put16(&q, 0xe000 | ts_st->pid);
desc_length_ptr = q;
@@ -346,7 +363,7 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
len_ptr = q++;
*len_ptr = 0;
- for (p = lang->value; next && *len_ptr < 255 / 4 * 4; p = next + 1) {
+ for (p = lang->value; next && *len_ptr < 255 / 4 * 4 && q - data < sizeof(data) - 4; p = next + 1) {
next = strchr(p, ',');
if (strlen(p) != 3 && (!next || next != p + 3))
continue; /* not a 3-letter code */
@@ -373,21 +390,79 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
break;
case AVMEDIA_TYPE_SUBTITLE:
{
- const char *language;
- language = lang && strlen(lang->value)==3 ? lang->value : "eng";
- *q++ = 0x59;
- *q++ = 8;
- *q++ = language[0];
- *q++ = language[1];
- *q++ = language[2];
- *q++ = 0x10; /* normal subtitles (0x20 = if hearing pb) */
- if(st->codec->extradata_size == 4) {
- memcpy(q, st->codec->extradata, 4);
- q += 4;
- } else {
- put16(&q, 1); /* page id */
- put16(&q, 1); /* ancillary page id */
- }
+ const char default_language[] = "und";
+ const char *language = lang && strlen(lang->value) >= 3 ? lang->value : default_language;
+
+ if (st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
+ uint8_t *len_ptr;
+ int extradata_copied = 0;
+
+ *q++ = 0x59; /* subtitling_descriptor */
+ len_ptr = q++;
+
+ while (strlen(language) >= 3 && (sizeof(data) - (q - data)) >= 8) { /* 8 bytes per DVB subtitle substream data */
+ *q++ = *language++;
+ *q++ = *language++;
+ *q++ = *language++;
+ /* Skip comma */
+ if (*language != '\0')
+ language++;
+
+ if (st->codec->extradata_size - extradata_copied >= 5) {
+ *q++ = st->codec->extradata[extradata_copied + 4]; /* subtitling_type */
+ memcpy(q, st->codec->extradata + extradata_copied, 4); /* composition_page_id and ancillary_page_id */
+ extradata_copied += 5;
+ q += 4;
+ } else {
+ /* subtitling_type:
+ * 0x10 - normal with no monitor aspect ratio criticality
+ * 0x20 - for the hard of hearing with no monitor aspect ratio criticality */
+ *q++ = (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) ? 0x20 : 0x10;
+ if ((st->codec->extradata_size == 4) && (extradata_copied == 0)) {
+ /* support of old 4-byte extradata format */
+ memcpy(q, st->codec->extradata, 4); /* composition_page_id and ancillary_page_id */
+ extradata_copied += 4;
+ q += 4;
+ } else {
+ put16(&q, 1); /* composition_page_id */
+ put16(&q, 1); /* ancillary_page_id */
+ }
+ }
+ }
+
+ *len_ptr = q - len_ptr - 1;
+ } else if (st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
+ uint8_t *len_ptr = NULL;
+ int extradata_copied = 0;
+
+ /* The descriptor tag. teletext_descriptor */
+ *q++ = 0x56;
+ len_ptr = q++;
+
+ while (strlen(language) >= 3 && q - data < sizeof(data) - 6) {
+ *q++ = *language++;
+ *q++ = *language++;
+ *q++ = *language++;
+ /* Skip comma */
+ if (*language != '\0')
+ language++;
+
+ if (st->codec->extradata_size - 1 > extradata_copied) {
+ memcpy(q, st->codec->extradata + extradata_copied, 2);
+ extradata_copied += 2;
+ q += 2;
+ } else {
+ /* The Teletext descriptor:
+ * teletext_type: This 5-bit field indicates the type of Teletext page indicated. (0x01 Initial Teletext page)
+ * teletext_magazine_number: This is a 3-bit field which identifies the magazine number.
+ * teletext_page_number: This is an 8-bit field giving two 4-bit hex digits identifying the page number. */
+ *q++ = 0x08;
+ *q++ = 0x00;
+ }
+ }
+
+ *len_ptr = q - len_ptr - 1;
+ }
}
break;
case AVMEDIA_TYPE_VIDEO:
@@ -418,6 +493,7 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
}
mpegts_write_section1(&service->pmt, PMT_TID, service->sid, ts->tables_version, 0, 0,
data, q - data);
+ return 0;
}
/* NOTE: str == NULL is accepted for an empty string */
@@ -562,7 +638,7 @@ static int mpegts_write_header(AVFormatContext *s)
ts->sdt.write_packet = section_write_packet;
ts->sdt.opaque = s;
- pids = av_malloc(s->nb_streams * sizeof(*pids));
+ pids = av_malloc_array(s->nb_streams, sizeof(*pids));
if (!pids)
return AVERROR(ENOMEM);
@@ -630,6 +706,10 @@ static int mpegts_write_header(AVFormatContext *s)
goto fail;
}
ast = avformat_new_stream(ts_st->amux, NULL);
+ if (!ast) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
ret = avcodec_copy_context(ast->codec, st->codec);
if (ret != 0)
goto fail;
@@ -859,7 +939,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
MpegTSWrite *ts = s->priv_data;
uint8_t buf[TS_PACKET_SIZE];
uint8_t *q;
- int val, is_start, len, header_len, write_pcr, private_code, flags;
+ int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
int afc_len, stuffing_len;
int64_t pcr = -1; /* avoid warning */
int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
@@ -923,11 +1003,13 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
}
if (is_start) {
int pes_extension = 0;
+ int pes_header_stuffing_bytes = 0;
/* write PES header */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 0x01;
- private_code = 0;
+ is_dvb_subtitle = 0;
+ is_dvb_teletext = 0;
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
if (st->codec->codec_id == AV_CODEC_ID_DIRAC) {
*q++ = 0xfd;
@@ -944,8 +1026,12 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
*q++ = 0xfd;
} else {
*q++ = 0xbd;
- if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- private_code = 0x20;
+ if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ if (st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
+ is_dvb_subtitle = 1;
+ } else if (st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
+ is_dvb_teletext = 1;
+ }
}
}
header_len = 0;
@@ -982,11 +1068,21 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
flags |= 0x01;
header_len += 3;
}
+ if (is_dvb_teletext) {
+ pes_header_stuffing_bytes = 0x24 - header_len;
+ header_len = 0x24;
+ }
len = payload_size + header_len + 3;
- if (private_code != 0)
- len++;
+ /* 3 extra bytes should be added to DVB subtitle payload: 0x20 0x00 at the beginning and trailing 0xff */
+ if (is_dvb_subtitle) {
+ len += 3;
+ payload_size++;
+ }
if (len > 0xffff)
len = 0;
+ if (ts->omit_video_pes_length && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ len = 0;
+ }
*q++ = len >> 8;
*q++ = len;
val = 0x80;
@@ -1025,8 +1121,17 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
}
- if (private_code != 0)
- *q++ = private_code;
+ if (is_dvb_subtitle) {
+ /* First two fields of DVB subtitles PES data:
+ * data_identifier: for DVB subtitle streams shall be coded with the value 0x20
+ * subtitle_stream_id: for DVB subtitle stream shall be identified by the value 0x00 */
+ *q++ = 0x20;
+ *q++ = 0x00;
+ }
+ if (is_dvb_teletext) {
+ memset(q, 0xff, pes_header_stuffing_bytes);
+ q += pes_header_stuffing_bytes;
+ }
is_start = 0;
}
/* header size */
@@ -1057,7 +1162,14 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
}
}
}
- memcpy(buf + TS_PACKET_SIZE - len, payload, len);
+
+ if (is_dvb_subtitle && payload_size == len) {
+ memcpy(buf + TS_PACKET_SIZE - len, payload, len - 1);
+ buf[TS_PACKET_SIZE - 1] = 0xff; /* end_of_PES_data_field_marker: an 8-bit field with fixed contents 0xff for DVB subtitle */
+ } else {
+ memcpy(buf + TS_PACKET_SIZE - len, payload, len);
+ }
+
payload += len;
payload_size -= len;
mpegts_prefix_m2ts_header(s);
@@ -1067,6 +1179,19 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
ts_st->prev_payload_key = key;
}
+int ff_check_h264_startcode(AVFormatContext *s, const AVStream *st, const AVPacket *pkt)
+{
+ if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) {
+ if (!st->nb_frames) {
+ av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, "
+ "no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)\n");
+ return AVERROR(EINVAL);
+ }
+ av_log(s, AV_LOG_WARNING, "H.264 bitstream error, startcode missing\n");
+ }
+ return 0;
+}
+
static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
{
AVStream *st = s->streams[pkt->stream_index];
@@ -1106,15 +1231,9 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
if (st->codec->codec_id == AV_CODEC_ID_H264) {
const uint8_t *p = buf, *buf_end = p+size;
uint32_t state = -1;
-
- if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) {
- if (!st->nb_frames) {
- av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, "
- "no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)\n");
- return AVERROR(EINVAL);
- }
- av_log(s, AV_LOG_WARNING, "H.264 bitstream error, startcode missing\n");
- }
+ int ret = ff_check_h264_startcode(s, st, pkt);
+ if (ret < 0)
+ return ret;
do {
p = avpriv_find_start_code(p, buf_end, &state);
diff --git a/chromium/third_party/ffmpeg/libavformat/mtv.c b/chromium/third_party/ffmpeg/libavformat/mtv.c
index 0517dd2d835..b449d5886f1 100644
--- a/chromium/third_party/ffmpeg/libavformat/mtv.c
+++ b/chromium/third_party/ffmpeg/libavformat/mtv.c
@@ -32,7 +32,8 @@
#define MTV_ASUBCHUNK_DATA_SIZE 500
#define MTV_HEADER_SIZE 512
#define MTV_AUDIO_PADDING_SIZE 12
-#define AUDIO_SAMPLING_RATE 44100
+#define MTV_IMAGE_DEFAULT_BPP 16
+#define MTV_AUDIO_SAMPLING_RATE 44100
typedef struct MTVDemuxContext {
@@ -52,12 +53,22 @@ typedef struct MTVDemuxContext {
static int mtv_probe(AVProbeData *p)
{
+ /* we need at least 57 bytes from the header
+ * to try parsing all required fields
+ */
+ if (p->buf_size < 57)
+ return 0;
+
/* Magic is 'AMV' */
if (*p->buf != 'A' || *(p->buf + 1) != 'M' || *(p->buf + 2) != 'V')
return 0;
+ /* Audio magic is always MP3 */
+ if (p->buf[43] != 'M' || p->buf[44] != 'P' || p->buf[45] != '3')
+ return 0;
+
/* Check for nonzero in bpp and (width|height) header fields */
- if(p->buf_size < 57 || !(p->buf[51] && AV_RL16(&p->buf[52]) | AV_RL16(&p->buf[54])))
+ if(!(p->buf[51] && AV_RL16(&p->buf[52]) | AV_RL16(&p->buf[54])))
return 0;
/* If width or height are 0 then imagesize header field should not */
@@ -69,8 +80,20 @@ static int mtv_probe(AVProbeData *p)
return 0;
}
- if(p->buf[51] != 16)
- return AVPROBE_SCORE_EXTENSION / 2; // But we are going to assume 16bpp anyway ..
+ /* Image bpp is not an absolutely required
+ * field as we latter claim it should be 16
+ * no matter what. All samples in the wild
+ * are RGB565/555.
+ */
+ if(p->buf[51] != MTV_IMAGE_DEFAULT_BPP)
+ return AVPROBE_SCORE_EXTENSION / 2;
+
+ /* We had enough data to parse header values
+ * but we expect to be able to get 512 bytes
+ * of header to be sure.
+ */
+ if (p->buf_size < MTV_HEADER_SIZE)
+ return AVPROBE_SCORE_EXTENSION;
return AVPROBE_SCORE_MAX;
}
@@ -89,22 +112,30 @@ static int mtv_read_header(AVFormatContext *s)
mtv->audio_identifier = avio_rl24(pb);
mtv->audio_br = avio_rl16(pb);
mtv->img_colorfmt = avio_rl24(pb);
- mtv->img_bpp = avio_r8(pb);
+ mtv->img_bpp = avio_r8(pb)>>3;
mtv->img_width = avio_rl16(pb);
mtv->img_height = avio_rl16(pb);
mtv->img_segment_size = avio_rl16(pb);
+ /* Assume 16bpp even if claimed otherwise.
+ * We know its going to be RGBG565/555 anyway
+ */
+ if (mtv->img_bpp != MTV_IMAGE_DEFAULT_BPP) {
+ av_log (s, AV_LOG_WARNING, "Header claims %dbpp (!= 16). Ignoring\n",
+ mtv->img_bpp);
+ mtv->img_bpp = MTV_IMAGE_DEFAULT_BPP;
+ }
+
/* Calculate width and height if missing from header */
- if(mtv->img_bpp>>3){
if(!mtv->img_width && mtv->img_height)
- mtv->img_width=mtv->img_segment_size / (mtv->img_bpp>>3)
+ mtv->img_width=mtv->img_segment_size / (mtv->img_bpp)
/ mtv->img_height;
if(!mtv->img_height && mtv->img_width)
- mtv->img_height=mtv->img_segment_size / (mtv->img_bpp>>3)
+ mtv->img_height=mtv->img_segment_size / (mtv->img_bpp)
/ mtv->img_width;
- }
+
if(!mtv->img_height || !mtv->img_width || !mtv->img_segment_size){
av_log(s, AV_LOG_ERROR, "width or height or segment_size is invalid and I cannot calculate them from other information\n");
return AVERROR(EINVAL);
@@ -149,7 +180,7 @@ static int mtv_read_header(AVFormatContext *s)
if(!st)
return AVERROR(ENOMEM);
- avpriv_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE);
+ avpriv_set_pts_info(st, 64, 1, MTV_AUDIO_SAMPLING_RATE);
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->codec_id = AV_CODEC_ID_MP3;
st->codec->bit_rate = mtv->audio_br;
diff --git a/chromium/third_party/ffmpeg/libavformat/mux.c b/chromium/third_party/ffmpeg/libavformat/mux.c
index 79625c6547c..a3a63f29a53 100644
--- a/chromium/third_party/ffmpeg/libavformat/mux.c
+++ b/chromium/third_party/ffmpeg/libavformat/mux.c
@@ -102,7 +102,7 @@ static void frac_add(AVFrac *f, int64_t incr)
f->num = num;
}
-AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precission)
+AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision)
{
AVRational q;
int j;
@@ -113,9 +113,9 @@ AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precissi
q = st->codec->time_base;
}
for (j=2; j<14; j+= 1+(j>2))
- while (q.den / q.num < min_precission && q.num % j == 0)
+ while (q.den / q.num < min_precision && q.num % j == 0)
q.num /= j;
- while (q.den / q.num < min_precission && q.den < (1<<24))
+ while (q.den / q.num < min_precision && q.den < (1<<24))
q.den <<= 1;
return q;
@@ -189,7 +189,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st)
const AVCodecTag *avctag;
int n;
enum AVCodecID id = AV_CODEC_ID_NONE;
- unsigned int tag = 0;
+ int64_t tag = -1;
/**
* Check that tag + id is in the table
@@ -212,7 +212,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st)
}
if (id != AV_CODEC_ID_NONE)
return 0;
- if (tag && (st->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL))
+ if (tag >= 0 && (st->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL))
return 0;
return 1;
}
@@ -232,12 +232,17 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
if ((ret = av_opt_set_dict(s, &tmp)) < 0)
goto fail;
if (s->priv_data && s->oformat->priv_class && *(const AVClass**)s->priv_data==s->oformat->priv_class &&
- (ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
+ (ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0)
goto fail;
+#if FF_API_LAVF_BITEXACT
+ if (s->nb_streams && s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)
+ s->flags |= AVFMT_FLAG_BITEXACT;
+#endif
+
// some sanity checks
if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) {
- av_log(s, AV_LOG_ERROR, "no streams\n");
+ av_log(s, AV_LOG_ERROR, "No streams to mux were specified\n");
ret = AVERROR(EINVAL);
goto fail;
}
@@ -320,6 +325,9 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
av_log(s, AV_LOG_WARNING,
"Codec for stream %d does not use global headers "
"but container format requires global headers\n", i);
+
+ if (codec->codec_type != AVMEDIA_TYPE_ATTACHMENT)
+ s->internal->nb_interleaved_streams++;
}
if (!s->priv_data && of->priv_data_size > 0) {
@@ -331,13 +339,13 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
if (of->priv_class) {
*(const AVClass **)s->priv_data = of->priv_class;
av_opt_set_defaults(s->priv_data);
- if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
+ if ((ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0)
goto fail;
}
}
/* set muxer identification string */
- if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+ if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0);
} else {
av_dict_set(&s->metadata, "encoder", NULL, 0);
@@ -414,6 +422,15 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
return 0;
}
+#define AV_PKT_FLAG_UNCODED_FRAME 0x2000
+
+/* Note: using sizeof(AVFrame) from outside lavu is unsafe in general, but
+ it is only being used internally to this file as a consistency check.
+ The value is chosen to be very unlikely to appear on its own and to cause
+ immediate failure if used anywhere as a real size. */
+#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame))
+
+
//FIXME merge with compute_pkt_fields
static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
@@ -423,6 +440,12 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
av_dlog(s, "compute_pkt_fields2: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n",
av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index);
+ if (pkt->duration < 0 && st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+ av_log(s, AV_LOG_WARNING, "Packet with invalid duration %d in stream %d\n",
+ pkt->duration, pkt->stream_index);
+ pkt->duration = 0;
+ }
+
/* duration field */
if (pkt->duration == 0) {
ff_compute_frame_duration(&num, &den, st, NULL, pkt);
@@ -479,7 +502,9 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
/* update pts */
switch (st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- frame_size = ff_get_audio_frame_size(st->codec, pkt->size, 1);
+ frame_size = (pkt->flags & AV_PKT_FLAG_UNCODED_FRAME) ?
+ ((AVFrame *)pkt->data)->nb_samples :
+ ff_get_audio_frame_size(st->codec, pkt->size, 1);
/* HACK/FIXME, we skip the initial 0 size packets as they are most
* likely equal to the encoder delay, but it would be better if we
@@ -510,11 +535,21 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, did_split;
+ if (s->output_ts_offset) {
+ AVStream *st = s->streams[pkt->stream_index];
+ int64_t offset = av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base);
+
+ if (pkt->dts != AV_NOPTS_VALUE)
+ pkt->dts += offset;
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts += offset;
+ }
+
if (s->avoid_negative_ts > 0) {
AVStream *st = s->streams[pkt->stream_index];
int64_t offset = st->mux_ts_offset;
- if (pkt->dts < 0 && pkt->dts != AV_NOPTS_VALUE && !s->offset) {
+ if ((pkt->dts < 0 || s->avoid_negative_ts == 2) && pkt->dts != AV_NOPTS_VALUE && !s->offset) {
s->offset = -pkt->dts;
s->offset_timebase = st->time_base;
}
@@ -536,7 +571,14 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
}
did_split = av_packet_split_side_data(pkt);
- ret = s->oformat->write_packet(s, pkt);
+ if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
+ AVFrame *frame = (AVFrame *)pkt->data;
+ av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
+ ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, &frame, 0);
+ av_frame_free(&frame);
+ } else {
+ ret = s->oformat->write_packet(s, pkt);
+ }
if (s->flush_packets && s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
avio_flush(s->pb);
@@ -547,10 +589,33 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}
+static int check_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ if (!pkt)
+ return 0;
+
+ if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) {
+ av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d\n",
+ pkt->stream_index);
+ return AVERROR(EINVAL);
+ }
+
+ if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
+ av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n");
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
{
int ret;
+ ret = check_packet(s, pkt);
+ if (ret < 0)
+ return ret;
+
if (!pkt) {
if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {
ret = s->oformat->write_packet(s, NULL);
@@ -585,6 +650,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
AVPacketList **next_point, *this_pktl;
AVStream *st = s->streams[pkt->stream_index];
int chunked = s->max_chunk_size || s->max_chunk_duration;
+ int ret;
this_pktl = av_mallocz(sizeof(AVPacketList));
if (!this_pktl)
@@ -596,8 +662,17 @@ FF_DISABLE_DEPRECATION_WARNINGS
FF_ENABLE_DEPRECATION_WARNINGS
#endif
pkt->buf = NULL;
- av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory
- av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data
+ if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
+ av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
+ av_assert0(((AVFrame *)pkt->data)->buf);
+ } else {
+ // duplicate the packet if it uses non-allocated memory
+ if ((ret = av_dup_packet(&this_pktl->pkt)) < 0) {
+ av_free(this_pktl);
+ return ret;
+ }
+ av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data
+ }
if (s->streams[pkt->stream_index]->last_in_packet_buffer) {
next_point = &(st->last_in_packet_buffer->next);
@@ -677,7 +752,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
{
AVPacketList *pktl;
int stream_count = 0, noninterleaved_count = 0;
- int64_t delta_dts_max = 0;
int i, ret;
if (pkt) {
@@ -694,27 +768,38 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
}
}
- if (s->nb_streams == stream_count) {
+ if (s->internal->nb_interleaved_streams == stream_count)
flush = 1;
- } else if (!flush) {
- for (i=0; i < s->nb_streams; i++) {
- if (s->streams[i]->last_in_packet_buffer) {
- int64_t delta_dts =
- av_rescale_q(s->streams[i]->last_in_packet_buffer->pkt.dts,
- s->streams[i]->time_base,
- AV_TIME_BASE_Q) -
- av_rescale_q(s->packet_buffer->pkt.dts,
- s->streams[s->packet_buffer->pkt.stream_index]->time_base,
- AV_TIME_BASE_Q);
- delta_dts_max= FFMAX(delta_dts_max, delta_dts);
- }
+
+ if (s->max_interleave_delta > 0 && s->packet_buffer && !flush) {
+ AVPacket *top_pkt = &s->packet_buffer->pkt;
+ int64_t delta_dts = INT64_MIN;
+ int64_t top_dts = av_rescale_q(top_pkt->dts,
+ s->streams[top_pkt->stream_index]->time_base,
+ AV_TIME_BASE_Q);
+
+ for (i = 0; i < s->nb_streams; i++) {
+ int64_t last_dts;
+ const AVPacketList *last = s->streams[i]->last_in_packet_buffer;
+
+ if (!last)
+ continue;
+
+ last_dts = av_rescale_q(last->pkt.dts,
+ s->streams[i]->time_base,
+ AV_TIME_BASE_Q);
+ delta_dts = FFMAX(delta_dts, last_dts - top_dts);
}
- if (s->nb_streams == stream_count+noninterleaved_count &&
- delta_dts_max > 20*AV_TIME_BASE) {
- av_log(s, AV_LOG_DEBUG, "flushing with %d noninterleaved\n", noninterleaved_count);
+
+ if (delta_dts > s->max_interleave_delta) {
+ av_log(s, AV_LOG_DEBUG,
+ "Delay between the first packet and last packet in the "
+ "muxing queue is %"PRId64" > %"PRId64": forcing output\n",
+ delta_dts, s->max_interleave_delta);
flush = 1;
}
}
+
if (stream_count && flush) {
AVStream *st;
pktl = s->packet_buffer;
@@ -760,20 +845,22 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
{
int ret, flush = 0;
+ ret = check_packet(s, pkt);
+ if (ret < 0)
+ goto fail;
+
if (pkt) {
AVStream *st = s->streams[pkt->stream_index];
- //FIXME/XXX/HACK drop zero sized packets
- if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size == 0)
- return 0;
-
av_dlog(s, "av_interleaved_write_frame size:%d dts:%s pts:%s\n",
pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts));
if ((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
- return ret;
+ goto fail;
- if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
- return AVERROR(EINVAL);
+ if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
} else {
av_dlog(s, "av_interleaved_write_frame FLUSH\n");
flush = 1;
@@ -782,6 +869,11 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
for (;; ) {
AVPacket opkt;
int ret = interleave_packet(s, &opkt, pkt, flush);
+ if (pkt) {
+ memset(pkt, 0, sizeof(*pkt));
+ av_init_packet(pkt);
+ pkt = NULL;
+ }
if (ret <= 0) //FIXME cleanup needed for ret<0 ?
return ret;
@@ -790,13 +882,15 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
s->streams[opkt.stream_index]->nb_frames++;
av_free_packet(&opkt);
- pkt = NULL;
if (ret < 0)
return ret;
if(s->pb && s->pb->error)
return s->pb->error;
}
+fail:
+ av_packet_unref(pkt);
+ return ret;
}
int av_write_trailer(AVFormatContext *s)
@@ -871,3 +965,51 @@ int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt,
dst->streams[dst_stream]->time_base);
return av_write_frame(dst, &local_pkt);
}
+
+static int av_write_uncoded_frame_internal(AVFormatContext *s, int stream_index,
+ AVFrame *frame, int interleaved)
+{
+ AVPacket pkt, *pktp;
+
+ av_assert0(s->oformat);
+ if (!s->oformat->write_uncoded_frame)
+ return AVERROR(ENOSYS);
+
+ if (!frame) {
+ pktp = NULL;
+ } else {
+ pktp = &pkt;
+ av_init_packet(&pkt);
+ pkt.data = (void *)frame;
+ pkt.size = UNCODED_FRAME_PACKET_SIZE;
+ pkt.pts =
+ pkt.dts = frame->pts;
+ pkt.duration = av_frame_get_pkt_duration(frame);
+ pkt.stream_index = stream_index;
+ pkt.flags |= AV_PKT_FLAG_UNCODED_FRAME;
+ }
+
+ return interleaved ? av_interleaved_write_frame(s, pktp) :
+ av_write_frame(s, pktp);
+}
+
+int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
+ AVFrame *frame)
+{
+ return av_write_uncoded_frame_internal(s, stream_index, frame, 0);
+}
+
+int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
+ AVFrame *frame)
+{
+ return av_write_uncoded_frame_internal(s, stream_index, frame, 1);
+}
+
+int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index)
+{
+ av_assert0(s->oformat);
+ if (!s->oformat->write_uncoded_frame)
+ return AVERROR(ENOSYS);
+ return s->oformat->write_uncoded_frame(s, stream_index, NULL,
+ AV_WRITE_UNCODED_FRAME_QUERY);
+}
diff --git a/chromium/third_party/ffmpeg/libavformat/mvdec.c b/chromium/third_party/ffmpeg/libavformat/mvdec.c
index 5525233db56..6e7c3ffd113 100644
--- a/chromium/third_party/ffmpeg/libavformat/mvdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/mvdec.c
@@ -24,48 +24,55 @@
* Silicon Graphics Movie demuxer
*/
+#include "libavutil/channel_layout.h"
#include "libavutil/eval.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/rational.h"
+
#include "avformat.h"
#include "internal.h"
-typedef struct {
+typedef struct MvContext {
int nb_video_tracks;
int nb_audio_tracks;
- int eof_count; /**< number of streams that have finished */
- int stream_index; /**< current stream index */
- int frame[2]; /**< frame nb for current stream */
+ int eof_count; ///< number of streams that have finished
+ int stream_index; ///< current stream index
+ int frame[2]; ///< frame nb for current stream
+
+ int acompression; ///< compression level for audio stream
+ int aformat; ///< audio format
} MvContext;
#define AUDIO_FORMAT_SIGNED 401
static int mv_probe(AVProbeData *p)
{
- if (AV_RB32(p->buf) == MKBETAG('M','O','V','I') && AV_RB16(p->buf + 4) < 3)
+ if (AV_RB32(p->buf) == MKBETAG('M', 'O', 'V', 'I') &&
+ AV_RB16(p->buf + 4) < 3)
return AVPROBE_SCORE_MAX;
return 0;
}
-static char * var_read_string(AVIOContext *pb, int size)
+static char *var_read_string(AVIOContext *pb, int size)
{
- char *str = av_malloc(size + 1);
int n;
+ char *str = av_malloc(size + 1);
if (!str)
return NULL;
n = avio_get_str(pb, size, str, size + 1);
if (n < size)
- avio_skip(pb, size - n);
+ avio_skip(pb, size - n);
return str;
}
static int var_read_int(AVIOContext *pb, int size)
{
int v;
- char * s = var_read_string(pb, size);
- if (!s || sscanf(s, "%d", &v) != 1)
- v = 0;
+ char *s = var_read_string(pb, size);
+ if (!s)
+ return 0;
+ v = strtol(s, NULL, 10);
av_free(s);
return v;
}
@@ -73,9 +80,9 @@ static int var_read_int(AVIOContext *pb, int size)
static AVRational var_read_float(AVIOContext *pb, int size)
{
AVRational v;
- char * s = var_read_string(pb, size);
+ char *s = var_read_string(pb, size);
if (!s)
- return (AVRational){0, 0};
+ return (AVRational) { 0, 0 };
v = av_d2q(av_strtod(s, NULL), INT_MAX);
av_free(s);
return v;
@@ -88,13 +95,15 @@ static void var_read_metadata(AVFormatContext *avctx, const char *tag, int size)
av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL);
}
-static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) {
+static int set_channels(AVFormatContext *avctx, AVStream *st, int channels)
+{
if (channels <= 0) {
- av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid\n", channels);
+ av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels);
return AVERROR_INVALIDDATA;
}
- st->codec->channels = channels;
- st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+ st->codec->channels = channels;
+ st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO
+ : AV_CH_LAYOUT_STEREO;
return 0;
}
@@ -102,7 +111,8 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) {
* Parse global variable
* @return < 0 if unknown
*/
-static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
+static int parse_global_var(AVFormatContext *avctx, AVStream *st,
+ const char *name, int size)
{
MvContext *mv = avctx->priv_data;
AVIOContext *pb = avctx->pb;
@@ -112,10 +122,11 @@ static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *na
mv->nb_audio_tracks = var_read_int(pb, size);
} else if (!strcmp(name, "COMMENT") || !strcmp(name, "TITLE")) {
var_read_metadata(avctx, name, size);
- } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") || !strcmp(name, "OPTIMIZED")) {
+ } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") ||
+ !strcmp(name, "OPTIMIZED")) {
avio_skip(pb, size); // ignore
} else
- return -1;
+ return AVERROR_INVALIDDATA;
return 0;
}
@@ -124,15 +135,17 @@ static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *na
* Parse audio variable
* @return < 0 if unknown
*/
-static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
+static int parse_audio_var(AVFormatContext *avctx, AVStream *st,
+ const char *name, int size)
{
+ MvContext *mv = avctx->priv_data;
AVIOContext *pb = avctx->pb;
if (!strcmp(name, "__DIR_COUNT")) {
st->nb_frames = var_read_int(pb, size);
} else if (!strcmp(name, "AUDIO_FORMAT")) {
- st->codec->codec_id = var_read_int(pb, size);
+ mv->aformat = var_read_int(pb, size);
} else if (!strcmp(name, "COMPRESSION")) {
- st->codec->codec_tag = var_read_int(pb, size);
+ mv->acompression = var_read_int(pb, size);
} else if (!strcmp(name, "DEFAULT_VOL")) {
var_read_metadata(avctx, name, size);
} else if (!strcmp(name, "NUM_CHANNELS")) {
@@ -143,7 +156,8 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *nam
} else if (!strcmp(name, "SAMPLE_WIDTH")) {
st->codec->bits_per_coded_sample = var_read_int(pb, size) * 8;
} else
- return -1;
+ return AVERROR_INVALIDDATA;
+
return 0;
}
@@ -151,13 +165,14 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *nam
* Parse video variable
* @return < 0 if unknown
*/
-static int parse_video_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
+static int parse_video_var(AVFormatContext *avctx, AVStream *st,
+ const char *name, int size)
{
AVIOContext *pb = avctx->pb;
if (!strcmp(name, "__DIR_COUNT")) {
st->nb_frames = st->duration = var_read_int(pb, size);
} else if (!strcmp(name, "COMPRESSION")) {
- char * str = var_read_string(pb, size);
+ char *str = var_read_string(pb, size);
if (!str)
return AVERROR_INVALIDDATA;
if (!strcmp(str, "1")) {
@@ -172,35 +187,40 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st, const char *nam
} else if (!strcmp(str, "MVC2")) {
st->codec->codec_id = AV_CODEC_ID_MVC2;
} else {
- avpriv_request_sample(avctx, "video compression %s", str);
+ avpriv_request_sample(avctx, "Video compression %s", str);
}
av_free(str);
} else if (!strcmp(name, "FPS")) {
AVRational fps = var_read_float(pb, size);
avpriv_set_pts_info(st, 64, fps.den, fps.num);
+ st->avg_frame_rate = fps;
} else if (!strcmp(name, "HEIGHT")) {
st->codec->height = var_read_int(pb, size);
} else if (!strcmp(name, "PIXEL_ASPECT")) {
st->sample_aspect_ratio = var_read_float(pb, size);
av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
- st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, INT_MAX);
+ st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
+ INT_MAX);
} else if (!strcmp(name, "WIDTH")) {
st->codec->width = var_read_int(pb, size);
} else if (!strcmp(name, "ORIENTATION")) {
if (var_read_int(pb, size) == 1101) {
- st->codec->extradata = av_strdup("BottomUp");
- st->codec->extradata_size = 9;
+ st->codec->extradata = av_strdup("BottomUp");
+ st->codec->extradata_size = 9;
}
} else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) {
var_read_metadata(avctx, name, size);
} else if (!strcmp(name, "INTERLACING") || !strcmp(name, "PACKING")) {
avio_skip(pb, size); // ignore
} else
- return -1;
+ return AVERROR_INVALIDDATA;
+
return 0;
}
-static void read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size))
+static void read_table(AVFormatContext *avctx, AVStream *st,
+ int (*parse)(AVFormatContext *avctx, AVStream *st,
+ const char *name, int size))
{
int count, i;
AVIOContext *pb = avctx->pb;
@@ -214,7 +234,7 @@ static void read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVForm
name[sizeof(name) - 1] = 0;
size = avio_rb32(pb);
if (parse(avctx, st, name, size) < 0) {
- avpriv_request_sample(avctx, "variable %s", name);
+ avpriv_request_sample(avctx, "Variable %s", name);
avio_skip(pb, size);
}
}
@@ -253,7 +273,7 @@ static int mv_read_header(AVFormatContext *avctx)
avio_skip(pb, 22);
/* allocate audio track first to prevent unnecessary seeking
- (audio packet always precede video packet for a given frame) */
+ * (audio packet always precede video packet for a given frame) */
ast = avformat_new_stream(avctx, NULL);
if (!ast)
return AVERROR(ENOMEM);
@@ -261,9 +281,10 @@ static int mv_read_header(AVFormatContext *avctx)
vst = avformat_new_stream(avctx, NULL);
if (!vst)
return AVERROR(ENOMEM);
- vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
avpriv_set_pts_info(vst, 64, 1, 15);
- vst->nb_frames = avio_rb32(pb);
+ vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ vst->avg_frame_rate = av_inv_q(vst->time_base);
+ vst->nb_frames = avio_rb32(pb);
v = avio_rb32(pb);
switch (v) {
case 1:
@@ -274,7 +295,7 @@ static int mv_read_header(AVFormatContext *avctx)
vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
break;
default:
- avpriv_request_sample(avctx, "video compression %i", v);
+ avpriv_request_sample(avctx, "Video compression %i", v);
break;
}
vst->codec->codec_tag = 0;
@@ -282,9 +303,9 @@ static int mv_read_header(AVFormatContext *avctx)
vst->codec->height = avio_rb32(pb);
avio_skip(pb, 12);
- ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- ast->nb_frames = vst->nb_frames;
- ast->codec->sample_rate = avio_rb32(pb);
+ ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ ast->nb_frames = vst->nb_frames;
+ ast->codec->sample_rate = avio_rb32(pb);
avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate);
if (set_channels(avctx, ast, avio_rb32(pb)) < 0)
return AVERROR_INVALIDDATA;
@@ -293,7 +314,7 @@ static int mv_read_header(AVFormatContext *avctx)
if (v == AUDIO_FORMAT_SIGNED) {
ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
} else {
- avpriv_request_sample(avctx, "audio compression (format %i)", v);
+ avpriv_request_sample(avctx, "Audio compression (format %i)", v);
}
avio_skip(pb, 12);
@@ -307,8 +328,8 @@ static int mv_read_header(AVFormatContext *avctx)
uint32_t asize = avio_rb32(pb);
uint32_t vsize = avio_rb32(pb);
avio_skip(pb, 8);
- av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME);
- av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME);
+ av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME);
+ av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME);
timestamp += asize / (ast->codec->channels * 2);
}
} else if (!version && avio_rb16(pb) == 3) {
@@ -317,31 +338,33 @@ static int mv_read_header(AVFormatContext *avctx)
read_table(avctx, NULL, parse_global_var);
if (mv->nb_audio_tracks > 1) {
- avpriv_request_sample(avctx, "multiple audio streams support");
+ avpriv_request_sample(avctx, "Multiple audio streams support");
return AVERROR_PATCHWELCOME;
} else if (mv->nb_audio_tracks) {
ast = avformat_new_stream(avctx, NULL);
if (!ast)
return AVERROR(ENOMEM);
ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- /* temporarily store compression value in codec_tag; format value in codec_id */
read_table(avctx, ast, parse_audio_var);
- if (ast->codec->codec_tag == 100 && ast->codec->codec_id == AUDIO_FORMAT_SIGNED && ast->codec->bits_per_coded_sample == 16) {
+ if (mv->acompression == 100 &&
+ mv->aformat == AUDIO_FORMAT_SIGNED &&
+ ast->codec->bits_per_coded_sample == 16) {
ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
} else {
- avpriv_request_sample(avctx, "audio compression %i (format %i, width %i)",
- ast->codec->codec_tag, ast->codec->codec_id, ast->codec->bits_per_coded_sample);
+ avpriv_request_sample(avctx,
+ "Audio compression %i (format %i, sr %i)",
+ mv->acompression, mv->aformat,
+ ast->codec->bits_per_coded_sample);
ast->codec->codec_id = AV_CODEC_ID_NONE;
}
- ast->codec->codec_tag = 0;
if (ast->codec->channels <= 0) {
- av_log(avctx, AV_LOG_ERROR, "No valid channel count found\n");
+ av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n");
return AVERROR_INVALIDDATA;
}
}
if (mv->nb_video_tracks > 1) {
- avpriv_request_sample(avctx, "multiple video streams support");
+ avpriv_request_sample(avctx, "Multiple video streams support");
return AVERROR_PATCHWELCOME;
} else if (mv->nb_video_tracks) {
vst = avformat_new_stream(avctx, NULL);
@@ -357,7 +380,7 @@ static int mv_read_header(AVFormatContext *avctx)
if (mv->nb_video_tracks)
read_index(pb, vst);
} else {
- avpriv_request_sample(avctx, "version %i", version);
+ avpriv_request_sample(avctx, "Version %i", version);
return AVERROR_PATCHWELCOME;
}
@@ -374,9 +397,9 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
int ret;
uint64_t pos;
- if (frame < st->nb_index_entries) {
+ if (frame < st->nb_index_entries) {
index = &st->index_entries[frame];
- pos = avio_tell(pb);
+ pos = avio_tell(pb);
if (index->pos > pos)
avio_skip(pb, index->pos - pos);
else if (index->pos < pos) {
@@ -391,8 +414,8 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
return ret;
pkt->stream_index = mv->stream_index;
- pkt->pts = index->timestamp;
- pkt->flags |= AV_PKT_FLAG_KEY;
+ pkt->pts = index->timestamp;
+ pkt->flags |= AV_PKT_FLAG_KEY;
mv->frame[mv->stream_index]++;
mv->eof_count = 0;
@@ -400,6 +423,9 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
mv->eof_count++;
if (mv->eof_count >= avctx->nb_streams)
return AVERROR_EOF;
+
+ // avoid returning 0 without a packet
+ return AVERROR(EAGAIN);
}
mv->stream_index++;
@@ -409,7 +435,8 @@ static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
return 0;
}
-static int mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
+static int mv_read_seek(AVFormatContext *avctx, int stream_index,
+ int64_t timestamp, int flags)
{
MvContext *mv = avctx->priv_data;
AVStream *st = avctx->streams[stream_index];
@@ -423,7 +450,7 @@ static int mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timest
frame = av_index_search_timestamp(st, timestamp, flags);
if (frame < 0)
- return -1;
+ return AVERROR_INVALIDDATA;
for (i = 0; i < avctx->nb_streams; i++)
mv->frame[i] = frame;
diff --git a/chromium/third_party/ffmpeg/libavformat/mvi.c b/chromium/third_party/ffmpeg/libavformat/mvi.c
index 5efc4431524..a7cfcb9a7a5 100644
--- a/chromium/third_party/ffmpeg/libavformat/mvi.c
+++ b/chromium/third_party/ffmpeg/libavformat/mvi.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
@@ -95,7 +97,8 @@ static int read_header(AVFormatContext *s)
mvi->audio_frame_size = ((uint64_t)mvi->audio_data_size << MVI_FRAC_BITS) / frames_count;
if (mvi->audio_frame_size <= 1 << MVI_FRAC_BITS - 1) {
- av_log(s, AV_LOG_ERROR, "Invalid audio_data_size (%d) or frames_count (%d)\n",
+ av_log(s, AV_LOG_ERROR,
+ "Invalid audio_data_size (%"PRIu32") or frames_count (%u)\n",
mvi->audio_data_size, frames_count);
return AVERROR_INVALIDDATA;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mxf.c b/chromium/third_party/ffmpeg/libavformat/mxf.c
index 4a4158a1d33..d20ed946ac6 100644
--- a/chromium/third_party/ffmpeg/libavformat/mxf.c
+++ b/chromium/third_party/ffmpeg/libavformat/mxf.c
@@ -45,6 +45,7 @@ const MXFCodecUL ff_mxf_codec_uls[] = {
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x71,0x00,0x00,0x00 }, 13, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x03,0x02,0x00,0x00 }, 14, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC SPS/PPS in-band */
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x01 }, 16, AV_CODEC_ID_V210 }, /* V210 */
/* SoundEssenceCompression */
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */
@@ -107,7 +108,7 @@ int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *
return -1;
}
-static const MXFSamplesPerFrame mxf_samples_per_frames[] = {
+static const MXFSamplesPerFrame mxf_spf[] = {
{ { 1001, 24000 }, { 2002, 0, 0, 0, 0, 0 } }, // FILM 23.976
{ { 1, 24}, { 2000, 0, 0, 0, 0, 0 } }, // FILM 24
{ { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97
@@ -116,22 +117,33 @@ static const MXFSamplesPerFrame mxf_samples_per_frames[] = {
{ { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50
};
-const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base)
+static const AVRational mxf_time_base[] = {
+ { 1001, 24000 },
+ { 1, 24},
+ { 1001, 30000 },
+ { 1001, 60000 },
+ { 1, 25 },
+ { 1, 50 },
+ { 0, 0}
+};
+
+const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s,
+ AVRational time_base)
{
- int i;
- for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) {
- if (!av_cmp_q(mxf_samples_per_frames[i].time_base, time_base))
- return &mxf_samples_per_frames[i];
- }
+ int idx = av_find_nearest_q_idx(time_base, mxf_time_base);
+ AVRational diff = av_sub_q(time_base, mxf_time_base[idx]);
- // Find closest container time base for approximative codec time base like 1/29.97, 1/30, ...
- for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) {
- if (fabs(av_q2d(mxf_samples_per_frames[i].time_base) - av_q2d(time_base)) < 0.0001) {
- av_log(s, AV_LOG_WARNING, "%d/%d input time base matched %d/%d container time base\n",
- time_base.num, time_base.den,
- mxf_samples_per_frames[i].time_base.num, mxf_samples_per_frames[i].time_base.den);
- return &mxf_samples_per_frames[i];
- }
- }
- return NULL;
+ diff.num = abs(diff.num);
+
+ if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0)
+ return NULL;
+
+ if (av_cmp_q(time_base, mxf_time_base[idx]))
+ av_log(s, AV_LOG_WARNING,
+ "%d/%d input time base matched %d/%d container time base\n",
+ time_base.num, time_base.den,
+ mxf_spf[idx].time_base.num,
+ mxf_spf[idx].time_base.den);
+
+ return &mxf_spf[idx];
}
diff --git a/chromium/third_party/ffmpeg/libavformat/mxf.h b/chromium/third_party/ffmpeg/libavformat/mxf.h
index 4c751e8eef8..cf7ec0bab59 100644
--- a/chromium/third_party/ffmpeg/libavformat/mxf.h
+++ b/chromium/third_party/ffmpeg/libavformat/mxf.h
@@ -79,7 +79,32 @@ extern const MXFCodecUL ff_mxf_pixel_format_uls[];
int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt);
const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base);
-#define PRINT_KEY(pc, s, x) av_dlog(pc, "%s %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", s, \
- (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15])
+#ifdef DEBUG
+#define PRINT_KEY(pc, s, x) \
+ av_log(pc, AV_LOG_VERBOSE, \
+ "%s " \
+ "0x%02x,0x%02x,0x%02x,0x%02x," \
+ "0x%02x,0x%02x,0x%02x,0x%02x," \
+ "0x%02x,0x%02x,0x%02x,0x%02x," \
+ "0x%02x,0x%02x,0x%02x,0x%02x ", \
+ s, \
+ (x)[0], (x)[1], (x)[2], (x)[3], \
+ (x)[4], (x)[5], (x)[6], (x)[7], \
+ (x)[8], (x)[9], (x)[10], (x)[11], \
+ (x)[12], (x)[13], (x)[14], (x)[15]); \
+ av_log(pc, AV_LOG_INFO, \
+ "%s " \
+ "%02x.%02x.%02x.%02x." \
+ "%02x.%02x.%02x.%02x." \
+ "%02x.%02x.%02x.%02x." \
+ "%02x.%02x.%02x.%02x\n", \
+ s, \
+ (x)[0], (x)[1], (x)[2], (x)[3], \
+ (x)[4], (x)[5], (x)[6], (x)[7], \
+ (x)[8], (x)[9], (x)[10], (x)[11], \
+ (x)[12], (x)[13], (x)[14], (x)[15])
+#else
+#define PRINT_KEY(pc, s, x)
+#endif
#endif /* AVFORMAT_MXF_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/mxfdec.c b/chromium/third_party/ffmpeg/libavformat/mxfdec.c
index 61c0cb2366b..0d17a029640 100644
--- a/chromium/third_party/ffmpeg/libavformat/mxfdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/mxfdec.c
@@ -43,7 +43,7 @@
* Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1
*/
-#include <stdint.h>
+#include <inttypes.h>
#include "libavutil/aes.h"
#include "libavutil/avassert.h"
@@ -135,7 +135,7 @@ typedef struct {
AVRational edit_rate;
int intra_only;
uint64_t sample_count;
- int64_t original_duration; ///< duration before multiplying st->duration by SampleRate/EditRate
+ int64_t original_duration; /* st->duration in SampleRate/EditRate units */
} MXFTrack;
typedef struct {
@@ -148,9 +148,11 @@ typedef struct {
int width;
int height; /* Field height, not frame height */
int frame_layout; /* See MXFFrameLayout enum */
+#define MXF_TFF 1
+#define MXF_BFF 2
+ int field_dominance;
int channels;
int bits_per_sample;
- int field_dominance;
unsigned int component_depth;
unsigned int horiz_subsampling;
unsigned int vert_subsampling;
@@ -252,13 +254,13 @@ static int mxf_read_close(AVFormatContext *s);
static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
static const uint8_t mxf_avid_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0e,0x04,0x03,0x01 };
-static const uint8_t mxf_system_item_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x03,0x01,0x04 };
+static const uint8_t mxf_system_item_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 };
static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 };
/* complete keys to match */
static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 };
static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 };
static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 };
-static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 };
+static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x11,0x01,0x00 };
static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 };
#define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
@@ -331,7 +333,7 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt,
data_ptr = pkt->data;
end_ptr = pkt->data + length;
buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */
- for (; buf_ptr + st->codec->channels*4 <= end_ptr; ) {
+ for (; end_ptr - buf_ptr >= st->codec->channels * 4; ) {
for (i = 0; i < st->codec->channels; i++) {
uint32_t sample = bytestream_get_le32(&buf_ptr);
if (st->codec->bits_per_coded_sample == 24)
@@ -487,9 +489,32 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
partition->index_sid = avio_rb32(pb);
avio_skip(pb, 8);
partition->body_sid = avio_rb32(pb);
- avio_read(pb, op, sizeof(UID));
+ if (avio_read(pb, op, sizeof(UID)) != sizeof(UID)) {
+ av_log(mxf->fc, AV_LOG_ERROR, "Failed reading UID\n");
+ return AVERROR_INVALIDDATA;
+ }
nb_essence_containers = avio_rb32(pb);
+ if (partition->this_partition &&
+ partition->previous_partition == partition->this_partition) {
+ av_log(mxf->fc, AV_LOG_ERROR,
+ "PreviousPartition equal to ThisPartition %"PRIx64"\n",
+ partition->previous_partition);
+ /* override with the actual previous partition offset */
+ if (!mxf->parsing_backward && mxf->last_forward_partition > 1) {
+ MXFPartition *prev =
+ mxf->partitions + mxf->last_forward_partition - 2;
+ partition->previous_partition = prev->this_partition;
+ }
+ /* if no previous body partition are found point to the header
+ * partition */
+ if (partition->previous_partition == partition->this_partition)
+ partition->previous_partition = 0;
+ av_log(mxf->fc, AV_LOG_ERROR,
+ "Overriding PreviousPartition with %"PRIx64"\n",
+ partition->previous_partition);
+ }
+
/* some files don'thave FooterPartition set in every partition */
if (footer_partition) {
if (mxf->footer_partition && mxf->footer_partition != footer_partition) {
@@ -537,8 +562,10 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
/* only nag once */
if (!mxf->op)
- av_log(mxf->fc, AV_LOG_WARNING, "\"OPAtom\" with %u ECs - assuming %s\n",
- nb_essence_containers, op == OP1a ? "OP1a" : "OPAtom");
+ av_log(mxf->fc, AV_LOG_WARNING,
+ "\"OPAtom\" with %"PRIu32" ECs - assuming %s\n",
+ nb_essence_containers,
+ op == OP1a ? "OP1a" : "OPAtom");
mxf->op = op;
} else
@@ -549,14 +576,15 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
}
if (partition->kag_size <= 0 || partition->kag_size > (1 << 20)) {
- av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %i - guessing ", partition->kag_size);
+ av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %"PRId32" - guessing ",
+ partition->kag_size);
if (mxf->op == OPSONYOpt)
partition->kag_size = 512;
else
partition->kag_size = 1;
- av_log(mxf->fc, AV_LOG_WARNING, "%i\n", partition->kag_size);
+ av_log(mxf->fc, AV_LOG_WARNING, "%"PRId32"\n", partition->kag_size);
}
return 0;
@@ -666,7 +694,7 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid
case 0x4804:
avio_read(pb, track->track_number, 4);
break;
- case 0x4B01:
+ case 0x4b01:
track->edit_rate.num = avio_rb32(pb);
track->edit_rate.den = avio_rb32(pb);
break;
@@ -925,31 +953,31 @@ static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe
static const MXFCodecUL mxf_picture_essence_container_uls[] = {
// video essence container uls
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
};
/* EC ULs for intra-only formats */
static const MXFCodecUL mxf_intra_only_essence_container_uls[] = {
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 Mappings */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 Mappings */
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
};
/* intra-only PictureEssenceCoding ULs, where no corresponding EC UL exists */
static const MXFCodecUL mxf_intra_only_picture_essence_coding_uls[] = {
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
};
static const MXFCodecUL mxf_sound_essence_container_uls[] = {
// sound essence container uls
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, AV_CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */
- { { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0xFF,0x4B,0x46,0x41,0x41,0x00,0x0D,0x4D,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, AV_CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */
+ { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
};
@@ -1246,7 +1274,9 @@ static int mxf_compute_index_tables(MXFContext *mxf)
}
}
- if (!(mxf->index_tables = av_calloc(mxf->nb_index_tables, sizeof(MXFIndexTable)))) {
+ mxf->index_tables = av_mallocz_array(mxf->nb_index_tables,
+ sizeof(*mxf->index_tables));
+ if (!mxf->index_tables) {
av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n");
ret = AVERROR(ENOMEM);
goto finish_decoding_index;
@@ -1265,8 +1295,12 @@ static int mxf_compute_index_tables(MXFContext *mxf)
for (i = j = 0; j < mxf->nb_index_tables; i += mxf->index_tables[j++].nb_segments) {
MXFIndexTable *t = &mxf->index_tables[j];
- if (!(t->segments = av_calloc(t->nb_segments, sizeof(MXFIndexTableSegment*)))) {
- av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment pointer array\n");
+ t->segments = av_mallocz_array(t->nb_segments,
+ sizeof(*t->segments));
+
+ if (!t->segments) {
+ av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment"
+ " pointer array\n");
ret = AVERROR(ENOMEM);
goto finish_decoding_index;
}
@@ -1453,15 +1487,19 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
if (st->duration == -1)
st->duration = AV_NOPTS_VALUE;
st->start_time = component->start_position;
- if (material_track->edit_rate.num <= 0 || material_track->edit_rate.den <= 0) {
+ if (material_track->edit_rate.num <= 0 ||
+ material_track->edit_rate.den <= 0) {
av_log(mxf->fc, AV_LOG_WARNING,
- "invalid edit rate (%d/%d) found on stream #%d, defaulting to 25/1\n",
- material_track->edit_rate.num, material_track->edit_rate.den, st->index);
+ "Invalid edit rate (%d/%d) found on stream #%d, "
+ "defaulting to 25/1\n",
+ material_track->edit_rate.num,
+ material_track->edit_rate.den, st->index);
material_track->edit_rate = (AVRational){25, 1};
}
avpriv_set_pts_info(st, 64, material_track->edit_rate.den, material_track->edit_rate.num);
- /* ensure SourceTrack EditRate == MaterialTrack EditRate since only the former is accessible via st->priv_data */
+ /* ensure SourceTrack EditRate == MaterialTrack EditRate since only
+ * the former is accessible via st->priv_data */
source_track->edit_rate = material_track->edit_rate;
PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul);
@@ -1543,7 +1581,21 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
case MixedFields:
break;
case SeparateFields:
- st->codec->height *= 2; /* Turn field height into frame height. */
+ switch (descriptor->field_dominance) {
+ case MXF_TFF:
+ st->codec->field_order = AV_FIELD_TT;
+ break;
+ case MXF_BFF:
+ st->codec->field_order = AV_FIELD_BB;
+ break;
+ default:
+ avpriv_request_sample(mxf->fc,
+ "Field dominance %d support",
+ descriptor->field_dominance);
+ break;
+ }
+ /* Turn field height into frame height. */
+ st->codec->height *= 2;
break;
default:
av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout);
@@ -1587,7 +1639,9 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
/* if duration is set, rescale it from EditRate to SampleRate */
if (st->duration != AV_NOPTS_VALUE)
- st->duration = av_rescale_q(st->duration, av_inv_q(material_track->edit_rate), st->time_base);
+ st->duration = av_rescale_q(st->duration,
+ av_inv_q(material_track->edit_rate),
+ st->time_base);
/* TODO: implement AV_CODEC_ID_RAWAUDIO */
if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
@@ -1632,7 +1686,7 @@ static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
if (size < 0)
return AVERROR(EINVAL);
- buf_size = size + size/2 + 1;
+ buf_size = size + size / 2 + 1;
*str = av_malloc(buf_size);
if (!*str)
return AVERROR(ENOMEM);
@@ -1665,7 +1719,7 @@ static int mxf_uid_to_str(UID uid, char **str)
static int mxf_timestamp_to_str(uint64_t timestamp, char **str)
{
- struct tm time = {0};
+ struct tm time = { 0 };
time.tm_year = (timestamp >> 48) - 1900;
time.tm_mon = (timestamp >> 40 & 0xFF) - 1;
time.tm_mday = (timestamp >> 32 & 0xFF);
@@ -1673,9 +1727,14 @@ static int mxf_timestamp_to_str(uint64_t timestamp, char **str)
time.tm_min = (timestamp >> 16 & 0xFF);
time.tm_sec = (timestamp >> 8 & 0xFF);
- /* ensure month/day are valid */
- time.tm_mon = FFMAX(time.tm_mon, 0);
- time.tm_mday = FFMAX(time.tm_mday, 1);
+ /* msvcrt versions of strftime calls the invalid parameter handler
+ * (aborting the process if one isn't set) if the parameters are out
+ * of range. */
+ time.tm_mon = av_clip(time.tm_mon, 0, 11);
+ time.tm_mday = av_clip(time.tm_mday, 1, 31);
+ time.tm_hour = av_clip(time.tm_hour, 0, 23);
+ time.tm_min = av_clip(time.tm_min, 0, 59);
+ time.tm_sec = av_clip(time.tm_sec, 0, 59);
*str = av_mallocz(32);
if (!*str)
@@ -1743,35 +1802,35 @@ static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag,
}
static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG 2 Video */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG 2 Video */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
+ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment },
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },
};
@@ -1860,10 +1919,14 @@ static int mxf_parse_handle_essence(MXFContext *mxf)
if (mxf->parsing_backward) {
return mxf_seek_to_previous_partition(mxf);
- } else if (mxf->footer_partition || mxf->last_partition){
- uint64_t offset;
+ } else {
+ uint64_t offset = mxf->footer_partition ? mxf->footer_partition
+ : mxf->last_partition;
- offset = mxf->footer_partition ? mxf->footer_partition : mxf->last_partition;
+ if (!offset) {
+ av_dlog(mxf->fc, "no last partition\n");
+ return 0;
+ }
av_dlog(mxf->fc, "seeking to last partition\n");
@@ -1877,16 +1940,15 @@ static int mxf_parse_handle_essence(MXFContext *mxf)
/* seek to last partition and parse backward */
if ((ret = avio_seek(pb, mxf->run_in + offset, SEEK_SET)) < 0) {
- av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to last partition @ 0x%"PRIx64" (%"PRId64") - partial file?\n",
+ av_log(mxf->fc, AV_LOG_ERROR,
+ "failed to seek to last partition @ 0x%" PRIx64
+ " (%"PRId64") - partial file?\n",
mxf->run_in + offset, ret);
return ret;
}
mxf->current_partition = NULL;
mxf->parsing_backward = 1;
- } else {
- av_dlog(mxf->fc, "can't find last partition\n");
- return 0;
}
return 1;
@@ -2011,6 +2073,8 @@ static int mxf_read_header(AVFormatContext *s)
MXFContext *mxf = s->priv_data;
KLVPacket klv;
int64_t essence_offset = 0;
+ int64_t last_pos = -1;
+ uint64_t last_pos_index = 1;
int ret;
mxf->last_forward_tell = INT64_MAX;
@@ -2028,7 +2092,12 @@ static int mxf_read_header(AVFormatContext *s)
while (!url_feof(s->pb)) {
const MXFMetadataReadTableEntry *metadata;
-
+ if (avio_tell(s->pb) == last_pos) {
+ av_log(mxf->fc, AV_LOG_ERROR, "MXF structure loop detected\n");
+ return AVERROR_INVALIDDATA;
+ }
+ if ((1ULL<<61) % last_pos_index++ == 0)
+ last_pos = avio_tell(s->pb);
if (klv_read_packet(&klv, s->pb) < 0) {
/* EOF - seek to previous partition or stop */
if(mxf_parse_handle_partition_or_eof(mxf) <= 0)
@@ -2195,7 +2264,8 @@ static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset
return next_ofs;
}
-static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t *sample_count)
+static int mxf_compute_sample_count(MXFContext *mxf, int stream_index,
+ uint64_t *sample_count)
{
int i, total = 0, size = 0;
AVStream *st = mxf->fc->streams[stream_index];
@@ -2207,13 +2277,16 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t
if ((sample_rate.num / sample_rate.den) == 48000)
spf = ff_mxf_get_samples_per_frame(mxf->fc, time_base);
if (!spf) {
- int remainder = (sample_rate.num * time_base.num) % (time_base.den * sample_rate.den);
+ int remainder = (sample_rate.num * time_base.num) %
+ (time_base.den * sample_rate.den);
*sample_count = av_q2d(av_mul_q((AVRational){mxf->current_edit_unit, 1},
av_mul_q(sample_rate, time_base)));
if (remainder)
av_log(mxf->fc, AV_LOG_WARNING,
- "seeking detected on stream #%d with time base (%d/%d) and sample rate (%d/%d), audio pts won't be accurate.\n",
- stream_index, time_base.num, time_base.den, sample_rate.num, sample_rate.den);
+ "seeking detected on stream #%d with time base (%d/%d) and "
+ "sample rate (%d/%d), audio pts won't be accurate.\n",
+ stream_index, time_base.num, time_base.den,
+ sample_rate.num, sample_rate.den);
return 0;
}
@@ -2232,15 +2305,19 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t
return 0;
}
-static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, AVPacket *pkt)
+static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec,
+ AVPacket *pkt)
{
MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data;
+ int64_t bits_per_sample = av_get_bits_per_sample(codec->codec_id);
+
pkt->pts = track->sample_count;
+
if ( codec->channels <= 0
- || av_get_bits_per_sample(codec->codec_id) <= 0
- || codec->channels * (int64_t)av_get_bits_per_sample(codec->codec_id) < 8)
+ || bits_per_sample <= 0
+ || codec->channels * (int64_t)bits_per_sample < 8)
return AVERROR(EINVAL);
- track->sample_count += pkt->size / (codec->channels * (int64_t)av_get_bits_per_sample(codec->codec_id) / 8);
+ track->sample_count += pkt->size / (codec->channels * (int64_t)bits_per_sample / 8);
return 0;
}
@@ -2248,16 +2325,16 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
{
KLVPacket klv;
MXFContext *mxf = s->priv_data;
+ int ret;
- while (klv_read_packet(&klv, s->pb) == 0) {
- int ret;
+ while ((ret = klv_read_packet(&klv, s->pb)) == 0) {
PRINT_KEY(s, "read packet", klv.key);
av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset);
if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {
ret = mxf_decrypt_triplet(s, pkt, &klv);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");
- return AVERROR_INVALIDDATA;
+ return ret;
}
return 0;
}
@@ -2270,7 +2347,9 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
AVCodecContext *codec;
if (index < 0) {
- av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12));
+ av_log(s, AV_LOG_ERROR,
+ "error getting stream index %"PRIu32"\n",
+ AV_RB32(klv.key + 12));
goto skip;
}
@@ -2296,9 +2375,11 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
/* check for 8 channels AES3 element */
if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) {
- if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) {
+ ret = mxf_get_d10_aes3_packet(s->pb, s->streams[index],
+ pkt, klv.length);
+ if (ret < 0) {
av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
- return AVERROR_INVALIDDATA;
+ return ret;
}
} else {
ret = av_get_packet(s->pb, pkt, klv.length);
@@ -2309,8 +2390,10 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
pkt->pos = klv.offset;
codec = s->streams[index]->codec;
+
if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
- /* mxf->current_edit_unit good - see if we have an index table to derive timestamps from */
+ /* mxf->current_edit_unit good - see if we have an
+ * index table to derive timestamps from */
MXFIndexTable *t = &mxf->index_tables[0];
if (mxf->nb_index_tables >= 1 && mxf->current_edit_unit < t->nb_ptses) {
@@ -2322,7 +2405,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
pkt->pts = mxf->current_edit_unit;
}
} else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- int ret = mxf_set_audio_pts(mxf, codec, pkt);
+ ret = mxf_set_audio_pts(mxf, codec, pkt);
if (ret < 0)
return ret;
}
@@ -2335,7 +2418,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
skip:
avio_skip(s->pb, klv.length);
}
- return url_feof(s->pb) ? AVERROR_EOF : -1;
+ return url_feof(s->pb) ? AVERROR_EOF : ret;
}
static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
@@ -2487,13 +2570,13 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
MXFContext* mxf = s->priv_data;
int64_t seekpos;
int i, ret;
- int64_t ret64;
MXFIndexTable *t;
MXFTrack *source_track = st->priv_data;
/* if audio then truncate sample_time to EditRate */
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
- sample_time = av_rescale_q(sample_time, st->time_base, av_inv_q(source_track->edit_rate));
+ sample_time = av_rescale_q(sample_time, st->time_base,
+ av_inv_q(source_track->edit_rate));
if (mxf->nb_index_tables <= 0) {
if (!s->bit_rate)
@@ -2502,8 +2585,10 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
sample_time = 0;
seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den);
- if ((ret64 = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET)) < 0)
- return ret64;
+ seekpos = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
+ if (seekpos < 0)
+ return seekpos;
+
ff_update_cur_dts(s, st, sample_time);
mxf->current_edit_unit = sample_time;
} else {
@@ -2523,7 +2608,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
sample_time = FFMIN(sample_time, source_track->original_duration - 1);
}
- if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) << 0)
+ if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) < 0)
return ret;
ff_update_cur_dts(s, st, sample_time);
diff --git a/chromium/third_party/ffmpeg/libavformat/mxfenc.c b/chromium/third_party/ffmpeg/libavformat/mxfenc.c
index 5e77a3f0684..6f3226b968d 100644
--- a/chromium/third_party/ffmpeg/libavformat/mxfenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/mxfenc.c
@@ -618,7 +618,7 @@ static void mxf_write_identification(AVFormatContext *s)
mxf_write_metadata_key(pb, 0x013000);
PRINT_KEY(s, "identification key", pb->buf_ptr - 16);
- version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ?
+ version = s->flags & AVFMT_FLAG_BITEXACT ?
"0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16
klv_encode_ber_length(pb, length);
@@ -1777,7 +1777,7 @@ static int mxf_write_header(AVFormatContext *s)
mxf->essence_container_count = 1;
}
- if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
+ if (!(s->flags & AVFMT_FLAG_BITEXACT))
mxf_gen_umid(s);
for (i = 0; i < s->nb_streams; i++) {
diff --git a/chromium/third_party/ffmpeg/libavformat/network.c b/chromium/third_party/ffmpeg/libavformat/network.c
index 2ba435d4726..5e574e3bbe0 100644
--- a/chromium/third_party/ffmpeg/libavformat/network.c
+++ b/chromium/third_party/ffmpeg/libavformat/network.c
@@ -76,7 +76,7 @@ void ff_tls_init(void)
#if HAVE_THREADS
if (!CRYPTO_get_locking_callback()) {
int i;
- openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
+ openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks());
for (i = 0; i < CRYPTO_num_locks(); i++)
pthread_mutex_init(&openssl_mutexes[i], NULL);
CRYPTO_set_locking_callback(openssl_lock);
@@ -281,7 +281,9 @@ int ff_listen_bind(int fd, const struct sockaddr *addr,
closesocket(fd);
- ff_socket_nonblock(ret, 1);
+ if (ff_socket_nonblock(ret, 1) < 0)
+ av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
+
return ret;
}
@@ -293,7 +295,8 @@ int ff_listen_connect(int fd, const struct sockaddr *addr,
int ret;
socklen_t optlen;
- ff_socket_nonblock(fd, 1);
+ if (ff_socket_nonblock(fd, 1) < 0)
+ av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
while ((ret = connect(fd, addr, addrlen))) {
ret = ff_neterrno();
diff --git a/chromium/third_party/ffmpeg/libavformat/network.h b/chromium/third_party/ffmpeg/libavformat/network.h
index c60e1424a1c..5ca906491ac 100644
--- a/chromium/third_party/ffmpeg/libavformat/network.h
+++ b/chromium/third_party/ffmpeg/libavformat/network.h
@@ -62,7 +62,7 @@ int ff_neterrno(void);
#include <netdb.h>
#define ff_neterrno() AVERROR(errno)
-#endif
+#endif /* HAVE_WINSOCK2_H */
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
@@ -104,12 +104,12 @@ struct sockaddr_storage {
uint8_t ss_family;
#else
uint16_t ss_family;
-#endif
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
char ss_pad1[6];
int64_t ss_align;
char ss_pad2[112];
};
-#endif
+#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
#if !HAVE_STRUCT_ADDRINFO
struct addrinfo {
@@ -122,7 +122,7 @@ struct addrinfo {
char *ai_canonname;
struct addrinfo *ai_next;
};
-#endif
+#endif /* !HAVE_STRUCT_ADDRINFO */
/* getaddrinfo constants */
#ifndef EAI_AGAIN
@@ -195,12 +195,13 @@ int ff_getnameinfo(const struct sockaddr *sa, int salen,
#define getaddrinfo ff_getaddrinfo
#define freeaddrinfo ff_freeaddrinfo
#define getnameinfo ff_getnameinfo
-#endif
+#endif /* !HAVE_GETADDRINFO */
+
#if !HAVE_GETADDRINFO || HAVE_WINSOCK2_H
const char *ff_gai_strerror(int ecode);
#undef gai_strerror
#define gai_strerror ff_gai_strerror
-#endif
+#endif /* !HAVE_GETADDRINFO || HAVE_WINSOCK2_H */
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
diff --git a/chromium/third_party/ffmpeg/libavformat/nistspheredec.c b/chromium/third_party/ffmpeg/libavformat/nistspheredec.c
index c09df9ccc1a..2c966863422 100644
--- a/chromium/third_party/ffmpeg/libavformat/nistspheredec.c
+++ b/chromium/third_party/ffmpeg/libavformat/nistspheredec.c
@@ -36,7 +36,7 @@ static int nist_read_header(AVFormatContext *s)
{
char buffer[32], coding[32] = "pcm", format[32] = "01";
int bps = 0, be = 0;
- int32_t header_size;
+ int32_t header_size = -1;
AVStream *st;
st = avformat_new_stream(s, NULL);
@@ -108,8 +108,11 @@ static int nist_read_header(AVFormatContext *s)
sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->bits_per_coded_sample);
} else {
char key[32], value[32];
- sscanf(buffer, "%31s %*s %31s", key, value);
- av_dict_set(&s->metadata, key, value, AV_DICT_APPEND);
+ if (sscanf(buffer, "%31s %*s %31s", key, value) == 3) {
+ av_dict_set(&s->metadata, key, value, AV_DICT_APPEND);
+ } else {
+ av_log(s, AV_LOG_ERROR, "Failed to parse '%s' as metadata\n", buffer);
+ }
}
}
diff --git a/chromium/third_party/ffmpeg/libavformat/nut.c b/chromium/third_party/ffmpeg/libavformat/nut.c
index 8b8a4cb8ac8..9224a963737 100644
--- a/chromium/third_party/ffmpeg/libavformat/nut.c
+++ b/chromium/third_party/ffmpeg/libavformat/nut.c
@@ -82,10 +82,10 @@ const AVCodecTag ff_nut_video_tags[] = {
{ AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 48 ) },
{ AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'B', 'G', 'R') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'R', 'G', 'B') },
- { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'B', 'A', 64 ) },
- { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) },
{ AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'R', 'B', 'A') },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 10 ) },
{ AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 11 , '3', 'Y') },
{ AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 10 ) },
@@ -157,10 +157,27 @@ const AVCodecTag ff_nut_video_tags[] = {
{ AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 16) },
{ AV_CODEC_ID_RAWVIDEO, MKTAG(16, 0, '3', 'G') },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG('X', 'Y', 'Z' , 36 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(36 , 'Z' , 'Y', 'X') },
+
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'B', 'G', 8 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'B', 'G', 16 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'G', 'B', 0xBA) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'R', 'G', 8 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'R', 'G', 16 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'G', 'R', 0xBA) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'G', 'B', 8 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'G', 'B', 16 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 'B', 'G', 0xBA) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'G', 'R', 8 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(0xBA, 'G', 'R', 16 ) },
+ { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 'R', 'G', 0xBA) },
+
{ AV_CODEC_ID_NONE, 0 }
};
-static const AVCodecTag nut_audio_extra_tags[] = {
+const AVCodecTag ff_nut_audio_extra_tags[] = {
+ { AV_CODEC_ID_COMFORT_NOISE, MKTAG('3', '3', '8', '9') },
{ AV_CODEC_ID_PCM_ALAW, MKTAG('A', 'L', 'A', 'W') },
{ AV_CODEC_ID_PCM_MULAW, MKTAG('U', 'L', 'A', 'W') },
{ AV_CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
@@ -196,7 +213,7 @@ const AVCodecTag ff_nut_audio_tags[] = {
const AVCodecTag * const ff_nut_codec_tags[] = {
ff_nut_video_tags, ff_nut_audio_tags, ff_nut_subtitle_tags,
- ff_codec_bmp_tags, ff_codec_wav_tags, nut_audio_extra_tags, ff_nut_data_tags, 0
+ ff_codec_bmp_tags, ff_codec_wav_tags, ff_nut_audio_extra_tags, ff_nut_data_tags, 0
};
void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val)
diff --git a/chromium/third_party/ffmpeg/libavformat/nut.h b/chromium/third_party/ffmpeg/libavformat/nut.h
index da456ac5b08..a08d30b9350 100644
--- a/chromium/third_party/ffmpeg/libavformat/nut.h
+++ b/chromium/third_party/ffmpeg/libavformat/nut.h
@@ -46,6 +46,7 @@ typedef enum{
FLAG_SIZE_MSB = 32, ///<if set, data_size_msb is at frame header, otherwise data_size_msb is 0
FLAG_CHECKSUM = 64, ///<if set, the frame header contains a checksum
FLAG_RESERVED = 128, ///<if set, reserved_count is coded in the frame header
+ FLAG_SM_DATA = 256, ///<if set, side / meta data is stored in the frame header.
FLAG_HEADER_IDX =1024, ///<If set, header_idx is coded in the frame header.
FLAG_MATCH_TIME =2048, ///<If set, match_time_delta is coded in the frame header
FLAG_CODED =4096, ///<if set, coded_flags are stored in the frame header
@@ -104,11 +105,14 @@ typedef struct NUTContext {
int sp_count;
int64_t max_pts;
AVRational *max_pts_tb;
+ int version;
+ int minor_version;
} NUTContext;
extern const AVCodecTag ff_nut_subtitle_tags[];
extern const AVCodecTag ff_nut_video_tags[];
extern const AVCodecTag ff_nut_audio_tags[];
+extern const AVCodecTag ff_nut_audio_extra_tags[];
extern const AVCodecTag ff_nut_data_tags[];
extern const AVCodecTag * const ff_nut_codec_tags[];
diff --git a/chromium/third_party/ffmpeg/libavformat/nutdec.c b/chromium/third_party/ffmpeg/libavformat/nutdec.c
index aa7ca676fb7..5d08a8e80b1 100644
--- a/chromium/third_party/ffmpeg/libavformat/nutdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/nutdec.c
@@ -24,8 +24,10 @@
#include "libavutil/avassert.h"
#include "libavutil/bswap.h"
#include "libavutil/dict.h"
+#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/tree.h"
+#include "libavcodec/bytestream.h"
#include "avio_internal.h"
#include "nut.h"
#include "riff.h"
@@ -227,11 +229,14 @@ static int decode_main_header(NUTContext *nut)
end += avio_tell(bc);
tmp = ffio_read_varlen(bc);
- if (tmp < 2 && tmp > NUT_VERSION) {
+ if (tmp < 2 && tmp > 4) {
av_log(s, AV_LOG_ERROR, "Version %"PRId64" not supported.\n",
tmp);
return AVERROR(ENOSYS);
}
+ nut->version = tmp;
+ if (nut->version > 3)
+ nut->minor_version = ffio_read_varlen(bc);
GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS);
@@ -385,6 +390,7 @@ static int decode_stream_header(NUTContext *nut)
st->codec->codec_id = av_codec_get_id((const AVCodecTag * const []) {
ff_nut_audio_tags,
ff_codec_wav_tags,
+ ff_nut_audio_extra_tags,
0
},
tmp);
@@ -415,9 +421,8 @@ static int decode_stream_header(NUTContext *nut)
GET_V(st->codec->extradata_size, tmp < (1 << 30));
if (st->codec->extradata_size) {
- if (ff_alloc_extradata(st->codec, st->codec->extradata_size))
+ if (ff_get_extradata(st->codec, bc, st->codec->extradata_size) < 0)
return AVERROR(ENOMEM);
- avio_read(bc, st->codec->extradata, st->codec->extradata_size);
}
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -774,6 +779,116 @@ static int nut_read_header(AVFormatContext *s)
return 0;
}
+static int read_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta, int64_t maxpos)
+{
+ int count = ffio_read_varlen(bc);
+ int skip_start = 0;
+ int skip_end = 0;
+ int channels = 0;
+ int64_t channel_layout = 0;
+ int sample_rate = 0;
+ int width = 0;
+ int height = 0;
+ int i;
+
+ for (i=0; i<count; i++) {
+ uint8_t name[256], str_value[256], type_str[256];
+ int value;
+ if (avio_tell(bc) >= maxpos)
+ return AVERROR_INVALIDDATA;
+ get_str(bc, name, sizeof(name));
+ value = get_s(bc);
+
+ if (value == -1) {
+ get_str(bc, str_value, sizeof(str_value));
+ av_log(s, AV_LOG_WARNING, "Unknown string %s / %s\n", name, str_value);
+ } else if (value == -2) {
+ uint8_t *dst = NULL;
+ int64_t v64, value_len;
+
+ get_str(bc, type_str, sizeof(type_str));
+ value_len = ffio_read_varlen(bc);
+ if (avio_tell(bc) + value_len >= maxpos)
+ return AVERROR_INVALIDDATA;
+ if (!strcmp(name, "Palette")) {
+ dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, value_len);
+ } else if (!strcmp(name, "Extradata")) {
+ dst = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, value_len);
+ } else if (sscanf(name, "CodecSpecificSide%"SCNd64"", &v64) == 1) {
+ dst = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, value_len + 8);
+ if(!dst)
+ return AVERROR(ENOMEM);
+ AV_WB64(dst, v64);
+ dst += 8;
+ } else if (!strcmp(name, "ChannelLayout") && value_len == 8) {
+ channel_layout = avio_rl64(bc);
+ continue;
+ } else {
+ av_log(s, AV_LOG_WARNING, "Unknown data %s / %s\n", name, type_str);
+ avio_skip(bc, value_len);
+ continue;
+ }
+ if(!dst)
+ return AVERROR(ENOMEM);
+ avio_read(bc, dst, value_len);
+ } else if (value == -3) {
+ value = get_s(bc);
+ } else if (value == -4) {
+ value = ffio_read_varlen(bc);
+ } else if (value < -4) {
+ get_s(bc);
+ } else {
+ if (!strcmp(name, "SkipStart")) {
+ skip_start = value;
+ } else if (!strcmp(name, "SkipEnd")) {
+ skip_end = value;
+ } else if (!strcmp(name, "Channels")) {
+ channels = value;
+ } else if (!strcmp(name, "SampleRate")) {
+ sample_rate = value;
+ } else if (!strcmp(name, "Width")) {
+ width = value;
+ } else if (!strcmp(name, "Height")) {
+ height = value;
+ } else {
+ av_log(s, AV_LOG_WARNING, "Unknown integer %s\n", name);
+ }
+ }
+ }
+
+ if (channels || channel_layout || sample_rate || width || height) {
+ uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, 28);
+ if (!dst)
+ return AVERROR(ENOMEM);
+ bytestream_put_le32(&dst,
+ AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT*(!!channels) +
+ AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT*(!!channel_layout) +
+ AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE*(!!sample_rate) +
+ AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS*(!!(width|height))
+ );
+ if (channels)
+ bytestream_put_le32(&dst, channels);
+ if (channel_layout)
+ bytestream_put_le64(&dst, channel_layout);
+ if (sample_rate)
+ bytestream_put_le32(&dst, sample_rate);
+ if (width || height){
+ bytestream_put_le32(&dst, width);
+ bytestream_put_le32(&dst, height);
+ }
+ }
+
+ if (skip_start || skip_end) {
+ uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+ if (!dst)
+ return AVERROR(ENOMEM);
+ AV_WL32(dst, skip_start);
+ AV_WL32(dst+4, skip_end);
+ }
+
+ return 0;
+}
+
static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id,
uint8_t *header_idx, int frame_code)
{
@@ -856,6 +971,7 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)
int64_t pts, last_IP_pts;
StreamContext *stc;
uint8_t header_idx;
+ int ret;
size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
if (size < 0)
@@ -881,7 +997,23 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)
return AVERROR(ENOMEM);
memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
pkt->pos = avio_tell(bc); // FIXME
- avio_read(bc, pkt->data + nut->header_len[header_idx], size);
+ if (stc->last_flags & FLAG_SM_DATA) {
+ int sm_size;
+ if (read_sm_data(s, bc, pkt, 0, pkt->pos + size) < 0)
+ return AVERROR_INVALIDDATA;
+ if (read_sm_data(s, bc, pkt, 1, pkt->pos + size) < 0)
+ return AVERROR_INVALIDDATA;
+ sm_size = avio_tell(bc) - pkt->pos;
+ size -= sm_size;
+ pkt->size -= sm_size;
+ }
+
+ ret = avio_read(bc, pkt->data + nut->header_len[header_idx], size);
+ if (ret != size) {
+ if (ret < 0)
+ return ret;
+ }
+ av_shrink_packet(pkt, nut->header_len[header_idx] + ret);
pkt->stream_index = stream_id;
if (stc->last_flags & FLAG_KEY)
diff --git a/chromium/third_party/ffmpeg/libavformat/nutenc.c b/chromium/third_party/ffmpeg/libavformat/nutenc.c
index 10b8fc88eb7..604fe760b69 100644
--- a/chromium/third_party/ffmpeg/libavformat/nutenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/nutenc.c
@@ -26,6 +26,7 @@
#include "libavutil/tree.h"
#include "libavutil/dict.h"
#include "libavutil/avassert.h"
+#include "libavcodec/bytestream.h"
#include "libavcodec/mpegaudiodata.h"
#include "nut.h"
#include "internal.h"
@@ -337,7 +338,9 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc)
tmp_head_idx;
int64_t tmp_match;
- ff_put_v(bc, NUT_VERSION);
+ ff_put_v(bc, nut->version = NUT_VERSION);
+ if (nut->version > 3)
+ ff_put_v(bc, nut->minor_version);
ff_put_v(bc, nut->avf->nb_streams);
ff_put_v(bc, nut->max_distance);
ff_put_v(bc, nut->time_base_count);
@@ -586,8 +589,15 @@ static int write_index(NUTContext *nut, AVIOContext *bc) {
int64_t last_pts= -1;
int j, k;
for (j=0; j<nut->sp_count; j++) {
- int flag = (nus->keyframe_pts[j] != AV_NOPTS_VALUE) ^ (j+1 == nut->sp_count);
+ int flag;
int n = 0;
+
+ if (j && nus->keyframe_pts[j] == nus->keyframe_pts[j-1]) {
+ av_log(nut->avf, AV_LOG_WARNING, "Multiple keyframes with same PTS\n");
+ nus->keyframe_pts[j] = AV_NOPTS_VALUE;
+ }
+
+ flag = (nus->keyframe_pts[j] != AV_NOPTS_VALUE) ^ (j+1 == nut->sp_count);
for (; j<nut->sp_count && (nus->keyframe_pts[j] != AV_NOPTS_VALUE) == flag; j++)
n++;
@@ -769,6 +779,8 @@ static int get_needed_flags(NUTContext *nut, StreamContext *nus, FrameCode *fc,
flags |= FLAG_SIZE_MSB;
if (pkt->pts - nus->last_pts != fc->pts_delta)
flags |= FLAG_CODED_PTS;
+ if (pkt->side_data_elems && nut->version > 3)
+ flags |= FLAG_SM_DATA;
if (pkt->size > 2 * nut->max_distance)
flags |= FLAG_CHECKSUM;
if (FFABS(pkt->pts - nus->last_pts) > nus->max_pts_distance)
@@ -801,11 +813,129 @@ static int find_best_header_idx(NUTContext *nut, AVPacket *pkt)
return best_i;
}
+static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ int ret, i, dyn_size;
+ unsigned flags;
+ AVIOContext *dyn_bc;
+ int sm_data_count = 0;
+ uint8_t tmp[256];
+ uint8_t *dyn_buf;
+
+ ret = avio_open_dyn_buf(&dyn_bc);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i<pkt->side_data_elems; i++) {
+ const uint8_t *data = pkt->side_data[i].data;
+ int size = pkt->side_data[i].size;
+ const uint8_t *data_end = data + size;
+
+ if (is_meta) {
+ if ( pkt->side_data[i].type == AV_PKT_DATA_METADATA_UPDATE
+ || pkt->side_data[i].type == AV_PKT_DATA_STRINGS_METADATA) {
+ if (!size || data[size-1])
+ return AVERROR(EINVAL);
+ while (data < data_end) {
+ const uint8_t *key = data;
+ const uint8_t *val = data + strlen(key) + 1;
+
+ if(val >= data_end)
+ return AVERROR(EINVAL);
+ put_str(dyn_bc, key);
+ put_s(dyn_bc, -1);
+ put_str(dyn_bc, val);
+ data = val + strlen(val) + 1;
+ sm_data_count++;
+ }
+ }
+ } else {
+ switch (pkt->side_data[i].type) {
+ case AV_PKT_DATA_PALETTE:
+ case AV_PKT_DATA_NEW_EXTRADATA:
+ case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL:
+ default:
+ if (pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
+ put_str(dyn_bc, "Palette");
+ } else if(pkt->side_data[i].type == AV_PKT_DATA_NEW_EXTRADATA) {
+ put_str(dyn_bc, "Extradata");
+ } else if(pkt->side_data[i].type == AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL) {
+ snprintf(tmp, sizeof(tmp), "CodecSpecificSide%"PRId64"", AV_RB64(data));
+ put_str(dyn_bc, tmp);
+ } else {
+ snprintf(tmp, sizeof(tmp), "UserData%s-SD-%d",
+ (st->codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT,
+ pkt->side_data[i].type);
+ put_str(dyn_bc, tmp);
+ }
+ put_s(dyn_bc, -2);
+ put_str(dyn_bc, "bin");
+ ff_put_v(dyn_bc, pkt->side_data[i].size);
+ avio_write(dyn_bc, data, pkt->side_data[i].size);
+ sm_data_count++;
+ break;
+ case AV_PKT_DATA_PARAM_CHANGE:
+ flags = bytestream_get_le32(&data);
+ if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
+ put_str(dyn_bc, "Channels");
+ put_s(dyn_bc, bytestream_get_le32(&data));
+ sm_data_count++;
+ }
+ if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
+ put_str(dyn_bc, "ChannelLayout");
+ put_s(dyn_bc, -2);
+ put_str(dyn_bc, "u64");
+ ff_put_v(bc, 8);
+ avio_write(dyn_bc, data, 8); data+=8;
+ sm_data_count++;
+ }
+ if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
+ put_str(dyn_bc, "SampleRate");
+ put_s(dyn_bc, bytestream_get_le32(&data));
+ sm_data_count++;
+ }
+ if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
+ put_str(dyn_bc, "Width");
+ put_s(dyn_bc, bytestream_get_le32(&data));
+ put_str(dyn_bc, "Height");
+ put_s(dyn_bc, bytestream_get_le32(&data));
+ sm_data_count+=2;
+ }
+ break;
+ case AV_PKT_DATA_SKIP_SAMPLES:
+ if (AV_RL32(data)) {
+ put_str(dyn_bc, "SkipStart");
+ put_s(dyn_bc, (unsigned)AV_RL32(data));
+ sm_data_count++;
+ }
+ if (AV_RL32(data+4)) {
+ put_str(dyn_bc, "SkipEnd");
+ put_s(dyn_bc, (unsigned)AV_RL32(data+4));
+ sm_data_count++;
+ }
+ break;
+ case AV_PKT_DATA_METADATA_UPDATE:
+ case AV_PKT_DATA_STRINGS_METADATA:
+ // belongs into meta, not side data
+ break;
+ }
+ }
+ }
+
+ ff_put_v(bc, sm_data_count);
+ dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
+ avio_write(bc, dyn_buf, dyn_size);
+ av_freep(&dyn_buf);
+
+ return 0;
+}
+
static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
{
NUTContext *nut = s->priv_data;
StreamContext *nus = &nut->stream[pkt->stream_index];
- AVIOContext *bc = s->pb, *dyn_bc;
+ AVIOContext *bc = s->pb, *dyn_bc, *sm_bc = NULL;
FrameCode *fc;
int64_t coded_pts;
int best_length, frame_code, flags, needed_flags, i, header_idx;
@@ -813,6 +943,9 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
int key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY);
int store_sp = 0;
int ret;
+ int sm_size = 0;
+ int data_size = pkt->size;
+ uint8_t *sm_buf;
if (pkt->pts < 0) {
av_log(s, AV_LOG_ERROR,
@@ -821,13 +954,23 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
return AVERROR(EINVAL);
}
+ if (pkt->side_data_elems && nut->version > 3) {
+ ret = avio_open_dyn_buf(&sm_bc);
+ if (ret < 0)
+ return ret;
+ write_sm_data(s, sm_bc, pkt, 0);
+ write_sm_data(s, sm_bc, pkt, 1);
+ sm_size = avio_close_dyn_buf(sm_bc, &sm_buf);
+ data_size += sm_size;
+ }
+
if (1LL << (20 + 3 * nut->header_count) <= avio_tell(bc))
write_headers(s, bc);
if (key_frame && !(nus->last_flags & FLAG_KEY))
store_sp = 1;
- if (pkt->size + 30 /*FIXME check*/ + avio_tell(bc) >= nut->last_syncpoint_pos + nut->max_distance)
+ if (data_size + 30 /*FIXME check*/ + avio_tell(bc) >= nut->last_syncpoint_pos + nut->max_distance)
store_sp = 1;
//FIXME: Ensure store_sp is 1 in the first place.
@@ -907,10 +1050,10 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
if (flags & FLAG_STREAM_ID)
length += ff_get_v_length(pkt->stream_index);
- if (pkt->size % fc->size_mul != fc->size_lsb)
+ if (data_size % fc->size_mul != fc->size_lsb)
continue;
if (flags & FLAG_SIZE_MSB)
- length += ff_get_v_length(pkt->size / fc->size_mul);
+ length += ff_get_v_length(data_size / fc->size_mul);
if (flags & FLAG_CHECKSUM)
length += 4;
@@ -952,13 +1095,18 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
}
if (flags & FLAG_STREAM_ID) ff_put_v(bc, pkt->stream_index);
if (flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts);
- if (flags & FLAG_SIZE_MSB ) ff_put_v(bc, pkt->size / fc->size_mul);
+ if (flags & FLAG_SIZE_MSB ) ff_put_v(bc, data_size / fc->size_mul);
if (flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx = best_header_idx);
if (flags & FLAG_CHECKSUM) avio_wl32(bc, ffio_get_checksum(bc));
else ffio_get_checksum(bc);
+ if (flags & FLAG_SM_DATA) {
+ avio_write(bc, sm_buf, sm_size);
+ av_freep(&sm_buf);
+ }
avio_write(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]);
+
nus->last_flags = flags;
nus->last_pts = pkt->pts;
diff --git a/chromium/third_party/ffmpeg/libavformat/nuv.c b/chromium/third_party/ffmpeg/libavformat/nuv.c
index 32d0e02f68b..2c02de1c6f1 100644
--- a/chromium/third_party/ffmpeg/libavformat/nuv.c
+++ b/chromium/third_party/ffmpeg/libavformat/nuv.c
@@ -86,9 +86,8 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst,
av_freep(&vst->codec->extradata);
vst->codec->extradata_size = 0;
}
- if (ff_alloc_extradata(vst->codec, size))
+ if (ff_get_extradata(vst->codec, pb, size) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, vst->codec->extradata, size);
size = 0;
if (!myth)
return 0;
diff --git a/chromium/third_party/ffmpeg/libavformat/oggdec.c b/chromium/third_party/ffmpeg/libavformat/oggdec.c
index 8639eaea8db..f7d00c1b4b1 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggdec.c
@@ -48,6 +48,7 @@ static const struct ogg_codec * const ogg_codecs[] = {
&ff_flac_codec,
&ff_celt_codec,
&ff_opus_codec,
+ &ff_vp8_codec,
&ff_old_dirac_codec,
&ff_old_flac_codec,
&ff_ogm_video_codec,
@@ -77,6 +78,8 @@ static int ogg_save(AVFormatContext *s)
struct ogg_stream *os = ogg->streams + i;
os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(os->buf, ost->streams[i].buf, os->bufpos);
+ os->new_metadata = NULL;
+ os->new_metadata_size = 0;
}
ogg->state = ost;
@@ -143,6 +146,8 @@ static int ogg_reset(AVFormatContext *s)
os->lastpts = 0;
}
os->end_trimming = 0;
+ av_freep(&os->new_metadata);
+ os->new_metadata_size = 0;
}
ogg->page_pos = -1;
@@ -640,7 +645,11 @@ static int ogg_read_close(AVFormatContext *s)
ogg->streams[i].codec->cleanup(s, i);
}
av_freep(&ogg->streams[i].private);
+ av_freep(&ogg->streams[i].new_metadata);
}
+
+ ogg->nstreams = 0;
+
av_freep(&ogg->streams);
return 0;
}
@@ -721,8 +730,16 @@ static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int p
{
struct ogg *ogg = s->priv_data;
struct ogg_stream *os = ogg->streams + idx;
- if (psize && s->streams[idx]->codec->codec_id == AV_CODEC_ID_THEORA) {
- if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
+ int invalid = 0;
+ if (psize) {
+ switch (s->streams[idx]->codec->codec_id) {
+ case AV_CODEC_ID_THEORA:
+ invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
+ break;
+ case AV_CODEC_ID_VP8:
+ invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
+ }
+ if (invalid) {
os->pflags ^= AV_PKT_FLAG_KEY;
av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
(os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
@@ -779,16 +796,29 @@ retry:
uint8_t *side_data = av_packet_new_side_data(pkt,
AV_PKT_DATA_SKIP_SAMPLES,
10);
- if(side_data == NULL) {
- av_free_packet(pkt);
- av_free(pkt);
- return AVERROR(ENOMEM);
- }
+ if(side_data == NULL)
+ goto fail;
AV_WL32(side_data + 4, os->end_trimming);
os->end_trimming = 0;
}
+ if (os->new_metadata) {
+ uint8_t *side_data = av_packet_new_side_data(pkt,
+ AV_PKT_DATA_METADATA_UPDATE,
+ os->new_metadata_size);
+ if(side_data == NULL)
+ goto fail;
+
+ memcpy(side_data, os->new_metadata, os->new_metadata_size);
+ av_freep(&os->new_metadata);
+ os->new_metadata_size = 0;
+ }
+
return psize;
+fail:
+ av_free_packet(pkt);
+ av_free(pkt);
+ return AVERROR(ENOMEM);
}
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
@@ -807,6 +837,11 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
&& !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
if (i == stream_index) {
struct ogg_stream *os = ogg->streams + stream_index;
+ // Do not trust the last timestamps of a ogm video
+ if ( (os->flags & OGG_FLAG_EOS)
+ && !(os->flags & OGG_FLAG_BOS)
+ && os->codec == &ff_ogm_video_codec)
+ continue;
pts = ogg_calc_pts(s, i, NULL);
ogg_validate_keyframe(s, i, pstart, psize);
if (os->pflags & AV_PKT_FLAG_KEY) {
diff --git a/chromium/third_party/ffmpeg/libavformat/oggdec.h b/chromium/third_party/ffmpeg/libavformat/oggdec.h
index c31859fecd7..231b5837704 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggdec.h
+++ b/chromium/third_party/ffmpeg/libavformat/oggdec.h
@@ -85,6 +85,8 @@ struct ogg_stream {
int got_data; ///< 1 if the stream got some data (non-initial packets), 0 otherwise
int nb_header; ///< set to the number of parsed headers
int end_trimming; ///< set the number of packets to drop from the end
+ uint8_t *new_metadata;
+ unsigned int new_metadata_size;
void *private;
};
@@ -125,6 +127,7 @@ extern const struct ogg_codec ff_skeleton_codec;
extern const struct ogg_codec ff_speex_codec;
extern const struct ogg_codec ff_theora_codec;
extern const struct ogg_codec ff_vorbis_codec;
+extern const struct ogg_codec ff_vp8_codec;
int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, const uint8_t *buf, int size);
diff --git a/chromium/third_party/ffmpeg/libavformat/oggenc.c b/chromium/third_party/ffmpeg/libavformat/oggenc.c
index d9ef23c445c..375abadd445 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggenc.c
@@ -427,9 +427,12 @@ static int ogg_write_header(AVFormatContext *s)
return -1;
}
oggstream = av_mallocz(sizeof(*oggstream));
+ if (!oggstream)
+ return AVERROR(ENOMEM);
+
oggstream->page.stream_index = i;
- if (!(st->codec->flags & CODEC_FLAG_BITEXACT))
+ if (!(s->flags & AVFMT_FLAG_BITEXACT))
do {
serial_num = av_get_random_seed();
for (j = 0; j < i; j++) {
@@ -445,7 +448,7 @@ static int ogg_write_header(AVFormatContext *s)
st->priv_data = oggstream;
if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
int err = ogg_build_flac_headers(st->codec, oggstream,
- st->codec->flags & CODEC_FLAG_BITEXACT,
+ s->flags & AVFMT_FLAG_BITEXACT,
&st->metadata);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
@@ -454,7 +457,7 @@ static int ogg_write_header(AVFormatContext *s)
}
} else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
int err = ogg_build_speex_headers(st->codec, oggstream,
- st->codec->flags & CODEC_FLAG_BITEXACT,
+ s->flags & AVFMT_FLAG_BITEXACT,
&st->metadata);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
@@ -463,7 +466,7 @@ static int ogg_write_header(AVFormatContext *s)
}
} else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
int err = ogg_build_opus_headers(st->codec, oggstream,
- st->codec->flags & CODEC_FLAG_BITEXACT,
+ s->flags & AVFMT_FLAG_BITEXACT,
&st->metadata);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
@@ -484,7 +487,7 @@ static int ogg_write_header(AVFormatContext *s)
return -1;
}
- p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT,
+ p = ogg_write_vorbiscomment(7, s->flags & AVFMT_FLAG_BITEXACT,
&oggstream->header_len[1], &st->metadata,
framing_bit);
oggstream->header[1] = p;
@@ -637,7 +640,8 @@ AVOutputFormat ff_ogg_muxer = {
#endif
,
.priv_data_size = sizeof(OGGContext),
- .audio_codec = AV_CODEC_ID_FLAC,
+ .audio_codec = CONFIG_LIBVORBIS_ENCODER ?
+ AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC,
.video_codec = AV_CODEC_ID_THEORA,
.write_header = ogg_write_header,
.write_packet = ogg_write_packet,
@@ -647,6 +651,30 @@ AVOutputFormat ff_ogg_muxer = {
};
#endif
+#if CONFIG_OGA_MUXER
+static const AVClass oga_muxer_class = {
+ .class_name = "Ogg audio muxer",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_oga_muxer = {
+ .name = "oga",
+ .long_name = NULL_IF_CONFIG_SMALL("Ogg audio"),
+ .mime_type = "audio/ogg",
+ .extensions = "oga",
+ .priv_data_size = sizeof(OGGContext),
+ .audio_codec = AV_CODEC_ID_VORBIS,
+ .video_codec = AV_CODEC_ID_NONE,
+ .write_header = ogg_write_header,
+ .write_packet = ogg_write_packet,
+ .write_trailer = ogg_write_trailer,
+ .flags = AVFMT_TS_NEGATIVE,
+ .priv_class = &oga_muxer_class,
+};
+#endif
+
#if CONFIG_SPEEX_MUXER
static const AVClass speex_muxer_class = {
.class_name = "Speex muxer",
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparsecelt.c b/chromium/third_party/ffmpeg/libavformat/oggparsecelt.c
index f3c2c1a632f..d6e99626509 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparsecelt.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparsecelt.c
@@ -48,8 +48,10 @@ static int celt_header(AVFormatContext *s, int idx)
priv = av_malloc(sizeof(struct oggcelt_private));
if (!priv)
return AVERROR(ENOMEM);
- if (ff_alloc_extradata(st->codec, 2 * sizeof(uint32_t)) < 0)
+ if (ff_alloc_extradata(st->codec, 2 * sizeof(uint32_t)) < 0) {
+ av_free(priv);
return AVERROR(ENOMEM);
+ }
version = AV_RL32(p + 28);
/* unused header size field skipped */
sample_rate = AV_RL32(p + 36);
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparseogm.c b/chromium/third_party/ffmpeg/libavformat/oggparseogm.c
index b8c502a5ffd..95369df89ea 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparseogm.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparseogm.c
@@ -79,6 +79,11 @@ ogm_header(AVFormatContext *s, int idx)
size = FFMIN(size, os->psize);
time_unit = bytestream2_get_le64(&p);
spu = bytestream2_get_le64(&p);
+ if (!time_unit || !spu) {
+ av_log(s, AV_LOG_ERROR, "Invalid timing values.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
bytestream2_skip(&p, 4); /* default_len */
bytestream2_skip(&p, 8); /* buffersize + bits_per_sample */
@@ -90,7 +95,7 @@ ogm_header(AVFormatContext *s, int idx)
st->codec->channels = bytestream2_get_le16(&p);
bytestream2_skip(&p, 2); /* block_align */
st->codec->bit_rate = bytestream2_get_le32(&p) * 8;
- st->codec->sample_rate = time_unit ? spu * 10000000 / time_unit : 0;
+ st->codec->sample_rate = spu * 10000000 / time_unit;
avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
if (size >= 56 && st->codec->codec_id == AV_CODEC_ID_AAC) {
bytestream2_skip(&p, 4);
@@ -126,15 +131,23 @@ ogm_dshow_header(AVFormatContext *s, int idx)
if(*p != 1)
return 1;
+ if (os->psize < 100)
+ return AVERROR_INVALIDDATA;
t = AV_RL32(p + 96);
if(t == 0x05589f80){
+ if (os->psize < 184)
+ return AVERROR_INVALIDDATA;
+
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000);
st->codec->width = AV_RL32(p + 176);
st->codec->height = AV_RL32(p + 180);
} else if(t == 0x05589f81){
+ if (os->psize < 136)
+ return AVERROR_INVALIDDATA;
+
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
st->codec->channels = AV_RL16(p + 126);
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparseopus.c b/chromium/third_party/ffmpeg/libavformat/oggparseopus.c
index aafefbbe65b..75c611413ec 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparseopus.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparseopus.c
@@ -32,6 +32,7 @@ struct oggopus_private {
int64_t cur_dts;
};
+#define OPUS_SEEK_PREROLL_MS 80
#define OPUS_HEAD_SIZE 19
static int opus_header(AVFormatContext *avf, int idx)
@@ -66,6 +67,9 @@ static int opus_header(AVFormatContext *avf, int idx)
memcpy(st->codec->extradata, packet, os->psize);
st->codec->sample_rate = 48000;
+ av_codec_set_seek_preroll(st->codec,
+ av_rescale(OPUS_SEEK_PREROLL_MS,
+ st->codec->sample_rate, 1000));
avpriv_set_pts_info(st, 64, 1, 48000);
priv->need_comments = 1;
return 1;
@@ -130,16 +134,13 @@ static int opus_packet(AVFormatContext *avf, int idx)
duration += d;
last_pkt = next_pkt = next_pkt + os->psize;
for (; seg < os->nsegs; seg++) {
- if (os->segments[seg] < 255) {
- int d = opus_duration(last_pkt, os->segments[seg]);
- if (d < 0) {
- duration = os->granule;
- break;
- }
- duration += d;
- last_pkt = next_pkt + os->segments[seg];
- }
next_pkt += os->segments[seg];
+ if (os->segments[seg] < 255 && next_pkt != last_pkt) {
+ int d = opus_duration(last_pkt, next_pkt - last_pkt);
+ if (d > 0)
+ duration += d;
+ last_pkt = next_pkt;
+ }
}
os->lastpts =
os->lastdts = os->granule - duration;
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c b/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c
index d94b0c2e07b..6c2105f324f 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c
@@ -34,7 +34,6 @@ static int skeleton_header(AVFormatContext *s, int idx)
uint64_t start_granule;
int target_idx, start_time;
- strcpy(st->codec->codec_name, "skeleton");
st->codec->codec_type = AVMEDIA_TYPE_DATA;
if ((os->flags & OGG_FLAG_EOS) && os->psize == 0)
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparsetheora.c b/chromium/third_party/ffmpeg/libavformat/oggparsetheora.c
index 6458b97bc0a..59df17efba1 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparsetheora.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparsetheora.c
@@ -131,6 +131,8 @@ static int theora_header(AVFormatContext *s, int idx)
st->codec->extradata_size = 0;
return err;
}
+ memset(st->codec->extradata + cds, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
cdp = st->codec->extradata + st->codec->extradata_size;
*cdp++ = os->psize >> 8;
*cdp++ = os->psize & 0xff;
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c b/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c
index 36ad7384ea4..2d8cb15af9a 100644
--- a/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c
+++ b/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c
@@ -36,6 +36,7 @@
#include "internal.h"
#include "oggdec.h"
#include "vorbiscomment.h"
+#include "replaygain.h"
static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
{
@@ -155,16 +156,21 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n");
continue;
}
- } else if (!ogm_chapter(as, tt, ct))
+ } else if (!ogm_chapter(as, tt, ct)) {
+ if (av_dict_get(*m, tt, NULL, 0)) {
+ av_dict_set(m, tt, ";", AV_DICT_APPEND);
+ }
av_dict_set(m, tt, ct,
AV_DICT_DONT_STRDUP_KEY |
- AV_DICT_DONT_STRDUP_VAL);
+ AV_DICT_APPEND);
+ av_freep(&ct);
+ }
}
}
if (p != end)
av_log(as, AV_LOG_INFO,
- "%ti bytes of comment header remain\n", end - p);
+ "%"PTRDIFF_SPECIFIER" bytes of comment header remain\n", end - p);
if (n > 0)
av_log(as, AV_LOG_INFO,
"truncated comment header, %i comments not found\n", n);
@@ -237,6 +243,36 @@ static void vorbis_cleanup(AVFormatContext *s, int idx)
av_freep(&priv->packet[i]);
}
+static int vorbis_update_metadata(AVFormatContext *s, int idx)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ int ret;
+
+ if (os->psize <= 8)
+ return 0;
+
+ /* New metadata packet; release old data. */
+ av_dict_free(&st->metadata);
+ ret = ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7,
+ os->psize - 8);
+ if (ret < 0)
+ return ret;
+
+ /* Update the metadata if possible. */
+ av_freep(&os->new_metadata);
+ if (st->metadata) {
+ os->new_metadata = av_packet_pack_dictionary(st->metadata, &os->new_metadata_size);
+ /* Send an empty dictionary to indicate that metadata has been cleared. */
+ } else {
+ os->new_metadata = av_malloc(1);
+ os->new_metadata_size = 0;
+ }
+
+ return ret;
+}
+
static int vorbis_header(AVFormatContext *s, int idx)
{
struct ogg *ogg = s->priv_data;
@@ -312,11 +348,15 @@ static int vorbis_header(AVFormatContext *s, int idx)
avpriv_set_pts_info(st, 64, 1, srate);
}
} else if (os->buf[os->pstart] == 3) {
- if (os->psize > 8 &&
- ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7,
- os->psize - 8) >= 0) {
+ if (vorbis_update_metadata(s, idx) >= 0 && priv->len[1] > 10) {
+ unsigned new_len;
+
+ int ret = ff_replaygain_export(st, st->metadata);
+ if (ret < 0)
+ return ret;
+
// drop all metadata we parsed and which is not required by libvorbis
- unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
+ new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
if (new_len >= 16 && new_len < os->psize) {
AV_WL32(priv->packet[1] + new_len - 5, 0);
priv->packet[1][new_len - 1] = 1;
@@ -345,13 +385,13 @@ static int vorbis_packet(AVFormatContext *s, int idx)
struct ogg *ogg = s->priv_data;
struct ogg_stream *os = ogg->streams + idx;
struct oggvorbis_private *priv = os->private;
- int duration;
+ int duration, flags = 0;
/* first packet handling
* here we parse the duration of each packet in the first page and compare
* the total duration to the page granule to find the encoder delay and
* set the first timestamp */
- if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
+ if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS) && (int64_t)os->granule>=0) {
int seg, d;
uint8_t *last_pkt = os->buf + os->pstart;
uint8_t *next_pkt = last_pkt;
@@ -359,19 +399,25 @@ static int vorbis_packet(AVFormatContext *s, int idx)
avpriv_vorbis_parse_reset(&priv->vp);
duration = 0;
seg = os->segp;
- d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
+ d = avpriv_vorbis_parse_frame_flags(&priv->vp, last_pkt, 1, &flags);
if (d < 0) {
os->pflags |= AV_PKT_FLAG_CORRUPT;
return 0;
+ } else if (flags & VORBIS_FLAG_COMMENT) {
+ vorbis_update_metadata(s, idx);
+ flags = 0;
}
duration += d;
last_pkt = next_pkt = next_pkt + os->psize;
for (; seg < os->nsegs; seg++) {
if (os->segments[seg] < 255) {
- int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
+ int d = avpriv_vorbis_parse_frame_flags(&priv->vp, last_pkt, 1, &flags);
if (d < 0) {
duration = os->granule;
break;
+ } else if (flags & VORBIS_FLAG_COMMENT) {
+ vorbis_update_metadata(s, idx);
+ flags = 0;
}
duration += d;
last_pkt = next_pkt + os->segments[seg];
@@ -380,9 +426,13 @@ static int vorbis_packet(AVFormatContext *s, int idx)
}
os->lastpts =
os->lastdts = os->granule - duration;
+
+ if (!os->granule && duration) //hack to deal with broken files (Ticket3710)
+ os->lastpts = os->lastdts = AV_NOPTS_VALUE;
+
if (s->streams[idx]->start_time == AV_NOPTS_VALUE) {
s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
- if (s->streams[idx]->duration)
+ if (s->streams[idx]->duration != AV_NOPTS_VALUE)
s->streams[idx]->duration -= s->streams[idx]->start_time;
}
priv->final_pts = AV_NOPTS_VALUE;
@@ -391,10 +441,13 @@ static int vorbis_packet(AVFormatContext *s, int idx)
/* parse packet duration */
if (os->psize > 0) {
- duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
+ duration = avpriv_vorbis_parse_frame_flags(&priv->vp, os->buf + os->pstart, 1, &flags);
if (duration < 0) {
os->pflags |= AV_PKT_FLAG_CORRUPT;
return 0;
+ } else if (flags & VORBIS_FLAG_COMMENT) {
+ vorbis_update_metadata(s, idx);
+ flags = 0;
}
os->pduration = duration;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/oggparsevp8.c b/chromium/third_party/ffmpeg/libavformat/oggparsevp8.c
new file mode 100644
index 00000000000..89295c86a68
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/oggparsevp8.c
@@ -0,0 +1,137 @@
+/*
+ * On2 VP8 parser for Ogg
+ * Copyright (C) 2013 James Almer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+#include "oggdec.h"
+
+#define VP8_HEADER_SIZE 26
+
+static int vp8_header(AVFormatContext *s, int idx)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+ uint8_t *p = os->buf + os->pstart;
+ AVStream *st = s->streams[idx];
+ AVRational framerate;
+
+ if (os->psize < 7 || p[0] != 0x4f)
+ return 0;
+
+ switch (p[5]){
+ case 0x01:
+ if (os->psize < VP8_HEADER_SIZE) {
+ av_log(s, AV_LOG_ERROR, "Invalid OggVP8 header packet");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (p[6] != 1) {
+ av_log(s, AV_LOG_WARNING, "Unknown OggVP8 version %d.%d\n", p[6], p[7]);
+ return AVERROR_INVALIDDATA;
+ }
+
+ st->codec->width = AV_RB16(p + 8);
+ st->codec->height = AV_RB16(p + 10);
+ st->sample_aspect_ratio.num = AV_RB24(p + 12);
+ st->sample_aspect_ratio.den = AV_RB24(p + 15);
+ framerate.den = AV_RB32(p + 18);
+ framerate.num = AV_RB32(p + 22);
+
+ avpriv_set_pts_info(st, 64, framerate.num, framerate.den);
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = AV_CODEC_ID_VP8;
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ break;
+ case 0x02:
+ if (p[6] != 0x20)
+ return AVERROR_INVALIDDATA;
+ ff_vorbis_comment(s, &st->metadata, p + 7, os->psize - 7);
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "Unknown VP8 header type 0x%02X\n", p[5]);
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 1;
+}
+
+static uint64_t vp8_gptopts(AVFormatContext *s, int idx, uint64_t granule, int64_t *dts)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+
+ uint64_t pts = (granule >> 32);
+ uint32_t dist = (granule >> 3) & 0x07ffffff;
+
+ if (!dist)
+ os->pflags |= AV_PKT_FLAG_KEY;
+
+ if (dts)
+ *dts = pts;
+
+ return pts;
+}
+
+static int vp8_packet(AVFormatContext *s, int idx)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+ uint8_t *p = os->buf + os->pstart;
+
+ if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
+ int seg;
+ int duration;
+ uint8_t *last_pkt = p;
+ uint8_t *next_pkt;
+
+ seg = os->segp;
+ duration = (last_pkt[0] >> 4) & 1;
+ next_pkt = last_pkt += os->psize;
+ for (; seg < os->nsegs; seg++) {
+ if (os->segments[seg] < 255) {
+ duration += (last_pkt[0] >> 4) & 1;
+ last_pkt = next_pkt + os->segments[seg];
+ }
+ next_pkt += os->segments[seg];
+ }
+ os->lastpts = os->lastdts = vp8_gptopts(s, idx, os->granule, NULL) - duration;
+ if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
+ s->streams[idx]->start_time = os->lastpts;
+ if (s->streams[idx]->duration)
+ s->streams[idx]->duration -= s->streams[idx]->start_time;
+ }
+ }
+
+ if (os->psize > 0)
+ os->pduration = (p[0] >> 4) & 1;
+
+ return 0;
+}
+
+const struct ogg_codec ff_vp8_codec = {
+ .magic = "OVP80",
+ .magicsize = 5,
+ .header = vp8_header,
+ .packet = vp8_packet,
+ .gptopts = vp8_gptopts,
+ .nb_header = 1,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/omadec.c b/chromium/third_party/ffmpeg/libavformat/omadec.c
index 6a08076f473..9f3d3aa860f 100644
--- a/chromium/third_party/ffmpeg/libavformat/omadec.c
+++ b/chromium/third_party/ffmpeg/libavformat/omadec.c
@@ -37,8 +37,11 @@
* - Sound data organized in packets follow the EA3 header
* (can be encrypted using the Sony DRM!).
*
+ * Supported decoders: ATRAC3, ATRAC3+, MP3, LPCM
*/
+#include <inttypes.h>
+
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
@@ -214,7 +217,7 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header)
if (geob->datasize < 64) {
av_log(s, AV_LOG_ERROR,
- "Invalid GEOB data size: %u\n", geob->datasize);
+ "Invalid GEOB data size: %"PRIu32"\n", geob->datasize);
return AVERROR_INVALIDDATA;
}
@@ -238,7 +241,7 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header)
return AVERROR_INVALIDDATA;
}
oc->rid = AV_RB32(&gdata[OMA_ENC_HEADER_SIZE + 28]);
- av_log(s, AV_LOG_DEBUG, "RID: %.8x\n", oc->rid);
+ av_log(s, AV_LOG_DEBUG, "RID: %.8"PRIx32"\n", oc->rid);
memcpy(oc->iv, &header[0x58], 8);
hex_log(s, AV_LOG_DEBUG, "IV", oc->iv, 8);
@@ -292,7 +295,7 @@ static int oma_read_header(AVFormatContext *s)
ID3v2ExtraMeta *extra_meta = NULL;
OMAContext *oc = s->priv_data;
- ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta);
+ ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta, 0);
ret = avio_read(s->pb, buf, EA3_HEADER_SIZE);
if (ret < EA3_HEADER_SIZE)
return -1;
@@ -365,7 +368,7 @@ static int oma_read_header(AVFormatContext *s)
channel_id = (codec_params >> 10) & 7;
if (!channel_id) {
av_log(s, AV_LOG_ERROR,
- "Invalid ATRAC-X channel id: %d\n", channel_id);
+ "Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id);
return AVERROR_INVALIDDATA;
}
st->codec->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1];
@@ -379,7 +382,6 @@ static int oma_read_header(AVFormatContext *s)
st->codec->sample_rate = samplerate;
st->codec->bit_rate = samplerate * framesize * 8 / 2048;
avpriv_set_pts_info(st, 64, 1, samplerate);
- av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n");
break;
case OMA_CODECID_MP3:
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
@@ -448,7 +450,7 @@ static int oma_read_probe(AVProbeData *p)
/* This check cannot overflow as tag_len has at most 28 bits */
if (p->buf_size < tag_len + 5)
/* EA3 header comes late, might be outside of the probe buffer */
- return tag_len ? AVPROBE_SCORE_EXTENSION : 0;
+ return tag_len ? AVPROBE_SCORE_EXTENSION/2 : 0;
buf += tag_len;
diff --git a/chromium/third_party/ffmpeg/libavformat/options.c b/chromium/third_party/ffmpeg/libavformat/options.c
index 5218e5b92a4..e0d6df6fbde 100644
--- a/chromium/third_party/ffmpeg/libavformat/options.c
+++ b/chromium/third_party/ffmpeg/libavformat/options.c
@@ -19,6 +19,7 @@
*/
#include "avformat.h"
#include "avio_internal.h"
+#include "internal.h"
#include "libavutil/opt.h"
/**
@@ -109,6 +110,13 @@ AVFormatContext *avformat_alloc_context(void)
ic = av_malloc(sizeof(AVFormatContext));
if (!ic) return ic;
avformat_get_context_defaults(ic);
+
+ ic->internal = av_mallocz(sizeof(*ic->internal));
+ if (!ic->internal) {
+ avformat_free_context(ic);
+ return NULL;
+ }
+
return ic;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/options_table.h b/chromium/third_party/ffmpeg/libavformat/options_table.h
index 8145325c1c7..359b38483aa 100644
--- a/chromium/third_party/ffmpeg/libavformat/options_table.h
+++ b/chromium/third_party/ffmpeg/libavformat/options_table.h
@@ -50,6 +50,7 @@ static const AVOption avformat_options[] = {
{"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"},
{"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"},
{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, D},
+{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.i64 = 5*AV_TIME_BASE }, 0, INT_MAX, D},
{"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D},
@@ -57,6 +58,7 @@ static const AVOption avformat_options[] = {
{"fdebug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, E|D, "fdebug"},
{"ts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_FDEBUG_TS }, INT_MIN, INT_MAX, E|D, "fdebug"},
{"max_delay", "maximum muxing or demuxing delay in microseconds", OFFSET(max_delay), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, E|D},
+{"start_time_realtime", "wall-clock time when stream begins (PTS==0)", OFFSET(start_time_realtime), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, E},
{"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX-1, D},
{"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},
{"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},
@@ -69,14 +71,22 @@ static const AVOption avformat_options[] = {
{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, D, "err_detect"},
{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, D, "err_detect"},
{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"},
+{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, D, "err_detect"},
{"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"},
{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"},
{"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"},
{"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D},
-{"avoid_negative_ts", "shift timestamps to make them non-negative. 1 enables, 0 disables, default of -1 enables when required by target format.", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, E},
+{"avoid_negative_ts", "shift timestamps so they start at 0", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, E, "avoid_negative_ts"},
+{"auto", "enabled when required by target format", 0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"disabled", "do not change timestamps", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"make_zero", "shift timestamps so they start at 0", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
{"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D},
{"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, D},
{"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E},
+{"metadata_header_padding", "set number of bytes to be written as padding in a metadata header", OFFSET(metadata_header_padding), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, E},
+{"output_ts_offset", "set output timestamp offset", OFFSET(output_ts_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E},
+{"max_interleave_delta", "maximum buffering duration for interleaving", OFFSET(max_interleave_delta), AV_OPT_TYPE_INT64, { .i64 = 10000000 }, 0, INT64_MAX, E },
{NULL},
};
diff --git a/chromium/third_party/ffmpeg/libavformat/paf.c b/chromium/third_party/ffmpeg/libavformat/paf.c
index 09aefe6770b..88a274fe156 100644
--- a/chromium/third_party/ffmpeg/libavformat/paf.c
+++ b/chromium/third_party/ffmpeg/libavformat/paf.c
@@ -44,13 +44,13 @@ typedef struct {
uint32_t *blocks_offset_table;
uint8_t *video_frame;
- int video_size;
+ int video_size;
uint8_t *audio_frame;
uint8_t *temp_audio_frame;
- int audio_size;
+ int audio_size;
- int got_audio;
+ int got_audio;
} PAFDemuxContext;
static int read_probe(AVProbeData *p)
@@ -87,10 +87,10 @@ static void read_table(AVFormatContext *s, uint32_t *table, uint32_t count)
static int read_header(AVFormatContext *s)
{
- PAFDemuxContext *p = s->priv_data;
+ PAFDemuxContext *p = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *ast, *vst;
- int ret = 0;
+ int ret = 0;
avio_skip(pb, 132);
@@ -101,11 +101,13 @@ static int read_header(AVFormatContext *s)
vst->start_time = 0;
vst->nb_frames =
vst->duration =
- p->nb_frames = avio_rl32(pb);
+ p->nb_frames = avio_rl32(pb);
avio_skip(pb, 4);
+
vst->codec->width = avio_rl32(pb);
vst->codec->height = avio_rl32(pb);
avio_skip(pb, 4);
+
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codec->codec_tag = 0;
vst->codec->codec_id = AV_CODEC_ID_PAF_VIDEO;
@@ -115,13 +117,13 @@ static int read_header(AVFormatContext *s)
if (!ast)
return AVERROR(ENOMEM);
- ast->start_time = 0;
- ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- ast->codec->codec_tag = 0;
- ast->codec->codec_id = AV_CODEC_ID_PAF_AUDIO;
- ast->codec->channels = 2;
+ ast->start_time = 0;
+ ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ ast->codec->codec_tag = 0;
+ ast->codec->codec_id = AV_CODEC_ID_PAF_AUDIO;
+ ast->codec->channels = 2;
ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
- ast->codec->sample_rate = 22050;
+ ast->codec->sample_rate = 22050;
avpriv_set_pts_info(ast, 64, 1, 22050);
p->buffer_size = avio_rl32(pb);
@@ -143,16 +145,19 @@ static int read_header(AVFormatContext *s)
p->frame_blks > INT_MAX / sizeof(uint32_t))
return AVERROR_INVALIDDATA;
- p->blocks_count_table = av_mallocz(p->nb_frames * sizeof(uint32_t));
- p->frames_offset_table = av_mallocz(p->nb_frames * sizeof(uint32_t));
- p->blocks_offset_table = av_mallocz(p->frame_blks * sizeof(uint32_t));
+ p->blocks_count_table = av_mallocz(p->nb_frames *
+ sizeof(*p->blocks_count_table));
+ p->frames_offset_table = av_mallocz(p->nb_frames *
+ sizeof(*p->frames_offset_table));
+ p->blocks_offset_table = av_mallocz(p->frame_blks *
+ sizeof(*p->blocks_offset_table));
- p->video_size = p->max_video_blks * p->buffer_size;
- p->video_frame = av_mallocz(p->video_size);
+ p->video_size = p->max_video_blks * p->buffer_size;
+ p->video_frame = av_mallocz(p->video_size);
- p->audio_size = p->max_audio_blks * p->buffer_size;
- p->audio_frame = av_mallocz(p->audio_size);
- p->temp_audio_frame = av_mallocz(p->audio_size);
+ p->audio_size = p->max_audio_blks * p->buffer_size;
+ p->audio_frame = av_mallocz(p->audio_size);
+ p->temp_audio_frame = av_mallocz(p->audio_size);
if (!p->blocks_count_table ||
!p->frames_offset_table ||
@@ -186,7 +191,7 @@ fail:
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
- PAFDemuxContext *p = s->priv_data;
+ PAFDemuxContext *p = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t count, offset;
int size, i;
@@ -209,7 +214,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
return pkt->size;
}
- count = (p->current_frame == 0) ? p->preload_count : p->blocks_count_table[p->current_frame - 1];
+ count = (p->current_frame == 0) ? p->preload_count
+ : p->blocks_count_table[p->current_frame - 1];
for (i = 0; i < count; i++) {
if (p->current_frame_block >= p->frame_blks)
return AVERROR_INVALIDDATA;
@@ -245,7 +251,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->duration = 1;
memcpy(pkt->data, p->video_frame + p->frames_offset_table[p->current_frame], size);
if (pkt->data[0] & 0x20)
- pkt->flags |= AV_PKT_FLAG_KEY;
+ pkt->flags |= AV_PKT_FLAG_KEY;
p->current_frame++;
return pkt->size;
diff --git a/chromium/third_party/ffmpeg/libavformat/pcm.c b/chromium/third_party/ffmpeg/libavformat/pcm.c
index 2fe44dcb407..a57a4b62493 100644
--- a/chromium/third_party/ffmpeg/libavformat/pcm.c
+++ b/chromium/third_party/ffmpeg/libavformat/pcm.c
@@ -37,8 +37,6 @@ int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
pkt->stream_index = 0;
- if (ret < 0)
- return ret;
return ret;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/pjsdec.c b/chromium/third_party/ffmpeg/libavformat/pjsdec.c
index a69a31660da..6f5db378866 100644
--- a/chromium/third_party/ffmpeg/libavformat/pjsdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/pjsdec.c
@@ -53,7 +53,8 @@ static int64_t read_ts(char **line, int *duration)
int64_t start, end;
if (sscanf(*line, "%"SCNd64",%"SCNd64, &start, &end) == 2) {
- *line += strcspn(*line, "\"") + 1;
+ *line += strcspn(*line, "\"");
+ *line += !!**line;
*duration = end - start;
return start;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/pmpdec.c b/chromium/third_party/ffmpeg/libavformat/pmpdec.c
index 71f450e9d37..d03283722a3 100644
--- a/chromium/third_party/ffmpeg/libavformat/pmpdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/pmpdec.c
@@ -138,10 +138,12 @@ static int pmp_packet(AVFormatContext *s, AVPacket *pkt)
if (pmp->cur_stream == 0) {
int num_packets;
pmp->audio_packets = avio_r8(pb);
+
if (!pmp->audio_packets) {
- avpriv_request_sample(s, "0 audio packets");
- return AVERROR_PATCHWELCOME;
+ av_log(s, AV_LOG_ERROR, "No audio packets.\n");
+ return AVERROR_INVALIDDATA;
}
+
num_packets = (pmp->num_streams - 1) * pmp->audio_packets + 1;
avio_skip(pb, 8);
pmp->current_packet = 0;
@@ -158,10 +160,6 @@ static int pmp_packet(AVFormatContext *s, AVPacket *pkt)
ret = av_get_packet(pb, pkt, pmp->packet_sizes[pmp->current_packet]);
if (ret >= 0) {
ret = 0;
- // FIXME: this is a hack that should be removed once
- // compute_pkt_fields() can handle timestamps properly
- if (pmp->cur_stream == 0)
- pkt->dts = s->streams[0]->cur_dts++;
pkt->stream_index = pmp->cur_stream;
}
if (pmp->current_packet % pmp->audio_packets == 0)
diff --git a/chromium/third_party/ffmpeg/libavformat/psxstr.c b/chromium/third_party/ffmpeg/libavformat/psxstr.c
index 3409d6a5af8..5efcadf64e6 100644
--- a/chromium/third_party/ffmpeg/libavformat/psxstr.c
+++ b/chromium/third_party/ffmpeg/libavformat/psxstr.c
@@ -221,6 +221,7 @@ static int str_read_packet(AVFormatContext *s,
av_free_packet(pkt);
if (av_new_packet(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE))
return AVERROR(EIO);
+ memset(pkt->data, 0, sector_count*VIDEO_DATA_CHUNK_SIZE);
pkt->pos= avio_tell(pb) - RAW_CD_SECTOR_SIZE;
pkt->stream_index =
diff --git a/chromium/third_party/ffmpeg/libavformat/pva.c b/chromium/third_party/ffmpeg/libavformat/pva.c
index 9b7a40a0682..18ab1cd3fc0 100644
--- a/chromium/third_party/ffmpeg/libavformat/pva.c
+++ b/chromium/third_party/ffmpeg/libavformat/pva.c
@@ -85,6 +85,7 @@ static int read_part_of_packet(AVFormatContext *s, int64_t *pts,
PVAContext *pvactx = s->priv_data;
int syncword, streamid, reserved, flags, length, pts_flag;
int64_t pva_pts = AV_NOPTS_VALUE, startpos;
+ int ret;
recover:
startpos = avio_tell(pb);
@@ -133,8 +134,8 @@ recover:
pes_flags = avio_rb16(pb);
pes_header_data_length = avio_r8(pb);
- if (pes_signal != 1) {
- pva_log(s, AV_LOG_WARNING, "expected signaled PES packet, "
+ if (pes_signal != 1 || pes_header_data_length == 0) {
+ pva_log(s, AV_LOG_WARNING, "expected non empty signaled PES packet, "
"trying to recover\n");
avio_skip(pb, length - 9);
if (!read_packet)
@@ -142,15 +143,23 @@ recover:
goto recover;
}
- avio_read(pb, pes_header_data, pes_header_data_length);
+ ret = avio_read(pb, pes_header_data, pes_header_data_length);
+ if (ret != pes_header_data_length)
+ return ret < 0 ? ret : AVERROR_INVALIDDATA;
length -= 9 + pes_header_data_length;
pes_packet_length -= 3 + pes_header_data_length;
pvactx->continue_pes = pes_packet_length;
- if (pes_flags & 0x80 && (pes_header_data[0] & 0xf0) == 0x20)
+ if (pes_flags & 0x80 && (pes_header_data[0] & 0xf0) == 0x20) {
+ if (pes_header_data_length < 5) {
+ pva_log(s, AV_LOG_ERROR, "header too short\n");
+ avio_skip(pb, length);
+ return AVERROR_INVALIDDATA;
+ }
pva_pts = ff_parse_pes_pts(pes_header_data);
+ }
}
pvactx->continue_pes -= length;
diff --git a/chromium/third_party/ffmpeg/libavformat/rawdec.c b/chromium/third_party/ffmpeg/libavformat/rawdec.c
index a9ff22ae182..9b2aa3551e4 100644
--- a/chromium/third_party/ffmpeg/libavformat/rawdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/rawdec.c
@@ -28,6 +28,7 @@
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/avassert.h"
+#include "libavutil/intreadwrite.h"
#define RAW_PACKET_SIZE 1024
@@ -121,6 +122,7 @@ AVInputFormat ff_data_demuxer = {
#endif
#if CONFIG_LATM_DEMUXER
+
AVInputFormat ff_latm_demuxer = {
.name = "latm",
.long_name = NULL_IF_CONFIG_SMALL("raw LOAS/LATM"),
diff --git a/chromium/third_party/ffmpeg/libavformat/rawenc.c b/chromium/third_party/ffmpeg/libavformat/rawenc.c
index 7a1fa93e8ba..abd7e66978e 100644
--- a/chromium/third_party/ffmpeg/libavformat/rawenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/rawenc.c
@@ -29,6 +29,16 @@ int ff_raw_write_packet(AVFormatContext *s, AVPacket *pkt)
return 0;
}
+static int force_one_stream(AVFormatContext *s)
+{
+ if (s->nb_streams != 1) {
+ av_log(s, AV_LOG_ERROR, "%s files have exactly one stream\n",
+ s->oformat->name);
+ return AVERROR(EINVAL);
+ }
+ return 0;
+}
+
/* Note: Do not forget to add new entries to the Makefile as well. */
#if CONFIG_AC3_MUXER
@@ -39,6 +49,7 @@ AVOutputFormat ff_ac3_muxer = {
.extensions = "ac3",
.audio_codec = AV_CODEC_ID_AC3,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -51,6 +62,7 @@ AVOutputFormat ff_adx_muxer = {
.extensions = "adx",
.audio_codec = AV_CODEC_ID_ADPCM_ADX,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -63,6 +75,7 @@ AVOutputFormat ff_cavsvideo_muxer = {
.extensions = "cavs",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_CAVS,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -72,6 +85,7 @@ AVOutputFormat ff_cavsvideo_muxer = {
AVOutputFormat ff_data_muxer = {
.name = "data",
.long_name = NULL_IF_CONFIG_SMALL("raw data"),
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -84,6 +98,7 @@ AVOutputFormat ff_dirac_muxer = {
.extensions = "drc",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_DIRAC,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -96,6 +111,7 @@ AVOutputFormat ff_dnxhd_muxer = {
.extensions = "dnxhd",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_DNXHD,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -109,6 +125,7 @@ AVOutputFormat ff_dts_muxer = {
.extensions = "dts",
.audio_codec = AV_CODEC_ID_DTS,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -122,6 +139,7 @@ AVOutputFormat ff_eac3_muxer = {
.extensions = "eac3",
.audio_codec = AV_CODEC_ID_EAC3,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -135,6 +153,7 @@ AVOutputFormat ff_g722_muxer = {
.extensions = "g722",
.audio_codec = AV_CODEC_ID_ADPCM_G722,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -148,6 +167,7 @@ AVOutputFormat ff_g723_1_muxer = {
.extensions = "tco,rco",
.audio_codec = AV_CODEC_ID_G723_1,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -161,6 +181,7 @@ AVOutputFormat ff_h261_muxer = {
.extensions = "h261",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_H261,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -174,6 +195,7 @@ AVOutputFormat ff_h263_muxer = {
.extensions = "h263",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_H263,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -186,6 +208,19 @@ AVOutputFormat ff_h264_muxer = {
.extensions = "h264",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_H264,
+ .write_header = force_one_stream,
+ .write_packet = ff_raw_write_packet,
+ .flags = AVFMT_NOTIMESTAMPS,
+};
+#endif
+
+#if CONFIG_HEVC_MUXER
+AVOutputFormat ff_hevc_muxer = {
+ .name = "hevc",
+ .long_name = NULL_IF_CONFIG_SMALL("raw HEVC video"),
+ .extensions = "hevc",
+ .audio_codec = AV_CODEC_ID_NONE,
+ .video_codec = AV_CODEC_ID_HEVC,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -211,6 +246,7 @@ AVOutputFormat ff_mjpeg_muxer = {
.extensions = "mjpg,mjpeg",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_MJPEG,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -223,6 +259,7 @@ AVOutputFormat ff_mlp_muxer = {
.extensions = "mlp",
.audio_codec = AV_CODEC_ID_MLP,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -236,6 +273,7 @@ AVOutputFormat ff_mpeg1video_muxer = {
.extensions = "mpg,mpeg,m1v",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_MPEG1VIDEO,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -248,6 +286,7 @@ AVOutputFormat ff_mpeg2video_muxer = {
.extensions = "m2v",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_MPEG2VIDEO,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -272,6 +311,7 @@ AVOutputFormat ff_truehd_muxer = {
.extensions = "thd",
.audio_codec = AV_CODEC_ID_TRUEHD,
.video_codec = AV_CODEC_ID_NONE,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
@@ -284,6 +324,7 @@ AVOutputFormat ff_vc1_muxer = {
.extensions = "vc1",
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_VC1,
+ .write_header = force_one_stream,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
diff --git a/chromium/third_party/ffmpeg/libavformat/replaygain.c b/chromium/third_party/ffmpeg/libavformat/replaygain.c
new file mode 100644
index 00000000000..8b8c81a0c3a
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/replaygain.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * replaygain tags parsing
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/avstring.h"
+#include "libavutil/dict.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/mem.h"
+#include "libavutil/replaygain.h"
+
+#include "avformat.h"
+#include "replaygain.h"
+
+static int32_t parse_value(const char *value, int32_t min)
+{
+ char *fraction;
+ int scale = 10000;
+ int32_t mb = 0;
+ int sign = 1;
+ int db;
+
+ if (!value)
+ return min;
+
+ value += strspn(value, " \t");
+
+ if (*value == '-')
+ sign = -1;
+
+ db = strtol(value, &fraction, 0);
+ if (*fraction++ == '.') {
+ while (av_isdigit(*fraction) && scale) {
+ mb += scale * (*fraction - '0');
+ scale /= 10;
+ fraction++;
+ }
+ }
+
+ if (abs(db) > (INT32_MAX - mb) / 100000)
+ return min;
+
+ return db * 100000 + sign * mb;
+}
+
+int ff_replaygain_export_raw(AVStream *st, int32_t tg, uint32_t tp,
+ int32_t ag, uint32_t ap)
+{
+ AVPacketSideData *sd, *tmp;
+ AVReplayGain *replaygain;
+ int i;
+
+ if (tg == INT32_MIN && ag == INT32_MIN)
+ return 0;
+
+ for (i = 0; i < st->nb_side_data; i++) {
+ AVPacketSideData *src_sd = &st->side_data[i];
+
+ if (src_sd->type == AV_PKT_DATA_REPLAYGAIN)
+ return 0;
+ }
+
+ replaygain = av_mallocz(sizeof(*replaygain));
+ if (!replaygain)
+ return AVERROR(ENOMEM);
+
+ tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp));
+ if (!tmp) {
+ av_freep(&replaygain);
+ return AVERROR(ENOMEM);
+ }
+ st->side_data = tmp;
+ st->nb_side_data++;
+
+ sd = &st->side_data[st->nb_side_data - 1];
+ sd->type = AV_PKT_DATA_REPLAYGAIN;
+ sd->data = (uint8_t*)replaygain;
+ sd->size = sizeof(*replaygain);
+
+ replaygain->track_gain = tg;
+ replaygain->track_peak = tp;
+ replaygain->album_gain = ag;
+ replaygain->album_peak = ap;
+
+ return 0;
+}
+
+int ff_replaygain_export(AVStream *st, AVDictionary *metadata)
+{
+ const AVDictionaryEntry *tg, *tp, *ag, *ap;
+
+ tg = av_dict_get(metadata, "REPLAYGAIN_TRACK_GAIN", NULL, 0);
+ tp = av_dict_get(metadata, "REPLAYGAIN_TRACK_PEAK", NULL, 0);
+ ag = av_dict_get(metadata, "REPLAYGAIN_ALBUM_GAIN", NULL, 0);
+ ap = av_dict_get(metadata, "REPLAYGAIN_ALBUM_PEAK", NULL, 0);
+
+ return ff_replaygain_export_raw(st,
+ parse_value(tg ? tg->value : NULL, INT32_MIN),
+ parse_value(tp ? tp->value : NULL, 0),
+ parse_value(ag ? ag->value : NULL, INT32_MIN),
+ parse_value(ap ? ap->value : NULL, 0));
+}
diff --git a/chromium/third_party/ffmpeg/libavformat/replaygain.h b/chromium/third_party/ffmpeg/libavformat/replaygain.h
new file mode 100644
index 00000000000..ceacb21421e
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/replaygain.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_REPLAYGAIN_H
+#define AVFORMAT_REPLAYGAIN_H
+
+#include "libavutil/dict.h"
+
+#include "avformat.h"
+
+/**
+ * Parse replaygain tags and export them as per-stream side data.
+ */
+int ff_replaygain_export(AVStream *st, AVDictionary *metadata);
+
+
+/**
+ * Export already decoded replaygain values as per-stream side data.
+ */
+int ff_replaygain_export_raw(AVStream *st, int32_t tg, uint32_t tp,
+ int32_t ag, uint32_t ap);
+
+#endif /* AVFORMAT_REPLAYGAIN_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/riff.c b/chromium/third_party/ffmpeg/libavformat/riff.c
index 52640d12411..735dea0eaf9 100644
--- a/chromium/third_party/ffmpeg/libavformat/riff.c
+++ b/chromium/third_party/ffmpeg/libavformat/riff.c
@@ -39,9 +39,10 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_H264, MKTAG('S', 'M', 'V', '2') },
{ AV_CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
{ AV_CODEC_ID_H264, MKTAG('Q', '2', '6', '4') }, /* QNAP surveillance system */
- { AV_CODEC_ID_H264, MKTAG('V', '2', '6', '4') },
+ { AV_CODEC_ID_H264, MKTAG('V', '2', '6', '4') }, /* CCTV recordings */
{ AV_CODEC_ID_H264, MKTAG('G', 'A', 'V', 'C') }, /* GeoVision camera */
{ AV_CODEC_ID_H264, MKTAG('U', 'M', 'S', 'V') },
+ { AV_CODEC_ID_H264, MKTAG('I', 'N', 'M', 'C') },
{ AV_CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
{ AV_CODEC_ID_H263, MKTAG('X', '2', '6', '3') },
{ AV_CODEC_ID_H263, MKTAG('T', '2', '6', '3') },
@@ -92,7 +93,6 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_MPEG4, MKTAG('D', 'M', 'K', '2') },
{ AV_CODEC_ID_MPEG4, MKTAG('D', 'Y', 'M', '4') },
{ AV_CODEC_ID_MPEG4, MKTAG('D', 'I', 'G', 'I') },
- { AV_CODEC_ID_MPEG4, MKTAG('I', 'N', 'M', 'C') },
/* Ephv MPEG-4 */
{ AV_CODEC_ID_MPEG4, MKTAG('E', 'P', 'H', 'V') },
{ AV_CODEC_ID_MPEG4, MKTAG('E', 'M', '4', 'A') },
@@ -258,6 +258,8 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_VP6A, MKTAG('V', 'P', '6', 'A') },
{ AV_CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') },
{ AV_CODEC_ID_VP6F, MKTAG('F', 'L', 'V', '4') },
+ { AV_CODEC_ID_VP7, MKTAG('V', 'P', '7', '0') },
+ { AV_CODEC_ID_VP7, MKTAG('V', 'P', '7', '1') },
{ AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') },
{ AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') },
{ AV_CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
@@ -300,7 +302,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
{ AV_CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
{ AV_CODEC_ID_WNV1, MKTAG('Y', 'U', 'V', '8') },
- { AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', '4') },
+ { AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', '4') }, /* Autodesk 24 bit RLE compressor */
{ AV_CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
{ AV_CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
{ AV_CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
@@ -356,6 +358,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '2') },
{ AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '3') },
{ AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '4') },
+ { AV_CODEC_ID_FIC, MKTAG('F', 'I', 'C', 'V') },
{ AV_CODEC_ID_NONE, 0 }
};
@@ -407,12 +410,16 @@ const AVCodecTag ff_codec_wav_tags[] = {
{ AV_CODEC_ID_ADPCM_G722, 0x028F },
{ AV_CODEC_ID_IMC, 0x0401 },
{ AV_CODEC_ID_IAC, 0x0402 },
+ { AV_CODEC_ID_ON2AVC, 0x0500 },
+ { AV_CODEC_ID_ON2AVC, 0x0501 },
{ AV_CODEC_ID_GSM_MS, 0x1500 },
{ AV_CODEC_ID_TRUESPEECH, 0x1501 },
/* ADTS AAC */
{ AV_CODEC_ID_AAC, 0x1600 },
{ AV_CODEC_ID_AAC_LATM, 0x1602 },
{ AV_CODEC_ID_AC3, 0x2000 },
+ /* There is no Microsoft Format Tag for E-AC3, the GUID has to be used */
+ { AV_CODEC_ID_EAC3, 0x2000 },
{ AV_CODEC_ID_DTS, 0x2001 },
{ AV_CODEC_ID_SONIC, 0x2048 },
{ AV_CODEC_ID_SONIC_LS, 0x2048 },
@@ -420,7 +427,7 @@ const AVCodecTag ff_codec_wav_tags[] = {
{ AV_CODEC_ID_AAC, 0x706d },
{ AV_CODEC_ID_AAC, 0x4143 },
{ AV_CODEC_ID_XAN_DPCM, 0x594a },
- { AV_CODEC_ID_G723_1, 0xA100 },
+ { AV_CODEC_ID_G723_1, 0xA100 }, /* Comverse Infosys Ltd. G723 1 */
{ AV_CODEC_ID_AAC, 0xA106 },
{ AV_CODEC_ID_SPEEX, 0xA109 },
{ AV_CODEC_ID_FLAC, 0xF1AC },
@@ -456,3 +463,11 @@ const struct AVCodecTag *avformat_get_riff_audio_tags(void)
{
return ff_codec_wav_tags;
}
+
+const AVCodecGuid ff_codec_wav_guids[] = {
+ { AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } },
+ { AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } },
+ { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } },
+ { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } },
+ { AV_CODEC_ID_NONE }
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/riff.h b/chromium/third_party/ffmpeg/libavformat/riff.h
index 1bf437e06c8..6f07179b2ae 100644
--- a/chromium/third_party/ffmpeg/libavformat/riff.h
+++ b/chromium/third_party/ffmpeg/libavformat/riff.h
@@ -45,8 +45,22 @@ void ff_end_tag(AVIOContext *pb, int64_t start);
*/
int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize);
-void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf);
-int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc);
+void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf, int ignore_extradata);
+
+/**
+ * Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs.
+ */
+#define FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX 0x00000001
+
+/**
+ * Write WAVEFORMAT header structure.
+ *
+ * @param flags a combination of FF_PUT_WAV_HEADER_* constants
+ *
+ * @return the size or -1 on error
+ */
+int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags);
+
enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps);
int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size);
@@ -91,7 +105,9 @@ static av_always_inline int ff_guidcmp(const void *g1, const void *g2)
return memcmp(g1, g2, sizeof(ff_asf_guid));
}
-void ff_get_guid(AVIOContext *s, ff_asf_guid *g);
+int ff_get_guid(AVIOContext *s, ff_asf_guid *g);
+void ff_put_guid(AVIOContext *s, const ff_asf_guid *g);
+const ff_asf_guid *get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid);
enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid);
diff --git a/chromium/third_party/ffmpeg/libavformat/riffdec.c b/chromium/third_party/ffmpeg/libavformat/riffdec.c
index de8eb5f5885..48c9a941b70 100644
--- a/chromium/third_party/ffmpeg/libavformat/riffdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/riffdec.c
@@ -29,19 +29,14 @@
#include "avio_internal.h"
#include "riff.h"
-const AVCodecGuid ff_codec_wav_guids[] = {
- { AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } },
- { AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } },
- { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } },
- { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } },
- { AV_CODEC_ID_NONE }
-};
-
-void ff_get_guid(AVIOContext *s, ff_asf_guid *g)
+int ff_get_guid(AVIOContext *s, ff_asf_guid *g)
{
av_assert0(sizeof(*g) == 16); //compiler will optimize this out
- if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g))
+ if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g)) {
memset(*g, 0, sizeof(*g));
+ return AVERROR_INVALIDDATA;
+ }
+ return 0;
}
enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid)
@@ -117,9 +112,8 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size)
}
if (cbSize > 0) {
av_free(codec->extradata);
- if (ff_alloc_extradata(codec, cbSize))
+ if (ff_get_extradata(codec, pb, cbSize) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, codec->extradata, codec->extradata_size);
size -= cbSize;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/riffenc.c b/chromium/third_party/ffmpeg/libavformat/riffenc.c
index bcfe018f74e..66c0ff29d63 100644
--- a/chromium/third_party/ffmpeg/libavformat/riffenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/riffenc.c
@@ -31,7 +31,7 @@
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
{
ffio_wfourcc(pb, tag);
- avio_wl32(pb, 0);
+ avio_wl32(pb, -1);
return avio_tell(pb);
}
@@ -51,10 +51,11 @@ void ff_end_tag(AVIOContext *pb, int64_t start)
/* WAVEFORMATEX header */
/* returns the size or -1 on error */
-int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
+int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
{
int bps, blkalign, bytespersec, frame_size;
- int hdrsize = 18;
+ int hdrsize;
+ int64_t hdrstart = avio_tell(pb);
int waveformatextensible;
uint8_t temp[256];
uint8_t *riff_extradata = temp;
@@ -72,6 +73,7 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
enc->sample_rate > 48000 ||
+ enc->codec_id == AV_CODEC_ID_EAC3 ||
av_get_bits_per_sample(enc->codec_id) > 16;
if (waveformatextensible)
@@ -134,14 +136,12 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
avio_wl16(pb, blkalign); /* block align */
avio_wl16(pb, bps); /* bits per sample */
if (enc->codec_id == AV_CODEC_ID_MP3) {
- hdrsize += 12;
bytestream_put_le16(&riff_extradata, 1); /* wID */
bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */
bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */
bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
} else if (enc->codec_id == AV_CODEC_ID_MP2) {
- hdrsize += 22;
/* fwHeadLayer */
bytestream_put_le16(&riff_extradata, 2);
/* dwHeadBitrate */
@@ -159,38 +159,44 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
/* dwPTSHigh */
bytestream_put_le32(&riff_extradata, 0);
} else if (enc->codec_id == AV_CODEC_ID_G723_1) {
- hdrsize += 20;
bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */
bytestream_put_le32(&riff_extradata, 0xaea2f732);
bytestream_put_le16(&riff_extradata, 0xacde);
} else if (enc->codec_id == AV_CODEC_ID_GSM_MS ||
enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
- hdrsize += 2;
/* wSamplesPerBlock */
bytestream_put_le16(&riff_extradata, frame_size);
} else if (enc->extradata_size) {
riff_extradata_start = enc->extradata;
riff_extradata = enc->extradata + enc->extradata_size;
- hdrsize += enc->extradata_size;
}
/* write WAVEFORMATEXTENSIBLE extensions */
if (waveformatextensible) {
- hdrsize += 22;
+ int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL ||
+ enc->channel_layout < 0x40000;
/* 22 is WAVEFORMATEXTENSIBLE size */
avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
/* ValidBitsPerSample || SamplesPerBlock || Reserved */
avio_wl16(pb, bps);
/* dwChannelMask */
- avio_wl32(pb, enc->channel_layout);
+ avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0);
/* GUID + next 3 */
+ if (enc->codec_id == AV_CODEC_ID_EAC3) {
+ ff_put_guid(pb, get_codec_guid(enc->codec_id, ff_codec_wav_guids));
+ } else {
avio_wl32(pb, enc->codec_tag);
avio_wl32(pb, 0x00100000);
avio_wl32(pb, 0xAA000080);
avio_wl32(pb, 0x719B3800);
- } else {
+ }
+ } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) ||
+ enc->codec_tag != 0x0001 /* PCM */ ||
+ riff_extradata - riff_extradata_start) {
+ /* WAVEFORMATEX */
avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
- }
+ } /* else PCMWAVEFORMAT */
avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
+ hdrsize = avio_tell(pb) - hdrstart;
if (hdrsize & 1) {
hdrsize++;
avio_w8(pb, 0);
@@ -201,10 +207,10 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
/* BITMAPINFOHEADER header */
void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc,
- const AVCodecTag *tags, int for_asf)
+ const AVCodecTag *tags, int for_asf, int ignore_extradata)
{
/* size */
- avio_wl32(pb, 40 + enc->extradata_size);
+ avio_wl32(pb, 40 + (ignore_extradata ? 0 : enc->extradata_size));
avio_wl32(pb, enc->width);
//We always store RGB TopDown
avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height);
@@ -220,10 +226,12 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc,
avio_wl32(pb, 0);
avio_wl32(pb, 0);
- avio_write(pb, enc->extradata, enc->extradata_size);
+ if (!ignore_extradata) {
+ avio_write(pb, enc->extradata, enc->extradata_size);
- if (!for_asf && enc->extradata_size & 1)
- avio_w8(pb, 0);
+ if (!for_asf && enc->extradata_size & 1)
+ avio_w8(pb, 0);
+ }
}
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate,
@@ -310,3 +318,19 @@ void ff_riff_write_info(AVFormatContext *s)
ff_riff_write_info_tag(s->pb, t->key, t->value);
ff_end_tag(pb, list_pos);
}
+
+void ff_put_guid(AVIOContext *s, const ff_asf_guid *g)
+{
+ av_assert0(sizeof(*g) == 16);
+ avio_write(s, *g, sizeof(*g));
+}
+
+const ff_asf_guid *get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid)
+{
+ int i;
+ for (i = 0; av_guid[i].id != AV_CODEC_ID_NONE; i++) {
+ if (id == av_guid[i].id)
+ return &(av_guid[i].guid);
+ }
+ return NULL;
+}
diff --git a/chromium/third_party/ffmpeg/libavformat/rl2.c b/chromium/third_party/ffmpeg/libavformat/rl2.c
index 56f4cf29ff6..d354339ea31 100644
--- a/chromium/third_party/ffmpeg/libavformat/rl2.c
+++ b/chromium/third_party/ffmpeg/libavformat/rl2.c
@@ -127,13 +127,9 @@ static av_cold int rl2_read_header(AVFormatContext *s)
if(signature == RLV3_TAG && back_size > 0)
st->codec->extradata_size += back_size;
- if(ff_alloc_extradata(st->codec, st->codec->extradata_size))
+ if(ff_get_extradata(st->codec, pb, st->codec->extradata_size) < 0)
return AVERROR(ENOMEM);
- if(avio_read(pb,st->codec->extradata,st->codec->extradata_size) !=
- st->codec->extradata_size)
- return AVERROR(EIO);
-
/** setup audio stream if present */
if(sound_rate){
if (!channels || channels > 42) {
diff --git a/chromium/third_party/ffmpeg/libavformat/rmdec.c b/chromium/third_party/ffmpeg/libavformat/rmdec.c
index b0876fe5bd5..36764ee9b22 100644
--- a/chromium/third_party/ffmpeg/libavformat/rmdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/rmdec.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <inttypes.h>
+
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
@@ -86,11 +88,8 @@ static int rm_read_extradata(AVIOContext *pb, AVCodecContext *avctx, unsigned si
{
if (size >= 1<<24)
return -1;
- if (ff_alloc_extradata(avctx, size))
+ if (ff_get_extradata(avctx, pb, size) < 0)
return AVERROR(ENOMEM);
- avctx->extradata_size = avio_read(pb, avctx->extradata, size);
- if (avctx->extradata_size != size)
- return AVERROR(EIO);
return 0;
}
@@ -185,6 +184,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
avio_read(pb, buf, 4);
buf[4] = 0;
} else {
+ AV_WL32(buf, 0);
get_str8(pb, buf, sizeof(buf)); /* desc */
ast->deint_id = AV_RL32(buf);
get_str8(pb, buf, sizeof(buf)); /* desc */
@@ -254,18 +254,6 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
return ret;
}
break;
- default:
- av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name));
- }
- if (ast->deint_id == DEINT_ID_INT4 ||
- ast->deint_id == DEINT_ID_GENR ||
- ast->deint_id == DEINT_ID_SIPR) {
- if (st->codec->block_align <= 0 ||
- ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX ||
- ast->audio_framesize * sub_packet_h < st->codec->block_align)
- return AVERROR_INVALIDDATA;
- if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
- return AVERROR(ENOMEM);
}
switch (ast->deint_id) {
case DEINT_ID_INT4:
@@ -273,11 +261,17 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
sub_packet_h <= 1 ||
ast->coded_framesize * sub_packet_h > (2 + (sub_packet_h & 1)) * ast->audio_framesize)
return AVERROR_INVALIDDATA;
+ if (ast->coded_framesize * sub_packet_h != 2*ast->audio_framesize) {
+ avpriv_request_sample(s, "mismatching interleaver parameters");
+ return AVERROR_INVALIDDATA;
+ }
break;
case DEINT_ID_GENR:
if (ast->sub_packet_size <= 0 ||
ast->sub_packet_size > ast->audio_framesize)
return AVERROR_INVALIDDATA;
+ if (ast->audio_framesize % ast->sub_packet_size)
+ return AVERROR_INVALIDDATA;
break;
case DEINT_ID_SIPR:
case DEINT_ID_INT0:
@@ -285,9 +279,19 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
case DEINT_ID_VBRF:
break;
default:
- av_log(s, AV_LOG_ERROR, "Unknown interleaver %X\n", ast->deint_id);
+ av_log(s, AV_LOG_ERROR ,"Unknown interleaver %"PRIX32"\n", ast->deint_id);
return AVERROR_INVALIDDATA;
}
+ if (ast->deint_id == DEINT_ID_INT4 ||
+ ast->deint_id == DEINT_ID_GENR ||
+ ast->deint_id == DEINT_ID_SIPR) {
+ if (st->codec->block_align <= 0 ||
+ ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX ||
+ ast->audio_framesize * sub_packet_h < st->codec->block_align)
+ return AVERROR_INVALIDDATA;
+ if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
+ return AVERROR(ENOMEM);
+ }
if (read_all) {
avio_r8(pb);
@@ -785,6 +789,16 @@ rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt)
}
}
+static int readfull(AVFormatContext *s, AVIOContext *pb, uint8_t *dst, int n) {
+ int ret = avio_read(pb, dst, n);
+ if (ret != n) {
+ if (ret >= 0) memset(dst + ret, 0, n - ret);
+ else memset(dst , 0, n);
+ av_log(s, AV_LOG_ERROR, "Failed to fully read block\n");
+ }
+ return ret;
+}
+
int
ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
AVStream *st, RMStream *ast, int len, AVPacket *pkt,
@@ -817,14 +831,14 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
switch (ast->deint_id) {
case DEINT_ID_INT4:
for (x = 0; x < h/2; x++)
- avio_read(pb, ast->pkt.data+x*2*w+y*cfs, cfs);
+ readfull(s, pb, ast->pkt.data+x*2*w+y*cfs, cfs);
break;
case DEINT_ID_GENR:
for (x = 0; x < w/sps; x++)
- avio_read(pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
+ readfull(s, pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
break;
case DEINT_ID_SIPR:
- avio_read(pb, ast->pkt.data + y * w, w);
+ readfull(s, pb, ast->pkt.data + y * w, w);
break;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/rpl.c b/chromium/third_party/ffmpeg/libavformat/rpl.c
index 85b573ea1f0..46a5796414e 100644
--- a/chromium/third_party/ffmpeg/libavformat/rpl.c
+++ b/chromium/third_party/ffmpeg/libavformat/rpl.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include "libavutil/avstring.h"
@@ -222,7 +222,8 @@ static int rpl_read_header(AVFormatContext *s)
break;
}
if (ast->codec->codec_id == AV_CODEC_ID_NONE)
- avpriv_request_sample(s, "Audio format %i", audio_format);
+ avpriv_request_sample(s, "Audio format %"PRId32,
+ audio_format);
avpriv_set_pts_info(ast, 32, 1, ast->codec->bit_rate);
} else {
for (i = 0; i < 3; i++)
@@ -254,8 +255,10 @@ static int rpl_read_header(AVFormatContext *s)
int64_t offset, video_size, audio_size;
error |= read_line(pb, line, sizeof(line));
if (3 != sscanf(line, "%"SCNd64" , %"SCNd64" ; %"SCNd64,
- &offset, &video_size, &audio_size))
+ &offset, &video_size, &audio_size)) {
error = -1;
+ continue;
+ }
av_add_index_entry(vst, offset, i * rpl->frames_per_chunk,
video_size, rpl->frames_per_chunk, 0);
if (ast)
diff --git a/chromium/third_party/ffmpeg/libavformat/rsd.c b/chromium/third_party/ffmpeg/libavformat/rsd.c
index 341f638c77c..b6f168633b1 100644
--- a/chromium/third_party/ffmpeg/libavformat/rsd.c
+++ b/chromium/third_party/ffmpeg/libavformat/rsd.c
@@ -104,13 +104,10 @@ static int rsd_read_header(AVFormatContext *s)
/* RSD3GADP is mono, so only alloc enough memory
to store the coeff table for a single channel. */
- if (ff_alloc_extradata(codec, 32))
- return AVERROR(ENOMEM);
-
start = avio_rl32(pb);
- if (avio_read(s->pb, codec->extradata, 32) != 32)
- return AVERROR_INVALIDDATA;
+ if (ff_get_extradata(codec, s->pb, 32) < 0)
+ return AVERROR(ENOMEM);
for (i = 0; i < 16; i++)
AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2));
diff --git a/chromium/third_party/ffmpeg/libavformat/rtmppkt.c b/chromium/third_party/ffmpeg/libavformat/rtmppkt.c
index 375ae2fcb13..65d5dd9d570 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtmppkt.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtmppkt.c
@@ -169,6 +169,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
uint8_t buf[16];
int channel_id, timestamp, size;
+ uint32_t ts_field; // non-extended timestamp or delta field
uint32_t extra = 0;
enum RTMPPacketType type;
int written = 0;
@@ -193,14 +194,14 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
type = prev_pkt[channel_id].type;
extra = prev_pkt[channel_id].extra;
- hdr >>= 6;
+ hdr >>= 6; // header size indicator
if (hdr == RTMP_PS_ONEBYTE) {
- timestamp = prev_pkt[channel_id].ts_delta;
+ ts_field = prev_pkt[channel_id].ts_field;
} else {
if (ffurl_read_complete(h, buf, 3) != 3)
return AVERROR(EIO);
written += 3;
- timestamp = AV_RB24(buf);
+ ts_field = AV_RB24(buf);
if (hdr != RTMP_PS_FOURBYTES) {
if (ffurl_read_complete(h, buf, 3) != 3)
return AVERROR(EIO);
@@ -217,11 +218,13 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
extra = AV_RL32(buf);
}
}
- if (timestamp == 0xFFFFFF) {
- if (ffurl_read_complete(h, buf, 4) != 4)
- return AVERROR(EIO);
- timestamp = AV_RB32(buf);
- }
+ }
+ if (ts_field == 0xFFFFFF) {
+ if (ffurl_read_complete(h, buf, 4) != 4)
+ return AVERROR(EIO);
+ timestamp = AV_RB32(buf);
+ } else {
+ timestamp = ts_field;
}
if (hdr != RTMP_PS_TWELVEBYTES)
timestamp += prev_pkt[channel_id].timestamp;
@@ -232,8 +235,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
return ret;
p->read = written;
p->offset = 0;
- prev_pkt[channel_id].ts_delta = timestamp -
- prev_pkt[channel_id].timestamp;
+ prev_pkt[channel_id].ts_field = ts_field;
prev_pkt[channel_id].timestamp = timestamp;
} else {
// previous packet in this channel hasn't completed reading
@@ -242,7 +244,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
p->size = prev->size;
p->channel_id = prev->channel_id;
p->type = prev->type;
- p->ts_delta = prev->ts_delta;
+ p->ts_field = prev->ts_field;
p->extra = prev->extra;
p->offset = prev->offset;
p->read = prev->read + written;
@@ -271,6 +273,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
prev->data = p->data;
prev->read = p->read;
prev->offset = p->offset;
+ p->data = NULL;
return AVERROR(EAGAIN);
}
@@ -303,21 +306,34 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
int written = 0;
int ret;
RTMPPacket *prev_pkt;
+ int use_delta; // flag if using timestamp delta, not RTMP_PS_TWELVEBYTES
+ uint32_t timestamp; // full 32-bit timestamp or delta value
if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
pkt->channel_id)) < 0)
return ret;
prev_pkt = *prev_pkt_ptr;
- pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
-
//if channel_id = 0, this is first presentation of prev_pkt, send full hdr.
- if (prev_pkt[pkt->channel_id].channel_id &&
- pkt->extra == prev_pkt[pkt->channel_id].extra) {
+ use_delta = prev_pkt[pkt->channel_id].channel_id &&
+ pkt->extra == prev_pkt[pkt->channel_id].extra &&
+ pkt->timestamp >= prev_pkt[pkt->channel_id].timestamp;
+
+ timestamp = pkt->timestamp;
+ if (use_delta) {
+ timestamp -= prev_pkt[pkt->channel_id].timestamp;
+ }
+ if (timestamp >= 0xFFFFFF) {
+ pkt->ts_field = 0xFFFFFF;
+ } else {
+ pkt->ts_field = timestamp;
+ }
+
+ if (use_delta) {
if (pkt->type == prev_pkt[pkt->channel_id].type &&
pkt->size == prev_pkt[pkt->channel_id].size) {
mode = RTMP_PS_FOURBYTES;
- if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta)
+ if (pkt->ts_field == prev_pkt[pkt->channel_id].ts_field)
mode = RTMP_PS_ONEBYTE;
} else {
mode = RTMP_PS_EIGHTBYTES;
@@ -334,29 +350,22 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
bytestream_put_le16(&p, pkt->channel_id - 64);
}
if (mode != RTMP_PS_ONEBYTE) {
- uint32_t timestamp = pkt->timestamp;
- if (mode != RTMP_PS_TWELVEBYTES)
- timestamp = pkt->ts_delta;
- bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp);
+ bytestream_put_be24(&p, pkt->ts_field);
if (mode != RTMP_PS_FOURBYTES) {
bytestream_put_be24(&p, pkt->size);
bytestream_put_byte(&p, pkt->type);
if (mode == RTMP_PS_TWELVEBYTES)
bytestream_put_le32(&p, pkt->extra);
}
- if (timestamp >= 0xFFFFFF)
- bytestream_put_be32(&p, timestamp);
}
+ if (pkt->ts_field == 0xFFFFFF)
+ bytestream_put_be32(&p, timestamp);
// save history
prev_pkt[pkt->channel_id].channel_id = pkt->channel_id;
prev_pkt[pkt->channel_id].type = pkt->type;
prev_pkt[pkt->channel_id].size = pkt->size;
prev_pkt[pkt->channel_id].timestamp = pkt->timestamp;
- if (mode != RTMP_PS_TWELVEBYTES) {
- prev_pkt[pkt->channel_id].ts_delta = pkt->ts_delta;
- } else {
- prev_pkt[pkt->channel_id].ts_delta = pkt->timestamp;
- }
+ prev_pkt[pkt->channel_id].ts_field = pkt->ts_field;
prev_pkt[pkt->channel_id].extra = pkt->extra;
if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0)
@@ -390,7 +399,7 @@ int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
pkt->type = type;
pkt->timestamp = timestamp;
pkt->extra = 0;
- pkt->ts_delta = 0;
+ pkt->ts_field = 0;
return 0;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/rtmppkt.h b/chromium/third_party/ffmpeg/libavformat/rtmppkt.h
index fb79fedac64..0d98f60981e 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtmppkt.h
+++ b/chromium/third_party/ffmpeg/libavformat/rtmppkt.h
@@ -78,7 +78,7 @@ typedef struct RTMPPacket {
int channel_id; ///< RTMP channel ID (nothing to do with audio/video channels though)
RTMPPacketType type; ///< packet payload type
uint32_t timestamp; ///< packet full timestamp
- uint32_t ts_delta; ///< timestamp increment to the previous one in milliseconds (latter only for media packets)
+ uint32_t ts_field; ///< 24-bit timestamp or increment to the previous one, in milliseconds (latter only for media packets). Clipped to a maximum of 0xFFFFFF, indicating an extended timestamp field.
uint32_t extra; ///< probably an additional channel ID used during streaming data
uint8_t *data; ///< packet payload
int size; ///< packet payload size
diff --git a/chromium/third_party/ffmpeg/libavformat/rtmpproto.c b/chromium/third_party/ffmpeg/libavformat/rtmpproto.c
index a4d7f0ee73d..308110b9c1b 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtmpproto.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtmpproto.c
@@ -150,6 +150,8 @@ static const uint8_t rtmp_server_key[] = {
0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
};
+static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
+
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
{
int err;
@@ -408,6 +410,17 @@ static int read_connect(URLContext *s, RTMPContext *rt)
if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
&rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
return ret;
+
+ if (pkt.type == RTMP_PT_CHUNK_SIZE) {
+ if ((ret = handle_chunk_size(s, &pkt)) < 0)
+ return ret;
+
+ ff_rtmp_packet_destroy(&pkt);
+ if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
+ &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
+ return ret;
+ }
+
cp = pkt.data;
bytestream2_init(&gbc, cp, pkt.size);
if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
@@ -2367,7 +2380,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
{
RTMPContext *rt = s->priv_data;
char proto[8], hostname[256], path[1024], auth[100], *fname;
- char *old_app;
+ char *old_app, *qmark, fname_buffer[1024];
uint8_t buf[2048];
int port;
AVDictionary *opts = NULL;
@@ -2465,7 +2478,20 @@ reconnect:
}
//extract "app" part from path
- if (!strncmp(path, "/ondemand/", 10)) {
+ qmark = strchr(path, '?');
+ if (qmark && strstr(qmark, "slist=")) {
+ char* amp;
+ // After slist we have the playpath, before the params, the app
+ av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH));
+ fname = strstr(path, "slist=") + 6;
+ // Strip any further query parameters from fname
+ amp = strchr(fname, '&');
+ if (amp) {
+ av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
+ sizeof(fname_buffer)));
+ fname = fname_buffer;
+ }
+ } else if (!strncmp(path, "/ondemand/", 10)) {
fname = path + 10;
memcpy(rt->app, "ondemand", 9);
} else {
@@ -2511,9 +2537,9 @@ reconnect:
(!strcmp(fname + len - 4, ".f4v") ||
!strcmp(fname + len - 4, ".mp4"))) {
memcpy(rt->playpath, "mp4:", 5);
- } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
- fname[len - 4] = '\0';
} else {
+ if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
+ fname[len - 4] = '\0';
rt->playpath[0] = 0;
}
av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
@@ -2556,7 +2582,7 @@ reconnect:
if ((ret = gen_connect(s, rt)) < 0)
goto fail;
} else {
- if (read_connect(s, s->priv_data) < 0)
+ if ((ret = read_connect(s, s->priv_data)) < 0)
goto fail;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec.h b/chromium/third_party/ffmpeg/libavformat/rtpdec.h
index 9321066ba78..7e356c048d5 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtpdec.h
+++ b/chromium/third_party/ffmpeg/libavformat/rtpdec.h
@@ -173,9 +173,9 @@ struct RTPDemuxContext {
/*@}*/
/* rtcp sender statistics receive */
- int64_t last_rtcp_ntp_time;
+ uint64_t last_rtcp_ntp_time;
int64_t last_rtcp_reception_time;
- int64_t first_rtcp_ntp_time;
+ uint64_t first_rtcp_ntp_time;
uint32_t last_rtcp_timestamp;
int64_t rtcp_ts_offset;
diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_asf.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_asf.c
index 123894f2756..541b86fe41b 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtpdec_asf.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_asf.c
@@ -144,6 +144,8 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
*s->streams[stream_index]->codec =
*rt->asf_ctx->streams[i]->codec;
+ s->streams[stream_index]->need_parsing =
+ rt->asf_ctx->streams[i]->need_parsing;
rt->asf_ctx->streams[i]->codec->extradata_size = 0;
rt->asf_ctx->streams[i]->codec->extradata = NULL;
avpriv_set_pts_info(s->streams[stream_index], 32, 1, 1000);
diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c
index be657c0ccc7..1ca78bc81c2 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c
@@ -190,7 +190,8 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
switch (type) {
case 0: // undefined, but pass them through
case 1:
- av_new_packet(pkt, len + sizeof(start_sequence));
+ if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0)
+ return result;
memcpy(pkt->data, start_sequence, sizeof(start_sequence));
memcpy(pkt->data + sizeof(start_sequence), buf, len);
COUNT_NAL_TYPE(data, nal);
@@ -247,7 +248,8 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
if (pass == 0) {
/* now we know the total size of the packet (with the
* start sequences added) */
- av_new_packet(pkt, total_length);
+ if ((result = av_new_packet(pkt, total_length)) < 0)
+ return result;
dst = pkt->data;
} else {
assert(dst - pkt->data == total_length);
@@ -292,12 +294,14 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
COUNT_NAL_TYPE(data, nal_type);
if (start_bit) {
/* copy in the start sequence, and the reconstructed nal */
- av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len);
+ if ((result = av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len)) < 0)
+ return result;
memcpy(pkt->data, start_sequence, sizeof(start_sequence));
pkt->data[sizeof(start_sequence)] = reconstructed_nal;
memcpy(pkt->data + sizeof(start_sequence) + sizeof(nal), buf, len);
} else {
- av_new_packet(pkt, len);
+ if ((result = av_new_packet(pkt, len)) < 0)
+ return result;
memcpy(pkt->data, buf, len);
}
} else {
diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c
index 887a65ed651..43f72a2305d 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c
@@ -256,7 +256,7 @@ parse_packed_headers(const uint8_t * packed_headers,
if (packed_headers_end - packed_headers < 9) {
av_log(codec, AV_LOG_ERROR,
- "Invalid %td byte packed header.",
+ "Invalid %"PTRDIFF_SPECIFIER" byte packed header.",
packed_headers_end - packed_headers);
return AVERROR_INVALIDDATA;
}
@@ -278,7 +278,7 @@ parse_packed_headers(const uint8_t * packed_headers,
if (packed_headers_end - packed_headers != length ||
length1 > length || length2 > length - length1) {
av_log(codec, AV_LOG_ERROR,
- "Bad packed header lengths (%d,%d,%td,%d)\n", length1,
+ "Bad packed header lengths (%d,%d,%"PTRDIFF_SPECIFIER",%d)\n", length1,
length2, packed_headers_end - packed_headers, length);
return AVERROR_INVALIDDATA;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/rtpenc.c b/chromium/third_party/ffmpeg/libavformat/rtpenc.c
index 6fdc908d0f9..457fef0cfcb 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtpenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtpenc.c
@@ -119,7 +119,7 @@ static int rtp_write_header(AVFormatContext *s1)
s->ssrc = av_get_random_seed();
s->first_packet = 1;
s->first_rtcp_ntp_time = ff_ntp_time();
- if (s1->start_time_realtime)
+ if (s1->start_time_realtime != 0 && s1->start_time_realtime != AV_NOPTS_VALUE)
/* Round the NTP time to whole milliseconds. */
s->first_rtcp_ntp_time = (s1->start_time_realtime / 1000) * 1000 +
NTP_OFFSET_US;
@@ -557,6 +557,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
const uint8_t *mb_info =
av_packet_get_side_data(pkt, AV_PKT_DATA_H263_MB_INFO,
&mb_info_size);
+ if (!mb_info) {
+ av_log(s1, AV_LOG_ERROR, "failed to allocate side data\n");
+ return AVERROR(ENOMEM);
+ }
ff_rtp_send_h263_rfc2190(s1, pkt->data, size, mb_info, mb_info_size);
break;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/rtsp.c b/chromium/third_party/ffmpeg/libavformat/rtsp.c
index 3b88fc72715..fcf9eca0d49 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtsp.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtsp.c
@@ -65,7 +65,7 @@
#define RTSP_FLAG_OPTS(name, longname) \
{ name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
- { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }
+ { "filter_src", "only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }
#define RTSP_MEDIATYPE_OPTS(name, longname) \
{ name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { .i64 = (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
@@ -74,23 +74,24 @@
{ "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
#define RTSP_REORDERING_OPTS() \
- { "reorder_queue_size", "Number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }
+ { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }
const AVOption ff_rtsp_options[] = {
- { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
+ { "initial_pause", "do not start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
- { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
+ { "rtsp_transport", "set RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
{ "udp", "UDP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
{ "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
{ "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
{ "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {.i64 = (1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
- RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"),
- { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" },
- RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
- { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
- { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
- { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC },
- { "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
+ RTSP_FLAG_OPTS("rtsp_flags", "set RTSP flags"),
+ { "listen", "wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" },
+ { "prefer_tcp", "try RTP via TCP first, if available", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_PREFER_TCP}, 0, 0, DEC|ENC, "rtsp_flags" },
+ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
+ { "min_port", "set minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
+ { "max_port", "set maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
+ { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC },
+ { "stimeout", "set timeout (in micro seconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
RTSP_REORDERING_OPTS(),
{ "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC },
{ NULL },
@@ -98,15 +99,15 @@ const AVOption ff_rtsp_options[] = {
static const AVOption sdp_options[] = {
RTSP_FLAG_OPTS("sdp_flags", "SDP flags"),
- { "custom_io", "Use custom IO", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" },
- { "rtcp_to_source", "Send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" },
- RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
+ { "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" },
+ { "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" },
+ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
RTSP_REORDERING_OPTS(),
{ NULL },
};
static const AVOption rtp_options[] = {
- RTSP_FLAG_OPTS("rtp_flags", "RTP flags"),
+ RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"),
RTSP_REORDERING_OPTS(),
{ NULL },
};
@@ -729,8 +730,8 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
s->ctx_flags |= AVFMTCTX_NOHEADER;
if (s->oformat && CONFIG_RTSP_MUXER) {
- int ret = ff_rtp_chain_mux_open((AVFormatContext **)&rtsp_st->transport_priv, s, st,
- rtsp_st->rtp_handle,
+ int ret = ff_rtp_chain_mux_open((AVFormatContext **)&rtsp_st->transport_priv,
+ s, st, rtsp_st->rtp_handle,
RTSP_TCP_MAX_PACKET_SIZE,
rtsp_st->stream_index);
/* Ownership of rtp_handle is passed to the rtp mux context */
@@ -1766,6 +1767,10 @@ redirect:
int lower_transport = ff_log2_tab[lower_transport_mask &
~(lower_transport_mask - 1)];
+ if ((lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP))
+ && (rt->rtsp_flags & RTSP_FLAG_PREFER_TCP))
+ lower_transport = RTSP_LOWER_TRANSPORT_TCP;
+
err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
rt->server_type == RTSP_SERVER_REAL ?
real_challenge : NULL);
@@ -2066,6 +2071,16 @@ redo:
st2->time_base);
}
}
+ // Make real NTP start time available in AVFormatContext
+ if (s->start_time_realtime == AV_NOPTS_VALUE) {
+ s->start_time_realtime = av_rescale (rtpctx->first_rtcp_ntp_time - (NTP_OFFSET << 32), 1000000, 1LL << 32);
+ if (rtpctx->st) {
+ s->start_time_realtime -=
+ av_rescale (rtpctx->rtcp_ts_offset,
+ (uint64_t) rtpctx->st->time_base.num * 1000000,
+ rtpctx->st->time_base.den);
+ }
+ }
}
if (ret == -RTCP_BYE) {
rt->nb_byes++;
diff --git a/chromium/third_party/ffmpeg/libavformat/rtsp.h b/chromium/third_party/ffmpeg/libavformat/rtsp.h
index 76c7f181cf7..d1597938351 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtsp.h
+++ b/chromium/third_party/ffmpeg/libavformat/rtsp.h
@@ -413,6 +413,7 @@ typedef struct RTSPState {
#define RTSP_FLAG_CUSTOM_IO 0x4 /**< Do all IO via the AVIOContext. */
#define RTSP_FLAG_RTCP_TO_SOURCE 0x8 /**< Send RTCP packets to the source
address of received packets. */
+#define RTSP_FLAG_PREFER_TCP 0x10 /**< Try RTP via TCP first if possible. */
typedef struct RTSPSource {
char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */
diff --git a/chromium/third_party/ffmpeg/libavformat/rtspcodes.h b/chromium/third_party/ffmpeg/libavformat/rtspcodes.h
index 4245e48642d..d4f762b00c3 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtspcodes.h
+++ b/chromium/third_party/ffmpeg/libavformat/rtspcodes.h
@@ -1,6 +1,8 @@
/*
* RTSP definitions
* copyright (c) 2002 Fabrice Bellard
+ * copyright (c) 2014 Samsung Electronics. All rights reserved.
+ * @Author: Reynaldo H. Verdejo Pinochet <r.verdejo@sisa.samsung.com>
*
* This file is part of FFmpeg.
*
@@ -22,21 +24,107 @@
#ifndef AVFORMAT_RTSPCODES_H
#define AVFORMAT_RTSPCODES_H
+#include "libavutil/common.h"
+
/** RTSP handling */
enum RTSPStatusCode {
-RTSP_STATUS_OK =200, /**< OK */
-RTSP_STATUS_METHOD =405, /**< Method Not Allowed */
-RTSP_STATUS_BANDWIDTH =453, /**< Not Enough Bandwidth */
-RTSP_STATUS_SESSION =454, /**< Session Not Found */
-RTSP_STATUS_STATE =455, /**< Method Not Valid in This State */
-RTSP_STATUS_AGGREGATE =459, /**< Aggregate operation not allowed */
-RTSP_STATUS_ONLY_AGGREGATE =460, /**< Only aggregate operation allowed */
-RTSP_STATUS_TRANSPORT =461, /**< Unsupported transport */
-RTSP_STATUS_INTERNAL =500, /**< Internal Server Error */
-RTSP_STATUS_SERVICE =503, /**< Service Unavailable */
-RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */
+RTSP_STATUS_CONTINUE =100,
+RTSP_STATUS_OK =200,
+RTSP_STATUS_CREATED =201,
+RTSP_STATUS_LOW_ON_STORAGE_SPACE =250,
+RTSP_STATUS_MULTIPLE_CHOICES =300,
+RTSP_STATUS_MOVED_PERMANENTLY =301,
+RTSP_STATUS_MOVED_TEMPORARILY =302,
+RTSP_STATUS_SEE_OTHER =303,
+RTSP_STATUS_NOT_MODIFIED =304,
+RTSP_STATUS_USE_PROXY =305,
+RTSP_STATUS_BAD_REQUEST =400,
+RTSP_STATUS_UNAUTHORIZED =401,
+RTSP_STATUS_PAYMENT_REQUIRED =402,
+RTSP_STATUS_FORBIDDEN =403,
+RTSP_STATUS_NOT_FOUND =404,
+RTSP_STATUS_METHOD =405,
+RTSP_STATUS_NOT_ACCEPTABLE =406,
+RTSP_STATUS_PROXY_AUTH_REQUIRED =407,
+RTSP_STATUS_REQ_TIME_OUT =408,
+RTSP_STATUS_GONE =410,
+RTSP_STATUS_LENGTH_REQUIRED =411,
+RTSP_STATUS_PRECONDITION_FAILED =412,
+RTSP_STATUS_REQ_ENTITY_2LARGE =413,
+RTSP_STATUS_REQ_URI_2LARGE =414,
+RTSP_STATUS_UNSUPPORTED_MTYPE =415,
+RTSP_STATUS_PARAM_NOT_UNDERSTOOD =451,
+RTSP_STATUS_CONFERENCE_NOT_FOUND =452,
+RTSP_STATUS_BANDWIDTH =453,
+RTSP_STATUS_SESSION =454,
+RTSP_STATUS_STATE =455,
+RTSP_STATUS_INVALID_HEADER_FIELD =456,
+RTSP_STATUS_INVALID_RANGE =457,
+RTSP_STATUS_RONLY_PARAMETER =458,
+RTSP_STATUS_AGGREGATE =459,
+RTSP_STATUS_ONLY_AGGREGATE =460,
+RTSP_STATUS_TRANSPORT =461,
+RTSP_STATUS_UNREACHABLE =462,
+RTSP_STATUS_INTERNAL =500,
+RTSP_STATUS_NOT_IMPLEMENTED =501,
+RTSP_STATUS_BAD_GATEWAY =502,
+RTSP_STATUS_SERVICE =503,
+RTSP_STATUS_GATEWAY_TIME_OUT =504,
+RTSP_STATUS_VERSION =505,
+RTSP_STATUS_UNSUPPORTED_OPTION =551,
+};
+
+static const av_unused char *rtsp_status_strings[] = {
+[RTSP_STATUS_CONTINUE] ="Continue",
+[RTSP_STATUS_OK] ="OK",
+[RTSP_STATUS_CREATED] ="Created",
+[RTSP_STATUS_LOW_ON_STORAGE_SPACE] ="Low on Storage Space",
+[RTSP_STATUS_MULTIPLE_CHOICES] ="Multiple Choices",
+[RTSP_STATUS_MOVED_PERMANENTLY] ="Moved Permanently",
+[RTSP_STATUS_MOVED_TEMPORARILY] ="Moved Temporarily",
+[RTSP_STATUS_SEE_OTHER] ="See Other",
+[RTSP_STATUS_NOT_MODIFIED] ="Not Modified",
+[RTSP_STATUS_USE_PROXY] ="Use Proxy",
+[RTSP_STATUS_BAD_REQUEST] ="Bad Request",
+[RTSP_STATUS_UNAUTHORIZED] ="Unauthorized",
+[RTSP_STATUS_PAYMENT_REQUIRED] ="Payment Required",
+[RTSP_STATUS_FORBIDDEN] ="Forbidden",
+[RTSP_STATUS_NOT_FOUND] ="Not Found",
+[RTSP_STATUS_METHOD] ="Method Not Allowed",
+[RTSP_STATUS_NOT_ACCEPTABLE] ="Not Acceptable",
+[RTSP_STATUS_PROXY_AUTH_REQUIRED] ="Proxy Authentication Required",
+[RTSP_STATUS_REQ_TIME_OUT] ="Request Time-out",
+[RTSP_STATUS_GONE] ="Gone",
+[RTSP_STATUS_LENGTH_REQUIRED] ="Length Required",
+[RTSP_STATUS_PRECONDITION_FAILED] ="Precondition Failed",
+[RTSP_STATUS_REQ_ENTITY_2LARGE] ="Request Entity Too Large",
+[RTSP_STATUS_REQ_URI_2LARGE] ="Request URI Too Large",
+[RTSP_STATUS_UNSUPPORTED_MTYPE] ="Unsupported Media Type",
+[RTSP_STATUS_PARAM_NOT_UNDERSTOOD] ="Parameter Not Understood",
+[RTSP_STATUS_CONFERENCE_NOT_FOUND] ="Conference Not Found",
+[RTSP_STATUS_BANDWIDTH] ="Not Enough Bandwidth",
+[RTSP_STATUS_SESSION] ="Session Not Found",
+[RTSP_STATUS_STATE] ="Method Not Valid in This State",
+[RTSP_STATUS_INVALID_HEADER_FIELD] ="Header Field Not Valid for Resource",
+[RTSP_STATUS_INVALID_RANGE] ="Invalid Range",
+[RTSP_STATUS_RONLY_PARAMETER] ="Parameter Is Read-Only",
+[RTSP_STATUS_AGGREGATE] ="Aggregate Operation no Allowed",
+[RTSP_STATUS_ONLY_AGGREGATE] ="Only Aggregate Operation Allowed",
+[RTSP_STATUS_TRANSPORT] ="Unsupported Transport",
+[RTSP_STATUS_UNREACHABLE] ="Destination Unreachable",
+[RTSP_STATUS_INTERNAL] ="Internal Server Error",
+[RTSP_STATUS_NOT_IMPLEMENTED] ="Not Implemented",
+[RTSP_STATUS_BAD_GATEWAY] ="Bad Gateway",
+[RTSP_STATUS_SERVICE] ="Service Unavailable",
+[RTSP_STATUS_GATEWAY_TIME_OUT] ="Gateway Time-out",
+[RTSP_STATUS_VERSION] ="RTSP Version not Supported",
+[RTSP_STATUS_UNSUPPORTED_OPTION] ="Option not supported",
};
+#define RTSP_STATUS_CODE2STRING(x) (\
+x >= 100 && x < FF_ARRAY_ELEMS(rtsp_status_strings) && rtsp_status_strings[x] \
+)? rtsp_status_strings[x] : NULL
+
enum RTSPMethod {
DESCRIBE,
ANNOUNCE,
diff --git a/chromium/third_party/ffmpeg/libavformat/rtspdec.c b/chromium/third_party/ffmpeg/libavformat/rtspdec.c
index eb650ff42a1..af20465783c 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtspdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtspdec.c
@@ -360,6 +360,10 @@ static inline int parse_command_line(AVFormatContext *s, const char *line,
RTSPState *rt = s->priv_data;
const char *linept, *searchlinept;
linept = strchr(line, ' ');
+ if (!linept) {
+ av_log(s, AV_LOG_ERROR, "Error parsing method string\n");
+ return AVERROR_INVALIDDATA;
+ }
if (linept - line > methodsize - 1) {
av_log(s, AV_LOG_ERROR, "Method string too long\n");
return AVERROR(EIO);
@@ -877,7 +881,7 @@ retry:
rt->get_parameter_supported)) {
ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
} else {
- ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
+ ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL);
}
/* The stale flag should be reset when creating the auth response in
* ff_rtsp_send_cmd_async, but reset it here just in case we never
diff --git a/chromium/third_party/ffmpeg/libavformat/rtspenc.c b/chromium/third_party/ffmpeg/libavformat/rtspenc.c
index d76ae872eb4..cc6e729e8cd 100644
--- a/chromium/third_party/ffmpeg/libavformat/rtspenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/rtspenc.c
@@ -51,7 +51,8 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
char *sdp;
AVFormatContext sdp_ctx, *ctx_array[1];
- s->start_time_realtime = av_gettime();
+ if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE)
+ s->start_time_realtime = av_gettime();
/* Announce the stream */
sdp = av_mallocz(SDP_MAX_SIZE);
diff --git a/chromium/third_party/ffmpeg/libavformat/sapenc.c b/chromium/third_party/ffmpeg/libavformat/sapenc.c
index 9fc78a83af8..738e8b8f911 100644
--- a/chromium/third_party/ffmpeg/libavformat/sapenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/sapenc.c
@@ -140,7 +140,8 @@ static int sap_write_header(AVFormatContext *s)
goto fail;
}
- s->start_time_realtime = av_gettime();
+ if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE)
+ s->start_time_realtime = av_gettime();
for (i = 0; i < s->nb_streams; i++) {
URLContext *fd;
diff --git a/chromium/third_party/ffmpeg/libavformat/sdp.c b/chromium/third_party/ffmpeg/libavformat/sdp.c
index 01242184958..c53de905171 100644
--- a/chromium/third_party/ffmpeg/libavformat/sdp.c
+++ b/chromium/third_party/ffmpeg/libavformat/sdp.c
@@ -217,7 +217,7 @@ static char *extradata2psets(AVCodecContext *c)
sps_end = r1;
}
if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
- av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
+ av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
av_free(psets);
return NULL;
@@ -402,7 +402,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
switch (c->codec_id) {
case AV_CODEC_ID_H264: {
int mode = 1;
- if (fmt && fmt->oformat->priv_class &&
+ if (fmt && fmt->oformat && fmt->oformat->priv_class &&
av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0"))
mode = 0;
if (c->extradata_size) {
@@ -513,13 +513,6 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
break;
case AV_CODEC_ID_THEORA: {
const char *pix_fmt;
- if (c->extradata_size)
- config = xiph_extradata2config(c);
- else
- av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
- if (!config)
- return NULL;
-
switch (c->pix_fmt) {
case AV_PIX_FMT_YUV420P:
pix_fmt = "YCbCr-4:2:0";
@@ -535,6 +528,13 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
return NULL;
}
+ if (c->extradata_size)
+ config = xiph_extradata2config(c);
+ else
+ av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
+ if (!config)
+ return NULL;
+
av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
"a=fmtp:%d delivery-method=inline; "
"width=%d; height=%d; sampling=%s; "
diff --git a/chromium/third_party/ffmpeg/libavformat/sdr2.c b/chromium/third_party/ffmpeg/libavformat/sdr2.c
new file mode 100644
index 00000000000..82405f69d18
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/sdr2.c
@@ -0,0 +1,121 @@
+/*
+ * SDR2 demuxer
+ * Copyright (c) 2014 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+
+static int sdr2_probe(AVProbeData *p)
+{
+ if (AV_RL32(p->buf) != MKTAG('S', 'R', 'A', 1))
+ return 0;
+
+ return AVPROBE_SCORE_EXTENSION;
+}
+
+#define FIRST 0xA8
+
+static int sdr2_read_header(AVFormatContext *s)
+{
+ AVStream *st, *ast;
+
+ ast = avformat_new_stream(s, 0);
+ if (!ast)
+ return AVERROR(ENOMEM);
+
+ st = avformat_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ avio_skip(s->pb, 20);
+ avpriv_set_pts_info(st, 64, 1, avio_rl32(s->pb));
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->width = avio_rl32(s->pb);
+ st->codec->height = avio_rl32(s->pb);
+ st->codec->codec_id = AV_CODEC_ID_H264;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+
+ ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ ast->codec->channels = 1;
+ ast->codec->sample_rate = 8000;
+ ast->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+ avpriv_set_pts_info(ast, 64, 1, 8000);
+
+ avio_seek(s->pb, FIRST, SEEK_SET);
+
+ return 0;
+}
+
+static const uint8_t header[24] = {
+ 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+ 0xa6, 0x80, 0xb0, 0x7e, 0x40, 0x00, 0x00, 0x00,
+ 0x01, 0x68, 0xce, 0x38, 0x80, 0x00, 0x00, 0x00
+};
+
+static int sdr2_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int64_t pos;
+ unsigned next;
+ int flags, ret = 0, is_video;
+
+ pos = avio_tell(s->pb);
+
+ flags = avio_rl32(s->pb);
+ avio_skip(s->pb, 4);
+
+ next = avio_rl32(s->pb);
+ if (next <= 52)
+ return AVERROR_INVALIDDATA;
+
+ avio_skip(s->pb, 6);
+ is_video = avio_rl32(s->pb);
+ avio_skip(s->pb, 30);
+
+ if (pos == FIRST) {
+ if (av_new_packet(pkt, next - 52 + 24) < 0)
+ return AVERROR(ENOMEM);
+ memcpy(pkt->data, header, 24);
+ ret = avio_read(s->pb, pkt->data + 24, next - 52);
+ if (ret < 0) {
+ av_free_packet(pkt);
+ return ret;
+ }
+ av_shrink_packet(pkt, ret + 24);
+ } else {
+ ret = av_get_packet(s->pb, pkt, next - 52);
+ }
+ pkt->stream_index = !!is_video;
+ pkt->pos = pos;
+ if (flags & (1 << 12))
+ pkt->flags |= AV_PKT_FLAG_KEY;
+
+ return ret;
+}
+
+AVInputFormat ff_sdr2_demuxer = {
+ .name = "sdr2",
+ .long_name = NULL_IF_CONFIG_SMALL("SDR2"),
+ .read_probe = sdr2_probe,
+ .read_header = sdr2_read_header,
+ .read_packet = sdr2_read_packet,
+ .extensions = "sdr2",
+ .flags = AVFMT_GENERIC_INDEX,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/segafilm.c b/chromium/third_party/ffmpeg/libavformat/segafilm.c
index 8a0e8bc3c6b..6b3ad52446a 100644
--- a/chromium/third_party/ffmpeg/libavformat/segafilm.c
+++ b/chromium/third_party/ffmpeg/libavformat/segafilm.c
@@ -75,13 +75,22 @@ static int film_probe(AVProbeData *p)
return AVPROBE_SCORE_MAX;
}
+static int film_read_close(AVFormatContext *s)
+{
+ FilmDemuxContext *film = s->priv_data;
+
+ av_freep(&film->sample_table);
+
+ return 0;
+}
+
static int film_read_header(AVFormatContext *s)
{
FilmDemuxContext *film = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
unsigned char scratch[256];
- int i;
+ int i, ret;
unsigned int data_offset;
unsigned int audio_frame_counter;
@@ -206,14 +215,16 @@ static int film_read_header(AVFormatContext *s)
for (i = 0; i < film->sample_count; i++) {
/* load the next sample record and transfer it to an internal struct */
if (avio_read(pb, scratch, 16) != 16) {
- av_freep(&film->sample_table);
- return AVERROR(EIO);
+ ret = AVERROR(EIO);
+ goto fail;
}
film->sample_table[i].sample_offset =
data_offset + AV_RB32(&scratch[0]);
film->sample_table[i].sample_size = AV_RB32(&scratch[4]);
- if (film->sample_table[i].sample_size > INT_MAX / 4)
- return AVERROR_INVALIDDATA;
+ if (film->sample_table[i].sample_size > INT_MAX / 4) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
if (AV_RB32(&scratch[8]) == 0xFFFFFFFF) {
film->sample_table[i].stream = film->audio_stream_index;
film->sample_table[i].pts = audio_frame_counter;
@@ -234,6 +245,9 @@ static int film_read_header(AVFormatContext *s)
film->current_sample = 0;
return 0;
+fail:
+ film_read_close(s);
+ return ret;
}
static int film_read_packet(AVFormatContext *s,
@@ -252,18 +266,10 @@ static int film_read_packet(AVFormatContext *s,
/* position the stream (will probably be there anyway) */
avio_seek(pb, sample->sample_offset, SEEK_SET);
- /* do a special song and dance when loading FILM Cinepak chunks */
- if ((sample->stream == film->video_stream_index) &&
- (film->video_type == AV_CODEC_ID_CINEPAK)) {
- pkt->pos= avio_tell(pb);
- if (av_new_packet(pkt, sample->sample_size))
- return AVERROR(ENOMEM);
- avio_read(pb, pkt->data, sample->sample_size);
- } else {
- ret= av_get_packet(pb, pkt, sample->sample_size);
- if (ret != sample->sample_size)
- ret = AVERROR(EIO);
- }
+
+ ret= av_get_packet(pb, pkt, sample->sample_size);
+ if (ret != sample->sample_size)
+ ret = AVERROR(EIO);
pkt->stream_index = sample->stream;
pkt->pts = sample->pts;
@@ -273,15 +279,6 @@ static int film_read_packet(AVFormatContext *s,
return ret;
}
-static int film_read_close(AVFormatContext *s)
-{
- FilmDemuxContext *film = s->priv_data;
-
- av_freep(&film->sample_table);
-
- return 0;
-}
-
AVInputFormat ff_segafilm_demuxer = {
.name = "film_cpk",
.long_name = NULL_IF_CONFIG_SMALL("Sega FILM / CPK"),
diff --git a/chromium/third_party/ffmpeg/libavformat/segment.c b/chromium/third_party/ffmpeg/libavformat/segment.c
index f07f464f71c..fe84f2710da 100644
--- a/chromium/third_party/ffmpeg/libavformat/segment.c
+++ b/chromium/third_party/ffmpeg/libavformat/segment.c
@@ -65,6 +65,7 @@ typedef struct {
const AVClass *class; /**< Class for private options. */
int segment_idx; ///< index of the segment file to write, starting from 0
int segment_idx_wrap; ///< number after which the index wraps
+ int segment_idx_wrap_nb; ///< number of time the index has wraped
int segment_count; ///< number of segment files already written
AVOutputFormat *oformat;
AVFormatContext *avf;
@@ -72,7 +73,7 @@ typedef struct {
char *list; ///< filename for the segment list file
int list_flags; ///< flags affecting list generation
int list_size; ///< number of entries for the segment list file
- char *list_entry_prefix; ///< prefix to add to list entry filenames
+ char *entry_prefix; ///< prefix to add to list entry filenames
ListType list_type; ///< set the list type
AVIOContext *list_pb; ///< list file put-byte context
char *time_str; ///< segment duration specification string
@@ -171,14 +172,14 @@ static int set_segment_filename(AVFormatContext *s)
/* copy modified name in list entry */
size = strlen(av_basename(oc->filename)) + 1;
- if (seg->list_entry_prefix)
- size += strlen(seg->list_entry_prefix);
+ if (seg->entry_prefix)
+ size += strlen(seg->entry_prefix);
seg->cur_entry.filename = av_mallocz(size);
if (!seg->cur_entry.filename)
return AVERROR(ENOMEM);
snprintf(seg->cur_entry.filename, size, "%s%s",
- seg->list_entry_prefix ? seg->list_entry_prefix : "",
+ seg->entry_prefix ? seg->entry_prefix : "",
av_basename(oc->filename));
return 0;
@@ -199,6 +200,9 @@ static int segment_start(AVFormatContext *s, int write_header)
}
seg->segment_idx++;
+ if ((seg->segment_idx_wrap) && (seg->segment_idx%seg->segment_idx_wrap == 0))
+ seg->segment_idx_wrap_nb++;
+
if ((err = set_segment_filename(s)) < 0)
return err;
@@ -242,6 +246,9 @@ static int segment_list_open(AVFormatContext *s)
avio_printf(seg->list_pb, "#EXT-X-ALLOW-CACHE:%s\n",
seg->list_flags & SEGMENT_LIST_FLAG_CACHE ? "YES" : "NO");
+ av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%d\n",
+ seg->segment_list_entries->index);
+
for (entry = seg->segment_list_entries; entry; entry = entry->next)
max_duration = FFMAX(max_duration, entry->end_time - entry->start_time);
avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", (int64_t)ceil(max_duration));
@@ -366,7 +373,7 @@ static int parse_times(void *log_ctx, int64_t **times, int *nb_times,
if (*p == ',')
(*nb_times)++;
- *times = av_malloc(sizeof(**times) * *nb_times);
+ *times = av_malloc_array(*nb_times, sizeof(**times));
if (!*times) {
av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced times array\n");
FAIL(AVERROR(ENOMEM));
@@ -424,7 +431,7 @@ static int parse_frames(void *log_ctx, int **frames, int *nb_frames,
if (*p == ',')
(*nb_frames)++;
- *frames = av_malloc(sizeof(**frames) * *nb_frames);
+ *frames = av_malloc_array(*nb_frames, sizeof(**frames));
if (!*frames) {
av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n");
FAIL(AVERROR(ENOMEM));
@@ -657,7 +664,6 @@ fail:
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
{
SegmentContext *seg = s->priv_data;
- AVFormatContext *oc = seg->avf;
AVStream *st = s->streams[pkt->stream_index];
int64_t end_pts = INT64_MAX, offset;
int start_frame = INT_MAX;
@@ -690,9 +696,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
if ((ret = segment_start(s, seg->individual_header_trailer)) < 0)
goto fail;
- oc = seg->avf;
-
- seg->cur_entry.index = seg->segment_idx;
+ seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap*seg->segment_idx_wrap_nb;
seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base);
seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
} else if (pkt->pts != AV_NOPTS_VALUE) {
@@ -701,7 +705,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
}
if (seg->is_first_pkt) {
- av_log(s, AV_LOG_DEBUG, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n",
+ av_log(s, AV_LOG_VERBOSE, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n",
seg->avf->filename, pkt->stream_index,
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), seg->frame_count);
seg->is_first_pkt = 0;
@@ -725,18 +729,12 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
- ret = ff_write_chained(oc, pkt->stream_index, pkt, s);
+ ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s);
fail:
if (pkt->stream_index == seg->reference_stream_index)
seg->frame_count++;
- if (ret < 0) {
- if (seg->list)
- avio_close(seg->list_pb);
- avformat_free_context(oc);
- }
-
return ret;
}
@@ -788,7 +786,6 @@ static const AVOption options[] = {
{ "live", "enable live-friendly list generation (useful for HLS)", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_LIVE }, INT_MIN, INT_MAX, E, "list_flags"},
{ "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
- { "segment_list_entry_prefix", "set prefix to prepend to each list entry filename", OFFSET(list_entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "segment_list_type", "set the segment list type", OFFSET(list_type), AV_OPT_TYPE_INT, {.i64 = LIST_TYPE_UNDEFINED}, -1, LIST_TYPE_NB-1, E, "list_type" },
{ "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, E, "list_type" },
@@ -803,7 +800,9 @@ static const AVOption options[] = {
{ "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
{ "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
{ "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
+ { "segment_list_entry_prefix", "set base url prefix for segments", OFFSET(entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
+ { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
{ "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
diff --git a/chromium/third_party/ffmpeg/libavformat/sierravmd.c b/chromium/third_party/ffmpeg/libavformat/sierravmd.c
index 8749ec1640c..9bd42b4e78a 100644
--- a/chromium/third_party/ffmpeg/libavformat/sierravmd.c
+++ b/chromium/third_party/ffmpeg/libavformat/sierravmd.c
@@ -204,7 +204,12 @@ static int vmd_read_header(AVFormatContext *s)
int type;
uint32_t size;
- avio_read(pb, chunk, BYTES_PER_FRAME_RECORD);
+ if ((ret = avio_read(pb, chunk, BYTES_PER_FRAME_RECORD)) != BYTES_PER_FRAME_RECORD) {
+ av_log(s, AV_LOG_ERROR, "Failed to read frame record\n");
+ if (ret >= 0)
+ ret = AVERROR_INVALIDDATA;
+ goto error;
+ }
type = chunk[0];
size = AV_RL32(&chunk[2]);
if (size > INT_MAX / 2) {
diff --git a/chromium/third_party/ffmpeg/libavformat/siff.c b/chromium/third_party/ffmpeg/libavformat/siff.c
index c8b68abe301..8da6c2f67a7 100644
--- a/chromium/third_party/ffmpeg/libavformat/siff.c
+++ b/chromium/third_party/ffmpeg/libavformat/siff.c
@@ -216,7 +216,10 @@ static int siff_read_packet(AVFormatContext *s, AVPacket *pkt)
AV_WL16(pkt->data, c->flags);
if (c->gmcsize)
memcpy(pkt->data + 2, c->gmc, c->gmcsize);
- avio_read(s->pb, pkt->data + 2 + c->gmcsize, size);
+ if (avio_read(s->pb, pkt->data + 2 + c->gmcsize, size) != size) {
+ av_free_packet(pkt);
+ return AVERROR_INVALIDDATA;
+ }
pkt->stream_index = 0;
c->curstrm = -1;
}else{
diff --git a/chromium/third_party/ffmpeg/libavformat/smacker.c b/chromium/third_party/ffmpeg/libavformat/smacker.c
index 0d38588e21f..46215ee73d3 100644
--- a/chromium/third_party/ffmpeg/libavformat/smacker.c
+++ b/chromium/third_party/ffmpeg/libavformat/smacker.c
@@ -23,6 +23,8 @@
* Based on http://wiki.multimedia.cx/index.php?title=Smacker
*/
+#include <inttypes.h>
+
#include "libavutil/bswap.h"
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
@@ -142,7 +144,7 @@ static int smacker_read_header(AVFormatContext *s)
smk->pad = avio_rl32(pb);
/* setup data */
if(smk->frames > 0xFFFFFF) {
- av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames);
+ av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", smk->frames);
return AVERROR_INVALIDDATA;
}
smk->frm_size = av_malloc_array(smk->frames, sizeof(*smk->frm_size));
@@ -221,7 +223,9 @@ static int smacker_read_header(AVFormatContext *s)
/* load trees to extradata, they will be unpacked by decoder */
if(ff_alloc_extradata(st->codec, smk->treesize + 16)){
- av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16);
+ av_log(s, AV_LOG_ERROR,
+ "Cannot allocate %"PRIu32" bytes of extradata\n",
+ smk->treesize + 16);
av_freep(&smk->frm_size);
av_freep(&smk->frm_flags);
return AVERROR(ENOMEM);
diff --git a/chromium/third_party/ffmpeg/libavformat/smjpegdec.c b/chromium/third_party/ffmpeg/libavformat/smjpegdec.c
index 38ac2fb0861..e4c7a9b890f 100644
--- a/chromium/third_party/ffmpeg/libavformat/smjpegdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/smjpegdec.c
@@ -24,6 +24,8 @@
* This is a demuxer for Loki SDL Motion JPEG files
*/
+#include <inttypes.h>
+
#include "avformat.h"
#include "internal.h"
#include "riff.h"
@@ -52,7 +54,7 @@ static int smjpeg_read_header(AVFormatContext *s)
avio_skip(pb, 8); // magic
version = avio_rb32(pb);
if (version)
- avpriv_request_sample(s, "Unknown version %d", version);
+ avpriv_request_sample(s, "Unknown version %"PRIu32, version);
duration = avio_rb32(pb); // in msec
@@ -124,7 +126,7 @@ static int smjpeg_read_header(AVFormatContext *s)
case SMJPEG_HEND:
return 0;
default:
- av_log(s, AV_LOG_ERROR, "unknown header %x\n", htype);
+ av_log(s, AV_LOG_ERROR, "unknown header %"PRIx32"\n", htype);
return AVERROR_INVALIDDATA;
}
}
@@ -164,7 +166,7 @@ static int smjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
ret = AVERROR_EOF;
break;
default:
- av_log(s, AV_LOG_ERROR, "unknown chunk %x\n", dtype);
+ av_log(s, AV_LOG_ERROR, "unknown chunk %"PRIx32"\n", dtype);
ret = AVERROR_INVALIDDATA;
break;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/smush.c b/chromium/third_party/ffmpeg/libavformat/smush.c
index e9c1937398d..a33d50915a7 100644
--- a/chromium/third_party/ffmpeg/libavformat/smush.c
+++ b/chromium/third_party/ffmpeg/libavformat/smush.c
@@ -20,11 +20,12 @@
*/
#include "libavutil/intreadwrite.h"
+
#include "avformat.h"
-#include "internal.h"
#include "avio.h"
+#include "internal.h"
-typedef struct {
+typedef struct SMUSHContext {
int version;
int audio_stream_index;
int video_stream_index;
@@ -32,9 +33,9 @@ typedef struct {
static int smush_read_probe(AVProbeData *p)
{
- if (((AV_RL32(p->buf) == MKTAG('S', 'A', 'N', 'M') &&
+ if (((AV_RL32(p->buf) == MKTAG('S', 'A', 'N', 'M') &&
AV_RL32(p->buf + 8) == MKTAG('S', 'H', 'D', 'R')) ||
- (AV_RL32(p->buf) == MKTAG('A', 'N', 'I', 'M') &&
+ (AV_RL32(p->buf) == MKTAG('A', 'N', 'I', 'M') &&
AV_RL32(p->buf + 8) == MKTAG('A', 'H', 'D', 'R')))) {
return AVPROBE_SCORE_MAX;
}
@@ -65,6 +66,8 @@ static int smush_read_header(AVFormatContext *ctx)
smush->version = 0;
subversion = avio_rl16(pb);
nframes = avio_rl16(pb);
+ if (!nframes)
+ return AVERROR_INVALIDDATA;
avio_skip(pb, 2); // skip pad
@@ -72,7 +75,7 @@ static int smush_read_header(AVFormatContext *ctx)
palette[i] = avio_rb24(pb);
avio_skip(pb, size - (3 * 256 + 6));
- } else if (magic == MKBETAG('S', 'A', 'N', 'M') ) {
+ } else if (magic == MKBETAG('S', 'A', 'N', 'M')) {
if (avio_rb32(pb) != MKBETAG('S', 'H', 'D', 'R'))
return AVERROR_INVALIDDATA;
@@ -81,8 +84,11 @@ static int smush_read_header(AVFormatContext *ctx)
return AVERROR_INVALIDDATA;
smush->version = 1;
- subversion = avio_rl16(pb);
+ subversion = avio_rl16(pb);
nframes = avio_rl32(pb);
+ if (!nframes)
+ return AVERROR_INVALIDDATA;
+
avio_skip(pb, 2); // skip pad
width = avio_rl16(pb);
height = avio_rl16(pb);
@@ -101,12 +107,18 @@ static int smush_read_header(AVFormatContext *ctx)
sig = avio_rb32(pb);
chunk_size = avio_rb32(pb);
- read += 8;
+ read += 8;
switch (sig) {
case MKBETAG('W', 'a', 'v', 'e'):
got_audio = 1;
sample_rate = avio_rl32(pb);
- channels = avio_rl32(pb);
+ if (!sample_rate)
+ return AVERROR_INVALIDDATA;
+
+ channels = avio_rl32(pb);
+ if (!channels)
+ return AVERROR_INVALIDDATA;
+
avio_skip(pb, chunk_size - 8);
read += chunk_size;
break;
@@ -133,17 +145,18 @@ static int smush_read_header(AVFormatContext *ctx)
smush->video_stream_index = vst->index;
+ avpriv_set_pts_info(vst, 64, 1, 15);
+
vst->start_time = 0;
vst->duration =
vst->nb_frames = nframes;
+ vst->avg_frame_rate = av_inv_q(vst->time_base);
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codec->codec_id = AV_CODEC_ID_SANM;
vst->codec->codec_tag = 0;
vst->codec->width = width;
vst->codec->height = height;
- avpriv_set_pts_info(vst, 64, 66667, 1000000);
-
if (!smush->version) {
if (ff_alloc_extradata(vst->codec, 1024 + 2))
return AVERROR(ENOMEM);
@@ -162,7 +175,7 @@ static int smush_read_header(AVFormatContext *ctx)
ast->start_time = 0;
ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- ast->codec->codec_id = AV_CODEC_ID_VIMA;
+ ast->codec->codec_id = AV_CODEC_ID_ADPCM_VIMA;
ast->codec->codec_tag = 0;
ast->codec->sample_rate = sample_rate;
ast->codec->channels = channels;
@@ -178,6 +191,7 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt)
SMUSHContext *smush = ctx->priv_data;
AVIOContext *pb = ctx->pb;
int done = 0;
+ int ret;
while (!done) {
uint32_t sig, size;
@@ -185,22 +199,22 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt)
if (url_feof(pb))
return AVERROR_EOF;
- sig = avio_rb32(pb);
- size = avio_rb32(pb);
+ sig = avio_rb32(pb);
+ size = avio_rb32(pb);
switch (sig) {
case MKBETAG('F', 'R', 'M', 'E'):
if (smush->version)
break;
- if (av_get_packet(pb, pkt, size) < 0)
- return AVERROR(EIO);
+ if ((ret = av_get_packet(pb, pkt, size)) < 0)
+ return ret;
pkt->stream_index = smush->video_stream_index;
done = 1;
break;
case MKBETAG('B', 'l', '1', '6'):
- if (av_get_packet(pb, pkt, size) < 0)
- return AVERROR(EIO);
+ if ((ret = av_get_packet(pb, pkt, size)) < 0)
+ return ret;
pkt->stream_index = smush->video_stream_index;
pkt->duration = 1;
@@ -214,7 +228,7 @@ static int smush_read_packet(AVFormatContext *ctx, AVPacket *pkt)
pkt->stream_index = smush->audio_stream_index;
pkt->flags |= AV_PKT_FLAG_KEY;
- pkt->duration = AV_RB32(pkt->data);
+ pkt->duration = AV_RB32(pkt->data);
if (pkt->duration == 0xFFFFFFFFu)
pkt->duration = AV_RB32(pkt->data + 8);
done = 1;
diff --git a/chromium/third_party/ffmpeg/libavformat/spdifenc.c b/chromium/third_party/ffmpeg/libavformat/spdifenc.c
index 210d63f39cd..18afd428019 100644
--- a/chromium/third_party/ffmpeg/libavformat/spdifenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/spdifenc.c
@@ -44,6 +44,8 @@
* dependent from data-type (spaces between packets are filled by zeros)
*/
+#include <inttypes.h>
+
#include "avformat.h"
#include "avio_internal.h"
#include "spdif.h"
@@ -274,7 +276,7 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt)
av_log(s, AV_LOG_ERROR, "stray DTS-HD frame\n");
return AVERROR_INVALIDDATA;
default:
- av_log(s, AV_LOG_ERROR, "bad DTS syncword 0x%x\n", syncword_dts);
+ av_log(s, AV_LOG_ERROR, "bad DTS syncword 0x%"PRIx32"\n", syncword_dts);
return AVERROR_INVALIDDATA;
}
blocks++;
@@ -369,8 +371,8 @@ static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt)
ctx->data_type = IEC61937_MPEG2_AAC_LSF_4096;
break;
default:
- av_log(s, AV_LOG_ERROR, "%i samples in AAC frame not supported\n",
- hdr.samples);
+ av_log(s, AV_LOG_ERROR,
+ "%"PRIu32" samples in AAC frame not supported\n", hdr.samples);
return AVERROR(EINVAL);
}
//TODO Data type dependent info (LC profile/SBR)
diff --git a/chromium/third_party/ffmpeg/libavformat/subfile.c b/chromium/third_party/ffmpeg/libavformat/subfile.c
new file mode 100644
index 00000000000..0e84384600b
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/subfile.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014 Nicolas George
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/opt.h"
+#include "avformat.h"
+#include "url.h"
+
+typedef struct SubfileContext {
+ const AVClass *class;
+ URLContext *h;
+ int64_t start;
+ int64_t end;
+ int64_t pos;
+} SubfileContext;
+
+#define OFFSET(field) offsetof(SubfileContext, field)
+#define D AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption subfile_options[] = {
+ { "start", "start offset", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D },
+ { "end", "end offset", OFFSET(end), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, D },
+ { NULL }
+};
+
+#undef OFFSET
+#undef D
+
+static const AVClass subfile_class = {
+ .class_name = "subfile",
+ .item_name = av_default_item_name,
+ .option = subfile_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static int slave_seek(URLContext *h)
+{
+ SubfileContext *c = h->priv_data;
+ int64_t ret;
+
+ if ((ret = ffurl_seek(c->h, c->pos, SEEK_SET)) != c->pos) {
+ if (ret >= 0)
+ ret = AVERROR_BUG;
+ av_log(h, AV_LOG_ERROR, "Impossible to seek in file: %s\n",
+ av_err2str(ret));
+ return ret;
+ }
+ return 0;
+}
+
+static int subfile_open(URLContext *h, const char *filename, int flags,
+ AVDictionary **options)
+{
+ SubfileContext *c = h->priv_data;
+ int ret;
+
+ if (c->end <= c->start) {
+ av_log(h, AV_LOG_ERROR, "end before start\n");
+ return AVERROR(EINVAL);
+ }
+ av_strstart(filename, "subfile:", &filename);
+ ret = ffurl_open(&c->h, filename, flags, &h->interrupt_callback, options);
+ if (ret < 0)
+ return ret;
+ c->pos = c->start;
+ if ((ret = slave_seek(h)) < 0) {
+ ffurl_close(c->h);
+ return ret;
+ }
+ return 0;
+}
+
+static int subfile_close(URLContext *h)
+{
+ SubfileContext *c = h->priv_data;
+ return ffurl_close(c->h);
+}
+
+static int subfile_read(URLContext *h, unsigned char *buf, int size)
+{
+ SubfileContext *c = h->priv_data;
+ int64_t rest = c->end - c->pos;
+ int ret;
+
+ if (rest <= 0)
+ return 0;
+ size = FFMIN(size, rest);
+ ret = ffurl_read(c->h, buf, size);
+ if (ret >= 0)
+ c->pos += ret;
+ return ret;
+}
+
+static int64_t subfile_seek(URLContext *h, int64_t pos, int whence)
+{
+ SubfileContext *c = h->priv_data;
+ int64_t new_pos = -1;
+ int ret;
+
+ if (whence == AVSEEK_SIZE)
+ return c->end - c->start;
+ switch (whence) {
+ case SEEK_SET:
+ new_pos = c->start + pos;
+ break;
+ case SEEK_CUR:
+ new_pos += pos;
+ break;
+ case SEEK_END:
+ new_pos = c->end + c->pos;
+ break;
+ }
+ if (new_pos < c->start)
+ return AVERROR(EINVAL);
+ c->pos = new_pos;
+ if ((ret = slave_seek(h)) < 0)
+ return ret;
+ return c->pos - c->start;
+}
+
+URLProtocol ff_subfile_protocol = {
+ .name = "subfile",
+ .url_open2 = subfile_open,
+ .url_read = subfile_read,
+ .url_seek = subfile_seek,
+ .url_close = subfile_close,
+ .priv_data_size = sizeof(SubfileContext),
+ .priv_data_class = &subfile_class,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/swfdec.c b/chromium/third_party/ffmpeg/libavformat/swfdec.c
index e6ceec818af..c95b18ec6cb 100644
--- a/chromium/third_party/ffmpeg/libavformat/swfdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/swfdec.c
@@ -446,16 +446,30 @@ bitmap_end_skip:
goto skip;
if ((res = av_new_packet(pkt, len)) < 0)
return res;
- avio_read(pb, pkt->data, 4);
+ if (avio_read(pb, pkt->data, 4) != 4) {
+ av_free_packet(pkt);
+ return AVERROR_INVALIDDATA;
+ }
if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
AV_RB32(pkt->data) == 0xffd9ffd8) {
/* old SWF files containing SOI/EOI as data start */
/* files created by swink have reversed tag */
pkt->size -= 4;
- avio_read(pb, pkt->data, pkt->size);
+ memset(pkt->data+pkt->size, 0, 4);
+ res = avio_read(pb, pkt->data, pkt->size);
} else {
- avio_read(pb, pkt->data + 4, pkt->size - 4);
+ res = avio_read(pb, pkt->data + 4, pkt->size - 4);
+ if (res >= 0)
+ res += 4;
+ }
+ if (res != pkt->size) {
+ if (res < 0) {
+ av_free_packet(pkt);
+ return res;
+ }
+ av_shrink_packet(pkt, res);
}
+
pkt->pos = pos;
pkt->stream_index = st->index;
return pkt->size;
diff --git a/chromium/third_party/ffmpeg/libavformat/swfenc.c b/chromium/third_party/ffmpeg/libavformat/swfenc.c
index 8d9cf0c246c..402f21ef40a 100644
--- a/chromium/third_party/ffmpeg/libavformat/swfenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/swfenc.c
@@ -490,8 +490,7 @@ static int swf_write_trailer(AVFormatContext *s)
if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
video_enc = enc;
else {
- av_fifo_free(swf->audio_fifo);
- swf->audio_fifo = NULL;
+ av_fifo_freep(&swf->audio_fifo);
}
}
diff --git a/chromium/third_party/ffmpeg/libavformat/takdec.c b/chromium/third_party/ffmpeg/libavformat/takdec.c
index 2ed8a1e3b71..4888a776305 100644
--- a/chromium/third_party/ffmpeg/libavformat/takdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/takdec.c
@@ -85,6 +85,7 @@ static int tak_read_header(AVFormatContext *s)
buffer = av_malloc(size - 3 + FF_INPUT_BUFFER_PADDING_SIZE);
if (!buffer)
return AVERROR(ENOMEM);
+ memset(buffer + size - 3, 0, FF_INPUT_BUFFER_PADDING_SIZE);
ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U);
if (avio_read(pb, buffer, size - 3) != size - 3) {
diff --git a/chromium/third_party/ffmpeg/libavformat/tcp.c b/chromium/third_party/ffmpeg/libavformat/tcp.c
index 634d99d0d02..e457fba94fa 100644
--- a/chromium/third_party/ffmpeg/libavformat/tcp.c
+++ b/chromium/third_party/ffmpeg/libavformat/tcp.c
@@ -44,8 +44,8 @@ typedef struct TCPContext {
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{"listen", "listen on port instead of connecting", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
-{"timeout", "timeout of socket i/o operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
-{"listen_timeout", "connection awaiting timeout", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
+{"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
+{"listen_timeout", "set connection awaiting timeout", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
{NULL}
};
@@ -79,8 +79,13 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
}
p = strchr(uri, '?');
if (p) {
- if (av_find_info_tag(buf, sizeof(buf), "listen", p))
- s->listen = 1;
+ if (av_find_info_tag(buf, sizeof(buf), "listen", p)) {
+ char *endptr = NULL;
+ s->listen = strtol(buf, &endptr, 10);
+ /* assume if no digits were found it is a request to enable it */
+ if (buf == endptr)
+ s->listen = 1;
+ }
if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
s->rw_timeout = strtol(buf, NULL, 10);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/tee.c b/chromium/third_party/ffmpeg/libavformat/tee.c
index 12ea0ea27d6..f26e15742a5 100644
--- a/chromium/third_party/ffmpeg/libavformat/tee.c
+++ b/chromium/third_party/ffmpeg/libavformat/tee.c
@@ -410,18 +410,17 @@ static int filter_packet(void *log_ctx, AVPacket *pkt,
if (!new_pkt.buf)
break;
}
+ if (ret < 0) {
+ av_log(log_ctx, AV_LOG_ERROR,
+ "Failed to filter bitstream with filter %s for stream %d in file '%s' with codec %s\n",
+ bsf_ctx->filter->name, pkt->stream_index, fmt_ctx->filename,
+ avcodec_get_name(enc_ctx->codec_id));
+ }
*pkt = new_pkt;
bsf_ctx = bsf_ctx->next;
}
- if (ret < 0) {
- av_log(log_ctx, AV_LOG_ERROR,
- "Failed to filter bitstream with filter %s for stream %d in file '%s' with codec %s\n",
- bsf_ctx->filter->name, pkt->stream_index, fmt_ctx->filename,
- avcodec_get_name(enc_ctx->codec_id));
- }
-
return ret;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/tls.c b/chromium/third_party/ffmpeg/libavformat/tls.c
index 5da82db7967..7fd18cfce0c 100644
--- a/chromium/third_party/ffmpeg/libavformat/tls.c
+++ b/chromium/third_party/ffmpeg/libavformat/tls.c
@@ -24,6 +24,9 @@
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
+#include "network.h"
+#include "os_support.h"
+#include "internal.h"
#if CONFIG_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
@@ -50,9 +53,6 @@
SSL_CTX_free(c->ctx); \
} while (0)
#endif
-#include "network.h"
-#include "os_support.h"
-#include "internal.h"
#if HAVE_POLL_H
#include <poll.h>
#endif
diff --git a/chromium/third_party/ffmpeg/libavformat/txd.c b/chromium/third_party/ffmpeg/libavformat/txd.c
index 194945bbc8f..400f2cc54bd 100644
--- a/chromium/third_party/ffmpeg/libavformat/txd.c
+++ b/chromium/third_party/ffmpeg/libavformat/txd.c
@@ -21,6 +21,7 @@
#include "libavutil/intreadwrite.h"
#include "avformat.h"
+#include "internal.h"
#define TXD_FILE 0x16
#define TXD_INFO 0x01
@@ -45,8 +46,8 @@ static int txd_read_header(AVFormatContext *s) {
return AVERROR(ENOMEM);
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_id = AV_CODEC_ID_TXD;
- st->codec->time_base.den = 5;
- st->codec->time_base.num = 1;
+ avpriv_set_pts_info(st, 64, 1, 5);
+ st->avg_frame_rate = av_inv_q(st->time_base);
/* the parameters will be extracted from the compressed bitstream */
return 0;
diff --git a/chromium/third_party/ffmpeg/libavformat/udp.c b/chromium/third_party/ffmpeg/libavformat/udp.c
index 3c0d6bf0123..91b411e679a 100644
--- a/chromium/third_party/ffmpeg/libavformat/udp.c
+++ b/chromium/third_party/ffmpeg/libavformat/udp.c
@@ -62,6 +62,7 @@ typedef struct {
int ttl;
int buffer_size;
int is_multicast;
+ int is_broadcast;
int local_port;
int reuse_socket;
int overrun_nonfatal;
@@ -84,23 +85,25 @@ typedef struct {
char *local_addr;
int packet_size;
int timeout;
+ struct sockaddr_storage local_addr_storage;
} UDPContext;
#define OFFSET(x) offsetof(UDPContext, x)
#define D AV_OPT_FLAG_DECODING_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
-{"buffer_size", "Socket buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
-{"localport", "Set local port to bind to", OFFSET(local_port), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
-{"localaddr", "Choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E },
-{"pkt_size", "Set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E },
-{"reuse", "Explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
-{"ttl", "Set the time to live value (for multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, {.i64 = 16}, 0, INT_MAX, E },
-{"connect", "Should connect() be called on socket", OFFSET(is_connected), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
+{"buffer_size", "set packet buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
+{"localport", "set local port to bind to", OFFSET(local_port), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
+{"localaddr", "choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E },
+{"pkt_size", "set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E },
+{"reuse", "explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
+{"broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
+{"ttl", "set the time to live value (for multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, {.i64 = 16}, 0, INT_MAX, E },
+{"connect", "set if connect() should be called on socket", OFFSET(is_connected), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
/* TODO 'sources', 'block' option */
-{"fifo_size", "Set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = 7*4096}, 0, INT_MAX, D },
-{"overrun_nonfatal", "Survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D },
-{"timeout", "In read mode: if no data arrived in more than this time interval, raise error", OFFSET(timeout), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D },
+{"fifo_size", "set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = 7*4096}, 0, INT_MAX, D },
+{"overrun_nonfatal", "survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D },
+{"timeout", "set raise error timeout (only in read mode)", OFFSET(timeout), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D },
{NULL}
};
@@ -140,14 +143,17 @@ static int udp_set_multicast_ttl(int sockfd, int mcastTTL,
return 0;
}
-static int udp_join_multicast_group(int sockfd, struct sockaddr *addr)
+static int udp_join_multicast_group(int sockfd, struct sockaddr *addr,struct sockaddr *local_addr)
{
#ifdef IP_ADD_MEMBERSHIP
if (addr->sa_family == AF_INET) {
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
- mreq.imr_interface.s_addr= INADDR_ANY;
+ if (local_addr)
+ mreq.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr;
+ else
+ mreq.imr_interface.s_addr= INADDR_ANY;
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)");
return -1;
@@ -169,14 +175,17 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr)
return 0;
}
-static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr)
+static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr,struct sockaddr *local_addr)
{
#ifdef IP_DROP_MEMBERSHIP
if (addr->sa_family == AF_INET) {
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
- mreq.imr_interface.s_addr= INADDR_ANY;
+ if (local_addr)
+ mreq.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr;
+ else
+ mreq.imr_interface.s_addr= INADDR_ANY;
if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)");
return -1;
@@ -595,6 +604,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p))
s->timeout = strtol(buf, NULL, 10);
+ if (is_output && av_find_info_tag(buf, sizeof(buf), "broadcast", p))
+ s->is_broadcast = strtol(buf, NULL, 10);
}
/* handling needed to support options picking from both AVOption and URL */
s->circular_buffer_size *= 188;
@@ -624,6 +635,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (udp_fd < 0)
goto fail;
+ s->local_addr_storage=my_addr; //store for future multicast join
+
/* Follow the requested reuse option, unless it's multicast in which
* case enable reuse unless explicitly disabled.
*/
@@ -633,6 +646,11 @@ static int udp_open(URLContext *h, const char *uri, int flags)
goto fail;
}
+ if (s->is_broadcast) {
+ if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0)
+ goto fail;
+ }
+
/* If multicast, try binding the multicast address first, to avoid
* receiving UDP packets from other sources aimed at the same UDP
* port. This fails on windows. This makes sending to the same address
@@ -668,7 +686,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0)
goto fail;
} else {
- if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
+ if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage) < 0)
goto fail;
}
if (num_exclude_sources) {
@@ -686,12 +704,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
goto fail;
}
} else {
- /* set udp recv buffer size to the largest possible udp packet size to
- * avoid losing data on OSes that set this too low by default. */
+ /* set udp recv buffer size to the requested value (default 64K) */
tmp = s->buffer_size;
if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)");
}
+ len = sizeof(tmp);
+ if (getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, &len) < 0) {
+ log_net_error(h, AV_LOG_WARNING, "getsockopt(SO_RCVBUF)");
+ } else {
+ av_log(h, AV_LOG_DEBUG, "end receive buffer size reported is %d\n", tmp);
+ if(tmp < s->buffer_size)
+ av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d", s->buffer_size, tmp);
+ }
+
/* make the socket non-blocking */
ff_socket_nonblock(udp_fd, 1);
}
@@ -744,7 +770,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
fail:
if (udp_fd >= 0)
closesocket(udp_fd);
- av_fifo_free(s->fifo);
+ av_fifo_freep(&s->fifo);
for (i = 0; i < num_include_sources; i++)
av_freep(&include_sources[i]);
for (i = 0; i < num_exclude_sources; i++)
@@ -838,7 +864,7 @@ static int udp_close(URLContext *h)
int ret;
if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
- udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
+ udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage);
closesocket(s->udp_fd);
#if HAVE_PTHREAD_CANCEL
if (s->thread_started) {
@@ -850,7 +876,7 @@ static int udp_close(URLContext *h)
pthread_cond_destroy(&s->cond);
}
#endif
- av_fifo_free(s->fifo);
+ av_fifo_freep(&s->fifo);
return 0;
}
diff --git a/chromium/third_party/ffmpeg/libavformat/uncodedframecrcenc.c b/chromium/third_party/ffmpeg/libavformat/uncodedframecrcenc.c
new file mode 100644
index 00000000000..414683fe23c
--- /dev/null
+++ b/chromium/third_party/ffmpeg/libavformat/uncodedframecrcenc.c
@@ -0,0 +1,172 @@
+/*
+* Copyright (c) 2013 Nicolas George
+*
+* This file is part of FFmpeg.
+*
+* FFmpeg is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* FFmpeg is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "libavutil/adler32.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/pixdesc.h"
+#include "avformat.h"
+#include "internal.h"
+
+/* Identical to Adler32 when the type is uint8_t. */
+#define DEFINE_CKSUM_LINE(name, type, conv) \
+static void cksum_line_ ## name(unsigned *cksum, void *data, unsigned size) \
+{ \
+ type *p = data; \
+ unsigned a = *cksum & 0xFFFF, b = *cksum >> 16; \
+ for (; size > 0; size--, p++) { \
+ a = (a + (unsigned)(conv)) % 65521; \
+ b = (b + a) % 65521; \
+ } \
+ *cksum = a | (b << 16); \
+}
+
+DEFINE_CKSUM_LINE(u8, uint8_t, *p)
+DEFINE_CKSUM_LINE(s16, int16_t, *p + 0x8000)
+DEFINE_CKSUM_LINE(s32, int32_t, *p + 0x80000000)
+DEFINE_CKSUM_LINE(flt, float, *p * 0x80000000 + 0x80000000)
+DEFINE_CKSUM_LINE(dbl, double, *p * 0x80000000 + 0x80000000)
+
+static void video_frame_cksum(AVBPrint *bp, AVFrame *frame)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
+ int i, y;
+ uint8_t *data;
+ int linesize[5] = { 0 };
+
+ av_bprintf(bp, ", %d x %d", frame->width, frame->height);
+ if (!desc) {
+ av_bprintf(bp, ", unknown");
+ return;
+ }
+ if (av_image_fill_linesizes(linesize, frame->format, frame->width) < 0)
+ return;
+ av_bprintf(bp, ", %s", desc->name);
+ for (i = 0; linesize[i]; i++) {
+ unsigned cksum = 0;
+ int h = frame->height;
+ if ((i == 1 || i == 2) && desc->nb_components >= 3)
+ h = -((-h) >> desc->log2_chroma_h);
+ data = frame->data[i];
+ for (y = 0; y < h; y++) {
+ cksum = av_adler32_update(cksum, data, linesize[i]);
+ data += frame->linesize[i];
+ }
+ av_bprintf(bp, ", 0x%08x", cksum);
+ }
+}
+
+static void audio_frame_cksum(AVBPrint *bp, AVFrame *frame)
+{
+ int nb_planes, nb_samples, p;
+ const char *name;
+
+ nb_planes = av_frame_get_channels(frame);
+ nb_samples = frame->nb_samples;
+ if (!av_sample_fmt_is_planar(frame->format)) {
+ nb_samples *= nb_planes;
+ nb_planes = 1;
+ }
+ name = av_get_sample_fmt_name(frame->format);
+ av_bprintf(bp, ", %d samples", frame->nb_samples);
+ av_bprintf(bp, ", %s", name ? name : "unknown");
+ for (p = 0; p < nb_planes; p++) {
+ uint32_t cksum = 0;
+ void *d = frame->extended_data[p];
+ switch (frame->format) {
+ case AV_SAMPLE_FMT_U8:
+ case AV_SAMPLE_FMT_U8P:
+ cksum_line_u8(&cksum, d, nb_samples);
+ break;
+ case AV_SAMPLE_FMT_S16:
+ case AV_SAMPLE_FMT_S16P:
+ cksum_line_s16(&cksum, d, nb_samples);
+ break;
+ case AV_SAMPLE_FMT_S32:
+ case AV_SAMPLE_FMT_S32P:
+ cksum_line_s32(&cksum, d, nb_samples);
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ case AV_SAMPLE_FMT_FLTP:
+ cksum_line_flt(&cksum, d, nb_samples);
+ break;
+ case AV_SAMPLE_FMT_DBL:
+ case AV_SAMPLE_FMT_DBLP:
+ cksum_line_dbl(&cksum, d, nb_samples);
+ break;
+ default:
+ av_assert0(!"reached");
+ }
+ av_bprintf(bp, ", 0x%08x", cksum);
+ }
+}
+
+static int write_frame(struct AVFormatContext *s, int stream_index,
+ AVFrame **frame, unsigned flags)
+{
+ AVBPrint bp;
+ int ret = 0;
+ enum AVMediaType type;
+ const char *type_name;
+
+ if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
+ return 0;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "%d, %10"PRId64"",
+ stream_index, (*frame)->pts);
+ type = s->streams[stream_index]->codec->codec_type;
+ type_name = av_get_media_type_string(type);
+ av_bprintf(&bp, ", %s", type_name ? type_name : "unknown");
+ switch (type) {
+ case AVMEDIA_TYPE_VIDEO:
+ video_frame_cksum(&bp, *frame);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ audio_frame_cksum(&bp, *frame);
+ break;
+ }
+
+ av_bprint_chars(&bp, '\n', 1);
+ if (av_bprint_is_complete(&bp))
+ avio_write(s->pb, bp.str, bp.len);
+ else
+ ret = AVERROR(ENOMEM);
+ av_bprint_finalize(&bp, NULL);
+ return ret;
+}
+
+static int write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ return AVERROR(ENOSYS);
+}
+
+AVOutputFormat ff_uncodedframecrc_muxer = {
+ .name = "uncodedframecrc",
+ .long_name = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"),
+ .audio_codec = AV_CODEC_ID_PCM_S16LE,
+ .video_codec = AV_CODEC_ID_RAWVIDEO,
+ .write_header = ff_framehash_write_header,
+ .write_packet = write_packet,
+ .write_uncoded_frame = write_frame,
+ .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+ AVFMT_TS_NEGATIVE,
+};
diff --git a/chromium/third_party/ffmpeg/libavformat/utils.c b/chromium/third_party/ffmpeg/libavformat/utils.c
index fc4de4c34eb..d84d6053ffa 100644
--- a/chromium/third_party/ffmpeg/libavformat/utils.c
+++ b/chromium/third_party/ffmpeg/libavformat/utils.c
@@ -19,36 +19,39 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#undef NDEBUG
+#include <assert.h>
+#include <stdarg.h>
#include <stdint.h>
-#include "avformat.h"
-#include "avio_internal.h"
-#include "internal.h"
-#include "libavcodec/internal.h"
-#include "libavcodec/raw.h"
-#include "libavcodec/bytestream.h"
-#include "libavutil/opt.h"
-#include "libavutil/dict.h"
-#include "libavutil/internal.h"
-#include "libavutil/pixdesc.h"
-#include "metadata.h"
-#include "id3v2.h"
+#include "config.h"
+
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
+#include "libavutil/dict.h"
+#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
+#include "libavutil/pixdesc.h"
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
-#include "riff.h"
+
+#include "libavcodec/bytestream.h"
+#include "libavcodec/internal.h"
+#include "libavcodec/raw.h"
+
#include "audiointerleave.h"
-#include "url.h"
-#include <stdarg.h>
+#include "avformat.h"
+#include "avio_internal.h"
+#include "id3v2.h"
+#include "internal.h"
+#include "metadata.h"
#if CONFIG_NETWORK
#include "network.h"
#endif
-
-#undef NDEBUG
-#include <assert.h>
+#include "riff.h"
+#include "url.h"
/**
* @file
@@ -91,10 +94,10 @@ static int64_t wrap_timestamp(AVStream *st, int64_t timestamp)
st->pts_wrap_reference != AV_NOPTS_VALUE && timestamp != AV_NOPTS_VALUE) {
if (st->pts_wrap_behavior == AV_PTS_WRAP_ADD_OFFSET &&
timestamp < st->pts_wrap_reference)
- return timestamp + (1ULL<<st->pts_wrap_bits);
+ return timestamp + (1ULL << st->pts_wrap_bits);
else if (st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET &&
timestamp >= st->pts_wrap_reference)
- return timestamp - (1ULL<<st->pts_wrap_bits);
+ return timestamp - (1ULL << st->pts_wrap_bits);
}
return timestamp;
}
@@ -103,21 +106,34 @@ MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec)
MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec)
+MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding)
+MAKE_ACCESSORS(AVFormatContext, format, void *, opaque)
+MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb)
-static AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id)
+void av_format_inject_global_side_data(AVFormatContext *s)
+{
+ int i;
+ s->internal->inject_global_side_data = 1;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ st->inject_global_side_data = 1;
+ }
+}
+
+static const AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id)
{
if (st->codec->codec)
return st->codec->codec;
- switch(st->codec->codec_type){
+ switch (st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- if(s->video_codec) return s->video_codec;
+ if (s->video_codec) return s->video_codec;
break;
case AVMEDIA_TYPE_AUDIO:
- if(s->audio_codec) return s->audio_codec;
+ if (s->audio_codec) return s->audio_codec;
break;
case AVMEDIA_TYPE_SUBTITLE:
- if(s->subtitle_codec) return s->subtitle_codec;
+ if (s->subtitle_codec) return s->subtitle_codec;
break;
}
@@ -134,28 +150,26 @@ int av_format_get_probe_score(const AVFormatContext *s)
int ffio_limit(AVIOContext *s, int size)
{
- if(s->maxsize>=0){
+ if (s->maxsize>= 0) {
int64_t remaining= s->maxsize - avio_tell(s);
- if(remaining < size){
- int64_t newsize= avio_size(s);
- if(!s->maxsize || s->maxsize<newsize)
- s->maxsize= newsize - !newsize;
+ if (remaining < size) {
+ int64_t newsize = avio_size(s);
+ if (!s->maxsize || s->maxsize<newsize)
+ s->maxsize = newsize - !newsize;
remaining= s->maxsize - avio_tell(s);
remaining= FFMAX(remaining, 0);
}
- if(s->maxsize>=0 && remaining+1 < size){
+ if (s->maxsize>= 0 && remaining+1 < size) {
av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1);
- size= remaining+1;
+ size = remaining+1;
}
}
return size;
}
-/*
- * Read the data in sane-sized chunks and append to pkt.
- * Return the number of bytes read or an error.
- */
+/* Read the data in sane-sized chunks and append to pkt.
+ * Return the number of bytes read or an error. */
static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
{
int64_t orig_pos = pkt->pos; // av_grow_packet might reset pos
@@ -166,10 +180,8 @@ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
int prev_size = pkt->size;
int read_size;
- /*
- * When the caller requests a lot of data, limit it to the amount left
- * in file or SANE_CHUNK_SIZE when it is not known
- */
+ /* When the caller requests a lot of data, limit it to the amount
+ * left in file or SANE_CHUNK_SIZE when it is not known. */
read_size = size;
if (read_size > SANE_CHUNK_SIZE/10) {
read_size = ffio_limit(s, read_size);
@@ -216,18 +228,19 @@ int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
return append_packet_chunked(s, pkt, size);
}
-
int av_filename_number_test(const char *filename)
{
char buf[1024];
- return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0);
+ return filename &&
+ (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0);
}
-AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret)
+AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened,
+ int *score_ret)
{
AVProbeData lpd = *pd;
AVInputFormat *fmt1 = NULL, *fmt;
- int score, nodat = 0, score_max=0;
+ int score, nodat = 0, score_max = 0;
const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE];
if (!lpd.buf)
@@ -236,9 +249,11 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score
if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {
int id3len = ff_id3v2_tag_len(lpd.buf);
if (lpd.buf_size > id3len + 16) {
- lpd.buf += id3len;
+ lpd.buf += id3len;
lpd.buf_size -= id3len;
- }else
+ } else if (id3len >= PROBE_BUF_MAX) {
+ nodat = 2;
+ } else
nodat = 1;
}
@@ -249,22 +264,24 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score
score = 0;
if (fmt1->read_probe) {
score = fmt1->read_probe(&lpd);
- if(fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions))
- score = FFMAX(score, nodat ? AVPROBE_SCORE_EXTENSION / 2 - 1 : 1);
+ if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) {
+ if (nodat == 0) score = FFMAX(score, 1);
+ else if (nodat == 1) score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1);
+ else score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
+ }
} else if (fmt1->extensions) {
- if (av_match_ext(lpd.filename, fmt1->extensions)) {
+ if (av_match_ext(lpd.filename, fmt1->extensions))
score = AVPROBE_SCORE_EXTENSION;
- }
}
if (score > score_max) {
score_max = score;
- fmt = fmt1;
- }else if (score == score_max)
+ fmt = fmt1;
+ } else if (score == score_max)
fmt = NULL;
}
- if(nodat)
+ if (nodat == 1)
score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);
- *score_ret= score_max;
+ *score_ret = score_max;
return fmt;
}
@@ -272,32 +289,37 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score
AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
{
int score_ret;
- AVInputFormat *fmt= av_probe_input_format3(pd, is_opened, &score_ret);
- if(score_ret > *score_max){
- *score_max= score_ret;
+ AVInputFormat *fmt = av_probe_input_format3(pd, is_opened, &score_ret);
+ if (score_ret > *score_max) {
+ *score_max = score_ret;
return fmt;
- }else
+ } else
return NULL;
}
-AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){
- int score=0;
+AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
+{
+ int score = 0;
return av_probe_input_format2(pd, is_opened, &score);
}
-static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd)
+static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
+ AVProbeData *pd)
{
static const struct {
- const char *name; enum AVCodecID id; enum AVMediaType type;
+ const char *name;
+ enum AVCodecID id;
+ enum AVMediaType type;
} fmt_id_type[] = {
- { "aac" , AV_CODEC_ID_AAC , AVMEDIA_TYPE_AUDIO },
- { "ac3" , AV_CODEC_ID_AC3 , AVMEDIA_TYPE_AUDIO },
- { "dts" , AV_CODEC_ID_DTS , AVMEDIA_TYPE_AUDIO },
- { "eac3" , AV_CODEC_ID_EAC3 , AVMEDIA_TYPE_AUDIO },
- { "h264" , AV_CODEC_ID_H264 , AVMEDIA_TYPE_VIDEO },
- { "loas" , AV_CODEC_ID_AAC_LATM , AVMEDIA_TYPE_AUDIO },
- { "m4v" , AV_CODEC_ID_MPEG4 , AVMEDIA_TYPE_VIDEO },
- { "mp3" , AV_CODEC_ID_MP3 , AVMEDIA_TYPE_AUDIO },
+ { "aac", AV_CODEC_ID_AAC, AVMEDIA_TYPE_AUDIO },
+ { "ac3", AV_CODEC_ID_AC3, AVMEDIA_TYPE_AUDIO },
+ { "dts", AV_CODEC_ID_DTS, AVMEDIA_TYPE_AUDIO },
+ { "eac3", AV_CODEC_ID_EAC3, AVMEDIA_TYPE_AUDIO },
+ { "h264", AV_CODEC_ID_H264, AVMEDIA_TYPE_VIDEO },
+ { "hevc", AV_CODEC_ID_HEVC, AVMEDIA_TYPE_VIDEO },
+ { "loas", AV_CODEC_ID_AAC_LATM, AVMEDIA_TYPE_AUDIO },
+ { "m4v", AV_CODEC_ID_MPEG4, AVMEDIA_TYPE_VIDEO },
+ { "mp3", AV_CODEC_ID_MP3, AVMEDIA_TYPE_AUDIO },
{ "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO },
{ 0 }
};
@@ -306,8 +328,10 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa
if (fmt && st->request_probe <= score) {
int i;
- av_log(s, AV_LOG_DEBUG, "Probe with size=%d, packets=%d detected %s with score=%d\n",
- pd->buf_size, MAX_PROBE_PACKETS - st->probe_packets, fmt->name, score);
+ av_log(s, AV_LOG_DEBUG,
+ "Probe with size=%d, packets=%d detected %s with score=%d\n",
+ pd->buf_size, MAX_PROBE_PACKETS - st->probe_packets,
+ fmt->name, score);
for (i = 0; fmt_id_type[i].name; i++) {
if (!strcmp(fmt->name, fmt_id_type[i].name)) {
st->codec->codec_id = fmt_id_type[i].id;
@@ -322,7 +346,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa
/************************************************************/
/* input media file */
-int av_demuxer_open(AVFormatContext *ic){
+int av_demuxer_open(AVFormatContext *ic) {
int err;
if (ic->iformat->read_header) {
@@ -342,25 +366,24 @@ int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size)
{
- AVProbeData pd = { filename ? filename : "", NULL, -offset };
- unsigned char *buf = NULL;
+ AVProbeData pd = { filename ? filename : "" };
+ uint8_t *buf = NULL;
uint8_t *mime_type;
int ret = 0, probe_size, buf_offset = 0;
int score = 0;
- if (!max_probe_size) {
+ if (!max_probe_size)
max_probe_size = PROBE_BUF_MAX;
- } else if (max_probe_size > PROBE_BUF_MAX) {
+ else if (max_probe_size > PROBE_BUF_MAX)
max_probe_size = PROBE_BUF_MAX;
- } else if (max_probe_size < PROBE_BUF_MIN) {
+ else if (max_probe_size < PROBE_BUF_MIN) {
av_log(logctx, AV_LOG_ERROR,
"Specified probe size value %u cannot be < %u\n", max_probe_size, PROBE_BUF_MIN);
return AVERROR(EINVAL);
}
- if (offset >= max_probe_size) {
+ if (offset >= max_probe_size)
return AVERROR(EINVAL);
- }
if (!*fmt && pb->av_class && av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type) >= 0 && mime_type) {
if (!av_strcasecmp(mime_type, "audio/aacp")) {
@@ -369,38 +392,44 @@ int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
av_freep(&mime_type);
}
- for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt;
- probe_size = FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) {
-
- if (probe_size < offset) {
- continue;
- }
+ for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt;
+ probe_size = FFMIN(probe_size << 1,
+ FFMAX(max_probe_size, probe_size + 1))) {
score = probe_size < max_probe_size ? AVPROBE_SCORE_RETRY : 0;
- /* read probe data */
+ /* Read probe data. */
if ((ret = av_reallocp(&buf, probe_size + AVPROBE_PADDING_SIZE)) < 0)
return ret;
- if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset)) < 0) {
- /* fail if error was not end of file, otherwise, lower score */
+ if ((ret = avio_read(pb, buf + buf_offset,
+ probe_size - buf_offset)) < 0) {
+ /* Fail if error was not end of file, otherwise, lower score. */
if (ret != AVERROR_EOF) {
av_free(buf);
return ret;
}
score = 0;
- ret = 0; /* error was end of file, nothing read */
+ ret = 0; /* error was end of file, nothing read */
}
- pd.buf_size = buf_offset += ret;
+ buf_offset += ret;
+ if (buf_offset < offset)
+ continue;
+ pd.buf_size = buf_offset - offset;
pd.buf = &buf[offset];
memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);
- /* guess file format */
+ /* Guess file format. */
*fmt = av_probe_input_format2(&pd, 1, &score);
- if(*fmt){
- if(score <= AVPROBE_SCORE_RETRY){ //this can only be true in the last iteration
- av_log(logctx, AV_LOG_WARNING, "Format %s detected only with low score of %d, misdetection possible!\n", (*fmt)->name, score);
- }else
- av_log(logctx, AV_LOG_DEBUG, "Format %s probed with size=%d and score=%d\n", (*fmt)->name, probe_size, score);
+ if (*fmt) {
+ /* This can only be true in the last iteration. */
+ if (score <= AVPROBE_SCORE_RETRY) {
+ av_log(logctx, AV_LOG_WARNING,
+ "Format %s detected only with low score of %d, "
+ "misdetection possible!\n", (*fmt)->name, score);
+ } else
+ av_log(logctx, AV_LOG_DEBUG,
+ "Format %s probed with size=%d and score=%d\n",
+ (*fmt)->name, probe_size, score);
#if 0
FILE *f = fopen("probestat.tmp", "ab");
fprintf(f, "probe_size:%d format:%s score:%d filename:%s\n", probe_size, (*fmt)->name, score, filename);
@@ -414,8 +443,8 @@ int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
return AVERROR_INVALIDDATA;
}
- /* rewind. reuse probe buffer to avoid seeking */
- ret = ffio_rewind_with_probe_data(pb, &buf, pd.buf_size);
+ /* Rewind. Reuse probe buffer to avoid seeking. */
+ ret = ffio_rewind_with_probe_data(pb, &buf, buf_offset);
return ret < 0 ? ret : score;
}
@@ -428,25 +457,26 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
return ret < 0 ? ret : 0;
}
-
-/* open input file and probe the format if necessary */
-static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options)
+/* Open input file and probe the format if necessary. */
+static int init_input(AVFormatContext *s, const char *filename,
+ AVDictionary **options)
{
int ret;
- AVProbeData pd = {filename, NULL, 0};
+ AVProbeData pd = { filename, NULL, 0 };
int score = AVPROBE_SCORE_RETRY;
if (s->pb) {
s->flags |= AVFMT_FLAG_CUSTOM_IO;
if (!s->iformat)
- return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->probesize);
+ return av_probe_input_buffer2(s->pb, &s->iformat, filename,
+ s, 0, s->probesize);
else if (s->iformat->flags & AVFMT_NOFILE)
av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
"will be ignored with AVFMT_NOFILE format.\n");
return 0;
}
- if ( (s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
+ if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
return score;
@@ -455,11 +485,13 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
return ret;
if (s->iformat)
return 0;
- return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->probesize);
+ return av_probe_input_buffer2(s->pb, &s->iformat, filename,
+ s, 0, s->probesize);
}
static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
- AVPacketList **plast_pktl){
+ AVPacketList **plast_pktl)
+{
AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
if (!pktl)
return NULL;
@@ -469,9 +501,9 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
else
*packet_buffer = pktl;
- /* add the packet in the buffered packet list */
+ /* Add the packet in the buffered packet list. */
*plast_pktl = pktl;
- pktl->pkt= *pkt;
+ pktl->pkt = *pkt;
return &pktl->pkt;
}
@@ -482,16 +514,18 @@ int avformat_queue_attached_pictures(AVFormatContext *s)
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
s->streams[i]->discard < AVDISCARD_ALL) {
AVPacket copy = s->streams[i]->attached_pic;
- copy.buf = av_buffer_ref(copy.buf);
+ copy.buf = av_buffer_ref(copy.buf);
if (!copy.buf)
return AVERROR(ENOMEM);
- add_to_pktbuf(&s->raw_packet_buffer, &copy, &s->raw_packet_buffer_end);
+ add_to_pktbuf(&s->raw_packet_buffer, &copy,
+ &s->raw_packet_buffer_end);
}
return 0;
}
-int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
+int avformat_open_input(AVFormatContext **ps, const char *filename,
+ AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
int ret = 0;
@@ -500,7 +534,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
- if (!s->av_class){
+ if (!s->av_class) {
av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");
return AVERROR(EINVAL);
}
@@ -518,7 +552,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
s->probe_score = ret;
avio_skip(s->pb, s->skip_initial_bytes);
- /* check filename in case an image number is expected */
+ /* Check filename in case an image number is expected. */
if (s->iformat->flags & AVFMT_NEEDNUMBER) {
if (!av_filename_number_test(filename)) {
ret = AVERROR(EINVAL);
@@ -529,14 +563,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
s->duration = s->start_time = AV_NOPTS_VALUE;
av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));
- /* allocate private data */
+ /* Allocate private data. */
if (s->iformat->priv_data_size > 0) {
if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
ret = AVERROR(ENOMEM);
goto fail;
}
if (s->iformat->priv_class) {
- *(const AVClass**)s->priv_data = s->iformat->priv_class;
+ *(const AVClass **) s->priv_data = s->iformat->priv_class;
av_opt_set_defaults(s->priv_data);
if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
goto fail;
@@ -545,7 +579,7 @@ 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, &id3v2_extra_meta);
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0);
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
if ((ret = s->iformat->read_header(s)) < 0)
@@ -554,7 +588,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
if (id3v2_extra_meta) {
if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||
!strcmp(s->iformat->name, "tta")) {
- if((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
+ if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
goto fail;
} else
av_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n");
@@ -590,22 +624,25 @@ fail:
static void force_codec_ids(AVFormatContext *s, AVStream *st)
{
- switch(st->codec->codec_type){
+ switch (st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- if(s->video_codec_id) st->codec->codec_id= s->video_codec_id;
+ if (s->video_codec_id)
+ st->codec->codec_id = s->video_codec_id;
break;
case AVMEDIA_TYPE_AUDIO:
- if(s->audio_codec_id) st->codec->codec_id= s->audio_codec_id;
+ if (s->audio_codec_id)
+ st->codec->codec_id = s->audio_codec_id;
break;
case AVMEDIA_TYPE_SUBTITLE:
- if(s->subtitle_codec_id)st->codec->codec_id= s->subtitle_codec_id;
+ if (s->subtitle_codec_id)
+ st->codec->codec_id = s->subtitle_codec_id;
break;
}
}
static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
{
- if(st->request_probe>0){
+ if (st->request_probe>0) {
AVProbeData *pd = &st->probe_data;
int end;
av_log(s, AV_LOG_DEBUG, "probing stream %d pp:%d\n", st->index, st->probe_packets);
@@ -613,38 +650,38 @@ static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
if (pkt) {
uint8_t *new_buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
- if(!new_buf) {
+ if (!new_buf) {
av_log(s, AV_LOG_WARNING,
"Failed to reallocate probe buffer for stream %d\n",
st->index);
goto no_packet;
}
pd->buf = new_buf;
- memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);
+ memcpy(pd->buf + pd->buf_size, pkt->data, pkt->size);
pd->buf_size += pkt->size;
- memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
+ memset(pd->buf + pd->buf_size, 0, AVPROBE_PADDING_SIZE);
} else {
no_packet:
st->probe_packets = 0;
if (!pd->buf_size) {
- av_log(s, AV_LOG_WARNING, "nothing to probe for stream %d\n",
- st->index);
+ av_log(s, AV_LOG_WARNING,
+ "nothing to probe for stream %d\n", st->index);
}
}
end= s->raw_packet_buffer_remaining_size <= 0
- || st->probe_packets<=0;
+ || st->probe_packets<= 0;
- if(end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){
- int score= set_codec_from_probe_data(s, st, pd);
- if( (st->codec->codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_RETRY)
- || end){
- pd->buf_size=0;
+ if (end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) {
+ int score = set_codec_from_probe_data(s, st, pd);
+ if ( (st->codec->codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_STREAM_RETRY)
+ || end) {
+ pd->buf_size = 0;
av_freep(&pd->buf);
- st->request_probe= -1;
- if(st->codec->codec_id != AV_CODEC_ID_NONE){
+ st->request_probe = -1;
+ if (st->codec->codec_id != AV_CODEC_ID_NONE) {
av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
- }else
+ } else
av_log(s, AV_LOG_WARNING, "probed stream %d failed\n", st->index);
}
force_codec_ids(s, st);
@@ -664,13 +701,13 @@ static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_in
ref = pkt->pts;
if (st->pts_wrap_reference != AV_NOPTS_VALUE || st->pts_wrap_bits >= 63 || ref == AV_NOPTS_VALUE || !s->correct_ts_overflow)
return 0;
- ref &= (1LL<<st->pts_wrap_bits)-1;
+ ref &= (1LL << st->pts_wrap_bits)-1;
// reference time stamp should be 60 s before first time stamp
pts_wrap_reference = ref - av_rescale(60, st->time_base.den, st->time_base.num);
// if first time stamp is not more than 1/8 and 60s before the wrap point, subtract rather than add wrap offset
- pts_wrap_behavior = (ref < (1LL<<st->pts_wrap_bits) - (1LL<<st->pts_wrap_bits-3)) ||
- (ref < (1LL<<st->pts_wrap_bits) - av_rescale(60, st->time_base.den, st->time_base.num)) ?
+ pts_wrap_behavior = (ref < (1LL << st->pts_wrap_bits) - (1LL << st->pts_wrap_bits-3)) ||
+ (ref < (1LL << st->pts_wrap_bits) - av_rescale(60, st->time_base.den, st->time_base.num)) ?
AV_PTS_WRAP_ADD_OFFSET : AV_PTS_WRAP_SUB_OFFSET;
first_program = av_find_program_from_stream(s, NULL, stream_index);
@@ -678,7 +715,7 @@ static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_in
if (!first_program) {
int default_stream_index = av_find_default_stream_index(s);
if (s->streams[default_stream_index]->pts_wrap_reference == AV_NOPTS_VALUE) {
- for (i=0; i<s->nb_streams; i++) {
+ for (i = 0; i < s->nb_streams; i++) {
s->streams[i]->pts_wrap_reference = pts_wrap_reference;
s->streams[i]->pts_wrap_behavior = pts_wrap_behavior;
}
@@ -701,9 +738,9 @@ static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_in
// update every program with differing pts_wrap_reference
program = first_program;
- while(program) {
+ while (program) {
if (program->pts_wrap_reference != pts_wrap_reference) {
- for (i=0; i<program->nb_stream_indexes; i++) {
+ for (i = 0; i<program->nb_stream_indexes; i++) {
s->streams[program->stream_index[i]]->pts_wrap_reference = pts_wrap_reference;
s->streams[program->stream_index[i]]->pts_wrap_behavior = pts_wrap_behavior;
}
@@ -722,18 +759,17 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
int ret, i, err;
AVStream *st;
- for(;;){
+ for (;;) {
AVPacketList *pktl = s->raw_packet_buffer;
if (pktl) {
*pkt = pktl->pkt;
- st = s->streams[pkt->stream_index];
- if (s->raw_packet_buffer_remaining_size <= 0) {
+ st = s->streams[pkt->stream_index];
+ if (s->raw_packet_buffer_remaining_size <= 0)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
- }
- if(st->request_probe <= 0){
- s->raw_packet_buffer = pktl->next;
+ if (st->request_probe <= 0) {
+ s->raw_packet_buffer = pktl->next;
s->raw_packet_buffer_remaining_size += pkt->size;
av_free(pktl);
return 0;
@@ -743,16 +779,15 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->data = NULL;
pkt->size = 0;
av_init_packet(pkt);
- ret= s->iformat->read_packet(s, pkt);
+ ret = s->iformat->read_packet(s, pkt);
if (ret < 0) {
if (!pktl || ret == AVERROR(EAGAIN))
return ret;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
- if (st->probe_packets) {
+ if (st->probe_packets)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
- }
av_assert0(st->request_probe <= 0);
}
continue;
@@ -767,12 +802,12 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
continue;
}
- if(pkt->stream_index >= (unsigned)s->nb_streams){
+ if (pkt->stream_index >= (unsigned)s->nb_streams) {
av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index);
continue;
}
- st= s->streams[pkt->stream_index];
+ st = s->streams[pkt->stream_index];
if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {
// correct first time stamps to negative values
@@ -793,7 +828,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
if (s->use_wallclock_as_timestamps)
pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base);
- if(!pktl && st->request_probe <= 0)
+ if (!pktl && st->request_probe <= 0)
return ret;
add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end);
@@ -845,7 +880,7 @@ int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux)
//For WMA we currently have no other means to calculate duration thus we
//do it here by assuming CBR, which is true for all known cases.
- if(!mux && enc->bit_rate>0 && size>0 && enc->sample_rate>0 && enc->block_align>1) {
+ if (!mux && enc->bit_rate>0 && size>0 && enc->sample_rate>0 && enc->block_align>1) {
if (enc->codec_id == AV_CODEC_ID_WMAV1 || enc->codec_id == AV_CODEC_ID_WMAV2)
return ((int64_t)size * 8 * enc->sample_rate) / enc->bit_rate;
}
@@ -853,7 +888,6 @@ int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux)
return -1;
}
-
/**
* Return the frame duration in seconds. Return 0 if not available.
*/
@@ -864,15 +898,15 @@ void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st,
*pnum = 0;
*pden = 0;
- switch(st->codec->codec_type) {
+ switch (st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (st->r_frame_rate.num && !pc) {
*pnum = st->r_frame_rate.den;
*pden = st->r_frame_rate.num;
- } else if(st->time_base.num*1000LL > st->time_base.den) {
+ } else if (st->time_base.num * 1000LL > st->time_base.den) {
*pnum = st->time_base.num;
*pden = st->time_base.den;
- }else if(st->codec->time_base.num*1000LL > st->codec->time_base.den){
+ } else if (st->codec->time_base.num * 1000LL > st->codec->time_base.den) {
*pnum = st->codec->time_base.num;
*pden = st->codec->time_base.den;
if (pc && pc->repeat_pict) {
@@ -881,11 +915,11 @@ void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st,
else
*pnum *= 1 + pc->repeat_pict;
}
- //If this codec can be interlaced or progressive then we need a parser to compute duration of a packet
- //Thus if we have no parser in such case leave duration undefined.
- if(st->codec->ticks_per_frame>1 && !pc){
+ /* If this codec can be interlaced or progressive then we need
+ * a parser to compute duration of a packet. Thus if we have
+ * no parser in such case leave duration undefined. */
+ if (st->codec->ticks_per_frame > 1 && !pc)
*pnum = *pden = 0;
- }
}
break;
case AVMEDIA_TYPE_AUDIO:
@@ -900,10 +934,10 @@ void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st,
}
}
-static int is_intra_only(AVCodecContext *enc){
+static int is_intra_only(AVCodecContext *enc) {
const AVCodecDescriptor *desc;
- if(enc->codec_type != AVMEDIA_TYPE_VIDEO)
+ if (enc->codec_type != AVMEDIA_TYPE_VIDEO)
return 1;
desc = av_codec_get_codec_descriptor(enc);
@@ -918,17 +952,17 @@ static int is_intra_only(AVCodecContext *enc){
static int has_decode_delay_been_guessed(AVStream *st)
{
- if(st->codec->codec_id != AV_CODEC_ID_H264) return 1;
- if(!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
+ if (st->codec->codec_id != AV_CODEC_ID_H264) return 1;
+ if (!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
return 1;
#if CONFIG_H264_DECODER
- if(st->codec->has_b_frames &&
+ if (st->codec->has_b_frames &&
avpriv_h264_has_num_reorder_frames(st->codec) == st->codec->has_b_frames)
return 1;
#endif
- if(st->codec->has_b_frames<3)
+ if (st->codec->has_b_frames<3)
return st->nb_decoded_frames >= 7;
- else if(st->codec->has_b_frames<4)
+ else if (st->codec->has_b_frames<4)
return st->nb_decoded_frames >= 18;
else
return st->nb_decoded_frames >= 20;
@@ -938,52 +972,97 @@ static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList
{
if (pktl->next)
return pktl->next;
- if (pktl == s->parse_queue_end)
- return s->packet_buffer;
+ if (pktl == s->packet_buffer_end)
+ return s->parse_queue;
return NULL;
}
+static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t dts) {
+ int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&
+ st->codec->codec_id != AV_CODEC_ID_HEVC;
+
+ if(!onein_oneout) {
+ int delay = st->codec->has_b_frames;
+ int i;
+
+ if (dts == AV_NOPTS_VALUE) {
+ int64_t best_score = INT64_MAX;
+ for (i = 0; i<delay; i++) {
+ if (st->pts_reorder_error_count[i]) {
+ int64_t score = st->pts_reorder_error[i] / st->pts_reorder_error_count[i];
+ if (score < best_score) {
+ best_score = score;
+ dts = pts_buffer[i];
+ }
+ }
+ }
+ } else {
+ for (i = 0; i<delay; i++) {
+ if (pts_buffer[i] != AV_NOPTS_VALUE) {
+ int64_t diff = FFABS(pts_buffer[i] - dts)
+ + (uint64_t)st->pts_reorder_error[i];
+ diff = FFMAX(diff, st->pts_reorder_error[i]);
+ st->pts_reorder_error[i] = diff;
+ st->pts_reorder_error_count[i]++;
+ if (st->pts_reorder_error_count[i] > 250) {
+ st->pts_reorder_error[i] >>= 1;
+ st->pts_reorder_error_count[i] >>= 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (dts == AV_NOPTS_VALUE)
+ dts = pts_buffer[0];
+
+ return dts;
+}
+
static void update_initial_timestamps(AVFormatContext *s, int stream_index,
int64_t dts, int64_t pts, AVPacket *pkt)
{
- AVStream *st= s->streams[stream_index];
- AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
+ AVStream *st = s->streams[stream_index];
+ AVPacketList *pktl = s->packet_buffer ? s->packet_buffer : s->parse_queue;
int64_t pts_buffer[MAX_REORDER_DELAY+1];
int64_t shift;
int i, delay;
- if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || is_relative(dts))
+ if (st->first_dts != AV_NOPTS_VALUE ||
+ dts == AV_NOPTS_VALUE ||
+ st->cur_dts == AV_NOPTS_VALUE ||
+ is_relative(dts))
return;
- delay = st->codec->has_b_frames;
- st->first_dts= dts - (st->cur_dts - RELATIVE_TS_BASE);
- st->cur_dts= dts;
- shift = st->first_dts - RELATIVE_TS_BASE;
+ delay = st->codec->has_b_frames;
+ st->first_dts = dts - (st->cur_dts - RELATIVE_TS_BASE);
+ st->cur_dts = dts;
+ shift = st->first_dts - RELATIVE_TS_BASE;
- for (i=0; i<MAX_REORDER_DELAY+1; i++)
+ for (i = 0; i<MAX_REORDER_DELAY+1; i++)
pts_buffer[i] = AV_NOPTS_VALUE;
if (is_relative(pts))
pts += shift;
- for(; pktl; pktl= get_next_pkt(s, st, pktl)){
- if(pktl->pkt.stream_index != stream_index)
+ for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
+ if (pktl->pkt.stream_index != stream_index)
continue;
- if(is_relative(pktl->pkt.pts))
+ if (is_relative(pktl->pkt.pts))
pktl->pkt.pts += shift;
- if(is_relative(pktl->pkt.dts))
+ if (is_relative(pktl->pkt.dts))
pktl->pkt.dts += shift;
- if(st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE)
- st->start_time= pktl->pkt.pts;
+ if (st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE)
+ st->start_time = pktl->pkt.pts;
+
+ if (pktl->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)) {
+ pts_buffer[0] = pktl->pkt.pts;
+ for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
+ FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
- if(pktl->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)){
- pts_buffer[0]= pktl->pkt.pts;
- for(i=0; i<delay && pts_buffer[i] > pts_buffer[i+1]; i++)
- FFSWAP(int64_t, pts_buffer[i], pts_buffer[i+1]);
- if(pktl->pkt.dts == AV_NOPTS_VALUE)
- pktl->pkt.dts= pts_buffer[0];
+ pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
}
}
@@ -994,48 +1073,54 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
static void update_initial_durations(AVFormatContext *s, AVStream *st,
int stream_index, int duration)
{
- AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
- int64_t cur_dts= RELATIVE_TS_BASE;
-
- if(st->first_dts != AV_NOPTS_VALUE){
- cur_dts= st->first_dts;
- for(; pktl; pktl= get_next_pkt(s, st, pktl)){
- if(pktl->pkt.stream_index == stream_index){
- if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration)
+ AVPacketList *pktl = s->packet_buffer ? s->packet_buffer : s->parse_queue;
+ int64_t cur_dts = RELATIVE_TS_BASE;
+
+ if (st->first_dts != AV_NOPTS_VALUE) {
+ if (st->update_initial_durations_done)
+ return;
+ st->update_initial_durations_done = 1;
+ cur_dts = st->first_dts;
+ for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
+ if (pktl->pkt.stream_index == stream_index) {
+ if (pktl->pkt.pts != pktl->pkt.dts ||
+ pktl->pkt.dts != AV_NOPTS_VALUE ||
+ pktl->pkt.duration)
break;
cur_dts -= duration;
}
}
- if(pktl && pktl->pkt.dts != st->first_dts) {
+ if (pktl && pktl->pkt.dts != st->first_dts) {
av_log(s, AV_LOG_DEBUG, "first_dts %s not matching first dts %s (pts %s, duration %d) in the queue\n",
av_ts2str(st->first_dts), av_ts2str(pktl->pkt.dts), av_ts2str(pktl->pkt.pts), pktl->pkt.duration);
return;
}
- if(!pktl) {
+ if (!pktl) {
av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in the queue\n", av_ts2str(st->first_dts));
return;
}
- pktl= s->parse_queue ? s->parse_queue : s->packet_buffer;
+ pktl = s->packet_buffer ? s->packet_buffer : s->parse_queue;
st->first_dts = cur_dts;
- }else if(st->cur_dts != RELATIVE_TS_BASE)
+ } else if (st->cur_dts != RELATIVE_TS_BASE)
return;
- for(; pktl; pktl= get_next_pkt(s, st, pktl)){
- if(pktl->pkt.stream_index != stream_index)
+ for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
+ if (pktl->pkt.stream_index != stream_index)
continue;
- if(pktl->pkt.pts == pktl->pkt.dts && (pktl->pkt.dts == AV_NOPTS_VALUE || pktl->pkt.dts == st->first_dts)
- && !pktl->pkt.duration){
- pktl->pkt.dts= cur_dts;
- if(!st->codec->has_b_frames)
- pktl->pkt.pts= cur_dts;
+ if (pktl->pkt.pts == pktl->pkt.dts &&
+ (pktl->pkt.dts == AV_NOPTS_VALUE || pktl->pkt.dts == st->first_dts) &&
+ !pktl->pkt.duration) {
+ pktl->pkt.dts = cur_dts;
+ if (!st->codec->has_b_frames)
+ pktl->pkt.pts = cur_dts;
// if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
pktl->pkt.duration = duration;
- }else
+ } else
break;
cur_dts = pktl->pkt.dts + pktl->pkt.duration;
}
- if(!pktl)
- st->cur_dts= cur_dts;
+ if (!pktl)
+ st->cur_dts = cur_dts;
}
static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
@@ -1043,12 +1128,37 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
{
int num, den, presentation_delayed, delay, i;
int64_t offset;
+ AVRational duration;
+ int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&
+ st->codec->codec_id != AV_CODEC_ID_HEVC;
if (s->flags & AVFMT_FLAG_NOFILLIN)
return;
- if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
- pkt->dts= AV_NOPTS_VALUE;
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {
+ if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) {
+ if (st->last_dts_for_order_check <= pkt->dts) {
+ st->dts_ordered++;
+ } else {
+ av_log(s, st->dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING,
+ "DTS %"PRIi64" < %"PRIi64" out of order\n",
+ pkt->dts,
+ st->last_dts_for_order_check);
+ st->dts_misordered++;
+ }
+ if (st->dts_ordered + st->dts_misordered > 250) {
+ st->dts_ordered >>= 1;
+ st->dts_misordered >>= 1;
+ }
+ }
+
+ st->last_dts_for_order_check = pkt->dts;
+ if (st->dts_ordered < 8*st->dts_misordered && pkt->dts == pkt->pts)
+ pkt->dts = AV_NOPTS_VALUE;
+ }
+
+ if ((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
+ pkt->dts = AV_NOPTS_VALUE;
if (pc && pc->pict_type == AV_PICTURE_TYPE_B
&& !st->codec->has_b_frames)
@@ -1056,11 +1166,11 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
st->codec->has_b_frames = 1;
/* do we have a video B-frame ? */
- delay= st->codec->has_b_frames;
+ delay = st->codec->has_b_frames;
presentation_delayed = 0;
/* XXX: need has_b_frame, but cannot get it if the codec is
- not initialized */
+ * not initialized */
if (delay &&
pc && pc->pict_type != AV_PICTURE_TYPE_B)
presentation_delayed = 1;
@@ -1068,50 +1178,64 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&
st->pts_wrap_bits < 63 &&
pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) {
- if(is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits-1)) > st->cur_dts) {
- pkt->dts -= 1LL<<st->pts_wrap_bits;
+ if (is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits - 1)) > st->cur_dts) {
+ pkt->dts -= 1LL << st->pts_wrap_bits;
} else
- pkt->pts += 1LL<<st->pts_wrap_bits;
+ pkt->pts += 1LL << st->pts_wrap_bits;
}
- // some mpeg2 in mpeg-ps lack dts (issue171 / input_file.mpg)
- // we take the conservative approach and discard both
- // Note, if this is misbehaving for a H.264 file then possibly presentation_delayed is not set correctly.
- if(delay==1 && pkt->dts == pkt->pts && pkt->dts != AV_NOPTS_VALUE && presentation_delayed){
+ /* Some MPEG-2 in MPEG-PS lack dts (issue #171 / input_file.mpg).
+ * We take the conservative approach and discard both.
+ * Note: If this is misbehaving for an H.264 file, then possibly
+ * presentation_delayed is not set correctly. */
+ if (delay == 1 && pkt->dts == pkt->pts &&
+ pkt->dts != AV_NOPTS_VALUE && presentation_delayed) {
av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts);
- if(strcmp(s->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2")) // otherwise we discard correct timestamps for vc1-wmapro.ism
- pkt->dts= AV_NOPTS_VALUE;
+ if ( strcmp(s->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2")
+ && strcmp(s->iformat->name, "flv")) // otherwise we discard correct timestamps for vc1-wmapro.ism
+ pkt->dts = AV_NOPTS_VALUE;
}
+ duration = av_mul_q((AVRational) {pkt->duration, 1}, st->time_base);
if (pkt->duration == 0) {
ff_compute_frame_duration(&num, &den, st, pc, pkt);
if (den && num) {
- pkt->duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num, AV_ROUND_DOWN);
+ duration = (AVRational) {num, den};
+ pkt->duration = av_rescale_rnd(1,
+ num * (int64_t) st->time_base.den,
+ den * (int64_t) st->time_base.num,
+ AV_ROUND_DOWN);
}
}
- if(pkt->duration != 0 && (s->packet_buffer || s->parse_queue))
+
+ if (pkt->duration != 0 && (s->packet_buffer || s->parse_queue))
update_initial_durations(s, st, pkt->stream_index, pkt->duration);
- /* correct timestamps with byte offset if demuxers only have timestamps
- on packet boundaries */
- if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){
+ /* Correct timestamps with byte offset if demuxers only have timestamps
+ * on packet boundaries */
+ if (pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size) {
/* this will estimate bitrate based on this frame's duration and size */
offset = av_rescale(pc->offset, pkt->duration, pkt->size);
- if(pkt->pts != AV_NOPTS_VALUE)
+ if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts += offset;
- if(pkt->dts != AV_NOPTS_VALUE)
+ if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts += offset;
}
/* This may be redundant, but it should not hurt. */
- if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)
+ if (pkt->dts != AV_NOPTS_VALUE &&
+ pkt->pts != AV_NOPTS_VALUE &&
+ pkt->pts > pkt->dts)
presentation_delayed = 1;
- av_dlog(NULL, "IN delayed:%d pts:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%d\n",
- presentation_delayed, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), pkt->stream_index, pc, pkt->duration);
- /* interpolate PTS and DTS if they are not present */
- //We skip H264 currently because delay and has_b_frames are not reliably set
- if((delay==0 || (delay==1 && pc)) && st->codec->codec_id != AV_CODEC_ID_H264){
+ av_dlog(NULL,
+ "IN delayed:%d pts:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%d\n",
+ presentation_delayed, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts),
+ pkt->stream_index, pc, pkt->duration);
+ /* Interpolate PTS and DTS if they are not present. We skip H264
+ * currently because delay and has_b_frames are not reliably set. */
+ if ((delay == 0 || (delay == 1 && pc)) &&
+ onein_oneout) {
if (presentation_delayed) {
/* DTS = decompression timestamp */
/* PTS = presentation timestamp */
@@ -1121,20 +1245,19 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
if (pkt->dts == AV_NOPTS_VALUE)
pkt->dts = st->cur_dts;
- /* this is tricky: the dts must be incremented by the duration
- of the frame we are displaying, i.e. the last I- or P-frame */
+ /* This is tricky: the dts must be incremented by the duration
+ * of the frame we are displaying, i.e. the last I- or P-frame. */
if (st->last_IP_duration == 0)
st->last_IP_duration = pkt->duration;
- if(pkt->dts != AV_NOPTS_VALUE)
+ if (pkt->dts != AV_NOPTS_VALUE)
st->cur_dts = pkt->dts + st->last_IP_duration;
- st->last_IP_duration = pkt->duration;
- st->last_IP_pts= pkt->pts;
- /* cannot compute PTS if not present (we can compute it only
- by knowing the future */
+ st->last_IP_duration = pkt->duration;
+ st->last_IP_pts = pkt->pts;
+ /* Cannot compute PTS if not present (we can compute it only
+ * by knowing the future. */
} else if (pkt->pts != AV_NOPTS_VALUE ||
pkt->dts != AV_NOPTS_VALUE ||
pkt->duration ) {
- int duration = pkt->duration;
/* presentation is not delayed : PTS and DTS are the same */
if (pkt->pts == AV_NOPTS_VALUE)
@@ -1145,21 +1268,22 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
pkt->pts = st->cur_dts;
pkt->dts = pkt->pts;
if (pkt->pts != AV_NOPTS_VALUE)
- st->cur_dts = pkt->pts + duration;
+ st->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);
}
}
- if(pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)){
- st->pts_buffer[0]= pkt->pts;
- for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++)
- FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
- if(pkt->dts == AV_NOPTS_VALUE)
- pkt->dts= st->pts_buffer[0];
- }
- if(st->codec->codec_id == AV_CODEC_ID_H264){ // we skipped it above so we try here
- update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt); // this should happen on the first packet
+ if (pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)) {
+ st->pts_buffer[0] = pkt->pts;
+ for (i = 0; i<delay && st->pts_buffer[i] > st->pts_buffer[i + 1]; i++)
+ FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]);
+
+ pkt->dts = select_from_pts_buffer(st, st->pts_buffer, pkt->dts);
}
- if(pkt->dts > st->cur_dts)
+ // We skipped it above so we try here.
+ if (!onein_oneout)
+ // This should happen on the first packet
+ update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt);
+ if (pkt->dts > st->cur_dts)
st->cur_dts = pkt->dts;
av_dlog(NULL, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s\n",
@@ -1184,21 +1308,21 @@ static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_en
}
/**
- * Parse a packet, add all split parts to parse_queue
+ * Parse a packet, add all split parts to parse_queue.
*
- * @param pkt packet to parse, NULL when flushing the parser at end of stream
+ * @param pkt Packet to parse, NULL when flushing the parser at end of stream.
*/
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
{
AVPacket out_pkt = { 0 }, flush_pkt = { 0 };
- AVStream *st = s->streams[stream_index];
- uint8_t *data = pkt ? pkt->data : NULL;
- int size = pkt ? pkt->size : 0;
+ AVStream *st = s->streams[stream_index];
+ uint8_t *data = pkt ? pkt->data : NULL;
+ int size = pkt ? pkt->size : 0;
int ret = 0, got_output = 0;
if (!pkt) {
av_init_packet(&flush_pkt);
- pkt = &flush_pkt;
+ pkt = &flush_pkt;
got_output = 1;
} else if (!size && st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) {
// preserve 0-size sync packets
@@ -1209,7 +1333,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
int len;
av_init_packet(&out_pkt);
- len = av_parser_parse2(st->parser, st->codec,
+ len = av_parser_parse2(st->parser, st->codec,
&out_pkt.data, &out_pkt.size, data, size,
pkt->pts, pkt->dts, pkt->pos);
@@ -1227,33 +1351,28 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
if (pkt->side_data) {
out_pkt.side_data = pkt->side_data;
out_pkt.side_data_elems = pkt->side_data_elems;
- pkt->side_data = NULL;
- pkt->side_data_elems = 0;
+ pkt->side_data = NULL;
+ pkt->side_data_elems = 0;
}
/* set the duration */
out_pkt.duration = 0;
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if (st->codec->sample_rate > 0) {
- out_pkt.duration = av_rescale_q_rnd(st->parser->duration,
- (AVRational){ 1, st->codec->sample_rate },
- st->time_base,
- AV_ROUND_DOWN);
+ out_pkt.duration =
+ av_rescale_q_rnd(st->parser->duration,
+ (AVRational) { 1, st->codec->sample_rate },
+ st->time_base,
+ AV_ROUND_DOWN);
}
- } else if (st->codec->time_base.num != 0 &&
- st->codec->time_base.den != 0) {
- out_pkt.duration = av_rescale_q_rnd(st->parser->duration,
- st->codec->time_base,
- st->time_base,
- AV_ROUND_DOWN);
}
out_pkt.stream_index = st->index;
- out_pkt.pts = st->parser->pts;
- out_pkt.dts = st->parser->dts;
- out_pkt.pos = st->parser->pos;
+ out_pkt.pts = st->parser->pts;
+ out_pkt.dts = st->parser->dts;
+ out_pkt.pos = st->parser->pos;
- if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
+ if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
out_pkt.pos = st->parser->frame_offset;
if (st->parser->key_frame == 1 ||
@@ -1261,14 +1380,14 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
st->parser->pict_type == AV_PICTURE_TYPE_I))
out_pkt.flags |= AV_PKT_FLAG_KEY;
- if(st->parser->key_frame == -1 && st->parser->pict_type==AV_PICTURE_TYPE_NONE && (pkt->flags&AV_PKT_FLAG_KEY))
+ if (st->parser->key_frame == -1 && st->parser->pict_type ==AV_PICTURE_TYPE_NONE && (pkt->flags&AV_PKT_FLAG_KEY))
out_pkt.flags |= AV_PKT_FLAG_KEY;
compute_pkt_fields(s, st, st->parser, &out_pkt);
if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) {
- out_pkt.buf = pkt->buf;
- pkt->buf = NULL;
+ out_pkt.buf = pkt->buf;
+ pkt->buf = NULL;
#if FF_API_DESTRUCT_PACKET
FF_DISABLE_DEPRECATION_WARNINGS
out_pkt.destruct = pkt->destruct;
@@ -1286,7 +1405,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
-
/* end of the stream => close and free the parser */
if (pkt == &flush_pkt) {
av_parser_close(st->parser);
@@ -1304,8 +1422,8 @@ static int read_from_packet_buffer(AVPacketList **pkt_buffer,
{
AVPacketList *pktl;
av_assert0(*pkt_buffer);
- pktl = *pkt_buffer;
- *pkt = pktl->pkt;
+ pktl = *pkt_buffer;
+ *pkt = pktl->pkt;
*pkt_buffer = pktl->next;
if (!pktl->next)
*pkt_buffer_end = NULL;
@@ -1329,7 +1447,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
if (ret == AVERROR(EAGAIN))
return ret;
/* flush the parsers */
- for(i = 0; i < s->nb_streams; i++) {
+ for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->parser && st->need_parsing)
parse_packet(s, NULL, st->index);
@@ -1344,20 +1462,20 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
if (cur_pkt.pts != AV_NOPTS_VALUE &&
cur_pkt.dts != AV_NOPTS_VALUE &&
cur_pkt.pts < cur_pkt.dts) {
- av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d\n",
+ av_log(s, AV_LOG_WARNING,
+ "Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d\n",
cur_pkt.stream_index,
av_ts2str(cur_pkt.pts),
av_ts2str(cur_pkt.dts),
cur_pkt.size);
}
if (s->debug & FF_FDEBUG_TS)
- av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
+ av_log(s, AV_LOG_DEBUG,
+ "ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
cur_pkt.stream_index,
av_ts2str(cur_pkt.pts),
av_ts2str(cur_pkt.dts),
- cur_pkt.size,
- cur_pkt.duration,
- cur_pkt.flags);
+ cur_pkt.size, cur_pkt.duration, cur_pkt.flags);
if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
st->parser = av_parser_init(st->codec->codec_id);
@@ -1367,13 +1485,12 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
avcodec_get_name(st->codec->codec_id));
/* no parser available: just output the raw packets */
st->need_parsing = AVSTREAM_PARSE_NONE;
- } else if(st->need_parsing == AVSTREAM_PARSE_HEADERS) {
+ } else if (st->need_parsing == AVSTREAM_PARSE_HEADERS)
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
- } else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE) {
+ else if (st->need_parsing == AVSTREAM_PARSE_FULL_ONCE)
st->parser->flags |= PARSER_FLAG_ONCE;
- } else if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
+ else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
- }
}
if (!st->need_parsing || !st->parser) {
@@ -1383,7 +1500,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
if ((s->iformat->flags & AVFMT_GENERIC_INDEX) &&
(pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) {
ff_reduce_index(s, st->index);
- av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);
+ av_add_index_entry(st, pkt->pos, pkt->dts,
+ 0, 0, AVINDEX_KEYFRAME);
}
got_packet = 1;
} else if (st->discard < AVDISCARD_ALL) {
@@ -1417,19 +1535,38 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
}
st->skip_samples = 0;
}
- }
- if(ret >= 0 && !(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA))
- av_packet_merge_side_data(pkt);
+ if (st->inject_global_side_data) {
+ for (i = 0; i < st->nb_side_data; i++) {
+ AVPacketSideData *src_sd = &st->side_data[i];
+ uint8_t *dst_data;
+
+ if (av_packet_get_side_data(pkt, src_sd->type, NULL))
+ continue;
+
+ dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size);
+ if (!dst_data) {
+ av_log(s, AV_LOG_WARNING, "Could not inject global side data\n");
+ continue;
+ }
+
+ memcpy(dst_data, src_sd->data, src_sd->size);
+ }
+ st->inject_global_side_data = 0;
+ }
- if(s->debug & FF_FDEBUG_TS)
- av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
- pkt->stream_index,
- av_ts2str(pkt->pts),
- av_ts2str(pkt->dts),
- pkt->size,
- pkt->duration,
- pkt->flags);
+ if (!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA))
+ av_packet_merge_side_data(pkt);
+ }
+
+ if (s->debug & FF_FDEBUG_TS)
+ av_log(s, AV_LOG_DEBUG,
+ "read_frame_internal stream=%d, pts=%s, dts=%s, "
+ "size=%d, duration=%d, flags=%d\n",
+ pkt->stream_index,
+ av_ts2str(pkt->pts),
+ av_ts2str(pkt->dts),
+ pkt->size, pkt->duration, pkt->flags);
return ret;
}
@@ -1437,14 +1574,15 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
const int genpts = s->flags & AVFMT_FLAG_GENPTS;
- int eof = 0;
+ int eof = 0;
int ret;
AVStream *st;
if (!genpts) {
- ret = s->packet_buffer ?
- read_from_packet_buffer(&s->packet_buffer, &s->packet_buffer_end, pkt) :
- read_frame_internal(s, pkt);
+ ret = s->packet_buffer
+ ? read_from_packet_buffer(&s->packet_buffer,
+ &s->packet_buffer_end, pkt)
+ : read_frame_internal(s, pkt);
if (ret < 0)
return ret;
goto return_packet;
@@ -1464,7 +1602,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {
if (pktl->pkt.stream_index == next_pkt->stream_index &&
(av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0)) {
- if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame
+ if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) {
+ // not B-frame
next_pkt->pts = pktl->pkt.dts;
}
if (last_dts != AV_NOPTS_VALUE) {
@@ -1504,7 +1643,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
}
if (av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt,
- &s->packet_buffer_end)) < 0)
+ &s->packet_buffer_end)) < 0)
return AVERROR(ENOMEM);
}
@@ -1545,21 +1684,20 @@ int av_find_default_stream_index(AVFormatContext *s)
if (s->nb_streams <= 0)
return -1;
- for(i = 0; i < s->nb_streams; i++) {
+ for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
!(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
return i;
}
- if (first_audio_index < 0 && st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ if (first_audio_index < 0 &&
+ st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
first_audio_index = i;
}
return first_audio_index >= 0 ? first_audio_index : 0;
}
-/**
- * Flush the frame reader.
- */
+/** Flush the frame reader. */
void ff_read_frame_flush(AVFormatContext *s)
{
AVStream *st;
@@ -1567,8 +1705,8 @@ void ff_read_frame_flush(AVFormatContext *s)
flush_packet_queue(s);
- /* for each stream, reset read state */
- for(i = 0; i < s->nb_streams; i++) {
+ /* Reset read state for each stream. */
+ for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->parser) {
@@ -1576,13 +1714,20 @@ void ff_read_frame_flush(AVFormatContext *s)
st->parser = NULL;
}
st->last_IP_pts = AV_NOPTS_VALUE;
- if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = RELATIVE_TS_BASE;
- else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */
+ st->last_dts_for_order_check = AV_NOPTS_VALUE;
+ if (st->first_dts == AV_NOPTS_VALUE)
+ st->cur_dts = RELATIVE_TS_BASE;
+ else
+ /* We set the current DTS to an unspecified origin. */
+ st->cur_dts = AV_NOPTS_VALUE;
st->probe_packets = MAX_PROBE_PACKETS;
- for(j=0; j<MAX_REORDER_DELAY+1; j++)
- st->pts_buffer[j]= AV_NOPTS_VALUE;
+ for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
+ st->pts_buffer[j] = AV_NOPTS_VALUE;
+
+ if (s->internal->inject_global_side_data)
+ st->inject_global_side_data = 1;
}
}
@@ -1590,40 +1735,42 @@ void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
{
int i;
- for(i = 0; i < s->nb_streams; i++) {
+ for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- st->cur_dts = av_rescale(timestamp,
- st->time_base.den * (int64_t)ref_st->time_base.num,
- st->time_base.num * (int64_t)ref_st->time_base.den);
+ st->cur_dts =
+ av_rescale(timestamp,
+ st->time_base.den * (int64_t) ref_st->time_base.num,
+ st->time_base.num * (int64_t) ref_st->time_base.den);
}
}
void ff_reduce_index(AVFormatContext *s, int stream_index)
{
- AVStream *st= s->streams[stream_index];
- unsigned int max_entries= s->max_index_size / sizeof(AVIndexEntry);
+ AVStream *st = s->streams[stream_index];
+ unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
- if((unsigned)st->nb_index_entries >= max_entries){
+ if ((unsigned) st->nb_index_entries >= max_entries) {
int i;
- for(i=0; 2*i<st->nb_index_entries; i++)
- st->index_entries[i]= st->index_entries[2*i];
- st->nb_index_entries= i;
+ for (i = 0; 2 * i < st->nb_index_entries; i++)
+ st->index_entries[i] = st->index_entries[2 * i];
+ st->nb_index_entries = i;
}
}
int ff_add_index_entry(AVIndexEntry **index_entries,
int *nb_index_entries,
unsigned int *index_entries_allocated_size,
- int64_t pos, int64_t timestamp, int size, int distance, int flags)
+ int64_t pos, int64_t timestamp,
+ int size, int distance, int flags)
{
AVIndexEntry *entries, *ie;
int index;
- if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
+ if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
return -1;
- if(timestamp == AV_NOPTS_VALUE)
+ if (timestamp == AV_NOPTS_VALUE)
return AVERROR(EINVAL);
if (size < 0 || size > 0x3FFFFFFF)
@@ -1636,39 +1783,42 @@ int ff_add_index_entry(AVIndexEntry **index_entries,
index_entries_allocated_size,
(*nb_index_entries + 1) *
sizeof(AVIndexEntry));
- if(!entries)
+ if (!entries)
return -1;
- *index_entries= entries;
+ *index_entries = entries;
- index= ff_index_search_timestamp(*index_entries, *nb_index_entries, timestamp, AVSEEK_FLAG_ANY);
+ index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
+ timestamp, AVSEEK_FLAG_ANY);
- if(index<0){
- index= (*nb_index_entries)++;
- ie= &entries[index];
- av_assert0(index==0 || ie[-1].timestamp < timestamp);
- }else{
- ie= &entries[index];
- if(ie->timestamp != timestamp){
- if(ie->timestamp <= timestamp)
+ if (index < 0) {
+ index = (*nb_index_entries)++;
+ ie = &entries[index];
+ av_assert0(index == 0 || ie[-1].timestamp < timestamp);
+ } else {
+ ie = &entries[index];
+ if (ie->timestamp != timestamp) {
+ if (ie->timestamp <= timestamp)
return -1;
- memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(*nb_index_entries - index));
+ memmove(entries + index + 1, entries + index,
+ sizeof(AVIndexEntry) * (*nb_index_entries - index));
(*nb_index_entries)++;
- }else if(ie->pos == pos && distance < ie->min_distance) //do not reduce the distance
- distance= ie->min_distance;
+ } else if (ie->pos == pos && distance < ie->min_distance)
+ // do not reduce the distance
+ distance = ie->min_distance;
}
- ie->pos = pos;
- ie->timestamp = timestamp;
- ie->min_distance= distance;
- ie->size= size;
- ie->flags = flags;
+ ie->pos = pos;
+ ie->timestamp = timestamp;
+ ie->min_distance = distance;
+ ie->size = size;
+ ie->flags = flags;
return index;
}
-int av_add_index_entry(AVStream *st,
- int64_t pos, int64_t timestamp, int size, int distance, int flags)
+int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
+ int size, int distance, int flags)
{
timestamp = wrap_timestamp(st, timestamp);
return ff_add_index_entry(&st->index_entries, &st->nb_index_entries,
@@ -1682,36 +1832,34 @@ int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries,
int a, b, m;
int64_t timestamp;
- a = - 1;
+ a = -1;
b = nb_entries;
- //optimize appending index entries at the end
- if(b && entries[b-1].timestamp < wanted_timestamp)
- a= b-1;
+ // Optimize appending index entries at the end.
+ if (b && entries[b - 1].timestamp < wanted_timestamp)
+ a = b - 1;
while (b - a > 1) {
- m = (a + b) >> 1;
+ m = (a + b) >> 1;
timestamp = entries[m].timestamp;
- if(timestamp >= wanted_timestamp)
+ if (timestamp >= wanted_timestamp)
b = m;
- if(timestamp <= wanted_timestamp)
+ if (timestamp <= wanted_timestamp)
a = m;
}
- m= (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
+ m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
- if(!(flags & AVSEEK_FLAG_ANY)){
- while(m>=0 && m<nb_entries && !(entries[m].flags & AVINDEX_KEYFRAME)){
+ if (!(flags & AVSEEK_FLAG_ANY))
+ while (m >= 0 && m < nb_entries &&
+ !(entries[m].flags & AVINDEX_KEYFRAME))
m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
- }
- }
- if(m == nb_entries)
+ if (m == nb_entries)
return -1;
- return m;
+ return m;
}
-int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp,
- int flags)
+int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
{
return ff_index_search_timestamp(st->index_entries, st->nb_index_entries,
wanted_timestamp, flags);
@@ -1726,9 +1874,10 @@ static int64_t ff_read_timestamp(AVFormatContext *s, int stream_index, int64_t *
return ts;
}
-int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
+int ff_seek_frame_binary(AVFormatContext *s, int stream_index,
+ int64_t target_ts, int flags)
{
- AVInputFormat *avif= s->iformat;
+ AVInputFormat *avif = s->iformat;
int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit;
int64_t ts_min, ts_max, ts;
int index;
@@ -1740,42 +1889,47 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
av_dlog(s, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
- ts_max=
- ts_min= AV_NOPTS_VALUE;
- pos_limit= -1; //gcc falsely says it may be uninitialized
+ ts_max =
+ ts_min = AV_NOPTS_VALUE;
+ pos_limit = -1; // GCC falsely says it may be uninitialized.
- st= s->streams[stream_index];
- if(st->index_entries){
+ st = s->streams[stream_index];
+ if (st->index_entries) {
AVIndexEntry *e;
- index= av_index_search_timestamp(st, target_ts, flags | AVSEEK_FLAG_BACKWARD); //FIXME whole func must be checked for non-keyframe entries in index case, especially read_timestamp()
- index= FFMAX(index, 0);
- e= &st->index_entries[index];
+ /* FIXME: Whole function must be checked for non-keyframe entries in
+ * index case, especially read_timestamp(). */
+ index = av_index_search_timestamp(st, target_ts,
+ flags | AVSEEK_FLAG_BACKWARD);
+ index = FFMAX(index, 0);
+ e = &st->index_entries[index];
- if(e->timestamp <= target_ts || e->pos == e->min_distance){
- pos_min= e->pos;
- ts_min= e->timestamp;
+ if (e->timestamp <= target_ts || e->pos == e->min_distance) {
+ pos_min = e->pos;
+ ts_min = e->timestamp;
av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
pos_min, av_ts2str(ts_min));
- }else{
- av_assert1(index==0);
+ } else {
+ av_assert1(index == 0);
}
- index= av_index_search_timestamp(st, target_ts, flags & ~AVSEEK_FLAG_BACKWARD);
+ index = av_index_search_timestamp(st, target_ts,
+ flags & ~AVSEEK_FLAG_BACKWARD);
av_assert0(index < st->nb_index_entries);
- if(index >= 0){
- e= &st->index_entries[index];
+ if (index >= 0) {
+ e = &st->index_entries[index];
av_assert1(e->timestamp >= target_ts);
- pos_max= e->pos;
- ts_max= e->timestamp;
- pos_limit= pos_max - e->min_distance;
- av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%s\n",
- pos_max, pos_limit, av_ts2str(ts_max));
+ pos_max = e->pos;
+ ts_max = e->timestamp;
+ pos_limit = pos_max - e->min_distance;
+ av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
+ " dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
}
}
- pos= ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp);
- if(pos<0)
+ pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
+ ts_min, ts_max, flags, &ts, avif->read_timestamp);
+ if (pos < 0)
return -1;
/* do the seek */
@@ -1791,28 +1945,30 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos,
int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
{
- int64_t step= 1024;
+ int64_t step = 1024;
int64_t limit, ts_max;
int64_t filesize = avio_size(s->pb);
- int64_t pos_max = filesize - 1;
- do{
+ int64_t pos_max = filesize - 1;
+ do {
limit = pos_max;
pos_max = FFMAX(0, (pos_max) - step);
- ts_max = ff_read_timestamp(s, stream_index, &pos_max, limit, read_timestamp);
- step += step;
- }while(ts_max == AV_NOPTS_VALUE && 2*limit > step);
+ ts_max = ff_read_timestamp(s, stream_index,
+ &pos_max, limit, read_timestamp);
+ step += step;
+ } while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
if (ts_max == AV_NOPTS_VALUE)
return -1;
- for(;;){
+ for (;;) {
int64_t tmp_pos = pos_max + 1;
- int64_t tmp_ts = ff_read_timestamp(s, stream_index, &tmp_pos, INT64_MAX, read_timestamp);
- if(tmp_ts == AV_NOPTS_VALUE)
+ int64_t tmp_ts = ff_read_timestamp(s, stream_index,
+ &tmp_pos, INT64_MAX, read_timestamp);
+ if (tmp_ts == AV_NOPTS_VALUE)
break;
av_assert0(tmp_pos > pos_max);
ts_max = tmp_ts;
pos_max = tmp_pos;
- if(tmp_pos >= filesize)
+ if (tmp_pos >= filesize)
break;
}
@@ -1826,8 +1982,10 @@ int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *
int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
int64_t pos_min, int64_t pos_max, int64_t pos_limit,
- int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret,
- int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
+ int64_t ts_min, int64_t ts_max,
+ int flags, int64_t *ts_ret,
+ int64_t (*read_timestamp)(struct AVFormatContext *, int,
+ int64_t *, int64_t))
{
int64_t pos, ts;
int64_t start_pos;
@@ -1836,107 +1994,114 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
av_dlog(s, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
- if(ts_min == AV_NOPTS_VALUE){
+ if (ts_min == AV_NOPTS_VALUE) {
pos_min = s->data_offset;
- ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
+ ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
if (ts_min == AV_NOPTS_VALUE)
return -1;
}
- if(ts_min >= target_ts){
- *ts_ret= ts_min;
+ if (ts_min >= target_ts) {
+ *ts_ret = ts_min;
return pos_min;
}
- if(ts_max == AV_NOPTS_VALUE){
+ if (ts_max == AV_NOPTS_VALUE) {
if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp)) < 0)
return ret;
- pos_limit= pos_max;
+ pos_limit = pos_max;
}
- if(ts_max <= target_ts){
- *ts_ret= ts_max;
+ if (ts_max <= target_ts) {
+ *ts_ret = ts_max;
return pos_max;
}
- if(ts_min > ts_max){
+ if (ts_min > ts_max)
return -1;
- }else if(ts_min == ts_max){
- pos_limit= pos_min;
- }
+ else if (ts_min == ts_max)
+ pos_limit = pos_min;
- no_change=0;
+ no_change = 0;
while (pos_min < pos_limit) {
- av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
+ av_dlog(s,
+ "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
assert(pos_limit <= pos_max);
- if(no_change==0){
- int64_t approximate_keyframe_distance= pos_max - pos_limit;
+ if (no_change == 0) {
+ int64_t approximate_keyframe_distance = pos_max - pos_limit;
// interpolate position (better than dichotomy)
- pos = av_rescale(target_ts - ts_min, pos_max - pos_min, ts_max - ts_min)
- + pos_min - approximate_keyframe_distance;
- }else if(no_change==1){
- // bisection, if interpolation failed to change min or max pos last time
- pos = (pos_min + pos_limit)>>1;
- }else{
+ pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
+ ts_max - ts_min) +
+ pos_min - approximate_keyframe_distance;
+ } else if (no_change == 1) {
+ // bisection if interpolation did not change min / max pos last time
+ pos = (pos_min + pos_limit) >> 1;
+ } else {
/* linear search if bisection failed, can only happen if there
- are very few or no keyframes between min/max */
- pos=pos_min;
+ * are very few or no keyframes between min/max */
+ pos = pos_min;
}
- if(pos <= pos_min)
- pos= pos_min + 1;
- else if(pos > pos_limit)
- pos= pos_limit;
- start_pos= pos;
-
- ts = ff_read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp); //may pass pos_limit instead of -1
- if(pos == pos_max)
+ if (pos <= pos_min)
+ pos = pos_min + 1;
+ else if (pos > pos_limit)
+ pos = pos_limit;
+ start_pos = pos;
+
+ // May pass pos_limit instead of -1.
+ ts = ff_read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp);
+ if (pos == pos_max)
no_change++;
else
- no_change=0;
- av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
+ no_change = 0;
+ av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s"
+ " target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
pos_min, pos, pos_max,
av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
pos_limit, start_pos, no_change);
- if(ts == AV_NOPTS_VALUE){
+ if (ts == AV_NOPTS_VALUE) {
av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
return -1;
}
assert(ts != AV_NOPTS_VALUE);
if (target_ts <= ts) {
pos_limit = start_pos - 1;
- pos_max = pos;
- ts_max = ts;
+ pos_max = pos;
+ ts_max = ts;
}
if (target_ts >= ts) {
pos_min = pos;
- ts_min = ts;
+ ts_min = ts;
}
}
- pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
- ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
+ pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
+ ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
#if 0
pos_min = pos;
- ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
+ ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
pos_min++;
ts_max = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
av_dlog(s, "pos=0x%"PRIx64" %s<=%s<=%s\n",
pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
#endif
- *ts_ret= ts;
+ *ts_ret = ts;
return pos;
}
-static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
+static int seek_frame_byte(AVFormatContext *s, int stream_index,
+ int64_t pos, int flags)
+{
int64_t pos_min, pos_max;
pos_min = s->data_offset;
pos_max = avio_size(s->pb) - 1;
- if (pos < pos_min) pos= pos_min;
- else if(pos > pos_max) pos= pos_max;
+ if (pos < pos_min)
+ pos = pos_min;
+ else if (pos > pos_max)
+ pos = pos_max;
avio_seek(s->pb, pos, SEEK_SET);
@@ -1945,8 +2110,8 @@ static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, in
return 0;
}
-static int seek_frame_generic(AVFormatContext *s,
- int stream_index, int64_t timestamp, int flags)
+static int seek_frame_generic(AVFormatContext *s, int stream_index,
+ int64_t timestamp, int flags)
{
int index;
int64_t ret;
@@ -1957,35 +2122,36 @@ static int seek_frame_generic(AVFormatContext *s,
index = av_index_search_timestamp(st, timestamp, flags);
- if(index < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
+ if (index < 0 && st->nb_index_entries &&
+ timestamp < st->index_entries[0].timestamp)
return -1;
- if(index < 0 || index==st->nb_index_entries-1){
+ if (index < 0 || index == st->nb_index_entries - 1) {
AVPacket pkt;
- int nonkey=0;
+ int nonkey = 0;
- if(st->nb_index_entries){
+ if (st->nb_index_entries) {
av_assert0(st->index_entries);
- ie= &st->index_entries[st->nb_index_entries-1];
+ ie = &st->index_entries[st->nb_index_entries - 1];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
ff_update_cur_dts(s, st, ie->timestamp);
- }else{
+ } else {
if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0)
return ret;
}
for (;;) {
int read_status;
- do{
+ do {
read_status = av_read_frame(s, &pkt);
} while (read_status == AVERROR(EAGAIN));
if (read_status < 0)
break;
av_free_packet(&pkt);
- if(stream_index == pkt.stream_index && pkt.dts > timestamp){
- if(pkt.flags & AV_PKT_FLAG_KEY)
+ if (stream_index == pkt.stream_index && pkt.dts > timestamp) {
+ if (pkt.flags & AV_PKT_FLAG_KEY)
break;
- if(nonkey++ > 1000 && st->codec->codec_id != AV_CODEC_ID_CDGRAPHICS){
+ if (nonkey++ > 1000 && st->codec->codec_id != AV_CODEC_ID_CDGRAPHICS) {
av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey);
break;
}
@@ -1997,10 +2163,9 @@ static int seek_frame_generic(AVFormatContext *s,
return -1;
ff_read_frame_flush(s);
- if (s->iformat->read_seek){
- if(s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
+ if (s->iformat->read_seek)
+ if (s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
return 0;
- }
ie = &st->index_entries[index];
if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
@@ -2022,14 +2187,15 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index,
return seek_frame_byte(s, stream_index, timestamp, flags);
}
- if(stream_index < 0){
- stream_index= av_find_default_stream_index(s);
- if(stream_index < 0)
+ if (stream_index < 0) {
+ stream_index = av_find_default_stream_index(s);
+ if (stream_index < 0)
return -1;
- st= s->streams[stream_index];
+ st = s->streams[stream_index];
/* timestamp for default must be expressed in AV_TIME_BASE units */
- timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
+ timestamp = av_rescale(timestamp, st->time_base.den,
+ AV_TIME_BASE * (int64_t) st->time_base.num);
}
/* first, we try the format specific seek */
@@ -2038,22 +2204,22 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index,
ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
} else
ret = -1;
- if (ret >= 0) {
+ if (ret >= 0)
return 0;
- }
- if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
+ if (s->iformat->read_timestamp &&
+ !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
ff_read_frame_flush(s);
return ff_seek_frame_binary(s, stream_index, timestamp, flags);
} else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
ff_read_frame_flush(s);
return seek_frame_generic(s, stream_index, timestamp, flags);
- }
- else
+ } else
return -1;
}
-int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+int av_seek_frame(AVFormatContext *s, int stream_index,
+ int64_t timestamp, int flags)
{
int ret;
@@ -2075,14 +2241,15 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f
return ret;
}
-int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
+int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
+ int64_t ts, int64_t max_ts, int flags)
{
- if(min_ts > ts || max_ts < ts)
+ if (min_ts > ts || max_ts < ts)
return -1;
if (stream_index < -1 || stream_index >= (int)s->nb_streams)
return AVERROR(EINVAL);
- if(s->seek2any>0)
+ if (s->seek2any>0)
flags |= AVSEEK_FLAG_ANY;
flags &= ~AVSEEK_FLAG_BACKWARD;
@@ -2101,15 +2268,16 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int
AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
}
- ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
+ ret = s->iformat->read_seek2(s, stream_index, min_ts,
+ ts, max_ts, flags);
if (ret >= 0)
ret = avformat_queue_attached_pictures(s);
return ret;
}
- if(s->iformat->read_timestamp){
- //try to seek via read_timestamp()
+ if (s->iformat->read_timestamp) {
+ // try to seek via read_timestamp()
}
// Fall back on old API if new is not implemented but old is.
@@ -2141,7 +2309,7 @@ static int has_duration(AVFormatContext *ic)
int i;
AVStream *st;
- for(i = 0;i < ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->duration != AV_NOPTS_VALUE)
return 1;
@@ -2166,47 +2334,50 @@ static void update_stream_timings(AVFormatContext *ic)
start_time = INT64_MAX;
start_time_text = INT64_MAX;
- end_time = INT64_MIN;
- duration = INT64_MIN;
- for(i = 0;i < ic->nb_streams; i++) {
+ end_time = INT64_MIN;
+ duration = INT64_MIN;
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
- start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
+ start_time1 = av_rescale_q(st->start_time, st->time_base,
+ AV_TIME_BASE_Q);
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA) {
if (start_time1 < start_time_text)
start_time_text = start_time1;
} else
start_time = FFMIN(start_time, start_time1);
- end_time1 = AV_NOPTS_VALUE;
+ end_time1 = AV_NOPTS_VALUE;
if (st->duration != AV_NOPTS_VALUE) {
- end_time1 = start_time1
- + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
+ end_time1 = start_time1 +
+ av_rescale_q(st->duration, st->time_base,
+ AV_TIME_BASE_Q);
end_time = FFMAX(end_time, end_time1);
}
- for(p = NULL; (p = av_find_program_from_stream(ic, p, i)); ){
- if(p->start_time == AV_NOPTS_VALUE || p->start_time > start_time1)
+ for (p = NULL; (p = av_find_program_from_stream(ic, p, i)); ) {
+ if (p->start_time == AV_NOPTS_VALUE || p->start_time > start_time1)
p->start_time = start_time1;
- if(p->end_time < end_time1)
+ if (p->end_time < end_time1)
p->end_time = end_time1;
}
}
if (st->duration != AV_NOPTS_VALUE) {
- duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
- duration = FFMAX(duration, duration1);
+ duration1 = av_rescale_q(st->duration, st->time_base,
+ AV_TIME_BASE_Q);
+ duration = FFMAX(duration, duration1);
}
}
if (start_time == INT64_MAX || (start_time > start_time_text && start_time - start_time_text < AV_TIME_BASE))
start_time = start_time_text;
- else if(start_time > start_time_text)
+ else if (start_time > start_time_text)
av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE);
if (start_time != INT64_MAX) {
ic->start_time = start_time;
if (end_time != INT64_MIN) {
if (ic->nb_programs) {
- for (i=0; i<ic->nb_programs; i++) {
+ for (i = 0; i < ic->nb_programs; i++) {
p = ic->programs[i];
- if(p->start_time != AV_NOPTS_VALUE && p->end_time > p->start_time)
+ if (p->start_time != AV_NOPTS_VALUE && p->end_time > p->start_time)
duration = FFMAX(duration, p->end_time - p->start_time);
}
} else
@@ -2216,13 +2387,13 @@ static void update_stream_timings(AVFormatContext *ic)
if (duration != INT64_MIN && duration > 0 && ic->duration == AV_NOPTS_VALUE) {
ic->duration = duration;
}
- if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) {
- /* compute the bitrate */
- double bitrate = (double)filesize * 8.0 * AV_TIME_BASE /
- (double)ic->duration;
- if (bitrate >= 0 && bitrate <= INT_MAX)
- ic->bit_rate = bitrate;
- }
+ if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) {
+ /* compute the bitrate */
+ double bitrate = (double) filesize * 8.0 * AV_TIME_BASE /
+ (double) ic->duration;
+ if (bitrate >= 0 && bitrate <= INT_MAX)
+ ic->bit_rate = bitrate;
+ }
}
static void fill_all_stream_timings(AVFormatContext *ic)
@@ -2231,13 +2402,15 @@ static void fill_all_stream_timings(AVFormatContext *ic)
AVStream *st;
update_stream_timings(ic);
- for(i = 0;i < ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time == AV_NOPTS_VALUE) {
- if(ic->start_time != AV_NOPTS_VALUE)
- st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q, st->time_base);
- if(ic->duration != AV_NOPTS_VALUE)
- st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q, st->time_base);
+ if (ic->start_time != AV_NOPTS_VALUE)
+ st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q,
+ st->time_base);
+ if (ic->duration != AV_NOPTS_VALUE)
+ st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q,
+ st->time_base);
}
}
}
@@ -2251,7 +2424,7 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
/* if bit_rate is already set, we believe it */
if (ic->bit_rate <= 0) {
int bit_rate = 0;
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->codec->bit_rate > 0) {
if (INT_MAX - st->codec->bit_rate < bit_rate) {
@@ -2269,11 +2442,13 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
ic->bit_rate != 0) {
filesize = ic->pb ? avio_size(ic->pb) : 0;
if (filesize > 0) {
- for(i = 0; i < ic->nb_streams; i++) {
- st = ic->streams[i];
+ for (i = 0; i < ic->nb_streams; i++) {
+ st = ic->streams[i];
if ( st->time_base.num <= INT64_MAX / ic->bit_rate
&& st->duration == AV_NOPTS_VALUE) {
- duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num);
+ duration = av_rescale(8 * filesize, st->time_base.den,
+ ic->bit_rate *
+ (int64_t) st->time_base.num);
st->duration = duration;
show_warning = 1;
}
@@ -2281,7 +2456,8 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
}
}
if (show_warning)
- av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n");
+ av_log(ic, AV_LOG_WARNING,
+ "Estimating duration from bitrate, this may be inaccurate\n");
}
#define DURATION_MAX_READ_SIZE 250000LL
@@ -2295,19 +2471,22 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
int read_size, i, ret;
int64_t end_time;
int64_t filesize, offset, duration;
- int retry=0;
+ int retry = 0;
/* flush packet queue */
flush_packet_queue(ic);
- for (i=0; i<ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (st->start_time == AV_NOPTS_VALUE && st->first_dts == AV_NOPTS_VALUE)
- av_log(st->codec, AV_LOG_WARNING, "start time is not set in estimate_timings_from_pts\n");
+ if (st->start_time == AV_NOPTS_VALUE &&
+ st->first_dts == AV_NOPTS_VALUE &&
+ st->codec->codec_type != AVMEDIA_TYPE_UNKNOWN)
+ av_log(st->codec, AV_LOG_WARNING,
+ "start time for stream %d is not set in estimate_timings_from_pts\n", i);
if (st->parser) {
av_parser_close(st->parser);
- st->parser= NULL;
+ st->parser = NULL;
}
}
@@ -2315,24 +2494,24 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
/* XXX: may need to support wrapping */
filesize = ic->pb ? avio_size(ic->pb) : 0;
end_time = AV_NOPTS_VALUE;
- do{
- offset = filesize - (DURATION_MAX_READ_SIZE<<retry);
+ do {
+ offset = filesize - (DURATION_MAX_READ_SIZE << retry);
if (offset < 0)
offset = 0;
avio_seek(ic->pb, offset, SEEK_SET);
read_size = 0;
- for(;;) {
- if (read_size >= DURATION_MAX_READ_SIZE<<(FFMAX(retry-1,0)))
+ for (;;) {
+ if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0)))
break;
do {
ret = ff_read_packet(ic, pkt);
- } while(ret == AVERROR(EAGAIN));
+ } while (ret == AVERROR(EAGAIN));
if (ret != 0)
break;
read_size += pkt->size;
- st = ic->streams[pkt->stream_index];
+ st = ic->streams[pkt->stream_index];
if (pkt->pts != AV_NOPTS_VALUE &&
(st->start_time != AV_NOPTS_VALUE ||
st->first_dts != AV_NOPTS_VALUE)) {
@@ -2342,7 +2521,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
else
duration -= st->first_dts;
if (duration > 0) {
- if (st->duration == AV_NOPTS_VALUE || st->info->last_duration<=0 ||
+ if (st->duration == AV_NOPTS_VALUE || st->info->last_duration<= 0 ||
(st->duration < duration && FFABS(duration - st->info->last_duration) < 60LL*st->time_base.den / st->time_base.num))
st->duration = duration;
st->info->last_duration = duration;
@@ -2350,17 +2529,22 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
}
av_free_packet(pkt);
}
- }while( end_time==AV_NOPTS_VALUE
- && filesize > (DURATION_MAX_READ_SIZE<<retry)
- && ++retry <= DURATION_MAX_RETRY);
+ } while (end_time == AV_NOPTS_VALUE &&
+ filesize > (DURATION_MAX_READ_SIZE << retry) &&
+ ++retry <= DURATION_MAX_RETRY);
fill_all_stream_timings(ic);
avio_seek(ic->pb, old_offset, SEEK_SET);
- for (i=0; i<ic->nb_streams; i++) {
- st= ic->streams[i];
- st->cur_dts= st->first_dts;
+ for (i = 0; i < ic->nb_streams; i++) {
+ int j;
+
+ st = ic->streams[i];
+ st->cur_dts = st->first_dts;
st->last_IP_pts = AV_NOPTS_VALUE;
+ st->last_dts_for_order_check = AV_NOPTS_VALUE;
+ for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
+ st->pts_buffer[j] = AV_NOPTS_VALUE;
}
}
@@ -2384,7 +2568,7 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
} else if (has_duration(ic)) {
/* at least one component has timings - we use them for all
- the components */
+ * the components */
fill_all_stream_timings(ic);
ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
} else {
@@ -2397,13 +2581,14 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
{
int i;
AVStream av_unused *st;
- for(i = 0;i < ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
av_dlog(ic, "%d: start_time: %0.3f duration: %0.3f\n", i,
(double) st->start_time / AV_TIME_BASE,
(double) st->duration / AV_TIME_BASE);
}
- av_dlog(ic, "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
+ av_dlog(ic,
+ "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
(double) ic->start_time / AV_TIME_BASE,
(double) ic->duration / AV_TIME_BASE,
ic->bit_rate / 1000);
@@ -2424,7 +2609,8 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
case AVMEDIA_TYPE_AUDIO:
if (!avctx->frame_size && determinable_frame_size(avctx))
FAIL("unspecified frame size");
- if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
+ if (st->info->found_decoder >= 0 &&
+ avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
FAIL("unspecified sample format");
if (!avctx->sample_rate)
FAIL("unspecified sample rate");
@@ -2447,7 +2633,7 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
FAIL("unspecified size");
break;
case AVMEDIA_TYPE_DATA:
- if(avctx->codec_id == AV_CODEC_ID_NONE) return 1;
+ if (avctx->codec_id == AV_CODEC_ID_NONE) return 1;
}
if (avctx->codec_id == AV_CODEC_ID_NONE)
@@ -2456,7 +2642,8 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
}
/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
-static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, AVDictionary **options)
+static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
+ AVDictionary **options)
{
const AVCodec *codec;
int got_picture = 1, ret = 0;
@@ -2467,25 +2654,27 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, A
if (!frame)
return AVERROR(ENOMEM);
- if (!avcodec_is_open(st->codec) && !st->info->found_decoder) {
+ if (!avcodec_is_open(st->codec) &&
+ st->info->found_decoder <= 0 &&
+ (st->codec->codec_id != -st->info->found_decoder || !st->codec->codec_id)) {
AVDictionary *thread_opt = NULL;
codec = find_decoder(s, st, st->codec->codec_id);
if (!codec) {
- st->info->found_decoder = -1;
- ret = -1;
+ st->info->found_decoder = -st->codec->codec_id;
+ ret = -1;
goto fail;
}
- /* force thread count to 1 since the h264 decoder will not extract SPS
- * and PPS to extradata during multi-threaded decoding */
+ /* Force thread count to 1 since the H.264 decoder will not extract
+ * SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
if (!options)
av_dict_free(&thread_opt);
if (ret < 0) {
- st->info->found_decoder = -1;
+ st->info->found_decoder = -st->codec->codec_id;
goto fail;
}
st->info->found_decoder = 1;
@@ -2499,12 +2688,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, A
while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
ret >= 0 &&
- (!has_codec_parameters(st, NULL) ||
- !has_decode_delay_been_guessed(st) ||
- (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
+ (!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||
+ (!st->codec_info_nb_frames &&
+ st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
got_picture = 0;
- avcodec_get_frame_defaults(frame);
- switch(st->codec->codec_type) {
+ switch (st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_decode_video2(st->codec, frame,
&got_picture, &pkt);
@@ -2529,11 +2717,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, A
}
}
- if(!pkt.data && !got_picture)
+ if (!pkt.data && !got_picture)
ret = -1;
fail:
- avcodec_free_frame(&frame);
+ av_frame_free(&frame);
return ret;
}
@@ -2550,14 +2738,12 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
{
int i;
- for(i=0; tags[i].id != AV_CODEC_ID_NONE;i++) {
- if(tag == tags[i].tag)
+ for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
+ if (tag == tags[i].tag)
return tags[i].id;
- }
- for(i=0; tags[i].id != AV_CODEC_ID_NONE; i++) {
+ for (i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag))
return tags[i].id;
- }
return AV_CODEC_ID_NONE;
}
@@ -2565,34 +2751,47 @@ enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
{
if (flt) {
switch (bps) {
- case 32: return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
- case 64: return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
- default: return AV_CODEC_ID_NONE;
+ case 32:
+ return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
+ case 64:
+ return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
+ default:
+ return AV_CODEC_ID_NONE;
}
} else {
bps += 7;
bps >>= 3;
if (sflags & (1 << (bps - 1))) {
switch (bps) {
- case 1: return AV_CODEC_ID_PCM_S8;
- case 2: return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
- case 3: return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
- case 4: return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
- default: return AV_CODEC_ID_NONE;
+ case 1:
+ return AV_CODEC_ID_PCM_S8;
+ case 2:
+ return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
+ case 3:
+ return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
+ case 4:
+ return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
+ default:
+ return AV_CODEC_ID_NONE;
}
} else {
switch (bps) {
- case 1: return AV_CODEC_ID_PCM_U8;
- case 2: return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
- case 3: return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
- case 4: return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
- default: return AV_CODEC_ID_NONE;
+ case 1:
+ return AV_CODEC_ID_PCM_U8;
+ case 2:
+ return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
+ case 3:
+ return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
+ case 4:
+ return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
+ default:
+ return AV_CODEC_ID_NONE;
}
}
}
}
-unsigned int av_codec_get_tag(const AVCodecTag * const *tags, enum AVCodecID id)
+unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id)
{
unsigned int tag;
if (!av_codec_get_tag2(tags, id, &tag))
@@ -2604,7 +2803,7 @@ int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id,
unsigned int *tag)
{
int i;
- for(i=0; tags && tags[i]; i++){
+ for (i = 0; tags && tags[i]; i++) {
const AVCodecTag *codec_tags = tags[i];
while (codec_tags->id != AV_CODEC_ID_NONE) {
if (codec_tags->id == id) {
@@ -2617,12 +2816,13 @@ int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id,
return 0;
}
-enum AVCodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag)
+enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag)
{
int i;
- for(i=0; tags && tags[i]; i++){
- enum AVCodecID id= ff_codec_get_id(tags[i], tag);
- if(id!=AV_CODEC_ID_NONE) return id;
+ for (i = 0; tags && tags[i]; i++) {
+ enum AVCodecID id = ff_codec_get_id(tags[i], tag);
+ if (id != AV_CODEC_ID_NONE)
+ return id;
}
return AV_CODEC_ID_NONE;
}
@@ -2630,17 +2830,20 @@ enum AVCodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag)
static void compute_chapters_end(AVFormatContext *s)
{
unsigned int i, j;
- int64_t max_time = s->duration + ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time);
+ int64_t max_time = s->duration +
+ ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time);
for (i = 0; i < s->nb_chapters; i++)
if (s->chapters[i]->end == AV_NOPTS_VALUE) {
AVChapter *ch = s->chapters[i];
- int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, ch->time_base)
- : INT64_MAX;
+ int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q,
+ ch->time_base)
+ : INT64_MAX;
for (j = 0; j < s->nb_chapters; j++) {
- AVChapter *ch1 = s->chapters[j];
- int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, ch->time_base);
+ AVChapter *ch1 = s->chapters[j];
+ int64_t next_start = av_rescale_q(ch1->start, ch1->time_base,
+ ch->time_base);
if (j != i && next_start > ch->start && next_start < end)
end = next_start;
}
@@ -2648,28 +2851,30 @@ static void compute_chapters_end(AVFormatContext *s)
}
}
-static int get_std_framerate(int i){
- if(i<60*12) return (i+1)*1001;
- else return ((const int[]){24,30,60,12,15,48})[i-60*12]*1000*12;
+static int get_std_framerate(int i)
+{
+ if (i < 60 * 12)
+ return (i + 1) * 1001;
+ else
+ return ((const int[]) { 24, 30, 60, 12, 15, 48 })[i - 60 * 12] * 1000 * 12;
}
-/*
- * Is the time base unreliable.
+/* Is the time base unreliable?
* This is a heuristic to balance between quick acceptance of the values in
* the headers vs. some extra checks.
* Old DivX and Xvid often have nonsense timebases like 1fps or 2fps.
* MPEG-2 commonly misuses field repeat flags to store different framerates.
- * And there are "variable" fps files this needs to detect as well.
- */
-static int tb_unreliable(AVCodecContext *c){
- if( c->time_base.den >= 101L*c->time_base.num
- || c->time_base.den < 5L*c->time_base.num
-/* || c->codec_tag == AV_RL32("DIVX")
- || c->codec_tag == AV_RL32("XVID")*/
- || c->codec_tag == AV_RL32("mp4v")
- || c->codec_id == AV_CODEC_ID_MPEG2VIDEO
- || c->codec_id == AV_CODEC_ID_H264
- )
+ * And there are "variable" fps files this needs to detect as well. */
+static int tb_unreliable(AVCodecContext *c)
+{
+ if (c->time_base.den >= 101L * c->time_base.num ||
+ c->time_base.den < 5L * c->time_base.num ||
+ // c->codec_tag == AV_RL32("DIVX") ||
+ // c->codec_tag == AV_RL32("XVID") ||
+ c->codec_tag == AV_RL32("mp4v") ||
+ c->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
+ c->codec_id == AV_CODEC_ID_GIF ||
+ c->codec_id == AV_CODEC_ID_H264)
return 1;
return 0;
}
@@ -2701,29 +2906,45 @@ int ff_alloc_extradata(AVCodecContext *avctx, int size)
return ret;
}
+int ff_get_extradata(AVCodecContext *avctx, AVIOContext *pb, int size)
+{
+ int ret = ff_alloc_extradata(avctx, size);
+ if (ret < 0)
+ return ret;
+ ret = avio_read(pb, avctx->extradata, size);
+ if (ret != size) {
+ av_freep(&avctx->extradata);
+ avctx->extradata_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size);
+ return ret < 0 ? ret : AVERROR_INVALIDDATA;
+ }
+
+ return ret;
+}
+
int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts)
{
int i, j;
int64_t last = st->info->last_dts;
- if( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
- && ts - (uint64_t)last < INT64_MAX){
- double dts= (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base);
- int64_t duration= ts - last;
+ if ( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
+ && ts - (uint64_t)last < INT64_MAX) {
+ double dts = (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base);
+ int64_t duration = ts - last;
if (!st->info->duration_error)
st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
if (!st->info->duration_error)
return AVERROR(ENOMEM);
-// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+// if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
- for (i=0; i<MAX_STD_TIMEBASES; i++) {
+ for (i = 0; i<MAX_STD_TIMEBASES; i++) {
if (st->info->duration_error[0][1][i] < 1e10) {
- int framerate= get_std_framerate(i);
- double sdts= dts*framerate/(1001*12);
- for(j=0; j<2; j++){
- int64_t ticks= llrint(sdts+j*0.5);
+ int framerate = get_std_framerate(i);
+ double sdts = dts*framerate/(1001*12);
+ for (j= 0; j<2; j++) {
+ int64_t ticks = llrint(sdts+j*0.5);
double error= sdts - ticks + j*0.5;
st->info->duration_error[j][0][i] += error;
st->info->duration_error[j][1][i] += error*error;
@@ -2731,10 +2952,11 @@ int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts)
}
}
st->info->duration_count++;
+ st->info->rfps_duration_sum += duration;
if (st->info->duration_count % 10 == 0) {
int n = st->info->duration_count;
- for (i=0; i<MAX_STD_TIMEBASES; i++) {
+ for (i = 0; i<MAX_STD_TIMEBASES; i++) {
if (st->info->duration_error[0][1][i] < 1e10) {
double a0 = st->info->duration_error[0][0][i] / n;
double error0 = st->info->duration_error[0][1][i] / n - a0*a0;
@@ -2762,7 +2984,7 @@ void ff_rfps_calculate(AVFormatContext *ic)
{
int i, j;
- for (i = 0; i<ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
@@ -2776,35 +2998,50 @@ void ff_rfps_calculate(AVFormatContext *ic)
&& tb_unreliable(st->codec)) {
int num = 0;
double best_error= 0.01;
+ AVRational ref_rate = st->r_frame_rate.num ? st->r_frame_rate : av_inv_q(st->time_base);
- for (j=0; j<MAX_STD_TIMEBASES; j++) {
+ for (j= 0; j<MAX_STD_TIMEBASES; j++) {
int k;
- if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
+ if (st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
continue;
- if(!st->info->codec_info_duration && 1.0 < (1001*12.0)/get_std_framerate(j))
+ if (!st->info->codec_info_duration && 1.0 < (1001*12.0)/get_std_framerate(j))
+ continue;
+
+ if (av_q2d(st->time_base) * st->info->rfps_duration_sum / st->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j))
continue;
- for(k=0; k<2; k++){
- int n= st->info->duration_count;
+
+ for (k= 0; k<2; k++) {
+ int n = st->info->duration_count;
double a= st->info->duration_error[k][0][j] / n;
double error= st->info->duration_error[k][1][j]/n - a*a;
- if(error < best_error && best_error> 0.000000001){
+ if (error < best_error && best_error> 0.000000001) {
best_error= error;
num = get_std_framerate(j);
}
- if(error < 0.02)
+ if (error < 0.02)
av_log(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
}
}
// do not increase frame rate by more than 1 % in order to match a standard rate.
- if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
+ if (num && (!ref_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(ref_rate)))
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
}
+ if ( !st->avg_frame_rate.num
+ && st->r_frame_rate.num && st->info->rfps_duration_sum
+ && st->info->codec_info_duration <= 0
+ && st->info->duration_count > 2
+ && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->info->rfps_duration_sum / (double)st->info->duration_count) <= 1.0
+ ) {
+ av_log(ic, AV_LOG_DEBUG, "Setting avg frame rate based on r frame rate\n");
+ st->avg_frame_rate = st->r_frame_rate;
+ }
av_freep(&st->info->duration_error);
st->info->last_dts = AV_NOPTS_VALUE;
st->info->duration_count = 0;
+ st->info->rfps_duration_sum = 0;
}
}
@@ -2814,33 +3051,34 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int64_t read_size;
AVStream *st;
AVPacket pkt1, *pkt;
- int64_t old_offset = avio_tell(ic->pb);
- int orig_nb_streams = ic->nb_streams; // new streams might appear, no options for those
- int flush_codecs = ic->probesize > 0;
+ int64_t old_offset = avio_tell(ic->pb);
+ // new streams might appear, no options for those
+ int orig_nb_streams = ic->nb_streams;
+ int flush_codecs = ic->probesize > 0;
- if(ic->pb)
+ if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d\n",
avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count);
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
const AVCodec *codec;
AVDictionary *thread_opt = NULL;
st = ic->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-/* if(!st->time_base.num)
- st->time_base= */
- if(!st->codec->time_base.num)
- st->codec->time_base= st->time_base;
+/* if (!st->time_base.num)
+ st->time_base = */
+ if (!st->codec->time_base.num)
+ st->codec->time_base = st->time_base;
}
- //only for the split stuff
+ // only for the split stuff
if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) {
st->parser = av_parser_init(st->codec->codec_id);
- if(st->parser){
- if(st->need_parsing == AVSTREAM_PARSE_HEADERS){
+ if (st->parser) {
+ if (st->need_parsing == AVSTREAM_PARSE_HEADERS) {
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
- } else if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
+ } else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
}
} else if (st->need_parsing) {
@@ -2851,27 +3089,30 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
}
codec = find_decoder(ic, st, st->codec->codec_id);
- /* force thread count to 1 since the h264 decoder will not extract SPS
- * and PPS to extradata during multi-threaded decoding */
+ /* Force thread count to 1 since the H.264 decoder will not extract
+ * SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);
/* Ensure that subtitle_header is properly set. */
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
- && codec && !st->codec->codec)
- avcodec_open2(st->codec, codec, options ? &options[i]
- : &thread_opt);
+ && codec && !st->codec->codec) {
+ if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+ av_log(ic, AV_LOG_WARNING,
+ "Failed to open codec in av_find_stream_info\n");
+ }
- //try to just open decoders, in case this is enough to get parameters
+ // Try to just open decoders, in case this is enough to get parameters.
if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
if (codec && !st->codec->codec)
- avcodec_open2(st->codec, codec, options ? &options[i]
- : &thread_opt);
+ if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+ av_log(ic, AV_LOG_WARNING,
+ "Failed to open codec in av_find_stream_info\n");
}
if (!options)
av_dict_free(&thread_opt);
}
- for (i=0; i<ic->nb_streams; i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
#if FF_API_R_FRAME_RATE
ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
#endif
@@ -2879,37 +3120,40 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE;
}
- count = 0;
+ count = 0;
read_size = 0;
- for(;;) {
- if (ff_check_interrupt(&ic->interrupt_callback)){
- ret= AVERROR_EXIT;
+ for (;;) {
+ if (ff_check_interrupt(&ic->interrupt_callback)) {
+ ret = AVERROR_EXIT;
av_log(ic, AV_LOG_DEBUG, "interrupted\n");
break;
}
/* check if one codec still needs to be handled */
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
int fps_analyze_framecount = 20;
st = ic->streams[i];
if (!has_codec_parameters(st, NULL))
break;
- /* if the timebase is coarse (like the usual millisecond precision
- of mkv), we need to analyze more frames to reliably arrive at
- the correct fps */
+ /* If the timebase is coarse (like the usual millisecond precision
+ * of mkv), we need to analyze more frames to reliably arrive at
+ * the correct fps. */
if (av_q2d(st->time_base) > 0.0005)
fps_analyze_framecount *= 2;
+ if (!tb_unreliable(st->codec))
+ fps_analyze_framecount = 0;
if (ic->fps_probe_size >= 0)
fps_analyze_framecount = ic->fps_probe_size;
if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
fps_analyze_framecount = 0;
/* variable fps and no guess at the real fps */
- if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num)
- && st->info->duration_count < fps_analyze_framecount
- && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
+ st->info->duration_count < fps_analyze_framecount &&
+ st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
break;
- if(st->parser && st->parser->parser->split && !st->codec->extradata)
+ if (st->parser && st->parser->parser->split &&
+ !st->codec->extradata)
break;
if (st->first_dts == AV_NOPTS_VALUE &&
(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
@@ -2917,24 +3161,25 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
break;
}
if (i == ic->nb_streams) {
- /* NOTE: if the format has no header, then we need to read
- some packets to get most of the streams, so we cannot
- stop here */
+ /* NOTE: If the format has no header, then we need to read some
+ * packets to get most of the streams, so we cannot stop here. */
if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
- /* if we found the info for all the codecs, we can stop */
+ /* If we found the info for all the codecs, we can stop. */
ret = count;
av_log(ic, AV_LOG_DEBUG, "All info found\n");
flush_codecs = 0;
break;
}
}
- /* we did not get all the codec info, but we read too much data */
+ /* We did not get all the codec info, but we read too much data. */
if (read_size >= ic->probesize) {
ret = count;
- av_log(ic, AV_LOG_DEBUG, "Probe buffer size limit of %d bytes reached\n", ic->probesize);
+ av_log(ic, AV_LOG_DEBUG,
+ "Probe buffer size limit of %d bytes reached\n", ic->probesize);
for (i = 0; i < ic->nb_streams; i++)
if (!ic->streams[i]->r_frame_rate.num &&
ic->streams[i]->info->duration_count <= 1 &&
+ ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
strcmp(ic->iformat->name, "image2"))
av_log(ic, AV_LOG_WARNING,
"Stream #%d: not enough frames to estimate rate; "
@@ -2942,8 +3187,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
break;
}
- /* NOTE: a new stream can be added there if no header in file
- (AVFMTCTX_NOHEADER) */
+ /* NOTE: A new stream can be added there if no header in file
+ * (AVFMTCTX_NOHEADER). */
ret = read_frame_internal(ic, &pkt1);
if (ret == AVERROR(EAGAIN))
continue;
@@ -2974,24 +3219,31 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
/* check for non-increasing dts */
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
st->info->fps_last_dts >= pkt->dts) {
- av_log(ic, AV_LOG_DEBUG, "Non-increasing DTS in stream %d: "
- "packet %d with DTS %"PRId64", packet %d with DTS "
- "%"PRId64"\n", st->index, st->info->fps_last_dts_idx,
- st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts);
- st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE;
+ av_log(ic, AV_LOG_DEBUG,
+ "Non-increasing DTS in stream %d: packet %d with DTS "
+ "%"PRId64", packet %d with DTS %"PRId64"\n",
+ st->index, st->info->fps_last_dts_idx,
+ st->info->fps_last_dts, st->codec_info_nb_frames,
+ pkt->dts);
+ st->info->fps_first_dts =
+ st->info->fps_last_dts = AV_NOPTS_VALUE;
}
- /* check for a discontinuity in dts - if the difference in dts
- * is more than 1000 times the average packet duration in the sequence,
- * we treat it as a discontinuity */
+ /* Check for a discontinuity in dts. If the difference in dts
+ * is more than 1000 times the average packet duration in the
+ * sequence, we treat it as a discontinuity. */
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
st->info->fps_last_dts_idx > st->info->fps_first_dts_idx &&
(pkt->dts - st->info->fps_last_dts) / 1000 >
- (st->info->fps_last_dts - st->info->fps_first_dts) / (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {
- av_log(ic, AV_LOG_WARNING, "DTS discontinuity in stream %d: "
- "packet %d with DTS %"PRId64", packet %d with DTS "
- "%"PRId64"\n", st->index, st->info->fps_last_dts_idx,
- st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts);
- st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE;
+ (st->info->fps_last_dts - st->info->fps_first_dts) /
+ (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {
+ av_log(ic, AV_LOG_WARNING,
+ "DTS discontinuity in stream %d: packet %d with DTS "
+ "%"PRId64", packet %d with DTS %"PRId64"\n",
+ st->index, st->info->fps_last_dts_idx,
+ st->info->fps_last_dts, st->codec_info_nb_frames,
+ pkt->dts);
+ st->info->fps_first_dts =
+ st->info->fps_last_dts = AV_NOPTS_VALUE;
}
/* update stored dts values */
@@ -2999,53 +3251,57 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
st->info->fps_first_dts = pkt->dts;
st->info->fps_first_dts_idx = st->codec_info_nb_frames;
}
- st->info->fps_last_dts = pkt->dts;
+ st->info->fps_last_dts = pkt->dts;
st->info->fps_last_dts_idx = st->codec_info_nb_frames;
}
if (st->codec_info_nb_frames>1) {
- int64_t t=0;
+ int64_t t = 0;
if (st->time_base.den > 0)
t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);
if (st->avg_frame_rate.num > 0)
t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q));
- if ( t==0
+ if ( t == 0
&& st->codec_info_nb_frames>30
&& st->info->fps_first_dts != AV_NOPTS_VALUE
&& st->info->fps_last_dts != AV_NOPTS_VALUE)
t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
if (t >= ic->max_analyze_duration) {
- av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t);
+ av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n",
+ ic->max_analyze_duration,
+ t);
break;
}
if (pkt->duration) {
st->info->codec_info_duration += pkt->duration;
- st->info->codec_info_duration_fields += st->parser && st->need_parsing && st->codec->ticks_per_frame==2 ? st->parser->repeat_pict + 1 : 2;
+ st->info->codec_info_duration_fields += st->parser && st->need_parsing && st->codec->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
}
}
#if FF_API_R_FRAME_RATE
ff_rfps_add_frame(ic, st, pkt->dts);
#endif
- if(st->parser && st->parser->parser->split && !st->codec->extradata){
- int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
+ if (st->parser && st->parser->parser->split && !st->codec->extradata) {
+ int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);
if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) {
if (ff_alloc_extradata(st->codec, i))
return AVERROR(ENOMEM);
- memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
+ memcpy(st->codec->extradata, pkt->data,
+ st->codec->extradata_size);
}
}
- /* if still no information, we try to open the codec and to
- decompress the frame. We try to avoid that in most cases as
- it takes longer and uses more memory. For MPEG-4, we need to
- decompress for QuickTime.
-
- If CODEC_CAP_CHANNEL_CONF is set this will force decoding of at
- least one frame of codec data, this makes sure the codec initializes
- the channel configuration and does not only trust the values from the container.
- */
- try_decode_frame(ic, st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);
+ /* If still no information, we try to open the codec and to
+ * decompress the frame. We try to avoid that in most cases as
+ * it takes longer and uses more memory. For MPEG-4, we need to
+ * decompress for QuickTime.
+ *
+ * If CODEC_CAP_CHANNEL_CONF is set this will force decoding of at
+ * least one frame of codec data, this makes sure the codec initializes
+ * the channel configuration and does not only trust the values from
+ * the container. */
+ try_decode_frame(ic, st, pkt,
+ (options && i < orig_nb_streams) ? &options[i] : NULL);
st->codec_info_nb_frames++;
count++;
@@ -3056,7 +3312,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int err = 0;
av_init_packet(&empty_pkt);
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
@@ -3064,8 +3320,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
if (st->info->found_decoder == 1) {
do {
err = try_decode_frame(ic, st, &empty_pkt,
- (options && i < orig_nb_streams) ?
- &options[i] : NULL);
+ (options && i < orig_nb_streams)
+ ? &options[i] : NULL);
} while (err > 0 && !has_codec_parameters(st, NULL));
if (err < 0) {
@@ -3077,25 +3333,27 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
}
// close codecs which were opened in try_decode_frame()
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
avcodec_close(st->codec);
}
ff_rfps_calculate(ic);
- for(i=0;i<ic->nb_streams;i++) {
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if(st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample){
+ if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) {
uint32_t tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
if (avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, tag) == st->codec->pix_fmt)
st->codec->codec_tag= tag;
}
/* estimate average framerate if not set by demuxer */
- if (st->info->codec_info_duration_fields && !st->avg_frame_rate.num && st->info->codec_info_duration) {
- int best_fps = 0;
+ if (st->info->codec_info_duration_fields &&
+ !st->avg_frame_rate.num &&
+ st->info->codec_info_duration) {
+ int best_fps = 0;
double best_error = 0.01;
if (st->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2||
@@ -3103,61 +3361,68 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
st->info->codec_info_duration < 0)
continue;
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
- st->info->codec_info_duration_fields*(int64_t)st->time_base.den,
- st->info->codec_info_duration*2*(int64_t)st->time_base.num, 60000);
+ st->info->codec_info_duration_fields * (int64_t) st->time_base.den,
+ st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);
- /* round guessed framerate to a "standard" framerate if it's
- * within 1% of the original estimate*/
- for (j = 1; j < MAX_STD_TIMEBASES; j++) {
- AVRational std_fps = { get_std_framerate(j), 12*1001 };
- double error = fabs(av_q2d(st->avg_frame_rate) / av_q2d(std_fps) - 1);
+ /* Round guessed framerate to a "standard" framerate if it's
+ * within 1% of the original estimate. */
+ for (j = 0; j < MAX_STD_TIMEBASES; j++) {
+ AVRational std_fps = { get_std_framerate(j), 12 * 1001 };
+ double error = fabs(av_q2d(st->avg_frame_rate) /
+ av_q2d(std_fps) - 1);
if (error < best_error) {
best_error = error;
best_fps = std_fps.num;
}
}
- if (best_fps) {
+ if (best_fps)
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
- best_fps, 12*1001, INT_MAX);
- }
+ best_fps, 12 * 1001, INT_MAX);
}
- if (!st->r_frame_rate.num){
- if( st->codec->time_base.den * (int64_t)st->time_base.num
- <= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t)st->time_base.den){
+ if (!st->r_frame_rate.num) {
+ if ( st->codec->time_base.den * (int64_t) st->time_base.num
+ <= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t) st->time_base.den) {
st->r_frame_rate.num = st->codec->time_base.den;
st->r_frame_rate.den = st->codec->time_base.num * st->codec->ticks_per_frame;
- }else{
+ } else {
st->r_frame_rate.num = st->time_base.den;
st->r_frame_rate.den = st->time_base.num;
}
}
- }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- if(!st->codec->bits_per_coded_sample)
- st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id);
+ } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (!st->codec->bits_per_coded_sample)
+ st->codec->bits_per_coded_sample =
+ av_get_bits_per_sample(st->codec->codec_id);
// set stream disposition based on audio service type
switch (st->codec->audio_service_type) {
case AV_AUDIO_SERVICE_TYPE_EFFECTS:
- st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; break;
+ st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;
+ break;
case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:
- st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED; break;
+ st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED;
+ break;
case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:
- st->disposition = AV_DISPOSITION_HEARING_IMPAIRED; break;
+ st->disposition = AV_DISPOSITION_HEARING_IMPAIRED;
+ break;
case AV_AUDIO_SERVICE_TYPE_COMMENTARY:
- st->disposition = AV_DISPOSITION_COMMENT; break;
+ st->disposition = AV_DISPOSITION_COMMENT;
+ break;
case AV_AUDIO_SERVICE_TYPE_KARAOKE:
- st->disposition = AV_DISPOSITION_KARAOKE; break;
+ st->disposition = AV_DISPOSITION_KARAOKE;
+ break;
}
}
}
- if(ic->probesize)
+ if (ic->probesize)
estimate_timings(ic, old_offset);
if (ret >= 0 && ic->nb_streams)
- ret = -1; /* we could not have all the codec parameters before EOF */
- for(i=0;i<ic->nb_streams;i++) {
+ /* We could not have all the codec parameters before EOF. */
+ ret = -1;
+ for (i = 0; i < ic->nb_streams; i++) {
const char *errmsg;
st = ic->streams[i];
if (!has_codec_parameters(st, &errmsg)) {
@@ -3174,16 +3439,16 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
compute_chapters_end(ic);
- find_stream_info_err:
- for (i=0; i < ic->nb_streams; i++) {
+find_stream_info_err:
+ for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (ic->streams[i]->codec && ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+ if (ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
ic->streams[i]->codec->thread_count = 0;
if (st->info)
av_freep(&st->info->duration_error);
av_freep(&ic->streams[i]->info);
}
- if(ic->pb)
+ if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count);
return ret;
@@ -3206,34 +3471,35 @@ AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int
return NULL;
}
-int av_find_best_stream(AVFormatContext *ic,
- enum AVMediaType type,
- int wanted_stream_nb,
- int related_stream,
- AVCodec **decoder_ret,
- int flags)
+int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
+ int wanted_stream_nb, int related_stream,
+ AVCodec **decoder_ret, int flags)
{
int i, nb_streams = ic->nb_streams;
int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1, best_bitrate = -1, best_multiframe = -1, count, bitrate, multiframe;
unsigned *program = NULL;
- AVCodec *decoder = NULL, *best_decoder = NULL;
+ const AVCodec *decoder = NULL, *best_decoder = NULL;
if (related_stream >= 0 && wanted_stream_nb < 0) {
AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream);
if (p) {
- program = p->stream_index;
+ program = p->stream_index;
nb_streams = p->nb_stream_indexes;
}
}
for (i = 0; i < nb_streams; i++) {
int real_stream_index = program ? program[i] : i;
- AVStream *st = ic->streams[real_stream_index];
+ AVStream *st = ic->streams[real_stream_index];
AVCodecContext *avctx = st->codec;
if (avctx->codec_type != type)
continue;
if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
continue;
- if (st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED|AV_DISPOSITION_VISUAL_IMPAIRED))
+ if (wanted_stream_nb != real_stream_index &&
+ st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED |
+ AV_DISPOSITION_VISUAL_IMPAIRED))
+ continue;
+ if (type == AVMEDIA_TYPE_AUDIO && !avctx->channels)
continue;
if (decoder_ret) {
decoder = find_decoder(ic, st, st->codec->codec_id);
@@ -3250,19 +3516,20 @@ int av_find_best_stream(AVFormatContext *ic,
(best_multiframe == multiframe && best_bitrate > bitrate) ||
(best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count))
continue;
- best_count = count;
+ best_count = count;
best_bitrate = bitrate;
best_multiframe = multiframe;
- ret = real_stream_index;
+ ret = real_stream_index;
best_decoder = decoder;
if (program && i == nb_streams - 1 && ret < 0) {
- program = NULL;
+ program = NULL;
nb_streams = ic->nb_streams;
- i = 0; /* no related stream found, try again with everything */
+ /* no related stream found, try again with everything */
+ i = 0;
}
}
if (decoder_ret)
- *decoder_ret = best_decoder;
+ *decoder_ret = (AVCodec*)best_decoder;
return ret;
}
@@ -3286,9 +3553,15 @@ int av_read_pause(AVFormatContext *s)
return AVERROR(ENOSYS);
}
-void ff_free_stream(AVFormatContext *s, AVStream *st){
+void ff_free_stream(AVFormatContext *s, AVStream *st) {
+ int j;
av_assert0(s->nb_streams>0);
- av_assert0(s->streams[ s->nb_streams-1 ] == st);
+ av_assert0(s->streams[ s->nb_streams - 1 ] == st);
+
+ for (j = 0; j < st->nb_side_data; j++)
+ av_freep(&st->side_data[j].data);
+ av_freep(&st->side_data);
+ st->nb_side_data = 0;
if (st->parser) {
av_parser_close(st->parser);
@@ -3318,24 +3591,27 @@ void avformat_free_context(AVFormatContext *s)
av_opt_free(s);
if (s->iformat && s->iformat->priv_class && s->priv_data)
av_opt_free(s->priv_data);
+ if (s->oformat && s->oformat->priv_class && s->priv_data)
+ av_opt_free(s->priv_data);
- for(i=s->nb_streams-1; i>=0; i--) {
+ for (i = s->nb_streams - 1; i >= 0; i--) {
ff_free_stream(s, s->streams[i]);
}
- for(i=s->nb_programs-1; i>=0; i--) {
+ for (i = s->nb_programs - 1; i >= 0; i--) {
av_dict_free(&s->programs[i]->metadata);
av_freep(&s->programs[i]->stream_index);
av_freep(&s->programs[i]);
}
av_freep(&s->programs);
av_freep(&s->priv_data);
- while(s->nb_chapters--) {
+ while (s->nb_chapters--) {
av_dict_free(&s->chapters[s->nb_chapters]->metadata);
av_freep(&s->chapters[s->nb_chapters]);
}
av_freep(&s->chapters);
av_dict_free(&s->metadata);
av_freep(&s->streams);
+ av_freep(&s->internal);
av_free(s);
}
@@ -3354,7 +3630,7 @@ void avformat_close_input(AVFormatContext **ps)
if (!ps || !*ps)
return;
- s = *ps;
+ s = *ps;
pb = s->pb;
if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
@@ -3363,10 +3639,9 @@ void avformat_close_input(AVFormatContext **ps)
flush_packet_queue(s);
- if (s->iformat) {
+ if (s->iformat)
if (s->iformat->read_close)
s->iformat->read_close(s);
- }
avformat_free_context(s);
@@ -3408,19 +3683,18 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
st->info->last_dts = AV_NOPTS_VALUE;
st->codec = avcodec_alloc_context3(c);
- if (s->iformat) {
+ if (s->iformat)
/* no default bitrate if decoding */
st->codec->bit_rate = 0;
- }
- st->index = s->nb_streams;
+ st->index = s->nb_streams;
st->start_time = AV_NOPTS_VALUE;
- st->duration = AV_NOPTS_VALUE;
- /* we set the current DTS to 0 so that formats without any timestamps
- but durations get some timestamps, formats with some unknown
- timestamps have their first few packets buffered and the
- timestamps corrected before they are returned to the user */
- st->cur_dts = s->iformat ? RELATIVE_TS_BASE : 0;
- st->first_dts = AV_NOPTS_VALUE;
+ st->duration = AV_NOPTS_VALUE;
+ /* we set the current DTS to 0 so that formats without any timestamps
+ * but durations get some timestamps, formats with some unknown
+ * timestamps have their first few packets buffered and the
+ * timestamps corrected before they are returned to the user */
+ st->cur_dts = s->iformat ? RELATIVE_TS_BASE : 0;
+ st->first_dts = AV_NOPTS_VALUE;
st->probe_packets = MAX_PROBE_PACKETS;
st->pts_wrap_reference = AV_NOPTS_VALUE;
st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;
@@ -3428,10 +3702,11 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
/* default pts setting is MPEG-like */
avpriv_set_pts_info(st, 33, 1, 90000);
st->last_IP_pts = AV_NOPTS_VALUE;
- for(i=0; i<MAX_REORDER_DELAY+1; i++)
- st->pts_buffer[i]= AV_NOPTS_VALUE;
+ st->last_dts_for_order_check = AV_NOPTS_VALUE;
+ for (i = 0; i < MAX_REORDER_DELAY + 1; i++)
+ st->pts_buffer[i] = AV_NOPTS_VALUE;
- st->sample_aspect_ratio = (AVRational){0,1};
+ st->sample_aspect_ratio = (AVRational) { 0, 1 };
#if FF_API_R_FRAME_RATE
st->info->last_dts = AV_NOPTS_VALUE;
@@ -3439,22 +3714,24 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
st->info->fps_first_dts = AV_NOPTS_VALUE;
st->info->fps_last_dts = AV_NOPTS_VALUE;
+ st->inject_global_side_data = s->internal->inject_global_side_data;
+
s->streams[s->nb_streams++] = st;
return st;
}
AVProgram *av_new_program(AVFormatContext *ac, int id)
{
- AVProgram *program=NULL;
+ AVProgram *program = NULL;
int i;
av_dlog(ac, "new_program: id=0x%04x\n", id);
- for(i=0; i<ac->nb_programs; i++)
- if(ac->programs[i]->id == id)
+ for (i = 0; i < ac->nb_programs; i++)
+ if (ac->programs[i]->id == id)
program = ac->programs[i];
- if(!program){
+ if (!program) {
program = av_mallocz(sizeof(AVProgram));
if (!program)
return NULL;
@@ -3471,34 +3748,35 @@ AVProgram *av_new_program(AVFormatContext *ac, int id)
return program;
}
-AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title)
+AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base,
+ int64_t start, int64_t end, const char *title)
{
AVChapter *chapter = NULL;
int i;
- for(i=0; i<s->nb_chapters; i++)
- if(s->chapters[i]->id == id)
+ for (i = 0; i < s->nb_chapters; i++)
+ if (s->chapters[i]->id == id)
chapter = s->chapters[i];
- if(!chapter){
- chapter= av_mallocz(sizeof(AVChapter));
- if(!chapter)
+ if (!chapter) {
+ chapter = av_mallocz(sizeof(AVChapter));
+ if (!chapter)
return NULL;
dynarray_add(&s->chapters, &s->nb_chapters, chapter);
}
av_dict_set(&chapter->metadata, "title", title, 0);
- chapter->id = id;
- chapter->time_base= time_base;
- chapter->start = start;
- chapter->end = end;
+ chapter->id = id;
+ chapter->time_base = time_base;
+ chapter->start = start;
+ chapter->end = end;
return chapter;
}
-void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx)
+void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx)
{
int i, j;
- AVProgram *program=NULL;
+ AVProgram *program = NULL;
void *tmp;
if (idx >= ac->nb_streams) {
@@ -3506,16 +3784,16 @@ void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int i
return;
}
- for(i=0; i<ac->nb_programs; i++){
- if(ac->programs[i]->id != progid)
+ for (i = 0; i < ac->nb_programs; i++) {
+ if (ac->programs[i]->id != progid)
continue;
program = ac->programs[i];
- for(j=0; j<program->nb_stream_indexes; j++)
- if(program->stream_index[j] == idx)
+ for (j = 0; j < program->nb_stream_indexes; j++)
+ if (program->stream_index[j] == idx)
return;
tmp = av_realloc_array(program->stream_index, program->nb_stream_indexes+1, sizeof(unsigned int));
- if(!tmp)
+ if (!tmp)
return;
program->stream_index = tmp;
program->stream_index[program->nb_stream_indexes++] = idx;
@@ -3523,24 +3801,29 @@ void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int i
}
}
-static void print_fps(double d, const char *postfix){
- uint64_t v= lrintf(d*100);
- if (v% 100 ) av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix);
- else if(v%(100*1000)) av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix);
- else av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d/1000, postfix);
+static void print_fps(double d, const char *postfix)
+{
+ uint64_t v = lrintf(d * 100);
+ if (v % 100)
+ av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix);
+ else if (v % (100 * 1000))
+ av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix);
+ else
+ av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d / 1000, postfix);
}
static void dump_metadata(void *ctx, AVDictionary *m, const char *indent)
{
- if(m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))){
- AVDictionaryEntry *tag=NULL;
+ if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))) {
+ AVDictionaryEntry *tag = NULL;
av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent);
- while((tag=av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
- if(strcmp("language", tag->key)){
+ while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)))
+ if (strcmp("language", tag->key)) {
const char *p = tag->value;
- av_log(ctx, AV_LOG_INFO, "%s %-16s: ", indent, tag->key);
- while(*p) {
+ av_log(ctx, AV_LOG_INFO,
+ "%s %-16s: ", indent, tag->key);
+ while (*p) {
char tmp[256];
size_t len = strcspn(p, "\x8\xa\xb\xc\xd");
av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1));
@@ -3552,12 +3835,12 @@ static void dump_metadata(void *ctx, AVDictionary *m, const char *indent)
}
av_log(ctx, AV_LOG_INFO, "\n");
}
- }
}
}
/* "user interface" functions */
-static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
+static void dump_stream_format(AVFormatContext *ic, int i,
+ int index, int is_output)
{
char buf[256];
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
@@ -3572,30 +3855,31 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out
av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
if (lang)
av_log(NULL, AV_LOG_INFO, "(%s)", lang->value);
- av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, st->time_base.num/g, st->time_base.den/g);
+ av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames,
+ st->time_base.num / g, st->time_base.den / g);
av_log(NULL, AV_LOG_INFO, ": %s", buf);
if (st->sample_aspect_ratio.num && // default
av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
- st->codec->width*st->sample_aspect_ratio.num,
- st->codec->height*st->sample_aspect_ratio.den,
- 1024*1024);
+ st->codec->width * st->sample_aspect_ratio.num,
+ st->codec->height * st->sample_aspect_ratio.den,
+ 1024 * 1024);
av_log(NULL, AV_LOG_INFO, ", SAR %d:%d DAR %d:%d",
- st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
- display_aspect_ratio.num, display_aspect_ratio.den);
+ st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
+ display_aspect_ratio.num, display_aspect_ratio.den);
}
- if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
- if(st->avg_frame_rate.den && st->avg_frame_rate.num)
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ if (st->avg_frame_rate.den && st->avg_frame_rate.num)
print_fps(av_q2d(st->avg_frame_rate), "fps");
#if FF_API_R_FRAME_RATE
- if(st->r_frame_rate.den && st->r_frame_rate.num)
+ if (st->r_frame_rate.den && st->r_frame_rate.num)
print_fps(av_q2d(st->r_frame_rate), "tbr");
#endif
- if(st->time_base.den && st->time_base.num)
- print_fps(1/av_q2d(st->time_base), "tbn");
- if(st->codec->time_base.den && st->codec->time_base.num)
- print_fps(1/av_q2d(st->codec->time_base), "tbc");
+ if (st->time_base.den && st->time_base.num)
+ print_fps(1 / av_q2d(st->time_base), "tbn");
+ if (st->codec->time_base.den && st->codec->time_base.num)
+ print_fps(1 / av_q2d(st->codec->time_base), "tbc");
}
if (st->disposition & AV_DISPOSITION_DEFAULT)
av_log(NULL, AV_LOG_INFO, " (default)");
@@ -3621,10 +3905,8 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out
dump_metadata(NULL, st->metadata, " ");
}
-void av_dump_format(AVFormatContext *ic,
- int index,
- const char *url,
- int is_output)
+void av_dump_format(AVFormatContext *ic, int index,
+ const char *url, int is_output)
{
int i;
uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL;
@@ -3632,19 +3914,19 @@ void av_dump_format(AVFormatContext *ic,
return;
av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
- is_output ? "Output" : "Input",
- index,
- is_output ? ic->oformat->name : ic->iformat->name,
- is_output ? "to" : "from", url);
+ is_output ? "Output" : "Input",
+ index,
+ is_output ? ic->oformat->name : ic->iformat->name,
+ is_output ? "to" : "from", url);
dump_metadata(NULL, ic->metadata, " ");
if (!is_output) {
av_log(NULL, AV_LOG_INFO, " Duration: ");
if (ic->duration != AV_NOPTS_VALUE) {
int hours, mins, secs, us;
int64_t duration = ic->duration + 5000;
- secs = duration / AV_TIME_BASE;
- us = duration % AV_TIME_BASE;
- mins = secs / 60;
+ secs = duration / AV_TIME_BASE;
+ us = duration % AV_TIME_BASE;
+ mins = secs / 60;
secs %= 60;
hours = mins / 60;
mins %= 60;
@@ -3657,36 +3939,38 @@ void av_dump_format(AVFormatContext *ic,
int secs, us;
av_log(NULL, AV_LOG_INFO, ", start: ");
secs = ic->start_time / AV_TIME_BASE;
- us = abs(ic->start_time % AV_TIME_BASE);
+ us = abs(ic->start_time % AV_TIME_BASE);
av_log(NULL, AV_LOG_INFO, "%d.%06d",
- secs, (int)av_rescale(us, 1000000, AV_TIME_BASE));
+ secs, (int) av_rescale(us, 1000000, AV_TIME_BASE));
}
av_log(NULL, AV_LOG_INFO, ", bitrate: ");
- if (ic->bit_rate) {
- av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000);
- } else {
+ if (ic->bit_rate)
+ av_log(NULL, AV_LOG_INFO, "%d kb/s", ic->bit_rate / 1000);
+ else
av_log(NULL, AV_LOG_INFO, "N/A");
- }
av_log(NULL, AV_LOG_INFO, "\n");
}
for (i = 0; i < ic->nb_chapters; i++) {
AVChapter *ch = ic->chapters[i];
av_log(NULL, AV_LOG_INFO, " Chapter #%d.%d: ", index, i);
- av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base));
- av_log(NULL, AV_LOG_INFO, "end %f\n", ch->end * av_q2d(ch->time_base));
+ av_log(NULL, AV_LOG_INFO,
+ "start %f, ", ch->start * av_q2d(ch->time_base));
+ av_log(NULL, AV_LOG_INFO,
+ "end %f\n", ch->end * av_q2d(ch->time_base));
dump_metadata(NULL, ch->metadata, " ");
}
- if(ic->nb_programs) {
+ if (ic->nb_programs) {
int j, k, total = 0;
- for(j=0; j<ic->nb_programs; j++) {
+ for (j = 0; j < ic->nb_programs; j++) {
AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata,
"name", NULL, 0);
av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id,
name ? name->value : "");
dump_metadata(NULL, ic->programs[j]->metadata, " ");
- for(k=0; k<ic->programs[j]->nb_stream_indexes; k++) {
- dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
+ for (k = 0; k < ic->programs[j]->nb_stream_indexes; k++) {
+ dump_stream_format(ic, ic->programs[j]->stream_index[k],
+ index, is_output);
printed[ic->programs[j]->stream_index[k]] = 1;
}
total += ic->programs[j]->nb_stream_indexes;
@@ -3694,7 +3978,7 @@ void av_dump_format(AVFormatContext *ic,
if (total < ic->nb_streams)
av_log(NULL, AV_LOG_INFO, " No Program\n");
}
- for(i=0;i<ic->nb_streams;i++)
+ for (i = 0; i < ic->nb_streams; i++)
if (!printed[i])
dump_stream_format(ic, i, index, is_output);
@@ -3703,11 +3987,10 @@ void av_dump_format(AVFormatContext *ic,
uint64_t ff_ntp_time(void)
{
- return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
+ return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
-int av_get_frame_filename(char *buf, int buf_size,
- const char *path, int number)
+int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
{
const char *p;
char *q, buf1[20], c;
@@ -3716,20 +3999,19 @@ int av_get_frame_filename(char *buf, int buf_size,
q = buf;
p = path;
percentd_found = 0;
- for(;;) {
+ for (;;) {
c = *p++;
if (c == '\0')
break;
if (c == '%') {
do {
nd = 0;
- while (av_isdigit(*p)) {
+ while (av_isdigit(*p))
nd = nd * 10 + *p++ - '0';
- }
c = *p++;
} while (av_isdigit(c));
- switch(c) {
+ switch (c) {
case '%':
goto addchar;
case 'd':
@@ -3747,7 +4029,7 @@ int av_get_frame_filename(char *buf, int buf_size,
goto fail;
}
} else {
- addchar:
+addchar:
if ((q - buf) < buf_size - 1)
*q++ = c;
}
@@ -3756,38 +4038,44 @@ int av_get_frame_filename(char *buf, int buf_size,
goto fail;
*q = '\0';
return 0;
- fail:
+fail:
*q = '\0';
return -1;
}
+#define HEXDUMP_PRINT(...) \
+ do { \
+ if (!f) \
+ av_log(avcl, level, __VA_ARGS__); \
+ else \
+ fprintf(f, __VA_ARGS__); \
+ } while (0)
+
static void hex_dump_internal(void *avcl, FILE *f, int level,
const uint8_t *buf, int size)
{
int len, i, j, c;
-#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0)
- for(i=0;i<size;i+=16) {
+ for (i = 0; i < size; i += 16) {
len = size - i;
if (len > 16)
len = 16;
- PRINT("%08x ", i);
- for(j=0;j<16;j++) {
+ HEXDUMP_PRINT("%08x ", i);
+ for (j = 0; j < 16; j++) {
if (j < len)
- PRINT(" %02x", buf[i+j]);
+ HEXDUMP_PRINT(" %02x", buf[i + j]);
else
- PRINT(" ");
+ HEXDUMP_PRINT(" ");
}
- PRINT(" ");
- for(j=0;j<len;j++) {
- c = buf[i+j];
+ HEXDUMP_PRINT(" ");
+ for (j = 0; j < len; j++) {
+ c = buf[i + j];
if (c < ' ' || c > '~')
c = '.';
- PRINT("%c", c);
+ HEXDUMP_PRINT("%c", c);
}
- PRINT("\n");
+ HEXDUMP_PRINT("\n");
}
-#undef PRINT
}
void av_hex_dump(FILE *f, const uint8_t *buf, int size)
@@ -3800,38 +4088,37 @@ void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size)
hex_dump_internal(avcl, NULL, level, buf, size);
}
-static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload, AVRational time_base)
+static void pkt_dump_internal(void *avcl, FILE *f, int level, const AVPacket *pkt,
+ int dump_payload, AVRational time_base)
{
-#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0)
- PRINT("stream #%d:\n", pkt->stream_index);
- PRINT(" keyframe=%d\n", ((pkt->flags & AV_PKT_FLAG_KEY) != 0));
- PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base));
+ HEXDUMP_PRINT("stream #%d:\n", pkt->stream_index);
+ HEXDUMP_PRINT(" keyframe=%d\n", (pkt->flags & AV_PKT_FLAG_KEY) != 0);
+ HEXDUMP_PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base));
/* DTS is _always_ valid after av_read_frame() */
- PRINT(" dts=");
+ HEXDUMP_PRINT(" dts=");
if (pkt->dts == AV_NOPTS_VALUE)
- PRINT("N/A");
+ HEXDUMP_PRINT("N/A");
else
- PRINT("%0.3f", pkt->dts * av_q2d(time_base));
+ HEXDUMP_PRINT("%0.3f", pkt->dts * av_q2d(time_base));
/* PTS may not be known if B-frames are present. */
- PRINT(" pts=");
+ HEXDUMP_PRINT(" pts=");
if (pkt->pts == AV_NOPTS_VALUE)
- PRINT("N/A");
+ HEXDUMP_PRINT("N/A");
else
- PRINT("%0.3f", pkt->pts * av_q2d(time_base));
- PRINT("\n");
- PRINT(" size=%d\n", pkt->size);
-#undef PRINT
+ HEXDUMP_PRINT("%0.3f", pkt->pts * av_q2d(time_base));
+ HEXDUMP_PRINT("\n");
+ HEXDUMP_PRINT(" size=%d\n", pkt->size);
if (dump_payload)
av_hex_dump(f, pkt->data, pkt->size);
}
-void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st)
+void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st)
{
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base);
}
-void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
- AVStream *st)
+void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,
+ const AVStream *st)
{
pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base);
}
@@ -3839,24 +4126,29 @@ void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
void av_url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size,
- int *port_ptr,
- char *path, int path_size,
- const char *url)
+ int *port_ptr, char *path, int path_size, const char *url)
{
const char *p, *ls, *ls2, *at, *at2, *col, *brk;
- if (port_ptr) *port_ptr = -1;
- if (proto_size > 0) proto[0] = 0;
- if (authorization_size > 0) authorization[0] = 0;
- if (hostname_size > 0) hostname[0] = 0;
- if (path_size > 0) path[0] = 0;
+ if (port_ptr)
+ *port_ptr = -1;
+ if (proto_size > 0)
+ proto[0] = 0;
+ if (authorization_size > 0)
+ authorization[0] = 0;
+ if (hostname_size > 0)
+ hostname[0] = 0;
+ if (path_size > 0)
+ path[0] = 0;
/* parse protocol */
if ((p = strchr(url, ':'))) {
av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
p++; /* skip ':' */
- if (*p == '/') p++;
- if (*p == '/') p++;
+ if (*p == '/')
+ p++;
+ if (*p == '/')
+ p++;
} else {
/* no protocol means plain filename */
av_strlcpy(path, url, path_size);
@@ -3866,14 +4158,14 @@ void av_url_split(char *proto, int proto_size,
/* separate path from hostname */
ls = strchr(p, '/');
ls2 = strchr(p, '?');
- if(!ls)
+ if (!ls)
ls = ls2;
else if (ls && ls2)
ls = FFMIN(ls, ls2);
- if(ls)
+ if (ls)
av_strlcpy(path, ls, path_size);
else
- ls = &p[strlen(p)]; // XXX
+ ls = &p[strlen(p)]; // XXX
/* the rest is hostname, use that to parse auth/port */
if (ls != p) {
@@ -3894,7 +4186,8 @@ void av_url_split(char *proto, int proto_size,
} else if ((col = strchr(p, ':')) && col < ls) {
av_strlcpy(hostname, p,
FFMIN(col + 1 - p, hostname_size));
- if (port_ptr) *port_ptr = atoi(col + 1);
+ if (port_ptr)
+ *port_ptr = atoi(col + 1);
} else
av_strlcpy(hostname, p,
FFMIN(ls + 1 - p, hostname_size));
@@ -3914,7 +4207,7 @@ char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase)
'c', 'd', 'e', 'f' };
const char *hex_table = lowercase ? hex_table_lc : hex_table_uc;
- for(i = 0; i < s; i++) {
+ for (i = 0; i < s; i++) {
buff[i * 2] = hex_table[src[i] >> 4];
buff[i * 2 + 1] = hex_table[src[i] & 0xF];
}
@@ -3927,7 +4220,7 @@ int ff_hex_to_data(uint8_t *data, const char *p)
int c, len, v;
len = 0;
- v = 1;
+ v = 1;
for (;;) {
p += strspn(p, SPACE_CHARS);
if (*p == '\0')
@@ -3962,17 +4255,23 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
unsigned int pts_num, unsigned int pts_den)
{
AVRational new_tb;
- if(av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)){
- if(new_tb.num != pts_num)
- av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, pts_num/new_tb.num);
- }else
- av_log(NULL, AV_LOG_WARNING, "st:%d has too large timebase, reducing\n", s->index);
-
- if(new_tb.num <= 0 || new_tb.den <= 0) {
- av_log(NULL, AV_LOG_ERROR, "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", new_tb.num, new_tb.den, s->index);
+ if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) {
+ if (new_tb.num != pts_num)
+ av_log(NULL, AV_LOG_DEBUG,
+ "st:%d removing common factor %d from timebase\n",
+ s->index, pts_num / new_tb.num);
+ } else
+ av_log(NULL, AV_LOG_WARNING,
+ "st:%d has too large timebase, reducing\n", s->index);
+
+ if (new_tb.num <= 0 || new_tb.den <= 0) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Ignoring attempt to set invalid timebase %d/%d for st:%d\n",
+ new_tb.num, new_tb.den,
+ s->index);
return;
}
- s->time_base = new_tb;
+ s->time_base = new_tb;
av_codec_set_pkt_timebase(s->codec, new_tb);
s->pts_wrap_bits = pts_wrap_bits;
}
@@ -4034,16 +4333,15 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
int ff_find_stream_index(AVFormatContext *s, int id)
{
int i;
- for (i = 0; i < s->nb_streams; i++) {
+ for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->id == id)
return i;
- }
return -1;
}
int64_t ff_iso8601_to_unix_time(const char *datestr)
{
- struct tm time1 = {0}, time2 = {0};
+ struct tm time1 = { 0 }, time2 = { 0 };
char *ret1, *ret2;
ret1 = av_small_strptime(datestr, "%Y - %m - %d %H:%M:%S", &time1);
ret2 = av_small_strptime(datestr, "%Y - %m - %dT%H:%M:%S", &time2);
@@ -4053,14 +4351,16 @@ int64_t ff_iso8601_to_unix_time(const char *datestr)
return av_timegm(&time1);
}
-int avformat_query_codec(AVOutputFormat *ofmt, enum AVCodecID codec_id, int std_compliance)
+int avformat_query_codec(AVOutputFormat *ofmt, enum AVCodecID codec_id,
+ int std_compliance)
{
if (ofmt) {
if (ofmt->query_codec)
return ofmt->query_codec(codec_id, std_compliance);
else if (ofmt->codec_tag)
return !!av_codec_get_tag(ofmt->codec_tag, codec_id);
- else if (codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec ||
+ else if (codec_id == ofmt->video_codec ||
+ codec_id == ofmt->audio_codec ||
codec_id == ofmt->subtitle_codec)
return 1;
}
@@ -4098,19 +4398,19 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels,
if (!pkt)
return AVERROR(EINVAL);
if (channels) {
- size += 4;
+ size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT;
}
if (channel_layout) {
- size += 8;
+ size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT;
}
if (sample_rate) {
- size += 4;
+ size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE;
}
if (width || height) {
- size += 8;
+ size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
}
data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);
@@ -4156,10 +4456,16 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea
AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
{
AVRational fr = st->r_frame_rate;
+ AVRational codec_fr = av_inv_q(st->codec->time_base);
+ AVRational avg_fr = st->avg_frame_rate;
+
+ if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 &&
+ av_q2d(avg_fr) < 70 && av_q2d(fr) > 210) {
+ fr = avg_fr;
+ }
+
if (st->codec->ticks_per_frame > 1) {
- AVRational codec_fr = av_inv_q(st->codec->time_base);
- AVRational avg_fr = st->avg_frame_rate;
codec_fr.den *= st->codec->ticks_per_frame;
if ( codec_fr.num > 0 && codec_fr.den > 0 && av_q2d(codec_fr) < av_q2d(fr)*0.7
&& fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)
@@ -4217,12 +4523,14 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
return 1;
}
return 0;
- } else if (*spec == '#') {
- int sid;
+ } else if (*spec == '#' ||
+ (*spec == 'i' && *(spec + 1) == ':')) {
+ int stream_id;
char *endptr;
- sid = strtol(spec + 1, &endptr, 0);
+ spec += 1 + (*spec == 'i');
+ stream_id = strtol(spec, &endptr, 0);
if (!*endptr)
- return st->id == sid;
+ return stream_id == st->id;
} else if (!*spec) /* empty specifier, matches everything */
return 1;
@@ -4299,7 +4607,7 @@ int ff_generate_avci_extradata(AVStream *st)
};
const uint8_t *data = NULL;
- int size = 0;
+ int size = 0;
if (st->codec->width == 1920) {
if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
diff --git a/chromium/third_party/ffmpeg/libavformat/vc1test.c b/chromium/third_party/ffmpeg/libavformat/vc1test.c
index bf1bfe0318e..e5303fa46e7 100644
--- a/chromium/third_party/ffmpeg/libavformat/vc1test.c
+++ b/chromium/third_party/ffmpeg/libavformat/vc1test.c
@@ -61,9 +61,8 @@ static int vc1t_read_header(AVFormatContext *s)
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_id = AV_CODEC_ID_WMV3;
- if (ff_alloc_extradata(st->codec, VC1_EXTRADATA_SIZE))
+ if (ff_get_extradata(st->codec, pb, VC1_EXTRADATA_SIZE) < 0)
return AVERROR(ENOMEM);
- avio_read(pb, st->codec->extradata, VC1_EXTRADATA_SIZE);
st->codec->height = avio_rl32(pb);
st->codec->width = avio_rl32(pb);
if(avio_rl32(pb) != 0xC)
diff --git a/chromium/third_party/ffmpeg/libavformat/version.h b/chromium/third_party/ffmpeg/libavformat/version.h
index 4fe8364ab20..c6667ca7bfd 100644
--- a/chromium/third_party/ffmpeg/libavformat/version.h
+++ b/chromium/third_party/ffmpeg/libavformat/version.h
@@ -27,10 +27,10 @@
* Libavformat version macros
*/
-#include "libavutil/avutil.h"
+#include "libavutil/version.h"
#define LIBAVFORMAT_VERSION_MAJOR 55
-#define LIBAVFORMAT_VERSION_MINOR 22
+#define LIBAVFORMAT_VERSION_MINOR 38
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
@@ -51,6 +51,9 @@
#ifndef FF_API_REFERENCE_DTS
#define FF_API_REFERENCE_DTS (LIBAVFORMAT_VERSION_MAJOR < 56)
#endif
+#ifndef FF_API_LAVF_BITEXACT
+#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 56)
+#endif
#ifndef FF_API_ALLOC_OUTPUT_CONTEXT
#define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 56)
diff --git a/chromium/third_party/ffmpeg/libavformat/vqf.c b/chromium/third_party/ffmpeg/libavformat/vqf.c
index 526b5961461..74c7f5fc172 100644
--- a/chromium/third_party/ffmpeg/libavformat/vqf.c
+++ b/chromium/third_party/ffmpeg/libavformat/vqf.c
@@ -249,7 +249,7 @@ static int vqf_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->data[1] = c->last_frame_bits;
ret = avio_read(s->pb, pkt->data+2, size);
- if (ret<=0) {
+ if (ret != size) {
av_free_packet(pkt);
return AVERROR(EIO);
}
diff --git a/chromium/third_party/ffmpeg/libavformat/wavdec.c b/chromium/third_party/ffmpeg/libavformat/wavdec.c
index daea64edc5a..a865b760b78 100644
--- a/chromium/third_party/ffmpeg/libavformat/wavdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/wavdec.c
@@ -114,7 +114,7 @@ static void handle_stream_probing(AVStream *st)
{
if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
st->request_probe = AVPROBE_SCORE_EXTENSION;
- st->probe_packets = FFMIN(st->probe_packets, 4);
+ st->probe_packets = FFMIN(st->probe_packets, 14);
}
}
diff --git a/chromium/third_party/ffmpeg/libavformat/wavenc.c b/chromium/third_party/ffmpeg/libavformat/wavenc.c
index 0067dfef29b..c892c7b34db 100644
--- a/chromium/third_party/ffmpeg/libavformat/wavenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/wavenc.c
@@ -126,7 +126,7 @@ static int wav_write_header(AVFormatContext *s)
avio_wl32(pb, -1); /* RF64 chunk size: use size in ds64 */
} else {
ffio_wfourcc(pb, "RIFF");
- avio_wl32(pb, 0); /* file length */
+ avio_wl32(pb, -1); /* file length */
}
ffio_wfourcc(pb, "WAVE");
@@ -141,7 +141,7 @@ static int wav_write_header(AVFormatContext *s)
/* format header */
fmt = ff_start_tag(pb, "fmt ");
- if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
+ if (ff_put_wav_header(pb, s->streams[0]->codec, 0) < 0) {
av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
return -1;
@@ -323,7 +323,7 @@ static int w64_write_header(AVFormatContext *s)
avio_wl64(pb, -1);
avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave));
start_guid(pb, ff_w64_guid_fmt, &start);
- if ((ret = ff_put_wav_header(pb, s->streams[0]->codec)) < 0) {
+ if ((ret = ff_put_wav_header(pb, s->streams[0]->codec, 0)) < 0) {
av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
return ret;
diff --git a/chromium/third_party/ffmpeg/libavformat/wc3movie.c b/chromium/third_party/ffmpeg/libavformat/wc3movie.c
index 657380a6be1..408c050b7c7 100644
--- a/chromium/third_party/ffmpeg/libavformat/wc3movie.c
+++ b/chromium/third_party/ffmpeg/libavformat/wc3movie.c
@@ -27,6 +27,7 @@
* http://www.pcisys.net/~melanson/codecs/
*/
+#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
@@ -249,10 +250,16 @@ static int wc3_read_packet(AVFormatContext *s,
else {
int i = 0;
av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
+ if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1)
+ return AVERROR_INVALIDDATA;
av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]);
i += text[i] + 1;
+ if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1)
+ return AVERROR_INVALIDDATA;
av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]);
i += text[i] + 1;
+ if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1)
+ return AVERROR_INVALIDDATA;
av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]);
}
#endif
diff --git a/chromium/third_party/ffmpeg/libavformat/webvttdec.c b/chromium/third_party/ffmpeg/libavformat/webvttdec.c
index 065448532d3..e457e8f6d21 100644
--- a/chromium/third_party/ffmpeg/libavformat/webvttdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/webvttdec.c
@@ -119,7 +119,7 @@ static int webvtt_read_header(AVFormatContext *s)
break;
if (!(p = strstr(p, "-->")))
break;
- p += 3;
+ p += 2;
do p++; while (*p == ' ' || *p == '\t');
if ((ts_end = read_ts(p)) == AV_NOPTS_VALUE)
break;
diff --git a/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c b/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c
index 1d4bb5ad6c6..2a988ad3900 100644
--- a/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c
+++ b/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c
@@ -101,13 +101,9 @@ static int wsvqa_read_header(AVFormatContext *s)
avio_seek(pb, 20, SEEK_SET);
/* the VQA header needs to go to the decoder */
- if (ff_alloc_extradata(st->codec, VQA_HEADER_SIZE))
+ if (ff_get_extradata(st->codec, pb, VQA_HEADER_SIZE) < 0)
return AVERROR(ENOMEM);
header = (uint8_t *)st->codec->extradata;
- if (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
- VQA_HEADER_SIZE) {
- return AVERROR(EIO);
- }
st->codec->width = AV_RL16(&header[6]);
st->codec->height = AV_RL16(&header[8]);
fps = header[12];
diff --git a/chromium/third_party/ffmpeg/libavformat/wtv.h b/chromium/third_party/ffmpeg/libavformat/wtv.h
index efe90d68466..f26ad5efb90 100644
--- a/chromium/third_party/ffmpeg/libavformat/wtv.h
+++ b/chromium/third_party/ffmpeg/libavformat/wtv.h
@@ -55,4 +55,6 @@ extern const ff_asf_guid ff_mediasubtype_cpfilters_processed;
extern const ff_asf_guid ff_format_cpfilters_processed;
extern const ff_asf_guid ff_format_waveformatex;
extern const ff_asf_guid ff_format_mpeg2_video;
+extern const ff_asf_guid ff_format_videoinfo2;
+
#endif /* AVFORMAT_WTV_H */
diff --git a/chromium/third_party/ffmpeg/libavformat/wtv_common.c b/chromium/third_party/ffmpeg/libavformat/wtv_common.c
index 5b1e61b810b..ce4349dce54 100644
--- a/chromium/third_party/ffmpeg/libavformat/wtv_common.c
+++ b/chromium/third_party/ffmpeg/libavformat/wtv_common.c
@@ -75,6 +75,8 @@ const ff_asf_guid ff_format_waveformatex =
{0x81,0x9F,0x58,0x05,0x56,0xC3,0xCE,0x11,0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A};
const ff_asf_guid ff_format_mpeg2_video =
{0xE3,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA};
+const ff_asf_guid ff_format_videoinfo2 =
+ {0xA0,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};
const AVCodecGuid ff_video_guids[] = {
{AV_CODEC_ID_MPEG2VIDEO, {0x26,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}},
diff --git a/chromium/third_party/ffmpeg/libavformat/wtvdec.c b/chromium/third_party/ffmpeg/libavformat/wtvdec.c
index 4dfe7010d12..cfdc55523a8 100644
--- a/chromium/third_party/ffmpeg/libavformat/wtvdec.c
+++ b/chromium/third_party/ffmpeg/libavformat/wtvdec.c
@@ -25,6 +25,8 @@
* @author Peter Ross <pross@xvid.org>
*/
+#include <inttypes.h>
+
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
@@ -35,7 +37,7 @@
/* Macros for formating GUIDs */
#define PRI_PRETTY_GUID \
- "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x"
#define ARG_PRETTY_GUID(g) \
AV_RL32(g),AV_RL16(g+4),AV_RL16(g+6),g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15]
#define LEN_PRETTY_GUID 34
@@ -153,6 +155,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int
AVIOContext *pb;
WtvFile *wf;
uint8_t *buffer;
+ int64_t size;
if (seek_by_sector(s->pb, first_sector, 0) < 0)
return NULL;
@@ -205,7 +208,8 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int
return NULL;
}
- if ((int64_t)wf->sectors[wf->nb_sectors - 1] << WTV_SECTOR_BITS > avio_tell(s->pb))
+ size = avio_size(s->pb);
+ if (size >= 0 && (int64_t)wf->sectors[wf->nb_sectors - 1] << WTV_SECTOR_BITS > size)
av_log(s, AV_LOG_WARNING, "truncated file\n");
/* check length */
@@ -370,10 +374,6 @@ static const ff_asf_guid mediasubtype_dtvccdata =
static const ff_asf_guid mediasubtype_mpeg2_sections =
{0x79,0x85,0x9F,0x4A,0xF8,0x6B,0x92,0x43,0x8A,0x6D,0xD2,0xDD,0x09,0xFA,0x78,0x61};
-/* Formats */
-static const ff_asf_guid format_videoinfo2 =
- {0xA0,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};
-
static int read_probe(AVProbeData *p)
{
return ff_guidcmp(p->buf, ff_wtv_guid) ? 0 : AVPROBE_SCORE_MAX;
@@ -473,7 +473,7 @@ static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int ty
return;
if (type == 0 && length == 4) {
- snprintf(buf, buf_size, "%"PRIi32, avio_rl32(pb));
+ snprintf(buf, buf_size, "%u", avio_rl32(pb));
} else if (type == 1) {
avio_get_str16le(pb, length, buf, buf_size);
if (!strlen(buf)) {
@@ -562,7 +562,7 @@ static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st)
AVIOContext *pb = wtv->pb;
avio_skip(pb, 72); // picture aspect ratio is unreliable
- ff_get_bmp_header(pb, st, NULL);
+ st->codec->codec_tag = ff_get_bmp_header(pb, st, NULL);
return 72 + 40;
}
@@ -635,7 +635,7 @@ static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int code
*/
static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
ff_asf_guid mediatype, ff_asf_guid subtype,
- ff_asf_guid formattype, int size)
+ ff_asf_guid formattype, uint64_t size)
{
WtvContext *wtv = s->priv_data;
AVIOContext *pb = wtv->pb;
@@ -689,11 +689,12 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
st = new_stream(s, st, sid, AVMEDIA_TYPE_VIDEO);
if (!st)
return NULL;
- if (!ff_guidcmp(formattype, format_videoinfo2)) {
+ if (!ff_guidcmp(formattype, ff_format_videoinfo2)) {
int consumed = parse_videoinfoheader2(s, st);
avio_skip(pb, FFMAX(size - consumed, 0));
} else if (!ff_guidcmp(formattype, ff_format_mpeg2_video)) {
- int consumed = parse_videoinfoheader2(s, st);
+ uint64_t consumed = parse_videoinfoheader2(s, st);
+ /* ignore extradata; files produced by windows media center contain meaningless mpeg1 sequence header */
avio_skip(pb, FFMAX(size - consumed, 0));
} else {
if (ff_guidcmp(formattype, ff_format_none))
diff --git a/chromium/third_party/ffmpeg/libavformat/wtvenc.c b/chromium/third_party/ffmpeg/libavformat/wtvenc.c
index 04e6cc22f8d..634545d4594 100644
--- a/chromium/third_party/ffmpeg/libavformat/wtvenc.c
+++ b/chromium/third_party/ffmpeg/libavformat/wtvenc.c
@@ -30,8 +30,8 @@
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
+#include "mpegts.h"
#include "wtv.h"
-#include "asf.h"
#define WTV_BIGSECTOR_SIZE (1 << WTV_BIGSECTOR_BITS)
#define INDEX_BASE 0x2
@@ -130,16 +130,6 @@ typedef struct {
#define write_pad(pb, size) ffio_fill(pb, 0, size)
-static const ff_asf_guid *get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid)
-{
- int i;
- for (i = 0; av_guid[i].id != AV_CODEC_ID_NONE; i++) {
- if (id == av_guid[i].id)
- return &(av_guid[i].guid);
- }
- return NULL;
-}
-
/**
* Write chunk header. If header chunk (0x80000000 set) then add to list of header chunks
*/
@@ -223,10 +213,53 @@ static void finish_chunk(AVFormatContext *s)
write_index(s);
}
+static void put_videoinfoheader2(AVIOContext *pb, AVStream *st)
+{
+ AVRational dar = av_mul_q(st->sample_aspect_ratio, (AVRational){st->codec->width, st->codec->height});
+ unsigned int num, den;
+ av_reduce(&num, &den, dar.num, dar.den, 0xFFFFFFFF);
+
+ /* VIDEOINFOHEADER2 */
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+ avio_wl32(pb, st->codec->width);
+ avio_wl32(pb, st->codec->height);
+
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+
+ avio_wl32(pb, st->codec->bit_rate);
+ avio_wl32(pb, 0);
+ avio_wl64(pb, st->avg_frame_rate.num && st->avg_frame_rate.den ? INT64_C(10000000) / av_q2d(st->avg_frame_rate) : 0);
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+
+ avio_wl32(pb, num);
+ avio_wl32(pb, den);
+ avio_wl32(pb, 0);
+ avio_wl32(pb, 0);
+
+ ff_put_bmp_header(pb, st->codec, ff_codec_bmp_tags, 0, 1);
+
+ if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+ int padding = (st->codec->extradata_size & 3) ? 4 - (st->codec->extradata_size & 3) : 0;
+ /* MPEG2VIDEOINFO */
+ avio_wl32(pb, 0);
+ avio_wl32(pb, st->codec->extradata_size + padding);
+ avio_wl32(pb, -1);
+ avio_wl32(pb, -1);
+ avio_wl32(pb, 0);
+ avio_write(pb, st->codec->extradata, st->codec->extradata_size);
+ ffio_fill(pb, 0, padding);
+ }
+}
+
static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
{
- WtvContext *wctx = s->priv_data;
const ff_asf_guid *g, *media_type, *format_type;
+ const AVCodecTag *tags;
AVIOContext *pb = s->pb;
int64_t hdr_pos_start;
int hdr_size = 0;
@@ -234,21 +267,18 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
g = get_codec_guid(st->codec->codec_id, ff_video_guids);
media_type = &ff_mediatype_video;
- format_type = &ff_format_mpeg2_video;
+ format_type = st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO ? &ff_format_mpeg2_video : &ff_format_videoinfo2;
+ tags = ff_codec_bmp_tags;
} else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
g = get_codec_guid(st->codec->codec_id, ff_codec_wav_guids);
media_type = &ff_mediatype_audio;
format_type = &ff_format_waveformatex;
+ tags = ff_codec_wav_tags;
} else {
av_log(s, AV_LOG_ERROR, "unknown codec_type (0x%x)\n", st->codec->codec_type);
return -1;
}
- if (g == NULL) {
- av_log(s, AV_LOG_ERROR, "can't get video codec_id (0x%x) guid.\n", st->codec->codec_id);
- return -1;
- }
-
ff_put_guid(pb, media_type); // mediatype
ff_put_guid(pb, &ff_mediasubtype_cpfilters_processed); // subtype
write_pad(pb, 12);
@@ -257,15 +287,10 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
hdr_pos_start = avio_tell(pb);
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if (wctx->first_video_flag) {
- write_pad(pb, 216); //The size is sensitive.
- wctx->first_video_flag = 0;
- } else {
- write_pad(pb, 72); // aspect ratio
- ff_put_bmp_header(pb, st->codec, ff_codec_bmp_tags, 0);
- }
+ put_videoinfoheader2(pb, st);
} else {
- ff_put_wav_header(pb, st->codec);
+ if (ff_put_wav_header(pb, st->codec, 0) < 0)
+ format_type = &ff_format_none;
}
hdr_size = avio_tell(pb) - hdr_pos_start;
@@ -273,7 +298,17 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
avio_seek(pb, -(hdr_size + 4), SEEK_CUR);
avio_wl32(pb, hdr_size + 32);
avio_seek(pb, hdr_size, SEEK_CUR);
- ff_put_guid(pb, g); // actual_subtype
+ if (g) {
+ ff_put_guid(pb, g); // actual_subtype
+ } else {
+ int tag = ff_codec_get_tag(tags, st->codec->codec_id);
+ if (!tag) {
+ av_log(s, AV_LOG_ERROR, "unsupported codec_id (0x%x)\n", st->codec->codec_id);
+ return -1;
+ }
+ avio_wl32(pb, tag);
+ avio_write(pb, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12);
+ }
ff_put_guid(pb, format_type); // actual_formattype
return 0;
@@ -426,10 +461,15 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
WtvContext *wctx = s->priv_data;
+ AVStream *st = s->streams[pkt->stream_index];
- if (s->streams[pkt->stream_index]->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) {
+ if (st->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) {
av_copy_packet(&wctx->thumbnail, pkt);
return 0;
+ } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
+ int ret = ff_check_h264_startcode(s, st, pkt);
+ if (ret < 0)
+ return ret;
}
/* emit sync chunk and 'timeline.table.0.entries.Event' record every 50 frames */
diff --git a/chromium/third_party/ffmpeg/libavformat/xmv.c b/chromium/third_party/ffmpeg/libavformat/xmv.c
index 20f9bea55bc..6eac4d21e84 100644
--- a/chromium/third_party/ffmpeg/libavformat/xmv.c
+++ b/chromium/third_party/ffmpeg/libavformat/xmv.c
@@ -25,7 +25,7 @@
* Microsoft XMV demuxer
*/
-#include <stdint.h>
+#include <inttypes.h>
#include "libavutil/intreadwrite.h"
@@ -155,7 +155,7 @@ static int xmv_read_header(AVFormatContext *s)
file_version = avio_rl32(pb);
if ((file_version != 4) && (file_version != 2))
- avpriv_request_sample(s, "Uncommon version %d", file_version);
+ avpriv_request_sample(s, "Uncommon version %"PRIu32"", file_version);
/* Video track */
@@ -182,7 +182,7 @@ static int xmv_read_header(AVFormatContext *s)
avio_skip(pb, 2); /* Unknown (padding?) */
- xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
+ xmv->audio = av_malloc_array(xmv->audio_track_count, sizeof(XMVAudioPacket));
if (!xmv->audio) {
ret = AVERROR(ENOMEM);
goto fail;
@@ -219,7 +219,7 @@ static int xmv_read_header(AVFormatContext *s)
if (!packet->channels || !packet->sample_rate ||
packet->channels >= UINT16_MAX / XMV_BLOCK_ALIGN_SIZE) {
- av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %d.\n",
+ av_log(s, AV_LOG_ERROR, "Invalid parameters for audio track %"PRIu16".\n",
audio_track);
ret = AVERROR_INVALIDDATA;
goto fail;
diff --git a/chromium/third_party/ffmpeg/libavformat/xwma.c b/chromium/third_party/ffmpeg/libavformat/xwma.c
index e629b3f3844..127c097c449 100644
--- a/chromium/third_party/ffmpeg/libavformat/xwma.c
+++ b/chromium/third_party/ffmpeg/libavformat/xwma.c
@@ -46,7 +46,7 @@ static int xwma_read_header(AVFormatContext *s)
int64_t size;
int ret;
uint32_t dpds_table_size = 0;
- uint32_t *dpds_table = 0;
+ uint32_t *dpds_table = NULL;
unsigned int tag;
AVIOContext *pb = s->pb;
AVStream *st;
@@ -130,8 +130,10 @@ static int xwma_read_header(AVFormatContext *s)
/* parse the remaining RIFF chunks */
for (;;) {
- if (pb->eof_reached)
- return -1;
+ if (pb->eof_reached) {
+ ret = AVERROR_EOF;
+ goto end;
+ }
/* read next chunk tag */
tag = avio_rl32(pb);
size = avio_rl32(pb);
@@ -152,7 +154,8 @@ static int xwma_read_header(AVFormatContext *s)
/* Error out if there is more than one dpds chunk. */
if (dpds_table) {
av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
- return -1;
+ ret = AVERROR_INVALIDDATA;
+ goto end;
}
/* Compute the number of entries in the dpds chunk. */
@@ -164,7 +167,7 @@ static int xwma_read_header(AVFormatContext *s)
if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) {
av_log(s, AV_LOG_ERROR,
"dpds chunk size %"PRId64" invalid\n", size);
- return -1;
+ return AVERROR_INVALIDDATA;
}
/* Allocate some temporary storage to keep the dpds data around.
@@ -184,8 +187,10 @@ static int xwma_read_header(AVFormatContext *s)
}
/* Determine overall data length */
- if (size < 0)
- return -1;
+ if (size < 0) {
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
if (!size) {
xwma->data_end = INT64_MAX;
} else
@@ -204,7 +209,8 @@ static int xwma_read_header(AVFormatContext *s)
av_log(s, AV_LOG_ERROR,
"Invalid bits_per_coded_sample %d for %d channels\n",
st->codec->bits_per_coded_sample, st->codec->channels);
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto end;
}
st->duration = total_decoded_bytes / bytes_per_sample;
@@ -239,9 +245,10 @@ static int xwma_read_header(AVFormatContext *s)
st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
}
+end:
av_free(dpds_table);
- return 0;
+ return ret;
}
static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
diff --git a/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c b/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c
index 1999c733642..bc07b4c55de 100644
--- a/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c
+++ b/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c
@@ -517,6 +517,7 @@ static int yuv4_read_header(AVFormatContext *s)
st->codec->height = height;
av_reduce(&raten, &rated, raten, rated, (1UL << 31) - 1);
avpriv_set_pts_info(st, 64, rated, raten);
+ st->avg_frame_rate = av_inv_q(st->time_base);
st->codec->pix_fmt = pix_fmt;
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;