summaryrefslogtreecommitdiff
path: root/contrib/ffmpeg/libavformat
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ffmpeg/libavformat')
-rw-r--r--contrib/ffmpeg/libavformat/4xm.c50
-rw-r--r--contrib/ffmpeg/libavformat/Makefile209
-rw-r--r--contrib/ffmpeg/libavformat/adtsenc.c12
-rw-r--r--contrib/ffmpeg/libavformat/aiff.c173
-rw-r--r--contrib/ffmpeg/libavformat/allformats.c267
-rw-r--r--contrib/ffmpeg/libavformat/allformats.h182
-rw-r--r--contrib/ffmpeg/libavformat/amr.c34
-rw-r--r--contrib/ffmpeg/libavformat/apc.c90
-rw-r--r--contrib/ffmpeg/libavformat/ape.c523
-rw-r--r--contrib/ffmpeg/libavformat/asf-enc.c39
-rw-r--r--contrib/ffmpeg/libavformat/asf.c182
-rw-r--r--contrib/ffmpeg/libavformat/asf.h13
-rw-r--r--contrib/ffmpeg/libavformat/asfcrypt.c172
-rw-r--r--contrib/ffmpeg/libavformat/asfcrypt.h29
-rw-r--r--contrib/ffmpeg/libavformat/au.c23
-rw-r--r--contrib/ffmpeg/libavformat/audio.c344
-rw-r--r--contrib/ffmpeg/libavformat/avc.c135
-rw-r--r--contrib/ffmpeg/libavformat/avc.h32
-rw-r--r--contrib/ffmpeg/libavformat/avformat.h335
-rw-r--r--contrib/ffmpeg/libavformat/avidec.c148
-rw-r--r--contrib/ffmpeg/libavformat/avienc.c19
-rw-r--r--contrib/ffmpeg/libavformat/avio.c40
-rw-r--r--contrib/ffmpeg/libavformat/avio.h123
-rw-r--r--contrib/ffmpeg/libavformat/aviobuf.c189
-rw-r--r--contrib/ffmpeg/libavformat/avisynth.c4
-rw-r--r--contrib/ffmpeg/libavformat/avs.c48
-rw-r--r--contrib/ffmpeg/libavformat/beosaudio.cpp465
-rw-r--r--contrib/ffmpeg/libavformat/bethsoftvid.c233
-rw-r--r--contrib/ffmpeg/libavformat/c93.c198
-rw-r--r--contrib/ffmpeg/libavformat/crcenc.c (renamed from contrib/ffmpeg/libavformat/crc.c)37
-rw-r--r--contrib/ffmpeg/libavformat/cutils.c92
-rw-r--r--contrib/ffmpeg/libavformat/daud.c6
-rw-r--r--contrib/ffmpeg/libavformat/dc1394.c193
-rw-r--r--contrib/ffmpeg/libavformat/dsicin.c25
-rw-r--r--contrib/ffmpeg/libavformat/dv.c15
-rw-r--r--contrib/ffmpeg/libavformat/dv.h7
-rw-r--r--contrib/ffmpeg/libavformat/dv1394.c236
-rw-r--r--contrib/ffmpeg/libavformat/dv1394.h357
-rw-r--r--contrib/ffmpeg/libavformat/dvenc.c268
-rw-r--r--contrib/ffmpeg/libavformat/dxa.c34
-rw-r--r--contrib/ffmpeg/libavformat/eacdata.c100
-rw-r--r--contrib/ffmpeg/libavformat/electronicarts.c398
-rw-r--r--contrib/ffmpeg/libavformat/ffm.c37
-rw-r--r--contrib/ffmpeg/libavformat/file.c47
-rw-r--r--contrib/ffmpeg/libavformat/flic.c76
-rw-r--r--contrib/ffmpeg/libavformat/flv.h8
-rw-r--r--contrib/ffmpeg/libavformat/flvdec.c136
-rw-r--r--contrib/ffmpeg/libavformat/flvenc.c41
-rw-r--r--contrib/ffmpeg/libavformat/framecrcenc.c46
-rw-r--r--contrib/ffmpeg/libavformat/framehook.c4
-rw-r--r--contrib/ffmpeg/libavformat/framehook.h8
-rw-r--r--contrib/ffmpeg/libavformat/gif.c16
-rw-r--r--contrib/ffmpeg/libavformat/gifdec.c12
-rw-r--r--contrib/ffmpeg/libavformat/grab.c860
-rw-r--r--contrib/ffmpeg/libavformat/grab_bktr.c320
-rw-r--r--contrib/ffmpeg/libavformat/gxf.c50
-rw-r--r--contrib/ffmpeg/libavformat/gxf.h29
-rw-r--r--contrib/ffmpeg/libavformat/gxfenc.c56
-rw-r--r--contrib/ffmpeg/libavformat/http.c25
-rw-r--r--contrib/ffmpeg/libavformat/idcin.c38
-rw-r--r--contrib/ffmpeg/libavformat/idroq.c33
-rw-r--r--contrib/ffmpeg/libavformat/img2.c44
-rw-r--r--contrib/ffmpeg/libavformat/ipmovie.c22
-rw-r--r--contrib/ffmpeg/libavformat/isom.c28
-rw-r--r--contrib/ffmpeg/libavformat/isom.h7
-rw-r--r--contrib/ffmpeg/libavformat/libnut.c14
-rw-r--r--contrib/ffmpeg/libavformat/lmlm4.c126
-rw-r--r--contrib/ffmpeg/libavformat/matroska.c2827
-rw-r--r--contrib/ffmpeg/libavformat/matroska.h210
-rw-r--r--contrib/ffmpeg/libavformat/matroskadec.c2842
-rw-r--r--contrib/ffmpeg/libavformat/matroskaenc.c845
-rw-r--r--contrib/ffmpeg/libavformat/mm.c28
-rw-r--r--contrib/ffmpeg/libavformat/mmf.c26
-rw-r--r--contrib/ffmpeg/libavformat/mov.c913
-rw-r--r--contrib/ffmpeg/libavformat/movenc.c487
-rw-r--r--contrib/ffmpeg/libavformat/mp3.c374
-rw-r--r--contrib/ffmpeg/libavformat/mpc.c46
-rw-r--r--contrib/ffmpeg/libavformat/mpc8.c244
-rw-r--r--contrib/ffmpeg/libavformat/mpeg.c1495
-rw-r--r--contrib/ffmpeg/libavformat/mpeg.h69
-rw-r--r--contrib/ffmpeg/libavformat/mpegenc.c1294
-rw-r--r--contrib/ffmpeg/libavformat/mpegts.c589
-rw-r--r--contrib/ffmpeg/libavformat/mpegts.h10
-rw-r--r--contrib/ffmpeg/libavformat/mpegtsenc.c12
-rw-r--r--contrib/ffmpeg/libavformat/mpjpeg.c12
-rw-r--r--contrib/ffmpeg/libavformat/mtv.c21
-rw-r--r--contrib/ffmpeg/libavformat/mxf.c389
-rw-r--r--contrib/ffmpeg/libavformat/network.h40
-rw-r--r--contrib/ffmpeg/libavformat/nsvdec.c28
-rw-r--r--contrib/ffmpeg/libavformat/nut.c1449
-rw-r--r--contrib/ffmpeg/libavformat/nut.h35
-rw-r--r--contrib/ffmpeg/libavformat/nutdec.c321
-rw-r--r--contrib/ffmpeg/libavformat/nutenc.c775
-rw-r--r--contrib/ffmpeg/libavformat/nuv.c33
-rw-r--r--contrib/ffmpeg/libavformat/ogg.c283
-rw-r--r--contrib/ffmpeg/libavformat/oggdec.c (renamed from contrib/ffmpeg/libavformat/ogg2.c)170
-rw-r--r--contrib/ffmpeg/libavformat/oggdec.h (renamed from contrib/ffmpeg/libavformat/ogg2.h)20
-rw-r--r--contrib/ffmpeg/libavformat/oggenc.c292
-rw-r--r--contrib/ffmpeg/libavformat/oggparseflac.c20
-rw-r--r--contrib/ffmpeg/libavformat/oggparseogm.c71
-rw-r--r--contrib/ffmpeg/libavformat/oggparsespeex.c61
-rw-r--r--contrib/ffmpeg/libavformat/oggparsetheora.c37
-rw-r--r--contrib/ffmpeg/libavformat/oggparsevorbis.c123
-rw-r--r--contrib/ffmpeg/libavformat/os_support.c114
-rw-r--r--contrib/ffmpeg/libavformat/os_support.h32
-rw-r--r--contrib/ffmpeg/libavformat/psxstr.c26
-rw-r--r--contrib/ffmpeg/libavformat/pva.c211
-rw-r--r--contrib/ffmpeg/libavformat/qtpalette.h14
-rw-r--r--contrib/ffmpeg/libavformat/raw.c216
-rw-r--r--contrib/ffmpeg/libavformat/raw.h30
-rw-r--r--contrib/ffmpeg/libavformat/riff.c143
-rw-r--r--contrib/ffmpeg/libavformat/riff.h13
-rw-r--r--contrib/ffmpeg/libavformat/rm.c1147
-rw-r--r--contrib/ffmpeg/libavformat/rm.h108
-rw-r--r--contrib/ffmpeg/libavformat/rmdec.c801
-rw-r--r--contrib/ffmpeg/libavformat/rmenc.c444
-rw-r--r--contrib/ffmpeg/libavformat/rtp.c927
-rw-r--r--contrib/ffmpeg/libavformat/rtp.h26
-rw-r--r--contrib/ffmpeg/libavformat/rtp_aac.c88
-rw-r--r--contrib/ffmpeg/libavformat/rtp_aac.h27
-rw-r--r--contrib/ffmpeg/libavformat/rtp_h264.c21
-rw-r--r--contrib/ffmpeg/libavformat/rtp_h264.h10
-rw-r--r--contrib/ffmpeg/libavformat/rtp_internal.h31
-rw-r--r--contrib/ffmpeg/libavformat/rtp_mpv.c118
-rw-r--r--contrib/ffmpeg/libavformat/rtp_mpv.h27
-rw-r--r--contrib/ffmpeg/libavformat/rtpdec.c552
-rw-r--r--contrib/ffmpeg/libavformat/rtpenc.c366
-rw-r--r--contrib/ffmpeg/libavformat/rtpenc_h264.c78
-rw-r--r--contrib/ffmpeg/libavformat/rtpproto.c29
-rw-r--r--contrib/ffmpeg/libavformat/rtsp.c204
-rw-r--r--contrib/ffmpeg/libavformat/rtsp.h15
-rw-r--r--contrib/ffmpeg/libavformat/rtspcodes.h4
-rw-r--r--contrib/ffmpeg/libavformat/sdp.c320
-rw-r--r--contrib/ffmpeg/libavformat/segafilm.c39
-rw-r--r--contrib/ffmpeg/libavformat/sierravmd.c34
-rw-r--r--contrib/ffmpeg/libavformat/siff.c237
-rw-r--r--contrib/ffmpeg/libavformat/smacker.c51
-rw-r--r--contrib/ffmpeg/libavformat/sol.c10
-rw-r--r--contrib/ffmpeg/libavformat/swf.c379
-rw-r--r--contrib/ffmpeg/libavformat/tcp.c35
-rw-r--r--contrib/ffmpeg/libavformat/thp.c195
-rw-r--r--contrib/ffmpeg/libavformat/tiertexseq.c24
-rw-r--r--contrib/ffmpeg/libavformat/tta.c91
-rw-r--r--contrib/ffmpeg/libavformat/txd.c103
-rw-r--r--contrib/ffmpeg/libavformat/udp.c320
-rw-r--r--contrib/ffmpeg/libavformat/utils.c1048
-rw-r--r--contrib/ffmpeg/libavformat/v4l2.c631
-rw-r--r--contrib/ffmpeg/libavformat/vc1test.c112
-rw-r--r--contrib/ffmpeg/libavformat/voc.c2
-rw-r--r--contrib/ffmpeg/libavformat/voc.h8
-rw-r--r--contrib/ffmpeg/libavformat/vocdec.c26
-rw-r--r--contrib/ffmpeg/libavformat/vocenc.c10
-rw-r--r--contrib/ffmpeg/libavformat/wav.c34
-rw-r--r--contrib/ffmpeg/libavformat/wc3movie.c40
-rw-r--r--contrib/ffmpeg/libavformat/westwood.c40
-rw-r--r--contrib/ffmpeg/libavformat/wv.c25
-rw-r--r--contrib/ffmpeg/libavformat/x11grab.c529
-rw-r--r--contrib/ffmpeg/libavformat/yuv4mpeg.c24
158 files changed, 17966 insertions, 16876 deletions
diff --git a/contrib/ffmpeg/libavformat/4xm.c b/contrib/ffmpeg/libavformat/4xm.c
index bf10b9e82..151e9c9c8 100644
--- a/contrib/ffmpeg/libavformat/4xm.c
+++ b/contrib/ffmpeg/libavformat/4xm.c
@@ -44,6 +44,9 @@
#define ifrm_TAG MKTAG('i', 'f', 'r', 'm')
#define pfrm_TAG MKTAG('p', 'f', 'r', 'm')
#define cfrm_TAG MKTAG('c', 'f', 'r', 'm')
+#define ifr2_TAG MKTAG('i', 'f', 'r', '2')
+#define pfr2_TAG MKTAG('p', 'f', 'r', '2')
+#define cfr2_TAG MKTAG('c', 'f', 'r', '2')
#define snd__TAG MKTAG('s', 'n', 'd', '_')
#define vtrk_SIZE 0x44
@@ -79,9 +82,6 @@ typedef struct FourxmDemuxContext {
static int fourxm_probe(AVProbeData *p)
{
- if (p->buf_size < 12)
- return 0;
-
if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
(AV_RL32(&p->buf[8]) != _4XMV_TAG))
return 0;
@@ -92,11 +92,11 @@ static int fourxm_probe(AVProbeData *p)
static int fourxm_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size;
int header_size;
- FourxmDemuxContext *fourxm = (FourxmDemuxContext *)s->priv_data;
+ FourxmDemuxContext *fourxm = s->priv_data;
unsigned char *header;
int i;
int current_track = -1;
@@ -119,9 +119,9 @@ static int fourxm_read_header(AVFormatContext *s,
/* allocate space for the header and load the whole thing */
header = av_malloc(header_size);
if (!header)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
if (get_buffer(pb, header, header_size) != header_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* take the lazy approach and search for any and all vtrk and strk chunks */
for (i = 0; i < header_size - 8; i++) {
@@ -138,22 +138,24 @@ static int fourxm_read_header(AVFormatContext *s,
}
fourxm->width = AV_RL32(&header[i + 36]);
fourxm->height = AV_RL32(&header[i + 40]);
- i += 8 + size;
/* allocate a new AVStream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 60, 1, fourxm->fps);
fourxm->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_4XM;
- st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->extradata_size = 4;
+ st->codec->extradata = av_malloc(4);
+ AV_WL32(st->codec->extradata, AV_RL32(&header[i + 16]));
st->codec->width = fourxm->width;
st->codec->height = fourxm->height;
+ i += 8 + size;
} else if (fourcc_tag == strk_TAG) {
/* check that there is enough data */
if (size != strk_SIZE) {
@@ -169,7 +171,7 @@ static int fourxm_read_header(AVFormatContext *s,
fourxm->track_count * sizeof(AudioTrack));
if (!fourxm->tracks) {
av_free(header);
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
}
fourxm->tracks[current_track].adpcm = AV_RL32(&header[i + 12]);
@@ -181,7 +183,7 @@ static int fourxm_read_header(AVFormatContext *s,
/* allocate a new AVStream */
st = av_new_stream(s, current_track);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate);
@@ -222,7 +224,7 @@ static int fourxm_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
FourxmDemuxContext *fourxm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size, out_size;
int ret = 0;
@@ -233,12 +235,12 @@ static int fourxm_read_packet(AVFormatContext *s,
while (!packet_read) {
- if ((ret = get_buffer(&s->pb, header, 8)) < 0)
+ if ((ret = get_buffer(s->pb, header, 8)) < 0)
return ret;
fourcc_tag = AV_RL32(&header[0]);
size = AV_RL32(&header[4]);
if (url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
switch (fourcc_tag) {
case LIST_TAG:
@@ -251,17 +253,21 @@ static int fourxm_read_packet(AVFormatContext *s,
case ifrm_TAG:
case pfrm_TAG:
- case cfrm_TAG:{
+ case cfrm_TAG:
+ case ifr2_TAG:
+ case pfr2_TAG:
+ case cfr2_TAG:
+ {
/* allocate 8 more bytes than 'size' to account for fourcc
* and size */
if (size + 8 < size || av_new_packet(pkt, size + 8))
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = fourxm->video_stream_index;
pkt->pts = fourxm->video_pts;
- pkt->pos = url_ftell(&s->pb);
+ pkt->pos = url_ftell(s->pb);
memcpy(pkt->data, header, 8);
- ret = get_buffer(&s->pb, &pkt->data[8], size);
+ ret = get_buffer(s->pb, &pkt->data[8], size);
if (ret < 0)
av_free_packet(pkt);
@@ -276,9 +282,9 @@ static int fourxm_read_packet(AVFormatContext *s,
size-=8;
if (track_number == fourxm->selected_track) {
- ret= av_get_packet(&s->pb, pkt, size);
+ ret= av_get_packet(s->pb, pkt, size);
if(ret<0)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index =
fourxm->tracks[fourxm->selected_track].stream_index;
pkt->pts = fourxm->audio_pts;
@@ -313,7 +319,7 @@ static int fourxm_read_packet(AVFormatContext *s,
static int fourxm_read_close(AVFormatContext *s)
{
- FourxmDemuxContext *fourxm = (FourxmDemuxContext *)s->priv_data;
+ FourxmDemuxContext *fourxm = s->priv_data;
av_free(fourxm->tracks);
diff --git a/contrib/ffmpeg/libavformat/Makefile b/contrib/ffmpeg/libavformat/Makefile
index f1339bd9d..041f224a7 100644
--- a/contrib/ffmpeg/libavformat/Makefile
+++ b/contrib/ffmpeg/libavformat/Makefile
@@ -4,135 +4,175 @@
#
include ../config.mak
-CFLAGS+=-I$(SRC_PATH)/libavcodec
+CFLAGS += -I$(SRC_PATH)/libavcodec
-OBJS= utils.o cutils.o os_support.o allformats.o
+OBJS = allformats.o cutils.o os_support.o sdp.o utils.o
-HEADERS = avformat.h avio.h rtp.h rtsp.h rtspcodes.h
+HEADERS = avformat.h avio.h rtsp.h rtspcodes.h
# muxers/demuxers
-OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o
+OBJS-$(CONFIG_AAC_DEMUXER) += raw.o
+OBJS-$(CONFIG_AC3_DEMUXER) += raw.o
+OBJS-$(CONFIG_AC3_MUXER) += raw.o
OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o
-OBJS-$(CONFIG_AIFF_DEMUXER) += aiff.o riff.o
+OBJS-$(CONFIG_AIFF_DEMUXER) += aiff.o riff.o raw.o
OBJS-$(CONFIG_AIFF_MUXER) += aiff.o riff.o
OBJS-$(CONFIG_AMR_DEMUXER) += amr.o
OBJS-$(CONFIG_AMR_MUXER) += amr.o
-OBJS-$(CONFIG_ASF_DEMUXER) += asf.o riff.o
+OBJS-$(CONFIG_APC_DEMUXER) += apc.o
+OBJS-$(CONFIG_APE_DEMUXER) += ape.o
+OBJS-$(CONFIG_ASF_DEMUXER) += asf.o asfcrypt.o riff.o
OBJS-$(CONFIG_ASF_MUXER) += asf-enc.o riff.o
OBJS-$(CONFIG_ASF_STREAM_MUXER) += asf-enc.o riff.o
-OBJS-$(CONFIG_AU_DEMUXER) += au.o riff.o
-OBJS-$(CONFIG_AU_MUXER) += au.o riff.o
+OBJS-$(CONFIG_AU_DEMUXER) += au.o raw.o
+OBJS-$(CONFIG_AU_MUXER) += au.o
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o
OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o
OBJS-$(CONFIG_AVISYNTH) += avisynth.o
-OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o riff.o
-OBJS-$(CONFIG_CRC_MUXER) += crc.o
-OBJS-$(CONFIG_FRAMECRC_MUXER) += crc.o
+OBJS-$(CONFIG_AVM2_MUXER) += swf.o
+OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o
+OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o
+OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o
+OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o
-OBJS-$(CONFIG_DC1394_DEMUXER) += dc1394.o
OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o
+OBJS-$(CONFIG_DTS_DEMUXER) += raw.o
OBJS-$(CONFIG_DV_DEMUXER) += dv.o
OBJS-$(CONFIG_DV_MUXER) += dvenc.o
-OBJS-$(CONFIG_DV1394_DEMUXER) += dv1394.o
-OBJS-$(CONFIG_DXA_DEMUXER) += dxa.o
+OBJS-$(CONFIG_DXA_DEMUXER) += dxa.o riff.o
+OBJS-$(CONFIG_EA_CDATA_DEMUXER) += eacdata.o
OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o
OBJS-$(CONFIG_FFM_DEMUXER) += ffm.o
OBJS-$(CONFIG_FFM_MUXER) += ffm.o
+OBJS-$(CONFIG_FLAC_DEMUXER) += raw.o
+OBJS-$(CONFIG_FLAC_MUXER) += raw.o
OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o
OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o
OBJS-$(CONFIG_FLV_MUXER) += flvenc.o
+OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o
+OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o
OBJS-$(CONFIG_GIF_MUXER) += gif.o
OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o
OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o
OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o
+OBJS-$(CONFIG_H261_DEMUXER) += raw.o
+OBJS-$(CONFIG_H261_MUXER) += raw.o
+OBJS-$(CONFIG_H263_DEMUXER) += raw.o
+OBJS-$(CONFIG_H263_MUXER) += raw.o
+OBJS-$(CONFIG_H264_DEMUXER) += raw.o
+OBJS-$(CONFIG_H264_MUXER) += raw.o
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
-OBJS-$(CONFIG_ROQ_DEMUXER) += idroq.o
OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2.o
-OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2.o
OBJS-$(CONFIG_IMAGE2_MUXER) += img2.o
+OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2.o
OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2.o
+OBJS-$(CONFIG_INGENIENT_DEMUXER) += raw.o
OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o
-OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroska.o riff.o
+OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o
+OBJS-$(CONFIG_M4V_DEMUXER) += raw.o
+OBJS-$(CONFIG_M4V_MUXER) += raw.o
+OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += matroskaenc.o matroska.o riff.o avc.o
+OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o riff.o
+OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o riff.o avc.o
+OBJS-$(CONFIG_MJPEG_DEMUXER) += raw.o
+OBJS-$(CONFIG_MJPEG_MUXER) += raw.o
OBJS-$(CONFIG_MM_DEMUXER) += mm.o
-OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o riff.o
+OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o raw.o
OBJS-$(CONFIG_MMF_MUXER) += mmf.o riff.o
OBJS-$(CONFIG_MOV_DEMUXER) += mov.o riff.o isom.o
-OBJS-$(CONFIG_MOV_MUXER) += movenc.o riff.o isom.o
-OBJS-$(CONFIG_TGP_MUXER) += movenc.o riff.o isom.o
-OBJS-$(CONFIG_MP4_MUXER) += movenc.o riff.o isom.o
-OBJS-$(CONFIG_PSP_MUXER) += movenc.o riff.o isom.o
-OBJS-$(CONFIG_TG2_MUXER) += movenc.o riff.o isom.o
-OBJS-$(CONFIG_MP3_DEMUXER) += mp3.o
+OBJS-$(CONFIG_MOV_MUXER) += movenc.o riff.o isom.o avc.o
OBJS-$(CONFIG_MP2_MUXER) += mp3.o
+OBJS-$(CONFIG_MP3_DEMUXER) += mp3.o
OBJS-$(CONFIG_MP3_MUXER) += mp3.o
+OBJS-$(CONFIG_MP4_MUXER) += movenc.o riff.o isom.o avc.o
OBJS-$(CONFIG_MPC_DEMUXER) += mpc.o
-OBJS-$(CONFIG_MPEG1SYSTEM_MUXER) += mpeg.o
-OBJS-$(CONFIG_MPEG1VCD_MUXER) += mpeg.o
-OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpeg.o
-OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpeg.o
-OBJS-$(CONFIG_MPEG2DVD_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPC8_DEMUXER) += mpc8.o
+OBJS-$(CONFIG_MPEG1SYSTEM_MUXER) += mpegenc.o
+OBJS-$(CONFIG_MPEG1VCD_MUXER) += mpegenc.o
+OBJS-$(CONFIG_MPEG2DVD_MUXER) += mpegenc.o
+OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpegenc.o
+OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpegenc.o
+OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += raw.o
+OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += raw.o
OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o
+OBJS-$(CONFIG_MPEGTSRAW_DEMUXER) += mpegts.o
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o
+OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += raw.o
OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o
OBJS-$(CONFIG_MXF_DEMUXER) += mxf.o
-OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o riff.o
+OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o
+OBJS-$(CONFIG_NULL_MUXER) += raw.o
+OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o riff.o
+OBJS-$(CONFIG_NUT_MUXER) += nutenc.o nut.o riff.o
OBJS-$(CONFIG_NUV_DEMUXER) += nuv.o riff.o
-OBJS-$(CONFIG_OGG_DEMUXER) += ogg2.o \
- oggparsevorbis.o \
- oggparsetheora.o \
+OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \
oggparseflac.o \
oggparseogm.o \
+ oggparsespeex.o \
+ oggparsetheora.o \
+ oggparsevorbis.o \
riff.o
-OBJS-$(CONFIG_OGG_MUXER) += ogg.o
-OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o
-OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o
-OBJS-$(CONFIG_FLAC_DEMUXER) += raw.o
-OBJS-$(CONFIG_FLAC_MUXER) += raw.o
-OBJS-$(CONFIG_AC3_DEMUXER) += raw.o
-OBJS-$(CONFIG_AC3_MUXER) += raw.o
-OBJS-$(CONFIG_DTS_DEMUXER) += raw.o
-OBJS-$(CONFIG_AAC_DEMUXER) += raw.o
-OBJS-$(CONFIG_H261_DEMUXER) += raw.o
-OBJS-$(CONFIG_H261_MUXER) += raw.o
-OBJS-$(CONFIG_H263_DEMUXER) += raw.o
-OBJS-$(CONFIG_H263_MUXER) += raw.o
-OBJS-$(CONFIG_M4V_DEMUXER) += raw.o
-OBJS-$(CONFIG_M4V_MUXER) += raw.o
-OBJS-$(CONFIG_H264_DEMUXER) += raw.o
-OBJS-$(CONFIG_H264_MUXER) += raw.o
-OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += raw.o
-OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += raw.o
-OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += raw.o
-OBJS-$(CONFIG_MJPEG_DEMUXER) += raw.o
-OBJS-$(CONFIG_INGENIENT_DEMUXER) += raw.o
-OBJS-$(CONFIG_MJPEG_MUXER) += raw.o
+OBJS-$(CONFIG_OGG_MUXER) += oggenc.o
+OBJS-$(CONFIG_PCM_ALAW_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_ALAW_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_MULAW_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_MULAW_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_S16BE_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_S16BE_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_S16LE_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_S16LE_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_S8_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_S8_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_U16BE_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_U16BE_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_U16LE_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_U16LE_MUXER) += raw.o
+OBJS-$(CONFIG_PCM_U8_DEMUXER) += raw.o
+OBJS-$(CONFIG_PCM_U8_MUXER) += raw.o
+OBJS-$(CONFIG_PSP_MUXER) += movenc.o riff.o isom.o avc.o
+OBJS-$(CONFIG_PVA_DEMUXER) += pva.o
OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += raw.o
OBJS-$(CONFIG_RAWVIDEO_MUXER) += raw.o
-OBJS-$(CONFIG_NULL_MUXER) += raw.o
-OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o riff.o
-OBJS-$(CONFIG_RM_DEMUXER) += rm.o
-OBJS-$(CONFIG_RM_MUXER) += rm.o
+OBJS-$(CONFIG_REDIR_DEMUXER) += rtsp.o
+OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o
+OBJS-$(CONFIG_RM_MUXER) += rmenc.o
+OBJS-$(CONFIG_ROQ_DEMUXER) += idroq.o
+OBJS-$(CONFIG_ROQ_MUXER) += raw.o
+OBJS-$(CONFIG_RTP_MUXER) += rtp.o \
+ rtpenc.o \
+ rtp_mpv.o \
+ rtp_aac.o \
+ rtpenc_h264.o \
+ avc.o
+OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o
+OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o rtp.o rtpdec.o rtp_h264.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
-OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o
+OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o
+OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o
OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o
-OBJS-$(CONFIG_SOL_DEMUXER) += sol.o
+OBJS-$(CONFIG_SOL_DEMUXER) += sol.o raw.o
+OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o
OBJS-$(CONFIG_SWF_DEMUXER) += swf.o
OBJS-$(CONFIG_SWF_MUXER) += swf.o
+OBJS-$(CONFIG_TG2_MUXER) += movenc.o riff.o isom.o avc.o
+OBJS-$(CONFIG_TGP_MUXER) += movenc.o riff.o isom.o avc.o
OBJS-$(CONFIG_THP_DEMUXER) += thp.o
OBJS-$(CONFIG_TIERTEXSEQ_DEMUXER) += tiertexseq.o
OBJS-$(CONFIG_TTA_DEMUXER) += tta.o
-OBJS-$(CONFIG_V4L2_DEMUXER) += v4l2.o
-OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o riff.o
-OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o riff.o
-OBJS-$(CONFIG_WAV_DEMUXER) += wav.o riff.o
+OBJS-$(CONFIG_TXD_DEMUXER) += txd.o
+OBJS-$(CONFIG_VC1_DEMUXER) += raw.o
+OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o
+OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o
+OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o
+OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o
+OBJS-$(CONFIG_WAV_DEMUXER) += wav.o riff.o raw.o
OBJS-$(CONFIG_WAV_MUXER) += wav.o riff.o
OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o
OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood.o
OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o
OBJS-$(CONFIG_WV_DEMUXER) += wv.o
-OBJS-$(CONFIG_X11_GRAB_DEVICE_DEMUXER) += x11grab.o
OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o
OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o
@@ -140,37 +180,20 @@ OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o
OBJS-$(CONFIG_LIBNUT_DEMUXER) += libnut.o riff.o
OBJS-$(CONFIG_LIBNUT_MUXER) += libnut.o riff.o
-OBJS+= framehook.o
-
-ifeq ($(CONFIG_V4L),yes)
-OBJS-$(CONFIG_VIDEO_GRAB_DEVICE_DEMUXER) += grab.o
-endif
-
-ifeq ($(CONFIG_BKTR),yes)
-OBJS-$(CONFIG_VIDEO_GRAB_DEVICE_DEMUXER) += grab_bktr.o
-endif
-
-ifeq ($(CONFIG_AUDIO_OSS),yes)
-OBJS-$(CONFIG_AUDIO_DEMUXER) += audio.o
-OBJS-$(CONFIG_AUDIO_MUXER) += audio.o
-endif
-
-EXTRALIBS := -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) \
- -lavcodec$(BUILDSUF) -L$(BUILD_ROOT)/libavcodec $(EXTRALIBS)
+OBJS-$(CONFIG_VHOOK) += framehook.o
-ifeq ($(CONFIG_AUDIO_BEOS),yes)
-CPPOBJS+= beosaudio.o
-endif
+EXTRALIBS := -L$(BUILD_ROOT)/libavcodec -lavcodec$(BUILDSUF) \
+ -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) $(EXTRALIBS)
# protocols I/O
OBJS+= avio.o aviobuf.o
-ifeq ($(CONFIG_PROTOCOLS),yes)
-OBJS+= file.o
-ifeq ($(CONFIG_NETWORK),yes)
-OBJS+= udp.o tcp.o http.o rtsp.o rtp.o rtpproto.o mpegts.o rtp_h264.o
-endif
-endif
+OBJS-$(CONFIG_FILE_PROTOCOL) += file.o
+OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o
+OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o
+OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o
+OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o
+OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o
NAME=avformat
LIBVERSION=$(LAVFVERSION)
diff --git a/contrib/ffmpeg/libavformat/adtsenc.c b/contrib/ffmpeg/libavformat/adtsenc.c
index 1ef683838..1949fcf54 100644
--- a/contrib/ffmpeg/libavformat/adtsenc.c
+++ b/contrib/ffmpeg/libavformat/adtsenc.c
@@ -1,7 +1,7 @@
/*
* ADTS muxer.
* Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
- * Mans Rullgard <mru@inprovide.com>
+ * Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
@@ -84,20 +84,15 @@ static int adts_write_frame_header(AVFormatContext *s, int size)
put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
flush_put_bits(&pb);
- put_buffer(&s->pb, buf, ADTS_HEADER_SIZE);
+ put_buffer(s->pb, buf, ADTS_HEADER_SIZE);
return 0;
}
-static int adts_write_trailer(AVFormatContext *s)
-{
- return 0;
-}
-
static int adts_write_packet(AVFormatContext *s, AVPacket *pkt)
{
ADTSContext *adts = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
if (!pkt->size)
return 0;
@@ -119,5 +114,4 @@ AVOutputFormat adts_muxer = {
CODEC_ID_NONE,
adts_write_header,
adts_write_packet,
- adts_write_trailer,
};
diff --git a/contrib/ffmpeg/libavformat/aiff.c b/contrib/ffmpeg/libavformat/aiff.c
index 868d55219..91be89b30 100644
--- a/contrib/ffmpeg/libavformat/aiff.c
+++ b/contrib/ffmpeg/libavformat/aiff.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "allformats.h"
+#include "raw.h"
#include "riff.h"
#include "intfloat_readwrite.h"
@@ -29,13 +29,14 @@ static const AVCodecTag codec_aiff_tags[] = {
{ CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') },
{ CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') },
{ CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') },
- { CODEC_ID_PCM_ALAW, MKTAG('A','L','A','W') },
{ CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') },
- { CODEC_ID_PCM_MULAW, MKTAG('U','L','A','W') },
{ CODEC_ID_MACE3, MKTAG('M','A','C','3') },
{ CODEC_ID_MACE6, MKTAG('M','A','C','6') },
{ CODEC_ID_GSM, MKTAG('G','S','M',' ') },
{ CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') },
+ { CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') },
+ { CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') },
+ { CODEC_ID_QDM2, MKTAG('Q','D','M','2') },
{ 0, 0 },
};
@@ -63,7 +64,7 @@ static int get_tag(ByteIOContext *pb, uint32_t * tag)
int size;
if (url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
*tag = get_le32(pb);
size = get_be32(pb);
@@ -103,10 +104,8 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec,
double sample_rate;
unsigned int num_frames;
-
if (size & 1)
size++;
-
codec->codec_type = CODEC_TYPE_AUDIO;
codec->channels = get_be16(pb);
num_frames = get_be32(pb);
@@ -120,17 +119,28 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec,
/* Got an AIFF-C? */
if (version == AIFF_C_VERSION1) {
codec->codec_tag = get_le32(pb);
- codec->codec_id = codec_get_id (codec_aiff_tags, codec->codec_tag);
+ codec->codec_id = codec_get_id(codec_aiff_tags, codec->codec_tag);
- if (codec->codec_id == CODEC_ID_PCM_S16BE) {
- codec->codec_id = aiff_codec_get_id (codec->bits_per_sample);
+ switch (codec->codec_id) {
+ case CODEC_ID_PCM_S16BE:
+ codec->codec_id = aiff_codec_get_id(codec->bits_per_sample);
codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id);
+ break;
+ case CODEC_ID_ADPCM_IMA_QT:
+ codec->block_align = 34*codec->channels;
+ codec->frame_size = 64;
+ break;
+ case CODEC_ID_MACE3:
+ case CODEC_ID_MACE6:
+ codec->frame_size = 6;
+ break;
+ default:
+ break;
}
-
size -= 4;
} else {
/* Need the codec type */
- codec->codec_id = aiff_codec_get_id (codec->bits_per_sample);
+ codec->codec_id = aiff_codec_get_id(codec->bits_per_sample);
codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id);
}
@@ -139,7 +149,8 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec,
/* Block align needs to be computed in all cases, as the definition
* is specific to applications -> here we use the WAVE format definition */
- codec->block_align = (codec->bits_per_sample * codec->channels) >> 3;
+ if (!codec->block_align)
+ codec->block_align = (codec->bits_per_sample * codec->channels) >> 3;
codec->bit_rate = codec->sample_rate * (codec->block_align << 3);
@@ -160,16 +171,14 @@ typedef struct {
static int aiff_write_header(AVFormatContext *s)
{
AIFFOutputContext *aiff = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[0]->codec;
AVExtFloat sample_rate;
int aifc = 0;
/* First verify if format is ok */
- if (!enc->codec_tag) {
+ if (!enc->codec_tag)
return -1;
- }
-
if (enc->codec_tag != MKTAG('N','O','N','E'))
aifc = 1;
@@ -179,7 +188,12 @@ static int aiff_write_header(AVFormatContext *s)
put_be32(pb, 0); /* file length */
put_tag(pb, aifc ? "AIFC" : "AIFF");
- if (aifc) {
+ if (aifc) { // compressed audio
+ enc->bits_per_sample = 16;
+ if (!enc->block_align) {
+ av_log(s, AV_LOG_ERROR, "block align not set\n");
+ return -1;
+ }
/* Version chunk */
put_tag(pb, "FVER");
put_be32(pb, 4);
@@ -189,10 +203,10 @@ static int aiff_write_header(AVFormatContext *s)
/* Common chunk */
put_tag(pb, "COMM");
put_be32(pb, aifc ? 24 : 18); /* size */
- put_be16(pb, enc->channels); /* Number of channels */
+ put_be16(pb, enc->channels); /* Number of channels */
aiff->frames = url_ftell(pb);
- put_be32(pb, 0); /* Number of frames */
+ put_be32(pb, 0); /* Number of frames */
if (!enc->bits_per_sample)
enc->bits_per_sample = av_get_bits_per_sample(enc->codec_id);
@@ -230,14 +244,14 @@ static int aiff_write_header(AVFormatContext *s)
static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
put_buffer(pb, pkt->data, pkt->size);
return 0;
}
static int aiff_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AIFFOutputContext *aiff = s->priv_data;
AVCodecContext *enc = s->streams[0]->codec;
@@ -249,18 +263,18 @@ static int aiff_write_trailer(AVFormatContext *s)
end_size++;
}
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
/* File length */
url_fseek(pb, aiff->form, SEEK_SET);
- put_be32(pb, (uint32_t)(file_size - aiff->form - 4));
+ put_be32(pb, file_size - aiff->form - 4);
/* Number of sample frames */
url_fseek(pb, aiff->frames, SEEK_SET);
- put_be32(pb, ((uint32_t)(file_size-aiff->ssnd-12))/enc->block_align);
+ put_be32(pb, (file_size-aiff->ssnd-12)/enc->block_align);
/* Sound Data chunk size */
url_fseek(pb, aiff->ssnd, SEEK_SET);
- put_be32(pb, (uint32_t)(file_size - aiff->ssnd - 4));
+ put_be32(pb, file_size - aiff->ssnd - 4);
/* return to the end */
url_fseek(pb, end_size, SEEK_SET);
@@ -275,8 +289,6 @@ static int aiff_write_trailer(AVFormatContext *s)
static int aiff_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size < 16)
- return 0;
if (p->buf[0] == 'F' && p->buf[1] == 'O' &&
p->buf[2] == 'R' && p->buf[3] == 'M' &&
p->buf[8] == 'A' && p->buf[9] == 'I' &&
@@ -290,10 +302,11 @@ static int aiff_probe(AVProbeData *p)
static int aiff_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- int size, filesize, offset;
+ int size, filesize;
+ offset_t offset = 0;
uint32_t tag;
unsigned version = AIFF_C_VERSION1;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream * st = s->streams[0];
/* check FORM header */
@@ -312,7 +325,7 @@ static int aiff_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
while (filesize > 0) {
/* parse different chunks */
@@ -323,42 +336,54 @@ static int aiff_read_header(AVFormatContext *s,
filesize -= size + 8;
switch (tag) {
- case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
- /* Then for the complete header info */
- st->nb_frames = get_aiff_header (pb, st->codec, size, version);
- if (st->nb_frames < 0)
- return st->nb_frames;
- break;
-
- case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
- version = get_be32(pb);
- break;
-
- case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
- get_meta (pb, s->title, sizeof(s->title), size);
- break;
-
- case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
- get_meta (pb, s->author, sizeof(s->author), size);
- break;
-
- case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
- get_meta (pb, s->copyright, sizeof(s->copyright), size);
- break;
-
- case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
- get_meta (pb, s->comment, sizeof(s->comment), size);
- break;
-
- case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
- get_be32(pb); /* Block align... don't care */
- offset = get_be32(pb); /* Offset of sound data */
+ case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
+ /* Then for the complete header info */
+ st->nb_frames = get_aiff_header (pb, st->codec, size, version);
+ if (st->nb_frames < 0)
+ return st->nb_frames;
+ if (offset > 0) // COMM is after SSND
goto got_sound;
-
- default: /* Jump */
- if (size & 1) /* Always even aligned */
- size++;
- url_fskip (pb, size);
+ break;
+ case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
+ version = get_be32(pb);
+ break;
+ case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
+ get_meta (pb, s->title, sizeof(s->title), size);
+ break;
+ case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
+ get_meta (pb, s->author, sizeof(s->author), size);
+ break;
+ case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
+ get_meta (pb, s->copyright, sizeof(s->copyright), size);
+ break;
+ case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
+ get_meta (pb, s->comment, sizeof(s->comment), size);
+ break;
+ case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
+ offset = get_be32(pb); /* Offset of sound data */
+ get_be32(pb); /* BlockSize... don't care */
+ offset += url_ftell(pb); /* Compute absolute data offset */
+ if (st->codec->codec_id) /* Assume COMM already parsed */
+ goto got_sound;
+ if (url_is_streamed(pb)) {
+ av_log(s, AV_LOG_ERROR, "file is not seekable\n");
+ return -1;
+ }
+ url_fskip(pb, size - 8);
+ break;
+ case MKTAG('w', 'a', 'v', 'e'):
+ if ((uint64_t)size > (1<<30))
+ return -1;
+ st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
+ st->codec->extradata_size = size;
+ get_buffer(pb, st->codec->extradata, size);
+ break;
+ default: /* Jump */
+ if (size & 1) /* Always even aligned */
+ size++;
+ url_fskip (pb, size);
}
}
@@ -372,10 +397,11 @@ got_sound:
av_set_pts_info(st, 64, 1, st->codec->sample_rate);
st->start_time = 0;
- st->duration = st->nb_frames;
+ st->duration = st->codec->frame_size ?
+ st->nb_frames * st->codec->frame_size : st->nb_frames;
/* Position the stream at the first block */
- url_fskip(pb, offset);
+ url_fseek(pb, offset, SEEK_SET);
return 0;
}
@@ -389,11 +415,11 @@ static int aiff_read_packet(AVFormatContext *s,
int res;
/* End of stream may be reached */
- if (url_feof(&s->pb))
- return AVERROR_IO;
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
/* Now for that packet */
- res = av_get_packet(&s->pb, pkt, (MAX_SIZE / st->codec->block_align) * st->codec->block_align);
+ res = av_get_packet(s->pb, pkt, (MAX_SIZE / st->codec->block_align) * st->codec->block_align);
if (res < 0)
return res;
@@ -402,11 +428,6 @@ static int aiff_read_packet(AVFormatContext *s,
return 0;
}
-static int aiff_read_close(AVFormatContext *s)
-{
- return 0;
-}
-
static int aiff_read_seek(AVFormatContext *s,
int stream_index, int64_t timestamp, int flags)
{
@@ -421,7 +442,7 @@ AVInputFormat aiff_demuxer = {
aiff_probe,
aiff_read_header,
aiff_read_packet,
- aiff_read_close,
+ NULL,
aiff_read_seek,
.codec_tag= (const AVCodecTag*[]){codec_aiff_tags, 0},
};
diff --git a/contrib/ffmpeg/libavformat/allformats.c b/contrib/ffmpeg/libavformat/allformats.c
index 8534a18f6..5cafd6209 100644
--- a/contrib/ffmpeg/libavformat/allformats.c
+++ b/contrib/ffmpeg/libavformat/allformats.c
@@ -19,13 +19,18 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "allformats.h"
+#include "rtp_internal.h"
-#define REGISTER_MUXER(X,x) \
- if(ENABLE_##X##_MUXER) av_register_output_format(&x##_muxer)
-#define REGISTER_DEMUXER(X,x) \
- if(ENABLE_##X##_DEMUXER) av_register_input_format(&x##_demuxer)
+#define REGISTER_MUXER(X,x) { \
+ extern AVOutputFormat x##_muxer; \
+ if(ENABLE_##X##_MUXER) av_register_output_format(&x##_muxer); }
+#define REGISTER_DEMUXER(X,x) { \
+ extern AVInputFormat x##_demuxer; \
+ if(ENABLE_##X##_DEMUXER) av_register_input_format(&x##_demuxer); }
#define REGISTER_MUXDEMUX(X,x) REGISTER_MUXER(X,x); REGISTER_DEMUXER(X,x)
+#define REGISTER_PROTOCOL(X,x) { \
+ extern URLProtocol x##_protocol; \
+ if(ENABLE_##X##_PROTOCOL) register_protocol(&x##_protocol); }
/* If you do not call this function, then you can select exactly which
formats you want to support */
@@ -35,138 +40,140 @@
*/
void av_register_all(void)
{
- static int inited = 0;
+ static int initialized;
- if (inited != 0)
+ if (initialized)
return;
- inited = 1;
+ initialized = 1;
avcodec_init();
avcodec_register_all();
- REGISTER_DEMUXER (AAC, aac);
- REGISTER_MUXDEMUX(AC3, ac3);
- REGISTER_MUXER (ADTS, adts);
- REGISTER_MUXDEMUX(AIFF, aiff);
- REGISTER_MUXDEMUX(AMR, amr);
- REGISTER_MUXDEMUX(ASF, asf);
- REGISTER_MUXER (ASF_STREAM, asf_stream);
- REGISTER_MUXDEMUX(AU, au);
- REGISTER_MUXDEMUX(AUDIO, audio);
- REGISTER_MUXDEMUX(AVI, avi);
-#ifdef CONFIG_AVISYNTH
- av_register_input_format(&avisynth_demuxer);
-#endif
- REGISTER_DEMUXER (AVS, avs);
- REGISTER_MUXER (CRC, crc);
- REGISTER_DEMUXER (DAUD, daud);
- REGISTER_DEMUXER (DC1394, dc1394);
- REGISTER_DEMUXER (DSICIN, dsicin);
- REGISTER_DEMUXER (DTS, dts);
- REGISTER_MUXDEMUX(DV, dv);
- REGISTER_DEMUXER (DV1394, dv1394);
- REGISTER_DEMUXER (DXA, dxa);
- REGISTER_DEMUXER (EA, ea);
- REGISTER_MUXDEMUX(FFM, ffm);
- REGISTER_MUXDEMUX(FLAC, flac);
- REGISTER_DEMUXER (FLIC, flic);
- REGISTER_MUXDEMUX(FLV, flv);
- REGISTER_DEMUXER (FOURXM, fourxm);
- REGISTER_MUXER (FRAMECRC, framecrc);
- REGISTER_MUXDEMUX(GIF, gif);
- REGISTER_DEMUXER (GXF, gxf);
- REGISTER_MUXER (GXF, gxf);
- REGISTER_MUXDEMUX(H261, h261);
- REGISTER_MUXDEMUX(H263, h263);
- REGISTER_MUXDEMUX(H264, h264);
- REGISTER_DEMUXER (IDCIN, idcin);
- REGISTER_MUXDEMUX(IMAGE2, image2);
- REGISTER_MUXDEMUX(IMAGE2PIPE, image2pipe);
- REGISTER_DEMUXER (INGENIENT, ingenient);
- REGISTER_DEMUXER (IPMOVIE, ipmovie);
- if (!ENABLE_NUT_DEMUXER) REGISTER_DEMUXER (LIBNUT, libnut);
- REGISTER_MUXER (LIBNUT, libnut);
- REGISTER_MUXDEMUX(M4V, m4v);
- REGISTER_DEMUXER (MATROSKA, matroska);
- REGISTER_MUXDEMUX(MJPEG, mjpeg);
- REGISTER_DEMUXER (MM, mm);
- REGISTER_MUXDEMUX(MMF, mmf);
- REGISTER_MUXDEMUX(MOV, mov);
- REGISTER_MUXER (MP2, mp2);
- REGISTER_MUXDEMUX(MP3, mp3);
- REGISTER_MUXER (MP4, mp4);
- REGISTER_DEMUXER (MPC, mpc);
- REGISTER_MUXER (MPEG1SYSTEM, mpeg1system);
- REGISTER_MUXER (MPEG1VCD, mpeg1vcd);
- REGISTER_MUXER (MPEG1VIDEO, mpeg1video);
- REGISTER_MUXER (MPEG2DVD, mpeg2dvd);
- REGISTER_MUXER (MPEG2SVCD, mpeg2svcd);
- REGISTER_MUXER (MPEG2VIDEO, mpeg2video);
- REGISTER_MUXER (MPEG2VOB, mpeg2vob);
- REGISTER_DEMUXER (MPEGPS, mpegps);
- REGISTER_MUXDEMUX(MPEGTS, mpegts);
- REGISTER_DEMUXER (MPEGVIDEO, mpegvideo);
- REGISTER_MUXER (MPJPEG, mpjpeg);
- REGISTER_DEMUXER (MTV, mtv);
- REGISTER_DEMUXER (MXF, mxf);
- REGISTER_DEMUXER (NSV, nsv);
- REGISTER_MUXER (NULL, null);
- REGISTER_DEMUXER (NUT, nut);
- REGISTER_DEMUXER (NUV, nuv);
- REGISTER_DEMUXER (OGG, ogg);
- REGISTER_MUXER (OGG, ogg);
- REGISTER_MUXDEMUX(PCM_ALAW, pcm_alaw);
- REGISTER_MUXDEMUX(PCM_MULAW, pcm_mulaw);
- REGISTER_MUXDEMUX(PCM_S16BE, pcm_s16be);
- REGISTER_MUXDEMUX(PCM_S16LE, pcm_s16le);
- REGISTER_MUXDEMUX(PCM_S8, pcm_s8);
- REGISTER_MUXDEMUX(PCM_U16BE, pcm_u16be);
- REGISTER_MUXDEMUX(PCM_U16LE, pcm_u16le);
- REGISTER_MUXDEMUX(PCM_U8, pcm_u8);
- REGISTER_MUXER (PSP, psp);
- REGISTER_MUXDEMUX(RAWVIDEO, rawvideo);
- REGISTER_MUXDEMUX(RM, rm);
- REGISTER_DEMUXER (ROQ, roq);
- REGISTER_DEMUXER (REDIR, redir);
- REGISTER_MUXER (RTP, rtp);
- REGISTER_DEMUXER (RTSP, rtsp);
- REGISTER_DEMUXER (SDP, sdp);
-#ifdef CONFIG_NETWORK
+ /* (de)muxers */
+ REGISTER_DEMUXER (AAC, aac);
+ REGISTER_MUXDEMUX (AC3, ac3);
+ REGISTER_MUXER (ADTS, adts);
+ REGISTER_MUXDEMUX (AIFF, aiff);
+ REGISTER_MUXDEMUX (AMR, amr);
+ REGISTER_DEMUXER (APC, apc);
+ REGISTER_DEMUXER (APE, ape);
+ REGISTER_MUXDEMUX (ASF, asf);
+ REGISTER_MUXER (ASF_STREAM, asf_stream);
+ REGISTER_MUXDEMUX (AU, au);
+ REGISTER_MUXDEMUX (AVI, avi);
+ REGISTER_DEMUXER (AVISYNTH, avisynth);
+ REGISTER_MUXER (AVM2, avm2);
+ REGISTER_DEMUXER (AVS, avs);
+ REGISTER_DEMUXER (BETHSOFTVID, bethsoftvid);
+ REGISTER_DEMUXER (C93, c93);
+ REGISTER_MUXER (CRC, crc);
+ REGISTER_DEMUXER (DAUD, daud);
+ REGISTER_DEMUXER (DSICIN, dsicin);
+ REGISTER_DEMUXER (DTS, dts);
+ REGISTER_MUXDEMUX (DV, dv);
+ REGISTER_DEMUXER (DXA, dxa);
+ REGISTER_DEMUXER (EA, ea);
+ REGISTER_DEMUXER (EA_CDATA, ea_cdata);
+ REGISTER_MUXDEMUX (FFM, ffm);
+ REGISTER_MUXDEMUX (FLAC, flac);
+ REGISTER_DEMUXER (FLIC, flic);
+ REGISTER_MUXDEMUX (FLV, flv);
+ REGISTER_DEMUXER (FOURXM, fourxm);
+ REGISTER_MUXER (FRAMECRC, framecrc);
+ REGISTER_MUXDEMUX (GIF, gif);
+ REGISTER_MUXDEMUX (GXF, gxf);
+ REGISTER_MUXDEMUX (H261, h261);
+ REGISTER_MUXDEMUX (H263, h263);
+ REGISTER_MUXDEMUX (H264, h264);
+ REGISTER_DEMUXER (IDCIN, idcin);
+ REGISTER_MUXDEMUX (IMAGE2, image2);
+ REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe);
+ REGISTER_DEMUXER (INGENIENT, ingenient);
+ REGISTER_DEMUXER (IPMOVIE, ipmovie);
+ REGISTER_DEMUXER (LMLM4, lmlm4);
+ REGISTER_MUXDEMUX (M4V, m4v);
+ REGISTER_MUXDEMUX (MATROSKA, matroska);
+ REGISTER_MUXER (MATROSKA_AUDIO, matroska_audio);
+ REGISTER_MUXDEMUX (MJPEG, mjpeg);
+ REGISTER_DEMUXER (MM, mm);
+ REGISTER_MUXDEMUX (MMF, mmf);
+ REGISTER_MUXDEMUX (MOV, mov);
+ REGISTER_MUXER (MP2, mp2);
+ REGISTER_MUXDEMUX (MP3, mp3);
+ REGISTER_MUXER (MP4, mp4);
+ REGISTER_DEMUXER (MPC, mpc);
+ REGISTER_DEMUXER (MPC8, mpc8);
+ REGISTER_MUXER (MPEG1SYSTEM, mpeg1system);
+ REGISTER_MUXER (MPEG1VCD, mpeg1vcd);
+ REGISTER_MUXER (MPEG1VIDEO, mpeg1video);
+ REGISTER_MUXER (MPEG2DVD, mpeg2dvd);
+ REGISTER_MUXER (MPEG2SVCD, mpeg2svcd);
+ REGISTER_MUXER (MPEG2VIDEO, mpeg2video);
+ REGISTER_MUXER (MPEG2VOB, mpeg2vob);
+ REGISTER_DEMUXER (MPEGPS, mpegps);
+ REGISTER_MUXDEMUX (MPEGTS, mpegts);
+ REGISTER_DEMUXER (MPEGTSRAW, mpegtsraw);
+ REGISTER_DEMUXER (MPEGVIDEO, mpegvideo);
+ REGISTER_MUXER (MPJPEG, mpjpeg);
+ REGISTER_DEMUXER (MTV, mtv);
+ REGISTER_DEMUXER (MXF, mxf);
+ REGISTER_DEMUXER (NSV, nsv);
+ REGISTER_MUXER (NULL, null);
+ REGISTER_MUXDEMUX (NUT, nut);
+ REGISTER_DEMUXER (NUV, nuv);
+ REGISTER_MUXDEMUX (OGG, ogg);
+ REGISTER_MUXDEMUX (PCM_ALAW, pcm_alaw);
+ REGISTER_MUXDEMUX (PCM_MULAW, pcm_mulaw);
+ REGISTER_MUXDEMUX (PCM_S16BE, pcm_s16be);
+ REGISTER_MUXDEMUX (PCM_S16LE, pcm_s16le);
+ REGISTER_MUXDEMUX (PCM_S8, pcm_s8);
+ REGISTER_MUXDEMUX (PCM_U16BE, pcm_u16be);
+ REGISTER_MUXDEMUX (PCM_U16LE, pcm_u16le);
+ REGISTER_MUXDEMUX (PCM_U8, pcm_u8);
+ REGISTER_MUXER (PSP, psp);
+ REGISTER_DEMUXER (PVA, pva);
+ REGISTER_MUXDEMUX (RAWVIDEO, rawvideo);
+ REGISTER_MUXDEMUX (RM, rm);
+ REGISTER_MUXDEMUX (ROQ, roq);
+ REGISTER_DEMUXER (REDIR, redir);
+ REGISTER_MUXER (RTP, rtp);
+ REGISTER_DEMUXER (RTSP, rtsp);
+ REGISTER_DEMUXER (SDP, sdp);
+#ifdef CONFIG_SDP_DEMUXER
av_register_rtp_dynamic_payload_handlers();
#endif
- REGISTER_DEMUXER (SEGAFILM, segafilm);
- REGISTER_DEMUXER (SHORTEN, shorten);
- REGISTER_DEMUXER (SMACKER, smacker);
- REGISTER_DEMUXER (SOL, sol);
- REGISTER_DEMUXER (STR, str);
- REGISTER_MUXDEMUX(SWF, swf);
- REGISTER_MUXER (TG2, tg2);
- REGISTER_MUXER (TGP, tgp);
- REGISTER_DEMUXER (THP, thp);
- REGISTER_DEMUXER (TIERTEXSEQ, tiertexseq);
- REGISTER_DEMUXER (TTA, tta);
- REGISTER_DEMUXER (V4L2, v4l2);
- REGISTER_DEMUXER (VC1, vc1);
- REGISTER_DEMUXER (VIDEO_GRAB_DEVICE, video_grab_device);
- REGISTER_DEMUXER (VMD, vmd);
- REGISTER_MUXDEMUX(VOC, voc);
- REGISTER_MUXDEMUX(WAV, wav);
- REGISTER_DEMUXER (WC3, wc3);
- REGISTER_DEMUXER (WSAUD, wsaud);
- REGISTER_DEMUXER (WSVQA, wsvqa);
- REGISTER_DEMUXER (WV, wv);
- REGISTER_DEMUXER (X11_GRAB_DEVICE, x11_grab_device);
- REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe);
+ REGISTER_DEMUXER (SEGAFILM, segafilm);
+ REGISTER_DEMUXER (SHORTEN, shorten);
+ REGISTER_DEMUXER (SIFF, siff);
+ REGISTER_DEMUXER (SMACKER, smacker);
+ REGISTER_DEMUXER (SOL, sol);
+ REGISTER_DEMUXER (STR, str);
+ REGISTER_MUXDEMUX (SWF, swf);
+ REGISTER_MUXER (TG2, tg2);
+ REGISTER_MUXER (TGP, tgp);
+ REGISTER_DEMUXER (THP, thp);
+ REGISTER_DEMUXER (TIERTEXSEQ, tiertexseq);
+ REGISTER_DEMUXER (TTA, tta);
+ REGISTER_DEMUXER (TXD, txd);
+ REGISTER_DEMUXER (VC1, vc1);
+ REGISTER_DEMUXER (VC1T, vc1t);
+ REGISTER_DEMUXER (VMD, vmd);
+ REGISTER_MUXDEMUX (VOC, voc);
+ REGISTER_MUXDEMUX (WAV, wav);
+ REGISTER_DEMUXER (WC3, wc3);
+ REGISTER_DEMUXER (WSAUD, wsaud);
+ REGISTER_DEMUXER (WSVQA, wsvqa);
+ REGISTER_DEMUXER (WV, wv);
+ REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe);
-#ifdef CONFIG_PROTOCOLS
- /* file protocols */
- register_protocol(&file_protocol);
- register_protocol(&pipe_protocol);
-#ifdef CONFIG_NETWORK
- register_protocol(&udp_protocol);
- register_protocol(&rtp_protocol);
- register_protocol(&tcp_protocol);
- register_protocol(&http_protocol);
-#endif
-#endif
+ /* external libraries */
+ REGISTER_MUXDEMUX (LIBNUT, libnut);
+
+ /* protocols */
+ REGISTER_PROTOCOL (FILE, file);
+ REGISTER_PROTOCOL (HTTP, http);
+ REGISTER_PROTOCOL (PIPE, pipe);
+ REGISTER_PROTOCOL (RTP, rtp);
+ REGISTER_PROTOCOL (TCP, tcp);
+ REGISTER_PROTOCOL (UDP, udp);
}
diff --git a/contrib/ffmpeg/libavformat/allformats.h b/contrib/ffmpeg/libavformat/allformats.h
deleted file mode 100644
index 9734940d3..000000000
--- a/contrib/ffmpeg/libavformat/allformats.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Register all the formats and protocols.
- * copyright (c) 2000, 2001, 2002 Fabrice Bellard
- *
- * 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 ALLFORMATS_H
-#define ALLFORMATS_H
-
-extern AVInputFormat fourxm_demuxer;
-extern AVOutputFormat adts_muxer;
-extern AVInputFormat aiff_demuxer;
-extern AVOutputFormat aiff_muxer;
-extern AVInputFormat amr_demuxer;
-extern AVOutputFormat amr_muxer;
-extern AVInputFormat asf_demuxer;
-extern AVOutputFormat asf_muxer;
-extern AVOutputFormat asf_stream_muxer;
-extern AVInputFormat au_demuxer;
-extern AVOutputFormat au_muxer;
-extern AVInputFormat audio_demuxer;
-extern AVOutputFormat audio_muxer;
-extern AVInputFormat avi_demuxer;
-extern AVOutputFormat avi_muxer;
-extern AVInputFormat avisynth_demuxer;
-extern AVInputFormat avs_demuxer;
-extern AVOutputFormat crc_muxer;
-extern AVOutputFormat framecrc_muxer;
-extern AVInputFormat daud_demuxer;
-extern AVInputFormat dc1394_demuxer;
-extern AVInputFormat dsicin_demuxer;
-extern AVInputFormat dv1394_demuxer;
-extern AVInputFormat dv_demuxer;
-extern AVOutputFormat dv_muxer;
-extern AVInputFormat dxa_demuxer;
-extern AVInputFormat ea_demuxer;
-extern AVInputFormat ffm_demuxer;
-extern AVOutputFormat ffm_muxer;
-extern AVInputFormat flic_demuxer;
-extern AVInputFormat flv_demuxer;
-extern AVOutputFormat flv_muxer;
-extern AVOutputFormat gif_muxer;
-extern AVInputFormat gif_demuxer;
-extern AVInputFormat video_grab_device_demuxer;
-extern AVInputFormat gxf_demuxer;
-extern AVOutputFormat gxf_muxer;
-extern AVInputFormat idcin_demuxer;
-extern AVInputFormat roq_demuxer;
-extern AVInputFormat image2_demuxer;
-extern AVInputFormat image2pipe_demuxer;
-extern AVOutputFormat image2_muxer;
-extern AVOutputFormat image2pipe_muxer;
-extern AVInputFormat image_demuxer;
-extern AVInputFormat imagepipe_demuxer;
-extern AVOutputFormat image_muxer;
-extern AVOutputFormat imagepipe_muxer;
-extern AVInputFormat ipmovie_demuxer;
-extern AVInputFormat libnut_demuxer;
-extern AVOutputFormat libnut_muxer;
-extern AVInputFormat matroska_demuxer;
-extern AVInputFormat mm_demuxer;
-extern AVInputFormat mmf_demuxer;
-extern AVOutputFormat mmf_muxer;
-extern AVInputFormat mov_demuxer;
-extern AVOutputFormat mov_muxer;
-extern AVOutputFormat tgp_muxer;
-extern AVOutputFormat mp4_muxer;
-extern AVOutputFormat psp_muxer;
-extern AVOutputFormat tg2_muxer;
-extern AVInputFormat mp3_demuxer;
-extern AVOutputFormat mp2_muxer;
-extern AVOutputFormat mp3_muxer;
-extern AVInputFormat mpc_demuxer;
-extern AVOutputFormat mpeg1system_muxer;
-extern AVOutputFormat mpeg1vcd_muxer;
-extern AVOutputFormat mpeg2vob_muxer;
-extern AVOutputFormat mpeg2svcd_muxer;
-extern AVOutputFormat mpeg2dvd_muxer;
-extern AVInputFormat mpegps_demuxer;
-extern AVInputFormat mpegts_demuxer;
-extern AVOutputFormat mpegts_muxer;
-extern AVOutputFormat mpjpeg_muxer;
-extern AVInputFormat mtv_demuxer;
-extern AVInputFormat mxf_demuxer;
-extern AVInputFormat nsv_demuxer;
-extern AVInputFormat nut_demuxer;
-extern AVInputFormat nuv_demuxer;
-extern AVInputFormat ogg_demuxer;
-extern AVOutputFormat ogg_muxer;
-extern AVInputFormat str_demuxer;
-extern AVInputFormat shorten_demuxer;
-extern AVInputFormat flac_demuxer;
-extern AVOutputFormat flac_muxer;
-extern AVInputFormat ac3_demuxer;
-extern AVOutputFormat ac3_muxer;
-extern AVInputFormat dts_demuxer;
-extern AVInputFormat aac_demuxer;
-extern AVInputFormat h261_demuxer;
-extern AVOutputFormat h261_muxer;
-extern AVInputFormat h263_demuxer;
-extern AVOutputFormat h263_muxer;
-extern AVInputFormat m4v_demuxer;
-extern AVOutputFormat m4v_muxer;
-extern AVInputFormat h264_demuxer;
-extern AVOutputFormat h264_muxer;
-extern AVInputFormat mpegvideo_demuxer;
-extern AVOutputFormat mpeg1video_muxer;
-extern AVOutputFormat mpeg2video_muxer;
-extern AVInputFormat mjpeg_demuxer;
-extern AVInputFormat ingenient_demuxer;
-extern AVOutputFormat mjpeg_muxer;
-extern AVInputFormat pcm_s16le_demuxer;
-extern AVOutputFormat pcm_s16le_muxer;
-extern AVInputFormat pcm_s16be_demuxer;
-extern AVOutputFormat pcm_s16be_muxer;
-extern AVInputFormat pcm_u16le_demuxer;
-extern AVOutputFormat pcm_u16le_muxer;
-extern AVInputFormat pcm_u16be_demuxer;
-extern AVOutputFormat pcm_u16be_muxer;
-extern AVInputFormat pcm_s8_demuxer;
-extern AVOutputFormat pcm_s8_muxer;
-extern AVInputFormat pcm_u8_demuxer;
-extern AVOutputFormat pcm_u8_muxer;
-extern AVInputFormat pcm_mulaw_demuxer;
-extern AVOutputFormat pcm_mulaw_muxer;
-extern AVInputFormat pcm_alaw_demuxer;
-extern AVOutputFormat pcm_alaw_muxer;
-extern AVInputFormat rawvideo_demuxer;
-extern AVOutputFormat rawvideo_muxer;
-extern AVOutputFormat null_muxer;
-extern AVInputFormat rm_demuxer;
-extern AVOutputFormat rm_muxer;
-extern AVInputFormat sdp_demuxer;
-extern AVInputFormat redir_demuxer;
-extern AVInputFormat segafilm_demuxer;
-extern AVInputFormat vmd_demuxer;
-extern AVInputFormat smacker_demuxer;
-extern AVInputFormat sol_demuxer;
-extern AVInputFormat swf_demuxer;
-extern AVOutputFormat swf_muxer;
-extern AVInputFormat tta_demuxer;
-extern AVInputFormat v4l2_demuxer;
-extern AVInputFormat vc1_demuxer;
-extern AVInputFormat voc_demuxer;
-extern AVOutputFormat voc_muxer;
-extern AVInputFormat wav_demuxer;
-extern AVOutputFormat wav_muxer;
-extern AVInputFormat wc3_demuxer;
-extern AVInputFormat wsaud_demuxer;
-extern AVInputFormat wsvqa_demuxer;
-extern AVInputFormat wv_demuxer;
-extern AVOutputFormat yuv4mpegpipe_muxer;
-extern AVInputFormat yuv4mpegpipe_demuxer;
-extern AVInputFormat tiertexseq_demuxer;
-extern AVInputFormat x11_grab_device_demuxer;
-extern AVInputFormat thp_demuxer;
-
-/* raw.c */
-int pcm_read_seek(AVFormatContext *s,
- int stream_index, int64_t timestamp, int flags);
-
-/* rtsp.c */
-int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f);
-/* rtp.c */
-void av_register_rtp_dynamic_payload_handlers();
-
-#endif
diff --git a/contrib/ffmpeg/libavformat/amr.c b/contrib/ffmpeg/libavformat/amr.c
index 635a898fa..d8c5399e3 100644
--- a/contrib/ffmpeg/libavformat/amr.c
+++ b/contrib/ffmpeg/libavformat/amr.c
@@ -33,7 +33,7 @@ static const char AMRWB_header [] = "#!AMR-WB\n";
#ifdef CONFIG_MUXERS
static int amr_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[0]->codec;
s->priv_data = NULL;
@@ -56,13 +56,8 @@ static int amr_write_header(AVFormatContext *s)
static int amr_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- put_buffer(&s->pb, pkt->data, pkt->size);
- put_flush_packet(&s->pb);
- return 0;
-}
-
-static int amr_write_trailer(AVFormatContext *s)
-{
+ put_buffer(s->pb, pkt->data, pkt->size);
+ put_flush_packet(s->pb);
return 0;
}
#endif /* CONFIG_MUXERS */
@@ -73,8 +68,6 @@ static int amr_probe(AVProbeData *p)
//This will also trigger multichannel files: "#!AMR_MC1.0\n" and
//"#!AMR-WB_MC1.0\n" (not supported)
- if (p->buf_size < 5)
- return 0;
if(memcmp(p->buf,AMR_header,5)==0)
return AVPROBE_SCORE_MAX;
else
@@ -85,7 +78,7 @@ static int amr_probe(AVProbeData *p)
static int amr_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
uint8_t header[9];
@@ -94,7 +87,7 @@ static int amr_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
{
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
if(memcmp(header,AMR_header,6)!=0)
{
@@ -125,15 +118,15 @@ static int amr_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
AVCodecContext *enc = s->streams[0]->codec;
- int read, size, toc, mode;
+ int read, size = 0, toc, mode;
- if (url_feof(&s->pb))
+ if (url_feof(s->pb))
{
- return AVERROR_IO;
+ return AVERROR(EIO);
}
//FIXME this is wrong, this should rather be in a AVParset
- toc=get_byte(&s->pb);
+ toc=get_byte(s->pb);
mode = (toc >> 3) & 0x0F;
if (enc->codec_id == CODEC_ID_AMR_NB)
@@ -155,19 +148,19 @@ static int amr_read_packet(AVFormatContext *s,
if ( (size==0) || av_new_packet(pkt, size))
{
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->stream_index = 0;
- pkt->pos= url_ftell(&s->pb);
+ pkt->pos= url_ftell(s->pb);
pkt->data[0]=toc;
pkt->duration= enc->codec_id == CODEC_ID_AMR_NB ? 160 : 320;
- read = get_buffer(&s->pb, pkt->data+1, size-1);
+ read = get_buffer(s->pb, pkt->data+1, size-1);
if (read != size-1)
{
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
return 0;
@@ -196,6 +189,5 @@ AVOutputFormat amr_muxer = {
CODEC_ID_NONE,
amr_write_header,
amr_write_packet,
- amr_write_trailer,
};
#endif
diff --git a/contrib/ffmpeg/libavformat/apc.c b/contrib/ffmpeg/libavformat/apc.c
new file mode 100644
index 000000000..97de8c88e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/apc.c
@@ -0,0 +1,90 @@
+/*
+ * CRYO APC audio format demuxer
+ * Copyright (c) 2007 Anssi Hannula <anssi.hannula@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 "avformat.h"
+#include "string.h"
+
+static int apc_probe(AVProbeData *p)
+{
+ if (!strncmp(p->buf, "CRYO_APC", 8))
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+static int apc_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ByteIOContext *pb = s->pb;
+ AVStream *st;
+
+ get_le32(pb); /* CRYO */
+ get_le32(pb); /* _APC */
+ get_le32(pb); /* 1.20 */
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
+
+ get_le32(pb); /* number of samples */
+ st->codec->sample_rate = get_le32(pb);
+
+ st->codec->extradata_size = 2 * 4;
+ st->codec->extradata = av_malloc(st->codec->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
+
+ /* initial predictor values for adpcm decoder */
+ get_buffer(pb, st->codec->extradata, 2 * 4);
+
+ st->codec->channels = 1;
+ if (get_le32(pb))
+ st->codec->channels = 2;
+
+ st->codec->bits_per_sample = 4;
+ st->codec->bit_rate = st->codec->bits_per_sample * st->codec->channels
+ * st->codec->sample_rate;
+ st->codec->block_align = 1;
+
+ return 0;
+}
+
+#define MAX_READ_SIZE 4096
+
+static int apc_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ if (av_get_packet(s->pb, pkt, MAX_READ_SIZE) <= 0)
+ return AVERROR(EIO);
+ pkt->stream_index = 0;
+ return 0;
+}
+
+AVInputFormat apc_demuxer = {
+ "apc",
+ "CRYO APC format",
+ 0,
+ apc_probe,
+ apc_read_header,
+ apc_read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/ape.c b/contrib/ffmpeg/libavformat/ape.c
new file mode 100644
index 000000000..a90f887e5
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ape.c
@@ -0,0 +1,523 @@
+/*
+ * Monkey's Audio APE demuxer
+ * Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
+ * based upon libdemac from Dave Chapman.
+ *
+ * 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 <stdio.h>
+
+#include "avformat.h"
+
+#define ENABLE_DEBUG 0
+
+/* The earliest and latest file formats supported by this library */
+#define APE_MIN_VERSION 3950
+#define APE_MAX_VERSION 3990
+
+#define MAC_FORMAT_FLAG_8_BIT 1 // is 8-bit [OBSOLETE]
+#define MAC_FORMAT_FLAG_CRC 2 // uses the new CRC32 error detection [OBSOLETE]
+#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL 4 // uint32 nPeakLevel after the header [OBSOLETE]
+#define MAC_FORMAT_FLAG_24_BIT 8 // is 24-bit [OBSOLETE]
+#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS 16 // has the number of seek elements after the peak level
+#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER 32 // create the wave header on decompression (not stored)
+
+#define MAC_SUBFRAME_SIZE 4608
+
+#define APE_EXTRADATA_SIZE 6
+
+/* APE tags */
+#define APE_TAG_VERSION 2000
+#define APE_TAG_FOOTER_BYTES 32
+#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31)
+#define APE_TAG_FLAG_IS_HEADER (1 << 29)
+
+#define TAG(name, field) {name, offsetof(AVFormatContext, field), sizeof(((AVFormatContext *)0)->field)}
+
+static const struct {
+ const char *name;
+ int offset;
+ int size;
+} tags[] = {
+ TAG("Title" , title ),
+ TAG("Artist" , author ),
+ TAG("Copyright", copyright),
+ TAG("Comment" , comment ),
+ TAG("Album" , album ),
+ TAG("Year" , year ),
+ TAG("Track" , track ),
+ TAG("Genre" , genre ),
+ { NULL }
+};
+
+typedef struct {
+ int64_t pos;
+ int nblocks;
+ int size;
+ int skip;
+ int64_t pts;
+} APEFrame;
+
+typedef struct {
+ /* Derived fields */
+ uint32_t junklength;
+ uint32_t firstframe;
+ uint32_t totalsamples;
+ int currentframe;
+ APEFrame *frames;
+
+ /* Info from Descriptor Block */
+ char magic[4];
+ int16_t fileversion;
+ int16_t padding1;
+ uint32_t descriptorlength;
+ uint32_t headerlength;
+ uint32_t seektablelength;
+ uint32_t wavheaderlength;
+ uint32_t audiodatalength;
+ uint32_t audiodatalength_high;
+ uint32_t wavtaillength;
+ uint8_t md5[16];
+
+ /* Info from Header Block */
+ uint16_t compressiontype;
+ uint16_t formatflags;
+ uint32_t blocksperframe;
+ uint32_t finalframeblocks;
+ uint32_t totalframes;
+ uint16_t bps;
+ uint16_t channels;
+ uint32_t samplerate;
+
+ /* Seektable */
+ uint32_t *seektable;
+} APEContext;
+
+static void ape_tag_read_field(AVFormatContext *s)
+{
+ ByteIOContext *pb = s->pb;
+ uint8_t buf[1024];
+ uint32_t size;
+ int i;
+
+ memset(buf, 0, 1024);
+ size = get_le32(pb); /* field size */
+ url_fskip(pb, 4); /* skip field flags */
+
+ for (i=0; pb->buf_ptr[i]!='0' && pb->buf_ptr[i]>=0x20 && pb->buf_ptr[i]<=0x7E; i++);
+
+ get_buffer(pb, buf, FFMIN(i, 1024));
+ url_fskip(pb, 1);
+
+ for (i=0; tags[i].name; i++)
+ if (!strcmp (buf, tags[i].name)) {
+ if (tags[i].size == sizeof(int)) {
+ char tmp[16];
+ get_buffer(pb, tmp, FFMIN(sizeof(tmp), size));
+ *(int *)(((char *)s)+tags[i].offset) = atoi(tmp);
+ } else {
+ get_buffer(pb, ((char *)s) + tags[i].offset,
+ FFMIN(tags[i].size, size));
+ }
+ break;
+ }
+
+ if (!tags[i].name)
+ url_fskip(pb, size);
+}
+
+static void ape_parse_tag(AVFormatContext *s)
+{
+ ByteIOContext *pb = s->pb;
+ int file_size = url_fsize(pb);
+ uint32_t val, fields, tag_bytes;
+ uint8_t buf[8];
+ int i;
+
+ if (file_size < APE_TAG_FOOTER_BYTES)
+ return;
+
+ url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
+
+ get_buffer(pb, buf, 8); /* APETAGEX */
+ if (strncmp(buf, "APETAGEX", 8)) {
+ av_log(NULL, AV_LOG_ERROR, "Invalid APE Tags\n");
+ return;
+ }
+
+ val = get_le32(pb); /* APE tag version */
+ if (val > APE_TAG_VERSION) {
+ av_log(NULL, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION);
+ return;
+ }
+
+ tag_bytes = get_le32(pb); /* tag size */
+ if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {
+ av_log(NULL, AV_LOG_ERROR, "Tag size is way too big\n");
+ return;
+ }
+
+ fields = get_le32(pb); /* number of fields */
+ if (fields > 65536) {
+ av_log(NULL, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);
+ return;
+ }
+
+ val = get_le32(pb); /* flags */
+ if (val & APE_TAG_FLAG_IS_HEADER) {
+ av_log(NULL, AV_LOG_ERROR, "APE Tag is a header\n");
+ return;
+ }
+
+ if (val & APE_TAG_FLAG_CONTAINS_HEADER)
+ tag_bytes += 2*APE_TAG_FOOTER_BYTES;
+
+ url_fseek(pb, file_size - tag_bytes, SEEK_SET);
+
+ for (i=0; i<fields; i++)
+ ape_tag_read_field(s);
+
+#if ENABLE_DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "\nAPE Tags:\n\n");
+ av_log(NULL, AV_LOG_DEBUG, "title = %s\n", s->title);
+ av_log(NULL, AV_LOG_DEBUG, "author = %s\n", s->author);
+ av_log(NULL, AV_LOG_DEBUG, "copyright = %s\n", s->copyright);
+ av_log(NULL, AV_LOG_DEBUG, "comment = %s\n", s->comment);
+ av_log(NULL, AV_LOG_DEBUG, "album = %s\n", s->album);
+ av_log(NULL, AV_LOG_DEBUG, "year = %d\n", s->year);
+ av_log(NULL, AV_LOG_DEBUG, "track = %d\n", s->track);
+ av_log(NULL, AV_LOG_DEBUG, "genre = %s\n", s->genre);
+#endif
+}
+
+static int ape_probe(AVProbeData * p)
+{
+ if (p->buf[0] == 'M' && p->buf[1] == 'A' && p->buf[2] == 'C' && p->buf[3] == ' ')
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+static void ape_dumpinfo(APEContext * ape_ctx)
+{
+#if ENABLE_DEBUG
+ int i;
+
+ av_log(NULL, AV_LOG_DEBUG, "Descriptor Block:\n\n");
+ av_log(NULL, AV_LOG_DEBUG, "magic = \"%c%c%c%c\"\n", ape_ctx->magic[0], ape_ctx->magic[1], ape_ctx->magic[2], ape_ctx->magic[3]);
+ av_log(NULL, AV_LOG_DEBUG, "fileversion = %d\n", ape_ctx->fileversion);
+ av_log(NULL, AV_LOG_DEBUG, "descriptorlength = %d\n", ape_ctx->descriptorlength);
+ av_log(NULL, AV_LOG_DEBUG, "headerlength = %d\n", ape_ctx->headerlength);
+ av_log(NULL, AV_LOG_DEBUG, "seektablelength = %d\n", ape_ctx->seektablelength);
+ av_log(NULL, AV_LOG_DEBUG, "wavheaderlength = %d\n", ape_ctx->wavheaderlength);
+ av_log(NULL, AV_LOG_DEBUG, "audiodatalength = %d\n", ape_ctx->audiodatalength);
+ av_log(NULL, AV_LOG_DEBUG, "audiodatalength_high = %d\n", ape_ctx->audiodatalength_high);
+ av_log(NULL, AV_LOG_DEBUG, "wavtaillength = %d\n", ape_ctx->wavtaillength);
+ av_log(NULL, AV_LOG_DEBUG, "md5 = ");
+ for (i = 0; i < 16; i++)
+ av_log(NULL, AV_LOG_DEBUG, "%02x", ape_ctx->md5[i]);
+ av_log(NULL, AV_LOG_DEBUG, "\n");
+
+ av_log(NULL, AV_LOG_DEBUG, "\nHeader Block:\n\n");
+
+ av_log(NULL, AV_LOG_DEBUG, "compressiontype = %d\n", ape_ctx->compressiontype);
+ av_log(NULL, AV_LOG_DEBUG, "formatflags = %d\n", ape_ctx->formatflags);
+ av_log(NULL, AV_LOG_DEBUG, "blocksperframe = %d\n", ape_ctx->blocksperframe);
+ av_log(NULL, AV_LOG_DEBUG, "finalframeblocks = %d\n", ape_ctx->finalframeblocks);
+ av_log(NULL, AV_LOG_DEBUG, "totalframes = %d\n", ape_ctx->totalframes);
+ av_log(NULL, AV_LOG_DEBUG, "bps = %d\n", ape_ctx->bps);
+ av_log(NULL, AV_LOG_DEBUG, "channels = %d\n", ape_ctx->channels);
+ av_log(NULL, AV_LOG_DEBUG, "samplerate = %d\n", ape_ctx->samplerate);
+
+ av_log(NULL, AV_LOG_DEBUG, "\nSeektable\n\n");
+ if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes) {
+ av_log(NULL, AV_LOG_DEBUG, "No seektable\n");
+ } else {
+ for (i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t); i++) {
+ if (i < ape_ctx->totalframes - 1) {
+ av_log(NULL, AV_LOG_DEBUG, "%8d %d (%d bytes)\n", i, ape_ctx->seektable[i], ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]);
+ } else {
+ av_log(NULL, AV_LOG_DEBUG, "%8d %d\n", i, ape_ctx->seektable[i]);
+ }
+ }
+ }
+
+ av_log(NULL, AV_LOG_DEBUG, "\nFrames\n\n");
+ for (i = 0; i < ape_ctx->totalframes; i++)
+ av_log(NULL, AV_LOG_DEBUG, "%8d %8lld %8d (%d samples)\n", i, ape_ctx->frames[i].pos, ape_ctx->frames[i].size, ape_ctx->frames[i].nblocks);
+
+ av_log(NULL, AV_LOG_DEBUG, "\nCalculated information:\n\n");
+ av_log(NULL, AV_LOG_DEBUG, "junklength = %d\n", ape_ctx->junklength);
+ av_log(NULL, AV_LOG_DEBUG, "firstframe = %d\n", ape_ctx->firstframe);
+ av_log(NULL, AV_LOG_DEBUG, "totalsamples = %d\n", ape_ctx->totalsamples);
+#endif
+}
+
+static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap)
+{
+ ByteIOContext *pb = s->pb;
+ APEContext *ape = s->priv_data;
+ AVStream *st;
+ uint32_t tag;
+ int i;
+ int total_blocks;
+ int64_t pts;
+
+ /* TODO: Skip any leading junk such as id3v2 tags */
+ ape->junklength = 0;
+
+ tag = get_le32(pb);
+ if (tag != MKTAG('M', 'A', 'C', ' '))
+ return -1;
+
+ ape->fileversion = get_le16(pb);
+
+ if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) {
+ av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10);
+ return -1;
+ }
+
+ if (ape->fileversion >= 3980) {
+ ape->padding1 = get_le16(pb);
+ ape->descriptorlength = get_le32(pb);
+ ape->headerlength = get_le32(pb);
+ ape->seektablelength = get_le32(pb);
+ ape->wavheaderlength = get_le32(pb);
+ ape->audiodatalength = get_le32(pb);
+ ape->audiodatalength_high = get_le32(pb);
+ ape->wavtaillength = get_le32(pb);
+ get_buffer(pb, ape->md5, 16);
+
+ /* Skip any unknown bytes at the end of the descriptor.
+ This is for future compatibility */
+ if (ape->descriptorlength > 52)
+ url_fseek(pb, ape->descriptorlength - 52, SEEK_CUR);
+
+ /* Read header data */
+ ape->compressiontype = get_le16(pb);
+ ape->formatflags = get_le16(pb);
+ ape->blocksperframe = get_le32(pb);
+ ape->finalframeblocks = get_le32(pb);
+ ape->totalframes = get_le32(pb);
+ ape->bps = get_le16(pb);
+ ape->channels = get_le16(pb);
+ ape->samplerate = get_le32(pb);
+ } else {
+ ape->descriptorlength = 0;
+ ape->headerlength = 32;
+
+ ape->compressiontype = get_le16(pb);
+ ape->formatflags = get_le16(pb);
+ ape->channels = get_le16(pb);
+ ape->samplerate = get_le32(pb);
+ ape->wavheaderlength = get_le32(pb);
+ ape->wavtaillength = get_le32(pb);
+ ape->totalframes = get_le32(pb);
+ ape->finalframeblocks = get_le32(pb);
+
+ if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) {
+ url_fseek(pb, 4, SEEK_CUR); /* Skip the peak level */
+ ape->headerlength += 4;
+ }
+
+ if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) {
+ ape->seektablelength = get_le32(pb);
+ ape->headerlength += 4;
+ ape->seektablelength *= sizeof(int32_t);
+ } else
+ ape->seektablelength = ape->totalframes * sizeof(int32_t);
+
+ if (ape->formatflags & MAC_FORMAT_FLAG_8_BIT)
+ ape->bps = 8;
+ else if (ape->formatflags & MAC_FORMAT_FLAG_24_BIT)
+ ape->bps = 24;
+ else
+ ape->bps = 16;
+
+ if (ape->fileversion >= 3950)
+ ape->blocksperframe = 73728 * 4;
+ else if (ape->fileversion >= 3900 || (ape->fileversion >= 3800 && ape->compressiontype >= 4000))
+ ape->blocksperframe = 73728;
+ else
+ ape->blocksperframe = 9216;
+
+ /* Skip any stored wav header */
+ if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
+ url_fskip(pb, ape->wavheaderlength);
+ }
+
+ if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){
+ av_log(s, AV_LOG_ERROR, "Too many frames: %d\n", ape->totalframes);
+ return -1;
+ }
+ ape->frames = av_malloc(ape->totalframes * sizeof(APEFrame));
+ if(!ape->frames)
+ return AVERROR_NOMEM;
+ ape->firstframe = ape->junklength + ape->descriptorlength + ape->headerlength + ape->seektablelength + ape->wavheaderlength;
+ ape->currentframe = 0;
+
+
+ ape->totalsamples = ape->finalframeblocks;
+ if (ape->totalframes > 1)
+ ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1);
+
+ if (ape->seektablelength > 0) {
+ ape->seektable = av_malloc(ape->seektablelength);
+ for (i = 0; i < ape->seektablelength / sizeof(uint32_t); i++)
+ ape->seektable[i] = get_le32(pb);
+ }
+
+ ape->frames[0].pos = ape->firstframe;
+ ape->frames[0].nblocks = ape->blocksperframe;
+ ape->frames[0].skip = 0;
+ for (i = 1; i < ape->totalframes; i++) {
+ ape->frames[i].pos = ape->seektable[i]; //ape->frames[i-1].pos + ape->blocksperframe;
+ ape->frames[i].nblocks = ape->blocksperframe;
+ ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos;
+ ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3;
+ }
+ ape->frames[ape->totalframes - 1].size = ape->finalframeblocks * 4;
+ ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks;
+
+ for (i = 0; i < ape->totalframes; i++) {
+ if(ape->frames[i].skip){
+ ape->frames[i].pos -= ape->frames[i].skip;
+ ape->frames[i].size += ape->frames[i].skip;
+ }
+ ape->frames[i].size = (ape->frames[i].size + 3) & ~3;
+ }
+
+
+ ape_dumpinfo(ape);
+
+ /* try to read APE tags */
+ if (!url_is_streamed(pb)) {
+ ape_parse_tag(s);
+ url_fseek(pb, 0, SEEK_SET);
+ }
+
+ av_log(s, AV_LOG_DEBUG, "Decoding file - v%d.%02d, compression level %d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10, ape->compressiontype);
+
+ /* now we are ready: build format streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+
+ total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_APE;
+ st->codec->codec_tag = MKTAG('A', 'P', 'E', ' ');
+ st->codec->channels = ape->channels;
+ st->codec->sample_rate = ape->samplerate;
+ st->codec->bits_per_sample = ape->bps;
+ st->codec->frame_size = MAC_SUBFRAME_SIZE;
+
+ st->nb_frames = ape->totalframes;
+ s->start_time = 0;
+ s->duration = (int64_t) total_blocks * AV_TIME_BASE / ape->samplerate;
+ av_set_pts_info(st, 64, MAC_SUBFRAME_SIZE, ape->samplerate);
+
+ st->codec->extradata = av_malloc(APE_EXTRADATA_SIZE);
+ st->codec->extradata_size = APE_EXTRADATA_SIZE;
+ AV_WL16(st->codec->extradata + 0, ape->fileversion);
+ AV_WL16(st->codec->extradata + 2, ape->compressiontype);
+ AV_WL16(st->codec->extradata + 4, ape->formatflags);
+
+ pts = 0;
+ for (i = 0; i < ape->totalframes; i++) {
+ ape->frames[i].pts = pts;
+ av_add_index_entry(st, ape->frames[i].pos, ape->frames[i].pts, 0, 0, AVINDEX_KEYFRAME);
+ pts += ape->blocksperframe / MAC_SUBFRAME_SIZE;
+ }
+
+ return 0;
+}
+
+static int ape_read_packet(AVFormatContext * s, AVPacket * pkt)
+{
+ int ret;
+ int nblocks;
+ APEContext *ape = s->priv_data;
+ uint32_t extra_size = 8;
+
+ if (url_feof(s->pb))
+ return AVERROR_IO;
+ if (ape->currentframe > ape->totalframes)
+ return AVERROR_IO;
+
+ url_fseek (s->pb, ape->frames[ape->currentframe].pos, SEEK_SET);
+
+ /* Calculate how many blocks there are in this frame */
+ if (ape->currentframe == (ape->totalframes - 1))
+ nblocks = ape->finalframeblocks;
+ else
+ nblocks = ape->blocksperframe;
+
+ if (av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size) < 0)
+ return AVERROR_NOMEM;
+
+ AV_WL32(pkt->data , nblocks);
+ AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip);
+ ret = get_buffer(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size);
+
+ pkt->pts = ape->frames[ape->currentframe].pts;
+ pkt->stream_index = 0;
+
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret + extra_size;
+
+ ape->currentframe++;
+
+ return 0;
+}
+
+static int ape_read_close(AVFormatContext * s)
+{
+ APEContext *ape = s->priv_data;
+
+ av_freep(&ape->frames);
+ av_freep(&ape->seektable);
+ return 0;
+}
+
+static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+ AVStream *st = s->streams[stream_index];
+ APEContext *ape = s->priv_data;
+ int index = av_index_search_timestamp(st, timestamp, flags);
+
+ if (index < 0)
+ return -1;
+
+ ape->currentframe = index;
+ return 0;
+}
+
+AVInputFormat ape_demuxer = {
+ "ape",
+ "Monkey's Audio",
+ sizeof(APEContext),
+ ape_probe,
+ ape_read_header,
+ ape_read_packet,
+ ape_read_close,
+ ape_read_seek,
+ .extensions = "ape,apl,mac"
+};
diff --git a/contrib/ffmpeg/libavformat/asf-enc.c b/contrib/ffmpeg/libavformat/asf-enc.c
index f1d9c6903..a12cda1e7 100644
--- a/contrib/ffmpeg/libavformat/asf-enc.c
+++ b/contrib/ffmpeg/libavformat/asf-enc.c
@@ -199,7 +199,7 @@ static const AVCodecTag codec_asf_bmp_tags[] = {
static void put_guid(ByteIOContext *s, const GUID *g)
{
assert(sizeof(*g) == 16);
- put_buffer(s, g, sizeof(*g));
+ put_buffer(s, *g, sizeof(*g));
}
static void put_str16_nolen(ByteIOContext *s, const char *tag);
@@ -244,7 +244,7 @@ static void end_header(ByteIOContext *pb, int64_t pos)
static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
{
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int length;
length = payload_length + 8;
@@ -270,7 +270,7 @@ static int64_t unix_to_file_time(int ti)
static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size)
{
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
int has_title;
AVCodecContext *enc;
@@ -493,17 +493,20 @@ static int asf_write_header(AVFormatContext *s)
asf->nb_packets = 0;
asf->last_indexed_pts = 0;
- asf->index_ptr = (ASFIndex*)av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
+ asf->index_ptr = av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
asf->nb_index_count = 0;
asf->maximum_packet = 0;
- if (asf_write_header1(s, 0, 0) < 0) {
+ /* the data-chunk-size has to be 50, which is data_size - asf->data_offset
+ * at the moment this function is done. It is needed to use asf as
+ * streamable format. */
+ if (asf_write_header1(s, 0, 50) < 0) {
//av_free(asf);
return -1;
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
asf->packet_nb_payloads = 0;
asf->packet_timestamp_start = -1;
@@ -532,7 +535,7 @@ static int put_payload_parsing_info(
)
{
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int ppi_size, i;
int64_t start= url_ftell(pb);
@@ -581,6 +584,8 @@ static void flush_packet(AVFormatContext *s)
ASFContext *asf = s->priv_data;
int packet_hdr_size, packet_filled_size;
+ assert(asf->packet_timestamp_end >= asf->packet_timestamp_start);
+
if (asf->is_streamed) {
put_chunk(s, 0x4424, asf->packet_size, 0);
}
@@ -597,9 +602,9 @@ static void flush_packet(AVFormatContext *s)
assert(packet_hdr_size <= asf->packet_size_left);
memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
- put_buffer(&s->pb, asf->packet_buf, asf->packet_size - packet_hdr_size);
+ put_buffer(s->pb, asf->packet_buf, asf->packet_size - packet_hdr_size);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
asf->nb_packets++;
asf->packet_nb_payloads = 0;
asf->packet_timestamp_start = -1;
@@ -677,8 +682,6 @@ static void put_frame(
// multi payloads
frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1;
- asf->packet_timestamp_start = timestamp;
-
if(frag_len1 < payload_len && avst->codec->codec_type == CODEC_TYPE_AUDIO){
flush_packet(s);
continue;
@@ -763,7 +766,7 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
//
static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int i;
put_guid(pb, &simple_index_header);
@@ -790,22 +793,22 @@ static int asf_write_trailer(AVFormatContext *s)
flush_packet(s);
/* write index */
- data_size = url_ftell(&s->pb);
+ data_size = url_ftell(s->pb);
if ((!asf->is_streamed) && (asf->nb_index_count != 0)) {
asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count);
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
- if (asf->is_streamed || url_is_streamed(&s->pb)) {
+ if (asf->is_streamed || url_is_streamed(s->pb)) {
put_chunk(s, 0x4524, 0, 0); /* end of stream */
} else {
/* rewrite an updated header */
- file_size = url_ftell(&s->pb);
- url_fseek(&s->pb, 0, SEEK_SET);
+ file_size = url_ftell(s->pb);
+ url_fseek(s->pb, 0, SEEK_SET);
asf_write_header1(s, file_size, data_size - asf->data_offset);
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
av_free(asf->index_ptr);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/asf.c b/contrib/ffmpeg/libavformat/asf.c
index 498f6e79e..30330c535 100644
--- a/contrib/ffmpeg/libavformat/asf.c
+++ b/contrib/ffmpeg/libavformat/asf.c
@@ -23,6 +23,9 @@
#include "mpegaudio.h"
#include "asf.h"
#include "common.h"
+#include "asfcrypt.h"
+
+extern void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format);
#undef NDEBUG
#include <assert.h>
@@ -84,7 +87,7 @@ static void print_guid(const GUID *g)
static void get_guid(ByteIOContext *s, GUID *g)
{
assert(sizeof(*g) == 16);
- get_buffer(s, g, sizeof(*g));
+ get_buffer(s, *g, sizeof(*g));
}
#if 0
@@ -119,9 +122,6 @@ static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
static int asf_probe(AVProbeData *pd)
{
/* check file header */
- if (pd->buf_size <= 32)
- return 0;
-
if (!memcmp(pd->buf, &asf_header, sizeof(GUID)))
return AVPROBE_SCORE_MAX;
else
@@ -142,14 +142,16 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
ASFContext *asf = s->priv_data;
GUID g;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
ASFStream *asf_st;
int size, i;
int64_t gsize;
AVRational dar[128];
+ uint32_t bitrate[128];
memset(dar, 0, sizeof(dar));
+ memset(bitrate, 0, sizeof(bitrate));
get_guid(pb, &g);
if (memcmp(&g, &asf_header, sizeof(GUID)))
@@ -197,8 +199,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
int type, type_specific_size, sizeX;
uint64_t total_size;
unsigned int tag1;
- int64_t pos1, pos2;
- int test_for_ext_stream_audio;
+ int64_t pos1, pos2, start_time;
+ int test_for_ext_stream_audio, is_dvr_ms_audio=0;
pos1 = url_ftell(pb);
@@ -210,10 +212,11 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (!asf_st)
goto fail;
st->priv_data = asf_st;
- st->start_time = asf->hdr.preroll;
+ start_time = asf->hdr.preroll;
+
if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
st->duration = asf->hdr.send_time /
- (10000000 / 1000) - st->start_time;
+ (10000000 / 1000) - start_time;
}
get_guid(pb, &g);
@@ -244,6 +247,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_guid(pb, &g);
if (!memcmp(&g, &ext_stream_audio_stream, sizeof(GUID))) {
type = CODEC_TYPE_AUDIO;
+ is_dvr_ms_audio=1;
get_guid(pb, &g);
get_le32(pb);
get_le32(pb);
@@ -256,7 +260,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_type = type;
if (type == CODEC_TYPE_AUDIO) {
get_wav_header(pb, st->codec, type_specific_size);
- st->need_parsing = 1;
+ if (is_dvr_ms_audio) {
+ // codec_id and codec_tag are unreliable in dvr_ms
+ // files. Set them later by probing stream.
+ st->codec->codec_id = CODEC_ID_NONE;
+ st->codec->codec_tag = 0;
+ }
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* We have to init the frame size at some point .... */
pos2 = url_ftell(pb);
if (gsize >= (pos2 + 8 - pos1 + 24)) {
@@ -333,7 +343,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_tag = tag1;
st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
if(tag1 == MKTAG('D', 'V', 'R', ' '))
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
}
pos2 = url_ftell(pb);
url_fskip(pb, gsize - (pos2 - pos1 + 24));
@@ -363,7 +373,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
bitrate= get_le32(pb);
stream_id= (flags & 0x7f);
// av_log(NULL, AV_LOG_ERROR, "flags: 0x%x stream id %d, bitrate %d\n", flags, stream_id, bitrate);
- asf->stream_bitrates[stream_id-1]= bitrate;
+ asf->stream_bitrates[stream_id]= bitrate;
}
} else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
int desc_count, i;
@@ -383,12 +393,27 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
if (!strcmp(name,"WM/AlbumTitle")) get_str16_nolen(pb, value_len, s->album, sizeof(s->album));
else if(!strcmp(name,"WM/Genre" )) get_str16_nolen(pb, value_len, s->genre, sizeof(s->genre));
+ else if(!strcmp(name,"WM/Year" )) {
+ char year[8];
+ get_str16_nolen(pb, value_len, year, sizeof(year));
+ s->year = atoi(year);
+ }
+ else if(!strcmp(name,"WM/Track") && s->track == 0) {
+ char track[8];
+ get_str16_nolen(pb, value_len, track, sizeof(track));
+ s->track = strtol(track, NULL, 10) + 1;
+ }
+ else if(!strcmp(name,"WM/TrackNumber")) {
+ char track[8];
+ get_str16_nolen(pb, value_len, track, sizeof(track));
+ s->track = strtol(track, NULL, 10);
+ }
else url_fskip(pb, value_len);
}
if ((value_type >= 2) && (value_type <= 5)) // boolean or DWORD or QWORD or WORD
{
value_num= get_value(pb, value_type);
- if (!strcmp(name,"WM/Track" )) s->track = value_num + 1;
+ if (!strcmp(name,"WM/Track" ) && s->track == 0) s->track = value_num + 1;
if (!strcmp(name,"WM/TrackNumber")) s->track = value_num;
}
}
@@ -407,7 +432,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_str16_nolen(pb, name_len, name, sizeof(name));
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d <%s>\n", i, stream_num, name_len, value_type, value_len, name);
- value_num= get_le16(pb);//we should use get_value() here but it doesnt work 2 is le16 here but le32 elsewhere
+ value_num= get_le16(pb);//we should use get_value() here but it does not work 2 is le16 here but le32 elsewhere
url_fskip(pb, value_len - 2);
if(stream_num<128){
@@ -417,13 +442,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
} else if (!memcmp(&g, &ext_stream_header, sizeof(GUID))) {
int ext_len, payload_ext_ct, stream_ct;
- uint32_t ext_d;
+ uint32_t ext_d, leak_rate, stream_num;
int64_t pos_ex_st;
pos_ex_st = url_ftell(pb);
get_le64(pb); // starttime
get_le64(pb); // endtime
- get_le32(pb); // leak-datarate
+ leak_rate = get_le32(pb); // leak-datarate
get_le32(pb); // bucket-datasize
get_le32(pb); // init-bucket-fullness
get_le32(pb); // alt-leak-datarate
@@ -431,12 +456,15 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_le32(pb); // alt-init-bucket-fullness
get_le32(pb); // max-object-size
get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
- get_le16(pb); // stream-num
+ stream_num = get_le16(pb); // stream-num
get_le16(pb); // stream-language-id-index
get_le64(pb); // avg frametime in 100ns units
stream_ct = get_le16(pb); //stream-name-count
payload_ext_ct = get_le16(pb); //payload-extension-system-count
+ if (stream_num < 128)
+ bitrate[stream_num] = leak_rate;
+
for (i=0; i<stream_ct; i++){
get_le16(pb);
ext_len = get_le16(pb);
@@ -500,11 +528,14 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
for(i=0; i<128; i++){
int stream_num= asf->asfid2avid[i];
- if(stream_num>=0 && dar[i].num>0 && dar[i].den>0){
+ if(stream_num>=0){
AVCodecContext *codec= s->streams[stream_num]->codec;
- av_reduce(&codec->sample_aspect_ratio.num,
- &codec->sample_aspect_ratio.den,
- dar[i].num, dar[i].den, INT_MAX);
+ if (!codec->bit_rate)
+ codec->bit_rate = bitrate[i];
+ if (dar[i].num > 0 && dar[i].den > 0)
+ av_reduce(&codec->sample_aspect_ratio.num,
+ &codec->sample_aspect_ratio.den,
+ dar[i].num, dar[i].den, INT_MAX);
//av_log(NULL, AV_LOG_ERROR, "dar %d:%d sar=%d:%d\n", dar[i].num, dar[i].den, codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den);
}
}
@@ -539,12 +570,12 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int asf_get_packet(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t packet_length, padsize;
int rsize = 8;
int c, d, e, off;
- off= (url_ftell(&s->pb) - s->data_offset) % asf->packet_size + 3;
+ off= (url_ftell(s->pb) - s->data_offset) % asf->packet_size + 3;
c=d=e=-1;
while(off-- > 0){
@@ -615,7 +646,7 @@ static int asf_get_packet(AVFormatContext *s)
*/
static int asf_read_frame_header(AVFormatContext *s){
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int rsize = 1;
int num = get_byte(pb);
int64_t ts0, ts1;
@@ -651,7 +682,7 @@ static int asf_read_frame_header(AVFormatContext *s){
url_fskip(pb, asf->packet_replic_size - 8);
rsize += asf->packet_replic_size; // FIXME - check validity
} else if (asf->packet_replic_size==1){
- // multipacket - frag_offset is begining timestamp
+ // multipacket - frag_offset is beginning timestamp
asf->packet_time_start = asf->packet_frag_offset;
asf->packet_frag_offset = 0;
asf->packet_frag_timestamp = asf->packet_timestamp;
@@ -688,11 +719,11 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ASFContext *asf = s->priv_data;
ASFStream *asf_st = 0;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
//static int pc = 0;
for (;;) {
if(url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
if (asf->packet_size_left < FRAME_HEADER_SIZE
|| asf->packet_segments < 1) {
//asf->packet_size_left <= asf->packet_padsize) {
@@ -702,10 +733,10 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
/* fail safe */
url_fskip(pb, ret);
- asf->packet_pos= url_ftell(&s->pb);
+ asf->packet_pos= url_ftell(s->pb);
if (asf->data_object_size != (uint64_t)-1 &&
(asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
- return AVERROR_IO; /* Do not exceed the size of the data object */
+ return AVERROR(EIO); /* Do not exceed the size of the data object */
ret = asf_get_packet(s);
//printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++);
if (ret < 0)
@@ -735,7 +766,7 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
asf_st = asf->asf_st;
if (asf->packet_replic_size == 1) {
- // frag_offset is here used as the begining timestamp
+ // frag_offset is here used as the beginning timestamp
asf->packet_frag_timestamp = asf->packet_time_start;
asf->packet_time_start += asf->packet_time_delta;
asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
@@ -751,6 +782,15 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
asf->packet_multi_size -= asf->packet_obj_size;
//printf("COMPRESS size %d %d %d ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size);
}
+ if( /*asf->packet_frag_size == asf->packet_obj_size*/
+ asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size
+ && asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size){
+ av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
+ asf_st->frag_offset, asf->packet_frag_size,
+ asf->packet_obj_size, asf_st->pkt.size);
+ asf->packet_obj_size= asf_st->pkt.size;
+ }
+
if ( asf_st->pkt.size != asf->packet_obj_size
|| asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) { //FIXME is this condition sufficient?
if(asf_st->pkt.data){
@@ -791,13 +831,29 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
asf->packet_frag_size);
+ if (s->key && s->keylen == 20)
+ ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset,
+ asf->packet_frag_size);
asf_st->frag_offset += asf->packet_frag_size;
/* test if whole packet is read */
if (asf_st->frag_offset == asf_st->pkt.size) {
+ //workaround for macroshit radio DVR-MS files
+ if( s->streams[asf->stream_index]->codec->codec_id == CODEC_ID_MPEG2VIDEO
+ && asf_st->pkt.size > 100){
+ int i;
+ for(i=0; i<asf_st->pkt.size && !asf_st->pkt.data[i]; i++);
+ if(i == asf_st->pkt.size){
+ av_log(s, AV_LOG_DEBUG, "discarding ms fart\n");
+ asf_st->frag_offset = 0;
+ av_free_packet(&asf_st->pkt);
+ continue;
+ }
+ }
+
/* return packet */
if (asf_st->ds_span > 1) {
if(asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span){
- av_log(s, AV_LOG_ERROR, "pkt.size != ds_packet_size * ds_span\n");
+ av_log(s, AV_LOG_ERROR, "pkt.size != ds_packet_size * ds_span (%d %d %d)\n", asf_st->pkt.size, asf_st->ds_packet_size, asf_st->ds_span);
}else{
/* packet descrambling */
uint8_t *newdata = av_malloc(asf_st->pkt.size);
@@ -833,18 +889,6 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
return 0;
}
-static int asf_read_close(AVFormatContext *s)
-{
- int i;
-
- for(i=0;i<s->nb_streams;i++) {
- AVStream *st = s->streams[i];
- av_free(st->priv_data);
- av_free(st->codec->palctrl);
- }
- return 0;
-}
-
// Added to support seeking after packets have been read
// If information is not reset, read_packet fails due to
// leftover information from previous reads
@@ -883,6 +927,19 @@ static void asf_reset_header(AVFormatContext *s)
asf->asf_st= NULL;
}
+static int asf_read_close(AVFormatContext *s)
+{
+ int i;
+
+ asf_reset_header(s);
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ av_free(st->priv_data);
+ av_free(st->codec->palctrl);
+ }
+ return 0;
+}
+
static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit)
{
ASFContext *asf = s->priv_data;
@@ -899,7 +956,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset;
*ppos= pos;
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
//printf("asf_read_pts\n");
asf_reset_header(s);
@@ -943,21 +1000,21 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
int i;
int pct,ict;
- current_pos = url_ftell(&s->pb);
+ current_pos = url_ftell(s->pb);
- url_fseek(&s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
- get_guid(&s->pb, &g);
+ url_fseek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
+ get_guid(s->pb, &g);
if (!memcmp(&g, &index_guid, sizeof(GUID))) {
- gsize = get_le64(&s->pb);
- get_guid(&s->pb, &g);
- itime=get_le64(&s->pb);
- pct=get_le32(&s->pb);
- ict=get_le32(&s->pb);
+ gsize = get_le64(s->pb);
+ get_guid(s->pb, &g);
+ itime=get_le64(s->pb);
+ pct=get_le32(s->pb);
+ ict=get_le32(s->pb);
av_log(NULL, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
for (i=0;i<ict;i++){
- int pktnum=get_le32(&s->pb);
- int pktct =get_le16(&s->pb);
+ int pktnum=get_le32(s->pb);
+ int pktct =get_le16(s->pb);
av_log(NULL, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
pos=s->data_offset + asf->packet_size*(int64_t)pktnum;
@@ -967,7 +1024,7 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
}
asf->index_read= 1;
}
- url_fseek(&s->pb, current_pos, SEEK_SET);
+ url_fseek(s->pb, current_pos, SEEK_SET);
}
static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
@@ -980,6 +1037,15 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
if (asf->packet_size <= 0)
return -1;
+ /* Try using the protocol's read_seek if available */
+ if(s->pb) {
+ int ret = av_url_read_fseek(s->pb, stream_index, pts, flags);
+ if(ret >= 0)
+ asf_reset_header(s);
+ if (ret != AVERROR(ENOSYS))
+ return ret;
+ }
+
if (!asf->index_read)
asf_build_simple_index(s, stream_index);
@@ -997,10 +1063,10 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
// various attempts to find key frame have failed so far
// asf_reset_header(s);
- // url_fseek(&s->pb, pos, SEEK_SET);
+ // url_fseek(s->pb, pos, SEEK_SET);
// key_pos = pos;
// for(i=0;i<16;i++){
- // pos = url_ftell(&s->pb);
+ // pos = url_ftell(s->pb);
// if (av_read_frame(s, &pkt) < 0){
// av_log(s, AV_LOG_INFO, "seek failed\n");
// return -1;
@@ -1018,7 +1084,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
/* do the seek */
av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
}
asf_reset_header(s);
return 0;
diff --git a/contrib/ffmpeg/libavformat/asf.h b/contrib/ffmpeg/libavformat/asf.h
index 6d76ebecb..2486d8a6f 100644
--- a/contrib/ffmpeg/libavformat/asf.h
+++ b/contrib/ffmpeg/libavformat/asf.h
@@ -17,6 +17,13 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#ifndef FFMPEG_ASF_H
+#define FFMPEG_ASF_H
+
+#include <stdint.h>
+#include "avformat.h"
+
#define PACKET_SIZE 3200
typedef struct {
@@ -49,7 +56,7 @@ typedef struct {
uint64_t send_time; /**< time to send file, in 100-nanosecond units
* invalid if broadcasting (could be ignored) */
uint32_t preroll; /**< timestamp of the first packet, in milliseconds
- * if nonzero - substract from time */
+ * if nonzero - subtract from time */
uint32_t ignore; ///< preroll is 64bit - but let's just ignore it
uint32_t flags; /**< 0x01 - broadcast
* 0x02 - seekable
@@ -90,7 +97,7 @@ typedef struct {
uint8_t packet_buf[PACKET_SIZE];
ByteIOContext pb;
/* only for reading */
- uint64_t data_offset; ///< begining of the first data packet
+ uint64_t data_offset; ///< beginning of the first data packet
uint64_t data_object_offset; ///< data object offset (excl. GUID & size)
uint64_t data_object_size; ///< size of the data object
int index_read;
@@ -278,3 +285,5 @@ static const GUID my_guid = {
#define ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE 0xc0 //1100 0000
#define ASF_PL_FLAG_KEY_FRAME 0x80 //1000 0000
+
+#endif /* FFMPEG_ASF_H */
diff --git a/contrib/ffmpeg/libavformat/asfcrypt.c b/contrib/ffmpeg/libavformat/asfcrypt.c
new file mode 100644
index 000000000..10cc934b4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/asfcrypt.c
@@ -0,0 +1,172 @@
+/*
+ * ASF decryption
+ * Copyright (c) 2007 Reimar Doeffinger
+ * This is a rewrite of code contained in freeme/freeme2
+ *
+ * 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 "common.h"
+#include "intreadwrite.h"
+#include "bswap.h"
+#include "des.h"
+#include "rc4.h"
+#include "asfcrypt.h"
+
+/**
+ * \brief find multiplicative inverse modulo 2 ^ 32
+ * \param v number to invert, must be odd!
+ * \return number so that result * v = 1 (mod 2^32)
+ */
+static uint32_t inverse(uint32_t v) {
+ // v ^ 3 gives the inverse (mod 16), could also be implemented
+ // as table etc. (only lowest 4 bits matter!)
+ uint32_t inverse = v * v * v;
+ // uses a fixpoint-iteration that doubles the number
+ // of correct lowest bits each time
+ inverse *= 2 - v * inverse;
+ inverse *= 2 - v * inverse;
+ inverse *= 2 - v * inverse;
+ return inverse;
+}
+
+/**
+ * \brief read keys from keybuf into keys
+ * \param keybuf buffer containing the keys
+ * \param keys output key array containing the keys for encryption in
+ * native endianness
+ */
+static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) {
+ int i;
+ for (i = 0; i < 12; i++)
+ keys[i] = AV_RL32(keybuf + (i << 2)) | 1;
+}
+
+/**
+ * \brief invert the keys so that encryption become decryption keys and
+ * the other way round.
+ * \param keys key array of ints to invert
+ */
+static void multiswap_invert_keys(uint32_t keys[12]) {
+ int i;
+ for (i = 0; i < 5; i++)
+ keys[i] = inverse(keys[i]);
+ for (i = 6; i < 11; i++)
+ keys[i] = inverse(keys[i]);
+}
+
+static uint32_t multiswap_step(const uint32_t keys[12], uint32_t v) {
+ int i;
+ v *= keys[0];
+ for (i = 1; i < 5; i++) {
+ v = (v >> 16) | (v << 16);
+ v *= keys[i];
+ }
+ v += keys[5];
+ return v;
+}
+
+static uint32_t multiswap_inv_step(const uint32_t keys[12], uint32_t v) {
+ int i;
+ v -= keys[5];
+ for (i = 4; i > 0; i--) {
+ v *= keys[i];
+ v = (v >> 16) | (v << 16);
+ }
+ v *= keys[0];
+ return v;
+}
+
+/**
+ * \brief "MultiSwap" encryption
+ * \param keys 32 bit numbers in machine endianness,
+ * 0-4 and 6-10 must be inverted from decryption
+ * \param key another key, this one must be the same for the decryption
+ * \param data data to encrypt
+ * \return encrypted data
+ */
+static uint64_t multiswap_enc(const uint32_t keys[12], uint64_t key, uint64_t data) {
+ uint32_t a = data;
+ uint32_t b = data >> 32;
+ uint32_t c;
+ uint32_t tmp;
+ a += key;
+ tmp = multiswap_step(keys , a);
+ b += tmp;
+ c = (key >> 32) + tmp;
+ tmp = multiswap_step(keys + 6, b);
+ c += tmp;
+ return ((uint64_t)c << 32) | tmp;
+}
+
+/**
+ * \brief "MultiSwap" decryption
+ * \param keys 32 bit numbers in machine endianness,
+ * 0-4 and 6-10 must be inverted from encryption
+ * \param key another key, this one must be the same as for the encryption
+ * \param data data to decrypt
+ * \return decrypted data
+ */
+static uint64_t multiswap_dec(const uint32_t keys[12], uint64_t key, uint64_t data) {
+ uint32_t a;
+ uint32_t b;
+ uint32_t c = data >> 32;
+ uint32_t tmp = data;
+ c -= tmp;
+ b = multiswap_inv_step(keys + 6, tmp);
+ tmp = c - (key >> 32);
+ b -= tmp;
+ a = multiswap_inv_step(keys , tmp);
+ a -= key;
+ return ((uint64_t)b << 32) | a;
+}
+
+void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) {
+ int num_qwords = len >> 3;
+ uint64_t *qwords = (uint64_t *)data;
+ uint64_t rc4buff[8];
+ uint64_t packetkey;
+ uint32_t ms_keys[12];
+ uint64_t ms_state;
+ int i;
+ if (len < 16) {
+ for (i = 0; i < len; i++)
+ data[i] ^= key[i];
+ return;
+ }
+
+ memset(rc4buff, 0, sizeof(rc4buff));
+ ff_rc4_enc(key, 12, (uint8_t *)rc4buff, sizeof(rc4buff));
+ multiswap_init((uint8_t *)rc4buff, ms_keys);
+
+ packetkey = qwords[num_qwords - 1];
+ packetkey ^= rc4buff[7];
+ packetkey = be2me_64(packetkey);
+ packetkey = ff_des_encdec(packetkey, AV_RB64(key + 12), 1);
+ packetkey = be2me_64(packetkey);
+ packetkey ^= rc4buff[6];
+
+ ff_rc4_enc((uint8_t *)&packetkey, 8, data, len);
+
+ ms_state = 0;
+ for (i = 0; i < num_qwords - 1; i++, qwords++)
+ ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords));
+ multiswap_invert_keys(ms_keys);
+ packetkey = (packetkey << 32) | (packetkey >> 32);
+ packetkey = le2me_64(packetkey);
+ packetkey = multiswap_dec(ms_keys, ms_state, packetkey);
+ AV_WL64(qwords, packetkey);
+}
diff --git a/contrib/ffmpeg/libavformat/asfcrypt.h b/contrib/ffmpeg/libavformat/asfcrypt.h
new file mode 100644
index 000000000..dcd9c1da7
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/asfcrypt.h
@@ -0,0 +1,29 @@
+/*
+ * ASF decryption
+ * Copyright (c) 2007 Reimar Doeffinger
+ *
+ * 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 FFMPEG_ASFCRYPT_H
+#define FFMPEG_ASFCRYPT_H
+
+#include <inttypes.h>
+
+void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len);
+
+#endif /* FFMPEG_ASFCRYPT_H */
diff --git a/contrib/ffmpeg/libavformat/au.c b/contrib/ffmpeg/libavformat/au.c
index 9e84c9d31..c6d5026e9 100644
--- a/contrib/ffmpeg/libavformat/au.c
+++ b/contrib/ffmpeg/libavformat/au.c
@@ -28,7 +28,7 @@
*/
#include "avformat.h"
-#include "allformats.h"
+#include "raw.h"
#include "riff.h"
/* if we don't know the size in advance */
@@ -37,6 +37,7 @@
/* The ffmpeg codecs we support, and the IDs they have in the file */
static const AVCodecTag codec_au_tags[] = {
{ CODEC_ID_PCM_MULAW, 1 },
+ { CODEC_ID_PCM_S8, 2 },
{ CODEC_ID_PCM_S16BE, 3 },
{ CODEC_ID_PCM_ALAW, 27 },
{ 0, 0 },
@@ -59,7 +60,7 @@ static int put_au_header(ByteIOContext *pb, AVCodecContext *enc)
static int au_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
s->priv_data = NULL;
@@ -75,17 +76,17 @@ static int au_write_header(AVFormatContext *s)
static int au_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
put_buffer(pb, pkt->data, pkt->size);
return 0;
}
static int au_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t file_size;
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
/* update file size */
file_size = url_ftell(pb);
@@ -103,8 +104,6 @@ static int au_write_trailer(AVFormatContext *s)
static int au_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size <= 24)
- return 0;
if (p->buf[0] == '.' && p->buf[1] == 's' &&
p->buf[2] == 'n' && p->buf[3] == 'd')
return AVPROBE_SCORE_MAX;
@@ -118,7 +117,7 @@ static int au_read_header(AVFormatContext *s,
{
int size;
unsigned int tag;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned int id, codec, channels, rate;
AVStream *st;
@@ -160,11 +159,11 @@ static int au_read_packet(AVFormatContext *s,
{
int ret;
- if (url_feof(&s->pb))
- return AVERROR_IO;
- ret= av_get_packet(&s->pb, pkt, MAX_SIZE);
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
+ ret= av_get_packet(s->pb, pkt, MAX_SIZE);
if (ret < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = 0;
/* note: we need to modify the packet size here to handle the last
diff --git a/contrib/ffmpeg/libavformat/audio.c b/contrib/ffmpeg/libavformat/audio.c
deleted file mode 100644
index a9e5bffd5..000000000
--- a/contrib/ffmpeg/libavformat/audio.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Linux audio play and grab interface
- * Copyright (c) 2000, 2001 Fabrice Bellard.
- *
- * 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 "avformat.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-
-#define AUDIO_BLOCK_SIZE 4096
-
-typedef struct {
- int fd;
- int sample_rate;
- int channels;
- int frame_size; /* in bytes ! */
- int codec_id;
- int flip_left : 1;
- uint8_t buffer[AUDIO_BLOCK_SIZE];
- int buffer_ptr;
-} AudioData;
-
-static int audio_open(AudioData *s, int is_output, const char *audio_device)
-{
- int audio_fd;
- int tmp, err;
- char *flip = getenv("AUDIO_FLIP_LEFT");
-
- if (is_output)
- audio_fd = open(audio_device, O_WRONLY);
- else
- audio_fd = open(audio_device, O_RDONLY);
- if (audio_fd < 0) {
- perror(audio_device);
- return AVERROR_IO;
- }
-
- if (flip && *flip == '1') {
- s->flip_left = 1;
- }
-
- /* non blocking mode */
- if (!is_output)
- fcntl(audio_fd, F_SETFL, O_NONBLOCK);
-
- s->frame_size = AUDIO_BLOCK_SIZE;
-#if 0
- tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
- err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
- if (err < 0) {
- perror("SNDCTL_DSP_SETFRAGMENT");
- }
-#endif
-
- /* select format : favour native format */
- err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
-
-#ifdef WORDS_BIGENDIAN
- if (tmp & AFMT_S16_BE) {
- tmp = AFMT_S16_BE;
- } else if (tmp & AFMT_S16_LE) {
- tmp = AFMT_S16_LE;
- } else {
- tmp = 0;
- }
-#else
- if (tmp & AFMT_S16_LE) {
- tmp = AFMT_S16_LE;
- } else if (tmp & AFMT_S16_BE) {
- tmp = AFMT_S16_BE;
- } else {
- tmp = 0;
- }
-#endif
-
- switch(tmp) {
- case AFMT_S16_LE:
- s->codec_id = CODEC_ID_PCM_S16LE;
- break;
- case AFMT_S16_BE:
- s->codec_id = CODEC_ID_PCM_S16BE;
- break;
- default:
- av_log(NULL, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
- close(audio_fd);
- return AVERROR_IO;
- }
- err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
- if (err < 0) {
- perror("SNDCTL_DSP_SETFMT");
- goto fail;
- }
-
- tmp = (s->channels == 2);
- err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
- if (err < 0) {
- perror("SNDCTL_DSP_STEREO");
- goto fail;
- }
- if (tmp)
- s->channels = 2;
-
- tmp = s->sample_rate;
- err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
- if (err < 0) {
- perror("SNDCTL_DSP_SPEED");
- goto fail;
- }
- s->sample_rate = tmp; /* store real sample rate */
- s->fd = audio_fd;
-
- return 0;
- fail:
- close(audio_fd);
- return AVERROR_IO;
-}
-
-static int audio_close(AudioData *s)
-{
- close(s->fd);
- return 0;
-}
-
-/* sound output support */
-static int audio_write_header(AVFormatContext *s1)
-{
- AudioData *s = s1->priv_data;
- AVStream *st;
- int ret;
-
- st = s1->streams[0];
- s->sample_rate = st->codec->sample_rate;
- s->channels = st->codec->channels;
- ret = audio_open(s, 1, NULL);
- if (ret < 0) {
- return AVERROR_IO;
- } else {
- return 0;
- }
-}
-
-static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- AudioData *s = s1->priv_data;
- int len, ret;
- int size= pkt->size;
- uint8_t *buf= pkt->data;
-
- while (size > 0) {
- len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
- if (len > size)
- len = size;
- memcpy(s->buffer + s->buffer_ptr, buf, len);
- s->buffer_ptr += len;
- if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
- for(;;) {
- ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
- if (ret > 0)
- break;
- if (ret < 0 && (errno != EAGAIN && errno != EINTR))
- return AVERROR_IO;
- }
- s->buffer_ptr = 0;
- }
- buf += len;
- size -= len;
- }
- return 0;
-}
-
-static int audio_write_trailer(AVFormatContext *s1)
-{
- AudioData *s = s1->priv_data;
-
- audio_close(s);
- return 0;
-}
-
-/* grab support */
-
-static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- AudioData *s = s1->priv_data;
- AVStream *st;
- int ret;
-
- if (ap->sample_rate <= 0 || ap->channels <= 0)
- return -1;
-
- st = av_new_stream(s1, 0);
- if (!st) {
- return AVERROR(ENOMEM);
- }
- s->sample_rate = ap->sample_rate;
- s->channels = ap->channels;
-
- ret = audio_open(s, 0, s1->filename);
- if (ret < 0) {
- av_free(st);
- return AVERROR_IO;
- }
-
- /* take real parameters */
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = s->codec_id;
- st->codec->sample_rate = s->sample_rate;
- st->codec->channels = s->channels;
-
- av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
- return 0;
-}
-
-static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- AudioData *s = s1->priv_data;
- int ret, bdelay;
- int64_t cur_time;
- struct audio_buf_info abufi;
-
- if (av_new_packet(pkt, s->frame_size) < 0)
- return AVERROR_IO;
- for(;;) {
- struct timeval tv;
- fd_set fds;
-
- tv.tv_sec = 0;
- tv.tv_usec = 30 * 1000; /* 30 msecs -- a bit shorter than 1 frame at 30fps */
-
- FD_ZERO(&fds);
- FD_SET(s->fd, &fds);
-
- /* This will block until data is available or we get a timeout */
- (void) select(s->fd + 1, &fds, 0, 0, &tv);
-
- ret = read(s->fd, pkt->data, pkt->size);
- if (ret > 0)
- break;
- if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
- av_free_packet(pkt);
- pkt->size = 0;
- pkt->pts = av_gettime();
- return 0;
- }
- if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
- av_free_packet(pkt);
- return AVERROR_IO;
- }
- }
- pkt->size = ret;
-
- /* compute pts of the start of the packet */
- cur_time = av_gettime();
- bdelay = ret;
- if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
- bdelay += abufi.bytes;
- }
- /* substract time represented by the number of bytes in the audio fifo */
- cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
-
- /* convert to wanted units */
- pkt->pts = cur_time;
-
- if (s->flip_left && s->channels == 2) {
- int i;
- short *p = (short *) pkt->data;
-
- for (i = 0; i < ret; i += 4) {
- *p = ~*p;
- p += 2;
- }
- }
- return 0;
-}
-
-static int audio_read_close(AVFormatContext *s1)
-{
- AudioData *s = s1->priv_data;
-
- audio_close(s);
- return 0;
-}
-
-#ifdef CONFIG_AUDIO_DEMUXER
-AVInputFormat audio_demuxer = {
- "audio_device",
- "audio grab and output",
- sizeof(AudioData),
- NULL,
- audio_read_header,
- audio_read_packet,
- audio_read_close,
- .flags = AVFMT_NOFILE,
-};
-#endif
-
-#ifdef CONFIG_AUDIO_MUXER
-AVOutputFormat audio_muxer = {
- "audio_device",
- "audio grab and output",
- "",
- "",
- sizeof(AudioData),
- /* XXX: we make the assumption that the soundcard accepts this format */
- /* XXX: find better solution with "preinit" method, needed also in
- other formats */
-#ifdef WORDS_BIGENDIAN
- CODEC_ID_PCM_S16BE,
-#else
- CODEC_ID_PCM_S16LE,
-#endif
- CODEC_ID_NONE,
- audio_write_header,
- audio_write_packet,
- audio_write_trailer,
- .flags = AVFMT_NOFILE,
-};
-#endif
diff --git a/contrib/ffmpeg/libavformat/avc.c b/contrib/ffmpeg/libavformat/avc.c
new file mode 100644
index 000000000..0c180c86b
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avc.c
@@ -0,0 +1,135 @@
+/*
+ * AVC helper functions for muxers
+ * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.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 "avformat.h"
+#include "avio.h"
+
+const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end)
+{
+ const uint8_t *a = p + 4 - ((long)p & 3);
+
+ for( end -= 3; p < a && p < end; p++ ) {
+ if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
+ return p;
+ }
+
+ for( end -= 3; p < end; p += 4 ) {
+ uint32_t x = *(const uint32_t*)p;
+// if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian
+// if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian
+ if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic
+ if( p[1] == 0 ) {
+ if( p[0] == 0 && p[2] == 1 )
+ return p-1;
+ if( p[2] == 0 && p[3] == 1 )
+ return p;
+ }
+ if( p[3] == 0 ) {
+ if( p[2] == 0 && p[4] == 1 )
+ return p+1;
+ if( p[4] == 0 && p[5] == 1 )
+ return p+2;
+ }
+ }
+ }
+
+ for( end += 3; p < end; p++ ) {
+ if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
+ return p;
+ }
+
+ return end + 3;
+}
+
+int ff_avc_parse_nal_units(const uint8_t *buf_in, uint8_t **buf, int *size)
+{
+ ByteIOContext *pb;
+ const uint8_t *p = buf_in;
+ const uint8_t *end = p + *size;
+ const uint8_t *nal_start, *nal_end;
+ int ret = url_open_dyn_buf(&pb);
+ if(ret < 0)
+ return ret;
+
+ nal_start = ff_avc_find_startcode(p, end);
+ while (nal_start < end) {
+ while(!*(nal_start++));
+ nal_end = ff_avc_find_startcode(nal_start, end);
+ put_be32(pb, nal_end - nal_start);
+ put_buffer(pb, nal_start, nal_end - nal_start);
+ nal_start = nal_end;
+ }
+ av_freep(buf);
+ *size = url_close_dyn_buf(pb, buf);
+ return 0;
+}
+
+int ff_isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len)
+{
+ if (len > 6) {
+ /* check for h264 start code */
+ if (AV_RB32(data) == 0x00000001) {
+ uint8_t *buf=NULL, *end, *start;
+ uint32_t sps_size=0, pps_size=0;
+ uint8_t *sps=0, *pps=0;
+
+ int ret = ff_avc_parse_nal_units(data, &buf, &len);
+ if (ret < 0)
+ return ret;
+ start = buf;
+ end = buf + len;
+
+ /* look for sps and pps */
+ while (buf < end) {
+ unsigned int size;
+ uint8_t nal_type;
+ size = AV_RB32(buf);
+ nal_type = buf[4] & 0x1f;
+ if (nal_type == 7) { /* SPS */
+ sps = buf + 4;
+ sps_size = size;
+ } else if (nal_type == 8) { /* PPS */
+ pps = buf + 4;
+ pps_size = size;
+ }
+ buf += size + 4;
+ }
+ assert(sps);
+ assert(pps);
+
+ put_byte(pb, 1); /* version */
+ put_byte(pb, sps[1]); /* profile */
+ put_byte(pb, sps[2]); /* profile compat */
+ put_byte(pb, sps[3]); /* level */
+ put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
+ put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
+
+ put_be16(pb, sps_size);
+ put_buffer(pb, sps, sps_size);
+ put_byte(pb, 1); /* number of pps */
+ put_be16(pb, pps_size);
+ put_buffer(pb, pps, pps_size);
+ av_free(start);
+ } else {
+ put_buffer(pb, data, len);
+ }
+ }
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavformat/avc.h b/contrib/ffmpeg/libavformat/avc.h
new file mode 100644
index 000000000..334aa4347
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avc.h
@@ -0,0 +1,32 @@
+/*
+ * AVC helper functions for muxers
+ * Copyright (c) 2008 Aurelien Jacobs <aurel@gnuage.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
+ */
+
+#ifndef AVC_H
+#define AVC_H
+
+#include <stdint.h>
+#include "avio.h"
+
+int ff_avc_parse_nal_units(const uint8_t *buf_in, uint8_t **buf, int *size);
+int ff_isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len);
+const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end);
+
+#endif /* AVC_H */
diff --git a/contrib/ffmpeg/libavformat/avformat.h b/contrib/ffmpeg/libavformat/avformat.h
index eb8c4e153..ad186e443 100644
--- a/contrib/ffmpeg/libavformat/avformat.h
+++ b/contrib/ffmpeg/libavformat/avformat.h
@@ -18,22 +18,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef AVFORMAT_H
-#define AVFORMAT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define LIBAVFORMAT_VERSION_INT ((51<<16)+(11<<8)+0)
-#define LIBAVFORMAT_VERSION 51.11.0
+#ifndef FFMPEG_AVFORMAT_H
+#define FFMPEG_AVFORMAT_H
+
+#define LIBAVFORMAT_VERSION_MAJOR 52
+#define LIBAVFORMAT_VERSION_MINOR 7
+#define LIBAVFORMAT_VERSION_MICRO 0
+
+#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
+ LIBAVFORMAT_VERSION_MINOR, \
+ LIBAVFORMAT_VERSION_MICRO)
+#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \
+ LIBAVFORMAT_VERSION_MINOR, \
+ LIBAVFORMAT_VERSION_MICRO)
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
#include <time.h>
#include <stdio.h> /* FILE */
-#include "avcodec.h"
+#include "libavcodec/avcodec.h"
#include "avio.h"
@@ -60,20 +64,15 @@ void av_destruct_packet_nofree(AVPacket *pkt);
*/
void av_destruct_packet(AVPacket *pkt);
-/* initialize optional fields of a packet */
-static inline void av_init_packet(AVPacket *pkt)
-{
- pkt->pts = AV_NOPTS_VALUE;
- pkt->dts = AV_NOPTS_VALUE;
- pkt->pos = -1;
- pkt->duration = 0;
- pkt->flags = 0;
- pkt->stream_index = 0;
- pkt->destruct= av_destruct_packet_nofree;
-}
+/**
+ * Initialize optional fields of a packet to default values.
+ *
+ * @param pkt packet
+ */
+void av_init_packet(AVPacket *pkt);
/**
- * Allocate the payload of a packet and intialized its fields to default values.
+ * Allocate the payload of a packet and initialize its fields to default values.
*
* @param pkt packet
* @param size wanted payload size
@@ -82,7 +81,7 @@ static inline void av_init_packet(AVPacket *pkt)
int av_new_packet(AVPacket *pkt, int size);
/**
- * Allocate and read the payload of a packet and intialized its fields to default values.
+ * Allocate and read the payload of a packet and initialize its fields to default values.
*
* @param pkt packet
* @param size wanted payload size
@@ -111,8 +110,11 @@ static inline void av_free_packet(AVPacket *pkt)
/*************************************************/
/* fractional numbers for exact pts handling */
-/* the exact value of the fractional number is: 'val + num / den'. num
- is assumed to be such as 0 <= num < den */
+/**
+ * the exact value of the fractional number is: 'val + num / den'.
+ * num is assumed to be such as 0 <= num < den
+ * @deprecated Use AVRational instead
+*/
typedef struct AVFrac {
int64_t val, num, den;
} AVFrac attribute_deprecated;
@@ -132,6 +134,7 @@ typedef struct AVProbeData {
} AVProbeData;
#define AVPROBE_SCORE_MAX 100 ///< max score, half of that is used for file extension based detection
+#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer
typedef struct AVFormatParameters {
AVRational time_base;
@@ -141,19 +144,18 @@ typedef struct AVFormatParameters {
int height;
enum PixelFormat pix_fmt;
int channel; /**< used to select dv channel */
-#if LIBAVFORMAT_VERSION_INT < (52<<16)
- const char *device; /**< video, audio or DV device */
-#endif
const char *standard; /**< tv standard, NTSC, PAL, SECAM */
int mpeg2ts_raw:1; /**< force raw MPEG2 transport stream output, if possible */
int mpeg2ts_compute_pcr:1; /**< compute exact PCR for each transport
stream packet (only meaningful if
- mpeg2ts_raw is TRUE */
+ mpeg2ts_raw is TRUE) */
int initial_pause:1; /**< do not begin to play the stream
immediately (RTSP only) */
int prealloced_context:1;
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
enum CodecID video_codec_id;
enum CodecID audio_codec_id;
+#endif
} AVFormatParameters;
//! demuxer will use url_fopen, no opened file should be provided by the caller
@@ -163,7 +165,7 @@ typedef struct AVFormatParameters {
#define AVFMT_RAWPICTURE 0x0020 /**< format wants AVPicture structure for
raw picture data */
#define AVFMT_GLOBALHEADER 0x0040 /**< format wants global header */
-#define AVFMT_NOTIMESTAMPS 0x0080 /**< format doesnt need / has any timestamps */
+#define AVFMT_NOTIMESTAMPS 0x0080 /**< format does not need / have any timestamps */
#define AVFMT_GENERIC_INDEX 0x0100 /**< use generic index building code */
typedef struct AVOutputFormat {
@@ -191,6 +193,8 @@ typedef struct AVOutputFormat {
*/
const struct AVCodecTag **codec_tag;
+ enum CodecID subtitle_codec; /**< default subtitle codec */
+
/* private fields */
struct AVOutputFormat *next;
} AVOutputFormat;
@@ -200,11 +204,15 @@ typedef struct AVInputFormat {
const char *long_name;
/** size of private data so that it can be allocated in the wrapper */
int priv_data_size;
- /** tell if a given file has a chance of being parsing by this format */
+ /**
+ * Tell if a given file has a chance of being parsed by this format.
+ * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
+ * big so you do not have to check for that unless you need more.
+ */
int (*read_probe)(AVProbeData *);
/** read the format header and initialize the AVFormatContext
structure. Return 0 if OK. 'ap' if non NULL contains
- additionnal paramters. Only used in raw format right
+ additional paramters. Only used in raw format right
now. 'av_new_stream' should be called to create new streams. */
int (*read_header)(struct AVFormatContext *,
AVFormatParameters *ap);
@@ -221,11 +229,13 @@ typedef struct AVInputFormat {
* @param stream_index must not be -1
* @param flags selects which direction should be preferred if no exact
* match is available
+ * @return >= 0 on success (but not necessarily the new offset)
*/
int (*read_seek)(struct AVFormatContext *,
int stream_index, int64_t timestamp, int flags);
/**
- * gets the next timestamp in AV_TIME_BASE units.
+ * gets the next timestamp in stream[stream_index].time_base units.
+ * @return the timestamp or AV_NOPTS_VALUE if an error occured
*/
int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
int64_t *pos, int64_t pos_limit);
@@ -252,63 +262,84 @@ typedef struct AVInputFormat {
struct AVInputFormat *next;
} AVInputFormat;
+enum AVStreamParseType {
+ AVSTREAM_PARSE_NONE,
+ AVSTREAM_PARSE_FULL, /**< full parsing and repack */
+ AVSTREAM_PARSE_HEADERS, /**< only parse headers, don't repack */
+ AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on packet boundary */
+};
+
typedef struct AVIndexEntry {
int64_t pos;
int64_t timestamp;
#define AVINDEX_KEYFRAME 0x0001
int flags:2;
- int size:30; //yeah trying to keep the size of this small to reduce memory requirements (its 24 vs 32 byte due to possible 8byte align)
+ int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs 32 byte due to possible 8byte align).
int min_distance; /**< min distance between this and the previous keyframe, used to avoid unneeded searching */
} AVIndexEntry;
+/**
+ * Stream structure.
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * sizeof(AVStream) must not be used outside libav*.
+ */
typedef struct AVStream {
int index; /**< stream index in AVFormatContext */
int id; /**< format specific stream id */
AVCodecContext *codec; /**< codec context */
/**
- * real base frame rate of the stream.
- * this is the lowest framerate with which all timestamps can be
- * represented accurately (its the least common multiple of all
- * framerates in the stream), Note, this value is just a guess!
- * for example if the timebase is 1/90000 and all frames have either
- * approximately 3600 or 1800 timer ticks then r_frame_rate will be 50/1
+ * Real base frame rate of the stream.
+ * This is the lowest frame rate with which all timestamps can be
+ * represented accurately (it is the least common multiple of all
+ * frame rates in the stream), Note, this value is just a guess!
+ * For example if the timebase is 1/90000 and all frames have either
+ * approximately 3600 or 1800 timer ticks then r_frame_rate will be 50/1.
*/
AVRational r_frame_rate;
void *priv_data;
-#if LIBAVFORMAT_VERSION_INT < (52<<16)
+
/* internal data used in av_find_stream_info() */
- int64_t codec_info_duration;
- int codec_info_nb_frames;
-#endif
+ int64_t first_dts;
/** encoding: PTS generation when outputing stream */
- AVFrac pts;
+ struct AVFrac pts;
/**
- * this is the fundamental unit of time (in seconds) in terms
- * of which frame timestamps are represented. for fixed-fps content,
- * timebase should be 1/framerate and timestamp increments should be
+ * This is the fundamental unit of time (in seconds) in terms
+ * of which frame timestamps are represented. For fixed-fps content,
+ * timebase should be 1/frame rate and timestamp increments should be
* identically 1.
*/
AVRational time_base;
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
/* ffmpeg.c private use */
int stream_copy; /**< if set, just copy stream */
- enum AVDiscard discard; ///< selects which packets can be discarded at will and dont need to be demuxed
+ enum AVDiscard discard; ///< selects which packets can be discarded at will and do not need to be demuxed
//FIXME move stuff to a flags field?
/** quality, as it has been removed from AVCodecContext and put in AVVideoFrame
- * MN:dunno if thats the right place, for it */
+ * MN: dunno if that is the right place for it */
float quality;
- /** decoding: position of the first frame of the component, in
- AV_TIME_BASE fractional seconds. */
+ /**
+ * Decoding: pts of the first frame of the stream, in stream time base.
+ * Only set this if you are absolutely 100% sure that the value you set
+ * it to really is the pts of the first frame.
+ * This may be undefined (AV_NOPTS_VALUE).
+ * @note The ASF header does NOT contain a correct start_time the ASF
+ * demuxer must NOT set this.
+ */
int64_t start_time;
- /** decoding: duration of the stream, in AV_TIME_BASE fractional
- seconds. */
+ /**
+ * Decoding: duration of the stream, in stream time base.
+ * If a source file does not specify a duration, but does specify
+ * a bitrate, this value will be estimates from bit rate and file size.
+ */
int64_t duration;
char language[4]; /** ISO 639 3-letter language code (empty string if undefined) */
/* av_read_frame() support */
- int need_parsing; ///< 1->full parsing needed, 2->only parse headers dont repack
+ enum AVStreamParseType need_parsing;
struct AVCodecParserContext *parser;
int64_t cur_dts;
@@ -324,21 +355,47 @@ typedef struct AVStream {
#define MAX_REORDER_DELAY 4
int64_t pts_buffer[MAX_REORDER_DELAY+1];
+
+ char *filename; /**< source filename of the stream */
} AVStream;
+#define AV_PROGRAM_RUNNING 1
+
+/**
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * sizeof(AVProgram) must not be used outside libav*.
+ */
+typedef struct AVProgram {
+ int id;
+ char *provider_name; ///< Network name for DVB streams
+ char *name; ///< Service name for DVB streams
+ int flags;
+ enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller
+ unsigned int *stream_index;
+ unsigned int nb_stream_indexes;
+} AVProgram;
+
#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present
(streams are added dynamically) */
#define MAX_STREAMS 20
-/* format I/O context */
+/**
+ * format I/O context.
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * sizeof(AVFormatContext) must not be used outside libav*.
+ */
typedef struct AVFormatContext {
const AVClass *av_class; /**< set by av_alloc_format_context */
/* can only be iformat or oformat, not both at the same time */
struct AVInputFormat *iformat;
struct AVOutputFormat *oformat;
void *priv_data;
- ByteIOContext pb;
+ ByteIOContext *pb;
unsigned int nb_streams;
AVStream *streams[MAX_STREAMS];
char filename[1024]; /**< input or output filename */
@@ -398,6 +455,7 @@ typedef struct AVFormatContext {
int flags;
#define AVFMT_FLAG_GENPTS 0x0001 ///< generate pts if missing even if it requires parsing future frames
#define AVFMT_FLAG_IGNIDX 0x0002 ///< ignore index
+#define AVFMT_FLAG_NONBLOCK 0x0004 ///< do not block when reading packets from input
int loop_input;
/** decoding: size of data to probe; encoding unused */
@@ -410,6 +468,37 @@ typedef struct AVFormatContext {
const uint8_t *key;
int keylen;
+
+ unsigned int nb_programs;
+ AVProgram **programs;
+
+ /**
+ * Forced video codec_id.
+ * demuxing: set by user
+ */
+ enum CodecID video_codec_id;
+ /**
+ * Forced audio codec_id.
+ * demuxing: set by user
+ */
+ enum CodecID audio_codec_id;
+ /**
+ * Forced subtitle codec_id.
+ * demuxing: set by user
+ */
+ enum CodecID subtitle_codec_id;
+
+ /**
+ * Maximum amount of memory in bytes to use per stream for the index.
+ * If the needed index exceeds this size entries will be discarded as
+ * needed to maintain a smaller size. This can lead to slower or less
+ * accurate seeking (depends on demuxer).
+ * Demuxers for which a full in memory index is mandatory will ignore
+ * this.
+ * muxing : unused
+ * demuxing: set by user
+ */
+ unsigned int max_index_size;
} AVFormatContext;
typedef struct AVPacketList {
@@ -417,18 +506,19 @@ typedef struct AVPacketList {
struct AVPacketList *next;
} AVPacketList;
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
extern AVInputFormat *first_iformat;
extern AVOutputFormat *first_oformat;
+#endif
+
+AVInputFormat *av_iformat_next(AVInputFormat *f);
+AVOutputFormat *av_oformat_next(AVOutputFormat *f);
enum CodecID av_guess_image2_codec(const char *filename);
/* XXX: use automatic init with either ELF sections or C file parser */
/* modules */
-#include "rtp.h"
-
-#include "rtsp.h"
-
/* utils.c */
void av_register_input_format(AVInputFormat *format);
void av_register_output_format(AVOutputFormat *format);
@@ -519,21 +609,25 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
AVInputFormat *fmt, AVFormatParameters *ap);
/**
- * Open a media file as input. The codec are not opened. Only the file
+ * Open a media file as input. The codecs are not opened. Only the file
* header (if present) is read.
*
* @param ic_ptr the opened media file handle is put here
* @param filename filename to open.
* @param fmt if non NULL, force the file format to use
* @param buf_size optional buffer size (zero if default is OK)
- * @param ap additionnal parameters needed when opening the file (NULL if default)
+ * @param ap additional parameters needed when opening the file (NULL if default)
* @return 0 if OK. AVERROR_xxx otherwise.
*/
int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVInputFormat *fmt,
int buf_size,
AVFormatParameters *ap);
-/** no av_open for output, so applications will need this: */
+/**
+ * Allocate an AVFormatContext.
+ * Can be freed with av_free() but do not forget to free everything you
+ * explicitly allocated as well!
+ */
AVFormatContext *av_alloc_format_context(void);
/**
@@ -546,14 +640,14 @@ AVFormatContext *av_alloc_format_context(void);
*
* @param ic media file handle
* @return >=0 if OK. AVERROR_xxx if error.
- * @todo let user decide somehow what information is needed so we dont waste time geting stuff the user doesnt need
+ * @todo Let user decide somehow what information is needed so we do not waste time getting stuff the user does not need.
*/
int av_find_stream_info(AVFormatContext *ic);
/**
* Read a transport packet from a media file.
*
- * This function is absolete and should never be used.
+ * This function is obsolete and should never be used.
* Use av_read_frame() instead.
*
* @param s media file handle
@@ -610,6 +704,12 @@ int av_read_play(AVFormatContext *s);
int av_read_pause(AVFormatContext *s);
/**
+ * Free a AVFormatContext allocated by av_open_input_stream.
+ * @param s context to free
+ */
+void av_close_input_stream(AVFormatContext *s);
+
+/**
* Close a media file (but not its codecs).
*
* @param s media file handle
@@ -627,6 +727,7 @@ void av_close_input_file(AVFormatContext *s);
* @param id file format dependent stream id
*/
AVStream *av_new_stream(AVFormatContext *s, int id);
+AVProgram *av_new_program(AVFormatContext *s, int id);
/**
* Set the pts for a given stream.
@@ -657,6 +758,15 @@ int av_find_default_stream_index(AVFormatContext *s);
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
/**
+ * Ensures the index uses less memory than the maximum specified in
+ * AVFormatContext.max_index_size, by discarding entries if it grows
+ * too large.
+ * This function is not part of the public API and should only be called
+ * by demuxers.
+ */
+void ff_reduce_index(AVFormatContext *s, int stream_index);
+
+/**
* Add a index entry into a sorted list updateing if it is already there.
*
* @param timestamp timestamp in the timebase of the given stream
@@ -666,7 +776,7 @@ int av_add_index_entry(AVStream *st,
/**
* Does a binary search using av_index_search_timestamp() and AVCodec.read_timestamp().
- * this isnt supposed to be called directly by a user application, but by demuxers
+ * This is not supposed to be called directly by a user application, but by demuxers.
* @param target_ts target timestamp in the time base of the given stream
* @param stream_index stream number
*/
@@ -676,7 +786,7 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
* Updates cur_dts of all streams based on given timestamp and AVStream.
*
* Stream ref_st unchanged, others set cur_dts in their native timebase
- * only needed for timestamp wrapping or if (dts not set and pts!=dts)
+ * only needed for timestamp wrapping or if (dts not set and pts!=dts).
* @param timestamp new dts expressed in time_base of param ref_st
* @param ref_st reference stream giving time_base of param timestamp
*/
@@ -684,7 +794,7 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp);
/**
* Does a binary search using read_timestamp().
- * this isnt supposed to be called directly by a user application, but by demuxers
+ * This is not supposed to be called directly by a user application, but by demuxers.
* @param target_ts target timestamp in the time base of the given stream
* @param stream_index stream number
*/
@@ -694,8 +804,8 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
/**
- * allocate the stream private data and write the stream header to an
- * output media file
+ * Allocate the stream private data and write the stream header to an
+ * output media file.
*
* @param s media file handle
* @return 0 if OK. AVERROR_xxx if error.
@@ -720,10 +830,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
*
* 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 its slightly faster, its also important
- * to keep in mind that completly non interleaved input will need huge amounts
- * of memory to interleave with this, so its prefereable to interleave at the
- * demuxer level
+ * 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.
*
* @param s media file handle
* @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
@@ -763,28 +873,41 @@ void dump_format(AVFormatContext *ic,
/**
* parses width and height out of string str.
+ * @deprecated Use av_parse_video_frame_size instead.
*/
-int parse_image_size(int *width_ptr, int *height_ptr, const char *str);
+attribute_deprecated int parse_image_size(int *width_ptr, int *height_ptr, const char *str);
/**
* Converts frame rate from string to a fraction.
+ * @deprecated Use av_parse_video_frame_rate instead.
*/
-int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg);
+attribute_deprecated int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg);
/**
- * Converts date string to number of seconds since Jan 1st, 1970.
- *
+ * Parses \p datestr and returns a corresponding number of microseconds.
+ * @param datestr String representing a date or a duration.
+ * - If a date the syntax is:
* @code
- * Syntax:
- * - If not a duration:
* [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]}
- * Time is localtime unless Z is suffixed to the end. In this case GMT
- * Return the date in micro seconds since 1970
- *
- * - If a duration:
- * HH[:MM[:SS[.m...]]]
- * S+[.m...]
* @endcode
+ * Time is localtime unless Z is appended, in which case it is
+ * interpreted as UTC.
+ * If the year-month-day part isn't specified it takes the current
+ * year-month-day.
+ * Returns the number of microseconds since 1st of January, 1970 up to
+ * the time of the parsed date or INT64_MIN if \p datestr cannot be
+ * successfully parsed.
+ * - If a duration the syntax is:
+ * @code
+ * [-]HH[:MM[:SS[.m...]]]
+ * [-]S+[.m...]
+ * @endcode
+ * Returns the number of microseconds contained in a time interval
+ * with the specified duration or INT64_MIN if \p datestr cannot be
+ * successfully parsed.
+ * @param duration Flag which tells how to interpret \p datestr, if
+ * not zero \p datestr is interpreted as a duration, otherwise as a
+ * date.
*/
int64_t parse_date(const char *datestr, int duration);
@@ -813,7 +936,7 @@ int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info);
* @param buf destination buffer
* @param buf_size destination buffer size
* @param path numbered sequence string
- * @number frame number
+ * @param number frame number
* @return 0 if OK, -1 if format error.
*/
int av_get_frame_filename(char *buf, int buf_size,
@@ -827,23 +950,24 @@ int av_get_frame_filename(char *buf, int buf_size,
*/
int av_filename_number_test(const char *filename);
-/* grab specific */
-int video_grab_init(void);
-int audio_init(void);
-
-/* DV1394 */
-int dv1394_init(void);
-int dc1394_init(void);
+/**
+ * Generate an SDP for an RTP session.
+ *
+ * @param ac array of AVFormatContexts describing the RTP streams. If the
+ * array is composed by only one context, such context can contain
+ * multiple AVStreams (one AVStream per RTP stream). Otherwise,
+ * all the contexts in the array (an AVCodecContext per RTP stream)
+ * must contain only one AVStream
+ * @param n_files number of AVCodecContexts contained in ac
+ * @param buff buffer where the SDP will be stored (must be allocated by
+ * the caller
+ * @param size the size of the buffer
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size);
#ifdef HAVE_AV_CONFIG_H
-#include "os_support.h"
-
-int strstart(const char *str, const char *val, const char **ptr);
-int stristart(const char *str, const char *val, const char **ptr);
-void pstrcpy(char *buf, int buf_size, const char *str);
-char *pstrcat(char *buf, int buf_size, const char *s);
-
void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem);
#ifdef __GNUC__
@@ -880,9 +1004,4 @@ int match_ext(const char *filename, const char *extensions);
#endif /* HAVE_AV_CONFIG_H */
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVFORMAT_H */
-
+#endif /* FFMPEG_AVFORMAT_H */
diff --git a/contrib/ffmpeg/libavformat/avidec.c b/contrib/ffmpeg/libavformat/avidec.c
index 23c130ab7..4b9bcf2a4 100644
--- a/contrib/ffmpeg/libavformat/avidec.c
+++ b/contrib/ffmpeg/libavformat/avidec.c
@@ -48,6 +48,7 @@ typedef struct AVIStream {
typedef struct {
int64_t riff_end;
int64_t movi_end;
+ int64_t fsize;
offset_t movi_list;
int index_loaded;
int is_odml;
@@ -56,6 +57,15 @@ typedef struct {
DVDemuxContext* dv_demux;
} AVIContext;
+static const char avi_headers[][8] = {
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' },
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' },
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19},
+ { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' },
+ { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' },
+ { 0 }
+};
+
static int avi_load_index(AVFormatContext *s);
static int guess_ni_flag(AVFormatContext *s);
@@ -73,27 +83,30 @@ static void print_tag(const char *str, unsigned int tag, int size)
static int get_riff(AVIContext *avi, ByteIOContext *pb)
{
- uint32_t tag;
- /* check RIFF header */
- tag = get_le32(pb);
+ char header[8];
+ int i;
- if (tag != MKTAG('R', 'I', 'F', 'F'))
- return -1;
+ /* check RIFF header */
+ get_buffer(pb, header, 4);
avi->riff_end = get_le32(pb); /* RIFF chunk size */
avi->riff_end += url_ftell(pb); /* RIFF chunk end */
- tag = get_le32(pb);
- if(tag == MKTAG('A', 'V', 'I', 0x19))
- av_log(NULL, AV_LOG_INFO, "file has been generated with a totally broken muxer\n");
- else
- if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X'))
+ get_buffer(pb, header+4, 4);
+
+ for(i=0; avi_headers[i][0]; i++)
+ if(!memcmp(header, avi_headers[i], 8))
+ break;
+ if(!avi_headers[i][0])
return -1;
+ if(header[7] == 0x19)
+ av_log(NULL, AV_LOG_INFO, "file has been generated with a totally broken muxer\n");
+
return 0;
}
static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int longs_pre_entry= get_le16(pb);
int index_sub_type = get_byte(pb);
int index_type = get_byte(pb);
@@ -105,7 +118,7 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
AVIStream *ast;
int i;
int64_t last_pos= -1;
- int64_t filesize= url_fsize(&s->pb);
+ int64_t filesize= url_fsize(s->pb);
#ifdef DEBUG_SEEK
av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n",
@@ -212,7 +225,7 @@ static int avi_read_tag(ByteIOContext *pb, char *buf, int maxlen, unsigned int
static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t tag, tag1, handler;
int codec_type, stream_index, frame_period, bit_rate;
unsigned int size, nb_frames;
@@ -220,12 +233,18 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
AVStream *st;
AVIStream *ast = NULL;
char str_track[4];
+ int avih_width=0, avih_height=0;
+ int amv_file_format=0;
avi->stream_index= -1;
if (get_riff(avi, pb) < 0)
return -1;
+ avi->fsize = url_fsize(pb);
+ if(avi->fsize<=0)
+ avi->fsize= avi->riff_end;
+
/* first list tag */
stream_index = -1;
codec_type = -1;
@@ -260,6 +279,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
avi->is_odml = 1;
url_fskip(pb, size + (size & 1));
break;
+ case MKTAG('a', 'm', 'v', 'h'):
+ amv_file_format=1;
case MKTAG('a', 'v', 'i', 'h'):
/* avi header */
/* using frame_period is bad idea */
@@ -270,8 +291,11 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
url_fskip(pb, 2 * 4);
get_le32(pb);
+ get_le32(pb);
+ avih_width=get_le32(pb);
+ avih_height=get_le32(pb);
- url_fskip(pb, size - 7 * 4);
+ url_fskip(pb, size - 10 * 4);
break;
case MKTAG('s', 't', 'r', 'h'):
/* stream header */
@@ -293,6 +317,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
goto fail;
st->priv_data = ast;
}
+ if(amv_file_format)
+ tag1 = stream_index ? MKTAG('a','u','d','s') : MKTAG('v','i','d','s');
#ifdef DEBUG
print_tag("strh", tag1, -1);
@@ -400,6 +426,14 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
st = s->streams[stream_index];
switch(codec_type) {
case CODEC_TYPE_VIDEO:
+ if(amv_file_format){
+ st->codec->width=avih_width;
+ st->codec->height=avih_height;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_AMV;
+ url_fskip(pb, size);
+ break;
+ }
get_le32(pb); /* size */
st->codec->width = get_le32(pb);
st->codec->height = get_le32(pb);
@@ -412,6 +446,13 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_le32(pb); /* ClrUsed */
get_le32(pb); /* ClrImportant */
+ if (tag1 == MKTAG('D', 'X', 'S', 'B')) {
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ st->codec->codec_tag = tag1;
+ st->codec->codec_id = CODEC_ID_XSUB;
+ break;
+ }
+
if(size > 10*4 && size<(1<<30)){
st->codec->extradata_size= size - 10*4;
st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
@@ -442,7 +483,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_tag = tag1;
st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
- st->need_parsing = 2; //only parse headers dont do slower repacketization, this is needed to get the pict type which is needed for generating correct pts
+ st->need_parsing = AVSTREAM_PARSE_HEADERS; // this is needed to get the pict type which is needed for generating correct pts
// url_fskip(pb, size - 5 * 4);
break;
case CODEC_TYPE_AUDIO:
@@ -452,17 +493,19 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
url_fskip(pb, 1);
/* Force parsing as several audio frames can be in
- * one packet. */
- st->need_parsing = 1;
+ * one packet and timestamps refer to packet start*/
+ st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
/* ADTS header is in extradata, AAC without header must be stored as exact frames, parser not needed and it will fail */
if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size)
- st->need_parsing = 0;
+ st->need_parsing = AVSTREAM_PARSE_NONE;
/* AVI files with Xan DPCM audio (wrongly) declare PCM
* audio in the header but have Axan as stream_code_tag. */
if (st->codec->stream_codec_tag == ff_get_fourcc("Axan")){
st->codec->codec_id = CODEC_ID_XAN_DPCM;
st->codec->codec_tag = 0;
}
+ if (amv_file_format)
+ st->codec->codec_id = CODEC_ID_ADPCM_IMA_AMV;
break;
default:
st->codec->codec_type = CODEC_TYPE_DATA;
@@ -480,6 +523,31 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
url_fseek(pb, i+size, SEEK_SET);
break;
+ case MKTAG('v', 'p', 'r', 'p'):
+ if(stream_index < (unsigned)s->nb_streams && size > 9*4){
+ AVRational active, active_aspect;
+
+ st = s->streams[stream_index];
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+
+ active_aspect.num= get_le16(pb);
+ active_aspect.den= get_le16(pb);
+ active.num = get_le32(pb);
+ active.den = get_le32(pb);
+ get_le32(pb); //nbFieldsPerFrame
+
+ if(active_aspect.num && active_aspect.den && active.num && active.den){
+ st->codec->sample_aspect_ratio= av_div_q(active_aspect, active);
+//av_log(s, AV_LOG_ERROR, "vprp %d/%d %d/%d\n", active_aspect.num, active_aspect.den, active.num, active.den);
+ }
+ size -= 9*4;
+ }
+ url_fseek(pb, size, SEEK_CUR);
+ break;
case MKTAG('I', 'N', 'A', 'M'):
avi_read_tag(pb, s->title, sizeof(s->title), size);
break;
@@ -540,7 +608,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int n, d[8], size;
offset_t i, sync;
void* dstr;
@@ -585,7 +653,7 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
if(i>=0){
int64_t pos= best_st->index_entries[i].pos;
pos += best_ast->packet_size - best_ast->remaining;
- url_fseek(&s->pb, pos + 8, SEEK_SET);
+ url_fseek(s->pb, pos + 8, SEEK_SET);
// av_log(NULL, AV_LOG_DEBUG, "pos=%"PRId64"\n", pos);
assert(best_ast->remaining <= best_ast->packet_size);
@@ -662,14 +730,6 @@ resync:
for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
int j;
- if (i >= avi->movi_end) {
- if (avi->is_odml) {
- url_fskip(pb, avi->riff_end - i);
- avi->riff_end = avi->movi_end = url_fsize(pb);
- } else
- break;
- }
-
for(j=0; j<7; j++)
d[j]= d[j+1];
d[7]= get_byte(pb);
@@ -683,13 +743,14 @@ resync:
n= 100; //invalid stream id
}
//av_log(NULL, AV_LOG_DEBUG, "%X %X %X %X %X %X %X %X %"PRId64" %d %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
- if(i + size > avi->movi_end || d[0]<0)
+ if(i + size > avi->fsize || d[0]<0)
continue;
//parse ix##
if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
//parse JUNK
- ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')){
+ ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')
+ ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){
url_fskip(pb, size);
//av_log(NULL, AV_LOG_DEBUG, "SKIP\n");
goto resync;
@@ -748,7 +809,7 @@ resync:
if ( d[0] >= '0' && d[0] <= '9'
&& d[1] >= '0' && d[1] <= '9'
&& ((d[2] == 'p' && d[3] == 'c'))
- && n < s->nb_streams && i + size <= avi->movi_end) {
+ && n < s->nb_streams && i + size <= avi->fsize) {
AVStream *st;
int first, clr, flags, k, p;
@@ -783,7 +844,7 @@ resync:
static int avi_read_idx1(AVFormatContext *s, int size)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int nb_index_entries, i;
AVStream *st;
AVIStream *ast;
@@ -854,7 +915,7 @@ static int guess_ni_flag(AVFormatContext *s){
static int avi_load_index(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t tag, size;
offset_t pos= url_ftell(pb);
@@ -929,7 +990,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
/* DV demux so it can synth correct timestamps */
dv_offset_reset(avi->dv_demux, timestamp);
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
avi->stream_index= -1;
return 0;
}
@@ -969,7 +1030,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
}
/* do the seek */
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
avi->stream_index= -1;
return 0;
}
@@ -994,16 +1055,15 @@ static int avi_read_close(AVFormatContext *s)
static int avi_probe(AVProbeData *p)
{
+ int i;
+
/* check file header */
- if (p->buf_size <= 32)
- return 0;
- if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
- p->buf[2] == 'F' && p->buf[3] == 'F' &&
- p->buf[8] == 'A' && p->buf[9] == 'V' &&
- p->buf[10] == 'I' && (p->buf[11] == ' ' || p->buf[11] == 0x19))
- return AVPROBE_SCORE_MAX;
- else
- return 0;
+ for(i=0; avi_headers[i][0]; i++)
+ if(!memcmp(p->buf , avi_headers[i] , 4) &&
+ !memcmp(p->buf+8, avi_headers[i]+4, 4))
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
}
AVInputFormat avi_demuxer = {
diff --git a/contrib/ffmpeg/libavformat/avienc.c b/contrib/ffmpeg/libavformat/avienc.c
index ac8b2670d..6b62f76d8 100644
--- a/contrib/ffmpeg/libavformat/avienc.c
+++ b/contrib/ffmpeg/libavformat/avienc.c
@@ -105,7 +105,7 @@ static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *s
static int avi_write_counters(AVFormatContext* s, int riff_id)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVIContext *avi = s->priv_data;
int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
offset_t file_size;
@@ -138,7 +138,7 @@ static int avi_write_counters(AVFormatContext* s, int riff_id)
static int avi_write_header(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
AVCodecContext *stream, *video_enc;
offset_t list1, list2, strh, strf;
@@ -197,11 +197,6 @@ static int avi_write_header(AVFormatContext *s)
stream = s->streams[i]->codec;
- /* FourCC should really be set by the codec itself */
- if (! stream->codec_tag) {
- stream->codec_tag = codec_get_bmp_tag(stream->codec_id);
- }
-
/* stream generic header */
strh = start_tag(pb, "strh");
switch(stream->codec_type) {
@@ -337,7 +332,7 @@ static int avi_write_header(AVFormatContext *s)
static int avi_write_ix(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVIContext *avi = s->priv_data;
char tag[5];
char ix_tag[] = "ix00";
@@ -394,7 +389,7 @@ static int avi_write_ix(AVFormatContext *s)
static int avi_write_idx1(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVIContext *avi = s->priv_data;
offset_t idx_chunk;
int i;
@@ -440,7 +435,7 @@ static int avi_write_idx1(AVFormatContext *s)
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned char tag[5];
unsigned int flags=0;
const int stream_index= pkt->stream_index;
@@ -481,7 +476,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
avi->audio_strm_length[stream_index] += size;
}
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
AVIIndex* idx = &avi->indexes[stream_index];
int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
@@ -514,7 +509,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
static int avi_write_trailer(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int res = 0;
int i, j, n, nb_frames;
offset_t file_size;
diff --git a/contrib/ffmpeg/libavformat/avio.c b/contrib/ffmpeg/libavformat/avio.c
index a22bd22f3..5f5bff158 100644
--- a/contrib/ffmpeg/libavformat/avio.c
+++ b/contrib/ffmpeg/libavformat/avio.c
@@ -19,12 +19,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
+#include "avstring.h"
static int default_interrupt_cb(void);
URLProtocol *first_protocol = NULL;
URLInterruptCB *url_interrupt_cb = default_interrupt_cb;
+URLProtocol *av_protocol_next(URLProtocol *p)
+{
+ if(p) return p->next;
+ else return first_protocol;
+}
+
int register_protocol(URLProtocol *protocol)
{
URLProtocol **p;
@@ -75,9 +82,7 @@ int url_open(URLContext **puc, const char *filename, int flags)
err = AVERROR(ENOMEM);
goto fail;
}
-#if LIBAVFORMAT_VERSION_INT >= (52<<16)
uc->filename = (char *) &uc[1];
-#endif
strcpy(uc->filename, filename);
uc->prot = up;
uc->flags = flags;
@@ -100,24 +105,22 @@ int url_read(URLContext *h, unsigned char *buf, int size)
{
int ret;
if (h->flags & URL_WRONLY)
- return AVERROR_IO;
+ return AVERROR(EIO);
ret = h->prot->url_read(h, buf, size);
return ret;
}
-#if defined(CONFIG_MUXERS) || defined(CONFIG_PROTOCOLS)
int url_write(URLContext *h, unsigned char *buf, int size)
{
int ret;
if (!(h->flags & (URL_WRONLY | URL_RDWR)))
- return AVERROR_IO;
+ return AVERROR(EIO);
/* avoid sending too big packets */
if (h->max_packet_size && size > h->max_packet_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
ret = h->prot->url_write(h, buf, size);
return ret;
}
-#endif //CONFIG_MUXERS || CONFIG_PROTOCOLS
offset_t url_seek(URLContext *h, offset_t pos, int whence)
{
@@ -131,9 +134,11 @@ offset_t url_seek(URLContext *h, offset_t pos, int whence)
int url_close(URLContext *h)
{
- int ret;
+ int ret = 0;
+ if (!h) return 0; /* can happen when url_open fails */
- ret = h->prot->url_close(h);
+ if (h->prot->url_close)
+ ret = h->prot->url_close(h);
av_free(h);
return ret;
}
@@ -169,7 +174,7 @@ int url_get_max_packet_size(URLContext *h)
void url_get_filename(URLContext *h, char *buf, int buf_size)
{
- pstrcpy(buf, buf_size, h->filename);
+ av_strlcpy(buf, h->filename, buf_size);
}
@@ -184,3 +189,18 @@ void url_set_interrupt_cb(URLInterruptCB *interrupt_cb)
interrupt_cb = default_interrupt_cb;
url_interrupt_cb = interrupt_cb;
}
+
+int av_url_read_pause(URLContext *h, int pause)
+{
+ if (!h->prot->url_read_pause)
+ return AVERROR(ENOSYS);
+ return h->prot->url_read_pause(h, pause);
+}
+
+offset_t av_url_read_seek(URLContext *h,
+ int stream_index, int64_t timestamp, int flags)
+{
+ if (!h->prot->url_read_seek)
+ return AVERROR(ENOSYS);
+ return h->prot->url_read_seek(h, stream_index, timestamp, flags);
+}
diff --git a/contrib/ffmpeg/libavformat/avio.h b/contrib/ffmpeg/libavformat/avio.h
index be78c9a7b..9443cb017 100644
--- a/contrib/ffmpeg/libavformat/avio.h
+++ b/contrib/ffmpeg/libavformat/avio.h
@@ -18,8 +18,10 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef AVIO_H
-#define AVIO_H
+#ifndef FFMPEG_AVIO_H
+#define FFMPEG_AVIO_H
+
+#include <stdint.h>
/* output byte stream handling */
@@ -27,17 +29,20 @@ typedef int64_t offset_t;
/* unbuffered I/O */
+/**
+ * URL Context.
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * sizeof(URLContext) must not be used outside libav*.
+ */
struct URLContext {
struct URLProtocol *prot;
int flags;
int is_streamed; /**< true if streamed (no seek possible), default = false */
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
void *priv_data;
-#if LIBAVFORMAT_VERSION_INT >= (52<<16)
char *filename; /**< specified filename */
-#else
- char filename[1]; /**< specified filename */
-#endif
};
typedef struct URLContext URLContext;
@@ -64,7 +69,7 @@ offset_t url_filesize(URLContext *h);
/**
* Return the maximum packet size associated to packetized file
- * handle. If the file is not packetized (stream like http or file on
+ * handle. If the file is not packetized (stream like HTTP or file on
* disk), then 0 is returned.
*
* @param h file handle
@@ -74,10 +79,10 @@ int url_get_max_packet_size(URLContext *h);
void url_get_filename(URLContext *h, char *buf, int buf_size);
/**
- * the callback is called in blocking functions to test regulary if
+ * The callback is called in blocking functions to test regulary if
* asynchronous interruption is needed. AVERROR(EINTR) is returned
* in this case by the interrupted function. 'NULL' means no interrupt
- * callback is given. i
+ * callback is given.
*/
void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
@@ -85,9 +90,36 @@ void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
int url_poll(URLPollEntry *poll_table, int n, int timeout);
/**
- * passing this as the "whence" parameter to a seek function causes it to
- * return the filesize without seeking anywhere, supporting this is optional
- * if its not supprted then the seek function will return <0
+ * Pause and resume playing - only meaningful if using a network streaming
+ * protocol (e.g. MMS).
+ * @param pause 1 for pause, 0 for resume
+ */
+int av_url_read_pause(URLContext *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 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.
+ * If a stream_index >= 0 is used and the protocol does not support
+ * seeking based on component streams, the call will fail with ENOTSUP.
+ * @param timestamp timestamp in AVStream.time_base units
+ * or if there is no stream specified then in AV_TIME_BASE units.
+ * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
+ * and AVSEEK_FLAG_ANY. The protocol may silently ignore
+ * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
+ * fail with ENOTSUP if used and not supported.
+ * @return >= 0 on success
+ * @see AVInputFormat::read_seek
+ */
+offset_t av_url_read_seek(URLContext *h,
+ int stream_index, int64_t timestamp, int flags);
+
+/**
+ * Passing this as the "whence" parameter to a seek function causes it to
+ * return the filesize without seeking anywhere. Supporting this is optional.
+ * If it is not supported then the seek function will return <0.
*/
#define AVSEEK_SIZE 0x10000
@@ -99,13 +131,25 @@ typedef struct URLProtocol {
offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
int (*url_close)(URLContext *h);
struct URLProtocol *next;
+ int (*url_read_pause)(URLContext *h, int pause);
+ offset_t (*url_read_seek)(URLContext *h,
+ int stream_index, int64_t timestamp, int flags);
} URLProtocol;
extern URLProtocol *first_protocol;
extern URLInterruptCB *url_interrupt_cb;
+URLProtocol *av_protocol_next(URLProtocol *p);
+
int register_protocol(URLProtocol *protocol);
+/**
+ * Bytestream IO Context.
+ * New fields can be added to the end with minor version bumps.
+ * Removal, reordering and changes to existing fields require a major
+ * version bump.
+ * sizeof(ByteIOContext) must not be used outside libav*.
+ */
typedef struct {
unsigned char *buffer;
int buffer_size;
@@ -124,6 +168,9 @@ typedef struct {
unsigned char *checksum_ptr;
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
int error; ///< contains the error code or 0 if no error happened
+ int (*read_pause)(void *opaque, int pause);
+ offset_t (*read_seek)(void *opaque,
+ int stream_index, int64_t timestamp, int flags);
} ByteIOContext;
int init_put_byte(ByteIOContext *s,
@@ -134,6 +181,14 @@ int init_put_byte(ByteIOContext *s,
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
offset_t (*seek)(void *opaque, offset_t offset, int whence));
+ByteIOContext *av_alloc_put_byte(
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
+ int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
+ offset_t (*seek)(void *opaque, offset_t offset, int whence));
void put_byte(ByteIOContext *s, int b);
void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
@@ -156,6 +211,10 @@ offset_t url_fsize(ByteIOContext *s);
int url_feof(ByteIOContext *s);
int url_ferror(ByteIOContext *s);
+int av_url_read_fpause(ByteIOContext *h, int pause);
+offset_t av_url_read_fseek(ByteIOContext *h,
+ int stream_index, int64_t timestamp, int flags);
+
#define URL_EOF (-1)
/** @note return URL_EOF (-1) if EOF */
int url_fgetc(ByteIOContext *s);
@@ -190,19 +249,28 @@ unsigned int get_be24(ByteIOContext *s);
unsigned int get_be32(ByteIOContext *s);
uint64_t get_be64(ByteIOContext *s);
+uint64_t ff_get_v(ByteIOContext *bc);
+
static inline int url_is_streamed(ByteIOContext *s)
{
return s->is_streamed;
}
-int url_fdopen(ByteIOContext *s, URLContext *h);
+/** @note when opened as read/write, the buffers are only used for
+ writing */
+int url_fdopen(ByteIOContext **s, URLContext *h);
/** @warning must be called before any I/O */
int url_setbufsize(ByteIOContext *s, int buf_size);
+/** Reset the buffer for reading or writing.
+ * @note Will drop any data currently in the buffer without transmitting it.
+ * @param flags URL_RDONLY to set up the buffer for reading, or URL_WRONLY
+ * to set up the buffer for writing. */
+int url_resetbuf(ByteIOContext *s, int flags);
/** @note when opened as read/write, the buffers are only used for
- reading */
-int url_fopen(ByteIOContext *s, const char *filename, int flags);
+ writing */
+int url_fopen(ByteIOContext **s, const char *filename, int flags);
int url_fclose(ByteIOContext *s);
URLContext *url_fileno(ByteIOContext *s);
@@ -211,12 +279,12 @@ URLContext *url_fileno(ByteIOContext *s);
* handle. If the file is not packetized (stream like http or file on
* disk), then 0 is returned.
*
- * @param h buffered file handle
+ * @param s buffered file handle
* @return maximum packet size in bytes
*/
int url_fget_max_packet_size(ByteIOContext *s);
-int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags);
+int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags);
/** return the written or read size */
int url_close_buf(ByteIOContext *s);
@@ -227,7 +295,7 @@ int url_close_buf(ByteIOContext *s);
* @param s new IO context
* @return zero if no error.
*/
-int url_open_dyn_buf(ByteIOContext *s);
+int url_open_dyn_buf(ByteIOContext **s);
/**
* Open a write only packetized memory stream with a maximum packet
@@ -238,35 +306,24 @@ int url_open_dyn_buf(ByteIOContext *s);
* @param max_packet_size maximum packet size (must be > 0)
* @return zero if no error.
*/
-int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
+int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size);
/**
* Return the written size and a pointer to the buffer. The buffer
* must be freed with av_free().
* @param s IO context
- * @param pointer to a byte buffer
+ * @param pbuffer pointer to a byte buffer
* @return the length of the byte buffer
*/
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
+unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len);
unsigned long get_checksum(ByteIOContext *s);
void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
-/* file.c */
-extern URLProtocol file_protocol;
-extern URLProtocol pipe_protocol;
-
/* udp.c */
-extern URLProtocol udp_protocol;
int udp_set_remote_url(URLContext *h, const char *uri);
int udp_get_local_port(URLContext *h);
int udp_get_file_handle(URLContext *h);
-/* tcp.c */
-extern URLProtocol tcp_protocol;
-
-/* http.c */
-extern URLProtocol http_protocol;
-
-#endif
-
+#endif /* FFMPEG_AVIO_H */
diff --git a/contrib/ffmpeg/libavformat/aviobuf.c b/contrib/ffmpeg/libavformat/aviobuf.c
index 2cc247b62..3917270b1 100644
--- a/contrib/ffmpeg/libavformat/aviobuf.c
+++ b/contrib/ffmpeg/libavformat/aviobuf.c
@@ -20,6 +20,7 @@
*/
#include "avformat.h"
#include "avio.h"
+#include "crc.h"
#include <stdarg.h>
#define IO_BUFFER_SIZE 32768
@@ -38,11 +39,7 @@ int init_put_byte(ByteIOContext *s,
s->buffer = buffer;
s->buffer_size = buffer_size;
s->buf_ptr = buffer;
- s->write_flag = write_flag;
- if (!s->write_flag)
- s->buf_end = buffer;
- else
- s->buf_end = buffer + buffer_size;
+ url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY);
s->opaque = opaque;
s->write_packet = write_packet;
s->read_packet = read_packet;
@@ -58,9 +55,25 @@ int init_put_byte(ByteIOContext *s,
s->pos = buffer_size;
s->buf_end = s->buffer + buffer_size;
}
+ s->read_pause = NULL;
+ s->read_seek = NULL;
return 0;
}
+ByteIOContext *av_alloc_put_byte(
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
+ int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
+ offset_t (*seek)(void *opaque, offset_t offset, int whence)) {
+ ByteIOContext *s = av_mallocz(sizeof(ByteIOContext));
+ init_put_byte(s, buffer, buffer_size, write_flag, opaque,
+ read_packet, write_packet, seek);
+ return s;
+}
+
static void flush_buffer(ByteIOContext *s)
{
if (s->buf_ptr > s->buffer) {
@@ -114,7 +127,12 @@ void put_flush_packet(ByteIOContext *s)
offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
{
offset_t offset1;
- offset_t pos= s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
+ offset_t pos;
+
+ if(!s)
+ return AVERROR(EINVAL);
+
+ pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
if (whence != SEEK_CUR && whence != SEEK_SET)
return AVERROR(EINVAL);
@@ -134,6 +152,8 @@ offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
offset1 >= 0 && offset1 < (s->buf_end - s->buffer) + (1<<16)){
while(s->pos < offset && !s->eof_reached)
fill_buffer(s);
+ if (s->eof_reached)
+ return AVERROR(EPIPE);
s->buf_ptr = s->buf_end + offset - s->pos;
} else {
offset_t res = AVERROR(EPIPE);
@@ -170,6 +190,9 @@ offset_t url_fsize(ByteIOContext *s)
{
offset_t size;
+ if(!s)
+ return AVERROR(EINVAL);
+
if (!s->seek)
return AVERROR(EPIPE);
size = s->seek(s->opaque, 0, AVSEEK_SIZE);
@@ -184,11 +207,15 @@ offset_t url_fsize(ByteIOContext *s)
int url_feof(ByteIOContext *s)
{
+ if(!s)
+ return 0;
return s->eof_reached;
}
int url_ferror(ByteIOContext *s)
{
+ if(!s)
+ return 0;
return s->error;
}
@@ -263,7 +290,7 @@ void put_tag(ByteIOContext *s, const char *tag)
static void fill_buffer(ByteIOContext *s)
{
- int len;
+ int len=0;
/* no need to do anything if EOF already reached */
if (s->eof_reached)
@@ -275,13 +302,14 @@ static void fill_buffer(ByteIOContext *s)
s->checksum_ptr= s->buffer;
}
- len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
+ if(s->read_packet)
+ len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
if (len <= 0) {
/* do not modify buffer if EOF reached so that a seek back can
be done without rereading data */
s->eof_reached = 1;
- if(len<0)
- s->error= len;
+ if(len<0)
+ s->error= len;
} else {
s->pos += len;
s->buf_ptr = s->buffer;
@@ -289,6 +317,10 @@ static void fill_buffer(ByteIOContext *s)
}
}
+unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len){
+ return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
+}
+
unsigned long get_checksum(ByteIOContext *s){
s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
s->update_checksum= NULL;
@@ -341,7 +373,8 @@ int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
len = size;
if (len == 0) {
if(size > s->buffer_size && !s->update_checksum){
- len = s->read_packet(s->opaque, buf, size);
+ if(s->read_packet)
+ len = s->read_packet(s->opaque, buf, size);
if (len <= 0) {
/* do not modify buffer if EOF reached so that a seek back can
be done without rereading data */
@@ -469,32 +502,18 @@ uint64_t get_be64(ByteIOContext *s)
return val;
}
-/* link with avio functions */
-
-#ifdef CONFIG_MUXERS
-static int url_write_packet(void *opaque, uint8_t *buf, int buf_size)
-{
- URLContext *h = opaque;
- return url_write(h, buf, buf_size);
-}
-#else
-#define url_write_packet NULL
-#endif //CONFIG_MUXERS
-
-static int url_read_packet(void *opaque, uint8_t *buf, int buf_size)
-{
- URLContext *h = opaque;
- return url_read(h, buf, buf_size);
-}
+uint64_t ff_get_v(ByteIOContext *bc){
+ uint64_t val = 0;
+ int tmp;
-static offset_t url_seek_packet(void *opaque, offset_t offset, int whence)
-{
- URLContext *h = opaque;
- return url_seek(h, offset, whence);
- //return 0;
+ do{
+ tmp = get_byte(bc);
+ val= (val<<7) + (tmp&127);
+ }while(tmp&128);
+ return val;
}
-int url_fdopen(ByteIOContext *s, URLContext *h)
+int url_fdopen(ByteIOContext **s, URLContext *h)
{
uint8_t *buffer;
int buffer_size, max_packet_size;
@@ -510,14 +529,25 @@ int url_fdopen(ByteIOContext *s, URLContext *h)
if (!buffer)
return AVERROR(ENOMEM);
- if (init_put_byte(s, buffer, buffer_size,
+ *s = av_mallocz(sizeof(ByteIOContext));
+ if(!*s) {
+ av_free(buffer);
+ return AVERROR(ENOMEM);
+ }
+
+ if (init_put_byte(*s, buffer, buffer_size,
(h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
- url_read_packet, url_write_packet, url_seek_packet) < 0) {
+ url_read, url_write, url_seek) < 0) {
av_free(buffer);
- return AVERROR_IO;
+ av_freep(s);
+ return AVERROR(EIO);
+ }
+ (*s)->is_streamed = h->is_streamed;
+ (*s)->max_packet_size = max_packet_size;
+ if(h->prot) {
+ (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
+ (*s)->read_seek = (offset_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
}
- s->is_streamed = h->is_streamed;
- s->max_packet_size = max_packet_size;
return 0;
}
@@ -532,14 +562,27 @@ int url_setbufsize(ByteIOContext *s, int buf_size)
s->buffer = buffer;
s->buffer_size = buf_size;
s->buf_ptr = buffer;
- if (!s->write_flag)
- s->buf_end = buffer;
- else
- s->buf_end = buffer + buf_size;
+ url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY);
+ return 0;
+}
+
+int url_resetbuf(ByteIOContext *s, int flags)
+{
+ URLContext *h = s->opaque;
+ if ((flags & URL_RDWR) || (h && h->flags != flags && !h->flags & URL_RDWR))
+ return AVERROR(EINVAL);
+
+ if (flags & URL_WRONLY) {
+ s->buf_end = s->buffer + s->buffer_size;
+ s->write_flag = 1;
+ } else {
+ s->buf_end = s->buffer;
+ s->write_flag = 0;
+ }
return 0;
}
-int url_fopen(ByteIOContext *s, const char *filename, int flags)
+int url_fopen(ByteIOContext **s, const char *filename, int flags)
{
URLContext *h;
int err;
@@ -560,7 +603,7 @@ int url_fclose(ByteIOContext *s)
URLContext *h = s->opaque;
av_free(s->buffer);
- memset(s, 0, sizeof(ByteIOContext));
+ av_free(s);
return url_close(h);
}
@@ -610,15 +653,44 @@ int url_fget_max_packet_size(ByteIOContext *s)
return s->max_packet_size;
}
+int av_url_read_fpause(ByteIOContext *s, int pause)
+{
+ if (!s->read_pause)
+ return AVERROR(ENOSYS);
+ return s->read_pause(s->opaque, pause);
+}
+
+offset_t av_url_read_fseek(ByteIOContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ URLContext *h = s->opaque;
+ offset_t ret;
+ if (!s->read_seek)
+ return AVERROR(ENOSYS);
+ ret = s->read_seek(h, stream_index, timestamp, flags);
+ if(ret >= 0) {
+ s->buf_ptr = s->buf_end; // Flush buffer
+ s->pos = s->seek(h, 0, SEEK_CUR);
+ }
+ return ret;
+}
+
/* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
* back to the server even if CONFIG_MUXERS is not set. */
#if defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK)
/* buffer handling */
-int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags)
+int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags)
{
- return init_put_byte(s, buf, buf_size,
- (flags & URL_WRONLY || flags & URL_RDWR),
- NULL, NULL, NULL, NULL);
+ int ret;
+ *s = av_mallocz(sizeof(ByteIOContext));
+ if(!*s)
+ return AVERROR(ENOMEM);
+ ret = init_put_byte(*s, buf, buf_size,
+ (flags & URL_WRONLY || flags & URL_RDWR),
+ NULL, NULL, NULL, NULL);
+ if(ret != 0)
+ av_freep(s);
+ return ret;
}
int url_close_buf(ByteIOContext *s)
@@ -698,7 +770,7 @@ static offset_t dyn_buf_seek(void *opaque, offset_t offset, int whence)
return 0;
}
-static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size)
+static int url_open_dyn_buf_internal(ByteIOContext **s, int max_packet_size)
{
DynBuffer *d;
int io_buffer_size, ret;
@@ -713,27 +785,35 @@ static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size)
d = av_malloc(sizeof(DynBuffer) + io_buffer_size);
if (!d)
return -1;
+ *s = av_mallocz(sizeof(ByteIOContext));
+ if(!*s) {
+ av_free(d);
+ return AVERROR(ENOMEM);
+ }
d->io_buffer_size = io_buffer_size;
d->buffer = NULL;
d->pos = 0;
d->size = 0;
d->allocated_size = 0;
- ret = init_put_byte(s, d->io_buffer, io_buffer_size,
+ ret = init_put_byte(*s, d->io_buffer, io_buffer_size,
1, d, NULL,
max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
max_packet_size ? NULL : dyn_buf_seek);
if (ret == 0) {
- s->max_packet_size = max_packet_size;
+ (*s)->max_packet_size = max_packet_size;
+ } else {
+ av_free(d);
+ av_freep(s);
}
return ret;
}
-int url_open_dyn_buf(ByteIOContext *s)
+int url_open_dyn_buf(ByteIOContext **s)
{
return url_open_dyn_buf_internal(s, 0);
}
-int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size)
+int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size)
{
if (max_packet_size <= 0)
return -1;
@@ -750,6 +830,7 @@ int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
*pbuffer = d->buffer;
size = d->size;
av_free(d);
+ av_free(s);
return size;
}
#endif /* CONFIG_MUXERS || CONFIG_NETWORK */
diff --git a/contrib/ffmpeg/libavformat/avisynth.c b/contrib/ffmpeg/libavformat/avisynth.c
index 1afcdea5e..158cac1fc 100644
--- a/contrib/ffmpeg/libavformat/avisynth.c
+++ b/contrib/ffmpeg/libavformat/avisynth.c
@@ -156,10 +156,10 @@ static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
stream = &avs->streams[stream_id];
if (stream->read >= stream->info.dwLength)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (av_new_packet(pkt, stream->chunck_size))
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = stream_id;
pkt->pts = avs->streams[stream_id].read / avs->streams[stream_id].chunck_samples;
diff --git a/contrib/ffmpeg/libavformat/avs.c b/contrib/ffmpeg/libavformat/avs.c
index 0fa77deff..b1d6f89e0 100644
--- a/contrib/ffmpeg/libavformat/avs.c
+++ b/contrib/ffmpeg/libavformat/avs.c
@@ -16,7 +16,7 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
@@ -47,8 +47,6 @@ static int avs_probe(AVProbeData * p)
{
const uint8_t *d;
- if (p->buf_size < 2)
- return 0;
d = p->buf;
if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0)
return 50;
@@ -62,12 +60,12 @@ static int avs_read_header(AVFormatContext * s, AVFormatParameters * ap)
s->ctx_flags |= AVFMTCTX_NOHEADER;
- url_fskip(&s->pb, 4);
- avs->width = get_le16(&s->pb);
- avs->height = get_le16(&s->pb);
- avs->bits_per_sample = get_le16(&s->pb);
- avs->fps = get_le16(&s->pb);
- avs->nb_frames = get_le32(&s->pb);
+ url_fskip(s->pb, 4);
+ avs->width = get_le16(s->pb);
+ avs->height = get_le16(s->pb);
+ avs->bits_per_sample = get_le16(s->pb);
+ avs->fps = get_le16(s->pb);
+ avs->nb_frames = get_le32(s->pb);
avs->remaining_frame_size = 0;
avs->remaining_audio_size = 0;
@@ -105,10 +103,10 @@ avs_read_video_packet(AVFormatContext * s, AVPacket * pkt,
pkt->data[palette_size + 1] = type;
pkt->data[palette_size + 2] = size & 0xFF;
pkt->data[palette_size + 3] = (size >> 8) & 0xFF;
- ret = get_buffer(&s->pb, pkt->data + palette_size + 4, size - 4) + 4;
+ ret = get_buffer(s->pb, pkt->data + palette_size + 4, size - 4) + 4;
if (ret < size) {
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->size = ret + palette_size;
@@ -124,12 +122,12 @@ static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt)
avs_format_t *avs = s->priv_data;
int ret, size;
- size = url_ftell(&s->pb);
+ size = url_ftell(s->pb);
ret = voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size);
- size = url_ftell(&s->pb) - size;
+ size = url_ftell(s->pb) - size;
avs->remaining_audio_size -= size;
- if (ret == AVERROR_IO)
+ if (ret == AVERROR(EIO))
return 0; /* this indicate EOS */
if (ret < 0)
return ret;
@@ -155,22 +153,22 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
while (1) {
if (avs->remaining_frame_size <= 0) {
- if (!get_le16(&s->pb)) /* found EOF */
- return AVERROR_IO;
- avs->remaining_frame_size = get_le16(&s->pb) - 4;
+ if (!get_le16(s->pb)) /* found EOF */
+ return AVERROR(EIO);
+ avs->remaining_frame_size = get_le16(s->pb) - 4;
}
while (avs->remaining_frame_size > 0) {
- sub_type = get_byte(&s->pb);
- type = get_byte(&s->pb);
- size = get_le16(&s->pb);
+ sub_type = get_byte(s->pb);
+ type = get_byte(s->pb);
+ size = get_le16(s->pb);
avs->remaining_frame_size -= size;
switch (type) {
case AVS_PALETTE:
- ret = get_buffer(&s->pb, palette, size - 4);
+ ret = get_buffer(s->pb, palette, size - 4);
if (ret < size - 4)
- return AVERROR_IO;
+ return AVERROR(EIO);
palette_size = size;
break;
@@ -178,7 +176,7 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
if (!avs->st_video) {
avs->st_video = av_new_stream(s, AVS_VIDEO);
if (avs->st_video == NULL)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
avs->st_video->codec->codec_type = CODEC_TYPE_VIDEO;
avs->st_video->codec->codec_id = CODEC_ID_AVS;
avs->st_video->codec->width = avs->width;
@@ -195,7 +193,7 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
if (!avs->st_audio) {
avs->st_audio = av_new_stream(s, AVS_AUDIO);
if (avs->st_audio == NULL)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
avs->st_audio->codec->codec_type = CODEC_TYPE_AUDIO;
}
avs->remaining_audio_size = size - 4;
@@ -205,7 +203,7 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
break;
default:
- url_fskip(&s->pb, size - 4);
+ url_fskip(s->pb, size - 4);
}
}
}
diff --git a/contrib/ffmpeg/libavformat/beosaudio.cpp b/contrib/ffmpeg/libavformat/beosaudio.cpp
deleted file mode 100644
index 6c16f0048..000000000
--- a/contrib/ffmpeg/libavformat/beosaudio.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * BeOS audio play interface
- * Copyright (c) 2000, 2001 Fabrice Bellard.
- *
- * 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 <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-#include <Application.h>
-#include <SoundPlayer.h>
-
-extern "C" {
-#include "avformat.h"
-}
-
-#ifdef HAVE_BSOUNDRECORDER
-#include <SoundRecorder.h>
-using namespace BPrivate::Media::Experimental;
-#endif
-
-/* enable performance checks */
-//#define PERF_CHECK
-
-/* enable Media Kit latency checks */
-//#define LATENCY_CHECK
-
-#define AUDIO_BLOCK_SIZE 4096
-#define AUDIO_BLOCK_COUNT 8
-
-#define AUDIO_BUFFER_SIZE (AUDIO_BLOCK_SIZE*AUDIO_BLOCK_COUNT)
-
-typedef struct {
- int fd; // UNUSED
- int sample_rate;
- int channels;
- int frame_size; /* in bytes ! */
- CodecID codec_id;
- uint8_t buffer[AUDIO_BUFFER_SIZE];
- int buffer_ptr;
- /* ring buffer */
- sem_id input_sem;
- int input_index;
- sem_id output_sem;
- int output_index;
- BSoundPlayer *player;
-#ifdef HAVE_BSOUNDRECORDER
- BSoundRecorder *recorder;
-#endif
- int has_quit; /* signal callbacks not to wait */
- volatile bigtime_t starve_time;
-} AudioData;
-
-static thread_id main_thid;
-static thread_id bapp_thid;
-static int own_BApp_created = 0;
-static int refcount = 0;
-
-/* create the BApplication and Run() it */
-static int32 bapp_thread(void *arg)
-{
- new BApplication("application/x-vnd.ffmpeg");
- own_BApp_created = 1;
- be_app->Run();
- /* kill the process group */
-// kill(0, SIGINT);
-// kill(main_thid, SIGHUP);
- return B_OK;
-}
-
-/* create the BApplication only if needed */
-static void create_bapp_if_needed(void)
-{
- if (refcount++ == 0) {
- /* needed by libmedia */
- if (be_app == NULL) {
- bapp_thid = spawn_thread(bapp_thread, "ffmpeg BApplication", B_NORMAL_PRIORITY, NULL);
- resume_thread(bapp_thid);
- while (!own_BApp_created)
- snooze(50000);
- }
- }
-}
-
-static void destroy_bapp_if_needed(void)
-{
- if (--refcount == 0 && own_BApp_created) {
- be_app->Lock();
- be_app->Quit();
- be_app = NULL;
- }
-}
-
-/* called back by BSoundPlayer */
-static void audioplay_callback(void *cookie, void *buffer, size_t bufferSize, const media_raw_audio_format &format)
-{
- AudioData *s;
- size_t len, amount;
- unsigned char *buf = (unsigned char *)buffer;
-
- s = (AudioData *)cookie;
- if (s->has_quit)
- return;
- while (bufferSize > 0) {
-#ifdef PERF_CHECK
- bigtime_t t;
- t = system_time();
-#endif
- len = MIN(AUDIO_BLOCK_SIZE, bufferSize);
- if (acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
- s->has_quit = 1;
- s->player->SetHasData(false);
- return;
- }
- amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
- memcpy(buf, &s->buffer[s->output_index], amount);
- s->output_index += amount;
- if (s->output_index >= AUDIO_BUFFER_SIZE) {
- s->output_index %= AUDIO_BUFFER_SIZE;
- memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
- s->output_index += len-amount;
- s->output_index %= AUDIO_BUFFER_SIZE;
- }
- release_sem_etc(s->input_sem, len, 0);
-#ifdef PERF_CHECK
- t = system_time() - t;
- s->starve_time = MAX(s->starve_time, t);
-#endif
- buf += len;
- bufferSize -= len;
- }
-}
-
-#ifdef HAVE_BSOUNDRECORDER
-/* called back by BSoundRecorder */
-static void audiorecord_callback(void *cookie, bigtime_t timestamp, void *buffer, size_t bufferSize, const media_multi_audio_format &format)
-{
- AudioData *s;
- size_t len, amount;
- unsigned char *buf = (unsigned char *)buffer;
-
- s = (AudioData *)cookie;
- if (s->has_quit)
- return;
-
- while (bufferSize > 0) {
- len = MIN(bufferSize, AUDIO_BLOCK_SIZE);
- //printf("acquire_sem(input, %d)\n", len);
- if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
- s->has_quit = 1;
- return;
- }
- amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
- memcpy(&s->buffer[s->input_index], buf, amount);
- s->input_index += amount;
- if (s->input_index >= AUDIO_BUFFER_SIZE) {
- s->input_index %= AUDIO_BUFFER_SIZE;
- memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
- s->input_index += len - amount;
- }
- release_sem_etc(s->output_sem, len, 0);
- //printf("release_sem(output, %d)\n", len);
- buf += len;
- bufferSize -= len;
- }
-}
-#endif
-
-static int audio_open(AudioData *s, int is_output, const char *audio_device)
-{
- int p[2];
- int ret;
- media_raw_audio_format format;
- media_multi_audio_format iformat;
-
-#ifndef HAVE_BSOUNDRECORDER
- if (!is_output)
- return AVERROR(EIO); /* not for now */
-#endif
- s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input");
- if (s->input_sem < B_OK)
- return AVERROR(EIO);
- s->output_sem = create_sem(0, "ffmpeg_ringbuffer_output");
- if (s->output_sem < B_OK) {
- delete_sem(s->input_sem);
- return AVERROR(EIO);
- }
- s->input_index = 0;
- s->output_index = 0;
- create_bapp_if_needed();
- s->frame_size = AUDIO_BLOCK_SIZE;
- /* bump up the priority (avoid realtime though) */
- set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
-#ifdef HAVE_BSOUNDRECORDER
- if (!is_output) {
- bool wait_for_input = false;
- if (audio_device && !strcmp(audio_device, "wait:"))
- wait_for_input = true;
- s->recorder = new BSoundRecorder(&iformat, wait_for_input, "ffmpeg input", audiorecord_callback);
- if (wait_for_input && (s->recorder->InitCheck() == B_OK)) {
- s->recorder->WaitForIncomingConnection(&iformat);
- }
- if (s->recorder->InitCheck() != B_OK || iformat.format != media_raw_audio_format::B_AUDIO_SHORT) {
- delete s->recorder;
- s->recorder = NULL;
- if (s->input_sem)
- delete_sem(s->input_sem);
- if (s->output_sem)
- delete_sem(s->output_sem);
- return AVERROR(EIO);
- }
- s->codec_id = (iformat.byte_order == B_MEDIA_LITTLE_ENDIAN)?CODEC_ID_PCM_S16LE:CODEC_ID_PCM_S16BE;
- s->channels = iformat.channel_count;
- s->sample_rate = (int)iformat.frame_rate;
- s->frame_size = iformat.buffer_size;
- s->recorder->SetCookie(s);
- s->recorder->SetVolume(1.0);
- s->recorder->Start();
- return 0;
- }
-#endif
- format = media_raw_audio_format::wildcard;
- format.format = media_raw_audio_format::B_AUDIO_SHORT;
- format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
- format.channel_count = s->channels;
- format.buffer_size = s->frame_size;
- format.frame_rate = s->sample_rate;
- s->player = new BSoundPlayer(&format, "ffmpeg output", audioplay_callback);
- if (s->player->InitCheck() != B_OK) {
- delete s->player;
- s->player = NULL;
- if (s->input_sem)
- delete_sem(s->input_sem);
- if (s->output_sem)
- delete_sem(s->output_sem);
- return AVERROR(EIO);
- }
- s->player->SetCookie(s);
- s->player->SetVolume(1.0);
- s->player->Start();
- s->player->SetHasData(true);
- return 0;
-}
-
-static int audio_close(AudioData *s)
-{
- if (s->input_sem)
- delete_sem(s->input_sem);
- if (s->output_sem)
- delete_sem(s->output_sem);
- s->has_quit = 1;
- if (s->player) {
- s->player->Stop();
- }
- if (s->player)
- delete s->player;
-#ifdef HAVE_BSOUNDRECORDER
- if (s->recorder)
- delete s->recorder;
-#endif
- destroy_bapp_if_needed();
- return 0;
-}
-
-/* sound output support */
-static int audio_write_header(AVFormatContext *s1)
-{
- AudioData *s = (AudioData *)s1->priv_data;
- AVStream *st;
- int ret;
-
- st = s1->streams[0];
- s->sample_rate = st->codec->sample_rate;
- s->channels = st->codec->channels;
- ret = audio_open(s, 1, NULL);
- if (ret < 0)
- return AVERROR(EIO);
- return 0;
-}
-
-static int audio_write_packet(AVFormatContext *s1, int stream_index,
- const uint8_t *buf, int size, int64_t force_pts)
-{
- AudioData *s = (AudioData *)s1->priv_data;
- int len, ret;
-#ifdef LATENCY_CHECK
-bigtime_t lat1, lat2;
-lat1 = s->player->Latency();
-#endif
-#ifdef PERF_CHECK
- bigtime_t t = s->starve_time;
- s->starve_time = 0;
- printf("starve_time: %lld \n", t);
-#endif
- while (size > 0) {
- int amount;
- len = MIN(size, AUDIO_BLOCK_SIZE);
- if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK)
- return AVERROR(EIO);
- amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
- memcpy(&s->buffer[s->input_index], buf, amount);
- s->input_index += amount;
- if (s->input_index >= AUDIO_BUFFER_SIZE) {
- s->input_index %= AUDIO_BUFFER_SIZE;
- memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
- s->input_index += len - amount;
- }
- release_sem_etc(s->output_sem, len, 0);
- buf += len;
- size -= len;
- }
-#ifdef LATENCY_CHECK
-lat2 = s->player->Latency();
-printf("#### BSoundPlayer::Latency(): before= %lld, after= %lld\n", lat1, lat2);
-#endif
- return 0;
-}
-
-static int audio_write_trailer(AVFormatContext *s1)
-{
- AudioData *s = (AudioData *)s1->priv_data;
-
- audio_close(s);
- return 0;
-}
-
-/* grab support */
-
-static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- AudioData *s = (AudioData *)s1->priv_data;
- AVStream *st;
- int ret;
-
- if (!ap || ap->sample_rate <= 0 || ap->channels <= 0)
- return -1;
-
- st = av_new_stream(s1, 0);
- if (!st) {
- return AVERROR(ENOMEM);
- }
- s->sample_rate = ap->sample_rate;
- s->channels = ap->channels;
-
- ret = audio_open(s, 0, s1->filename);
- if (ret < 0) {
- av_free(st);
- return AVERROR(EIO);
- }
- /* take real parameters */
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = s->codec_id;
- st->codec->sample_rate = s->sample_rate;
- st->codec->channels = s->channels;
- return 0;
- av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */
-}
-
-static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- AudioData *s = (AudioData *)s1->priv_data;
- int size;
- size_t len, amount;
- unsigned char *buf;
- status_t err;
-
- if (av_new_packet(pkt, s->frame_size) < 0)
- return AVERROR(EIO);
- buf = (unsigned char *)pkt->data;
- size = pkt->size;
- while (size > 0) {
- len = MIN(AUDIO_BLOCK_SIZE, size);
- //printf("acquire_sem(output, %d)\n", len);
- while ((err=acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL)) == B_INTERRUPTED);
- if (err < B_OK) {
- av_free_packet(pkt);
- return AVERROR(EIO);
- }
- amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
- memcpy(buf, &s->buffer[s->output_index], amount);
- s->output_index += amount;
- if (s->output_index >= AUDIO_BUFFER_SIZE) {
- s->output_index %= AUDIO_BUFFER_SIZE;
- memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
- s->output_index += len-amount;
- s->output_index %= AUDIO_BUFFER_SIZE;
- }
- release_sem_etc(s->input_sem, len, 0);
- //printf("release_sem(input, %d)\n", len);
- buf += len;
- size -= len;
- }
- //XXX: add pts info
- return 0;
-}
-
-static int audio_read_close(AVFormatContext *s1)
-{
- AudioData *s = (AudioData *)s1->priv_data;
-
- audio_close(s);
- return 0;
-}
-
-static AVInputFormat audio_demuxer = {
- "audio_device",
- "audio grab and output",
- sizeof(AudioData),
- NULL,
- audio_read_header,
- audio_read_packet,
- audio_read_close,
- NULL,
- AVFMT_NOFILE,
-};
-
-AVOutputFormat audio_muxer = {
- "audio_device",
- "audio grab and output",
- "",
- "",
- sizeof(AudioData),
-#ifdef WORDS_BIGENDIAN
- CODEC_ID_PCM_S16BE,
-#else
- CODEC_ID_PCM_S16LE,
-#endif
- CODEC_ID_NONE,
- audio_write_header,
- audio_write_packet,
- audio_write_trailer,
- AVFMT_NOFILE,
-};
-
-extern "C" {
-
-int audio_init(void)
-{
- main_thid = find_thread(NULL);
- av_register_input_format(&audio_demuxer);
- av_register_output_format(&audio_muxer);
- return 0;
-}
-
-} // "C"
-
diff --git a/contrib/ffmpeg/libavformat/bethsoftvid.c b/contrib/ffmpeg/libavformat/bethsoftvid.c
new file mode 100644
index 000000000..594779698
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/bethsoftvid.c
@@ -0,0 +1,233 @@
+/*
+ * Bethsoft VID format Demuxer
+ * Copyright (c) 2007 Nicholas Tung
+ *
+ * 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 bethsoftvid.c
+ * @brief Bethesda Softworks VID (.vid) file demuxer
+ * @author Nicholas Tung [ntung (at. ntung com] (2007-03)
+ * @sa http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
+ * @sa http://www.svatopluk.com/andux/docs/dfvid.html
+ */
+
+#include "avformat.h"
+#include "bethsoftvideo.h"
+
+typedef struct BVID_DemuxContext
+{
+ int nframes;
+ /** delay value between frames, added to individual frame delay.
+ * custom units, which will be added to other custom units (~=16ms according
+ * to free, unofficial documentation) */
+ int bethsoft_global_delay;
+
+ /** video presentation time stamp.
+ * delay = 16 milliseconds * (global_delay + per_frame_delay) */
+ int video_pts;
+
+ int is_finished;
+
+} BVID_DemuxContext;
+
+static int vid_probe(AVProbeData *p)
+{
+ // little endian VID tag, file starts with "VID\0"
+ if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int vid_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ BVID_DemuxContext *vid = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVStream *stream;
+
+ /* load main header. Contents:
+ * bytes: 'V' 'I' 'D'
+ * int16s: always_512, nframes, width, height, delay, always_14
+ */
+ url_fseek(pb, 5, SEEK_CUR);
+ vid->nframes = get_le16(pb);
+
+ stream = av_new_stream(s, 0);
+ if (!stream)
+ return AVERROR(ENOMEM);
+ av_set_pts_info(stream, 32, 1, 60); // 16 ms increments, i.e. 60 fps
+ stream->codec->codec_type = CODEC_TYPE_VIDEO;
+ stream->codec->codec_id = CODEC_ID_BETHSOFTVID;
+ stream->codec->width = get_le16(pb);
+ stream->codec->height = get_le16(pb);
+ stream->codec->pix_fmt = PIX_FMT_PAL8;
+ vid->bethsoft_global_delay = get_le16(pb);
+ get_le16(pb);
+
+ // done with video codec, set up audio codec
+ stream = av_new_stream(s, 0);
+ if (!stream)
+ return AVERROR(ENOMEM);
+ stream->codec->codec_type = CODEC_TYPE_AUDIO;
+ stream->codec->codec_id = CODEC_ID_PCM_U8;
+ stream->codec->channels = 1;
+ stream->codec->sample_rate = 11025;
+ stream->codec->bits_per_sample = 8;
+ stream->codec->bit_rate = stream->codec->channels * stream->codec->sample_rate * stream->codec->bits_per_sample;
+
+ return 0;
+}
+
+#define BUFFER_PADDING_SIZE 1000
+static int read_frame(BVID_DemuxContext *vid, ByteIOContext *pb, AVPacket *pkt,
+ uint8_t block_type, AVFormatContext *s, int npixels)
+{
+ uint8_t * vidbuf_start = NULL;
+ int vidbuf_nbytes = 0;
+ int code;
+ int bytes_copied = 0;
+ int position;
+ unsigned int vidbuf_capacity;
+
+ vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE);
+ if(!vidbuf_start)
+ return AVERROR(ENOMEM);
+
+ // save the file position for the packet, include block type
+ position = url_ftell(pb) - 1;
+
+ vidbuf_start[vidbuf_nbytes++] = block_type;
+
+ // get the video delay (next int16), and set the presentation time
+ vid->video_pts += vid->bethsoft_global_delay + get_le16(pb);
+
+ // set the y offset if it exists (decoder header data should be in data section)
+ if(block_type == VIDEO_YOFF_P_FRAME){
+ if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2)
+ goto fail;
+ vidbuf_nbytes += 2;
+ }
+
+ do{
+ vidbuf_start = av_fast_realloc(vidbuf_start, &vidbuf_capacity, vidbuf_nbytes + BUFFER_PADDING_SIZE);
+ if(!vidbuf_start)
+ return AVERROR(ENOMEM);
+
+ code = get_byte(pb);
+ vidbuf_start[vidbuf_nbytes++] = code;
+
+ if(code >= 0x80){ // rle sequence
+ if(block_type == VIDEO_I_FRAME)
+ vidbuf_start[vidbuf_nbytes++] = get_byte(pb);
+ } else if(code){ // plain sequence
+ if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], code) != code)
+ goto fail;
+ vidbuf_nbytes += code;
+ }
+ bytes_copied += code & 0x7F;
+ if(bytes_copied == npixels){ // sometimes no stop character is given, need to keep track of bytes copied
+ // may contain a 0 byte even if read all pixels
+ if(get_byte(pb))
+ url_fseek(pb, -1, SEEK_CUR);
+ break;
+ }
+ if(bytes_copied > npixels)
+ goto fail;
+ } while(code);
+
+ // copy data into packet
+ if(av_new_packet(pkt, vidbuf_nbytes) < 0)
+ goto fail;
+ memcpy(pkt->data, vidbuf_start, vidbuf_nbytes);
+ av_free(vidbuf_start);
+
+ pkt->pos = position;
+ pkt->stream_index = 0; // use the video decoder, which was initialized as the first stream
+ pkt->pts = vid->video_pts;
+
+ vid->nframes--; // used to check if all the frames were read
+ return vidbuf_nbytes;
+fail:
+ av_free(vidbuf_start);
+ return -1;
+}
+
+static int vid_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ BVID_DemuxContext *vid = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ unsigned char block_type;
+ int audio_length;
+ int ret_value;
+
+ if(vid->is_finished || url_feof(pb))
+ return AVERROR(EIO);
+
+ block_type = get_byte(pb);
+ switch(block_type){
+ case PALETTE_BLOCK:
+ url_fseek(pb, -1, SEEK_CUR); // include block type
+ ret_value = av_get_packet(pb, pkt, 3 * 256 + 1);
+ if(ret_value != 3 * 256 + 1){
+ av_free_packet(pkt);
+ return AVERROR(EIO);
+ }
+ pkt->stream_index = 0;
+ return ret_value;
+
+ case FIRST_AUDIO_BLOCK:
+ get_le16(pb);
+ // soundblaster DAC used for sample rate, as on specification page (link above)
+ s->streams[1]->codec->sample_rate = 1000000 / (256 - get_byte(pb));
+ s->streams[1]->codec->bit_rate = s->streams[1]->codec->channels * s->streams[1]->codec->sample_rate * s->streams[1]->codec->bits_per_sample;
+ case AUDIO_BLOCK:
+ audio_length = get_le16(pb);
+ ret_value = av_get_packet(pb, pkt, audio_length);
+ pkt->stream_index = 1;
+ return (ret_value != audio_length ? AVERROR(EIO) : ret_value);
+
+ case VIDEO_P_FRAME:
+ case VIDEO_YOFF_P_FRAME:
+ case VIDEO_I_FRAME:
+ return read_frame(vid, pb, pkt, block_type, s,
+ s->streams[0]->codec->width * s->streams[0]->codec->height);
+
+ case EOF_BLOCK:
+ if(vid->nframes != 0)
+ av_log(s, AV_LOG_VERBOSE, "reached terminating character but not all frames read.\n");
+ vid->is_finished = 1;
+ return AVERROR(EIO);
+ default:
+ av_log(s, AV_LOG_ERROR, "unknown block (character = %c, decimal = %d, hex = %x)!!!\n",
+ block_type, block_type, block_type); return -1;
+ }
+
+ return 0;
+}
+
+AVInputFormat bethsoftvid_demuxer = {
+ "bethsoftvid",
+ "Bethesda Softworks 'Daggerfall' VID format",
+ sizeof(BVID_DemuxContext),
+ vid_probe,
+ vid_read_header,
+ vid_read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/c93.c b/contrib/ffmpeg/libavformat/c93.c
new file mode 100644
index 000000000..996012f6e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/c93.c
@@ -0,0 +1,198 @@
+/*
+ * Interplay C93 demuxer
+ * Copyright (c) 2007 Anssi Hannula <anssi.hannula@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 "avformat.h"
+#include "voc.h"
+
+typedef struct {
+ uint16_t index;
+ uint8_t length;
+ uint8_t frames;
+} C93BlockRecord;
+
+typedef struct {
+ voc_dec_context_t voc;
+
+ C93BlockRecord block_records[512];
+ int current_block;
+
+ uint32_t frame_offsets[32];
+ int current_frame;
+ int next_pkt_is_audio;
+
+ AVStream *audio;
+} C93DemuxContext;
+
+static int probe(AVProbeData *p)
+{
+ if (p->buf[0] == 0x01 && p->buf[1] == 0x00 &&
+ p->buf[4] == 0x01 + p->buf[2] &&
+ p->buf[8] == p->buf[4] + p->buf[6] &&
+ p->buf[12] == p->buf[8] + p->buf[10])
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+static int read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *video;
+ ByteIOContext *pb = s->pb;
+ C93DemuxContext *c93 = s->priv_data;
+ int i;
+ int framecount = 0;
+
+ for (i = 0; i < 512; i++) {
+ c93->block_records[i].index = get_le16(pb);
+ c93->block_records[i].length = get_byte(pb);
+ c93->block_records[i].frames = get_byte(pb);
+ if (c93->block_records[i].frames > 32) {
+ av_log(s, AV_LOG_ERROR, "too many frames in block\n");
+ return AVERROR_INVALIDDATA;
+ }
+ framecount += c93->block_records[i].frames;
+ }
+
+ /* Audio streams are added if audio packets are found */
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+
+ video = av_new_stream(s, 0);
+ if (!video)
+ return AVERROR(ENOMEM);
+
+ video->codec->codec_type = CODEC_TYPE_VIDEO;
+ video->codec->codec_id = CODEC_ID_C93;
+ video->codec->width = 320;
+ video->codec->height = 192;
+ /* 4:3 320x200 with 8 empty lines */
+ video->codec->sample_aspect_ratio = (AVRational) { 5, 6 };
+ video->time_base = (AVRational) { 2, 25 };
+ video->nb_frames = framecount;
+ video->duration = framecount;
+ video->start_time = 0;
+
+ c93->current_block = 0;
+ c93->current_frame = 0;
+ c93->next_pkt_is_audio = 0;
+ return 0;
+}
+
+#define C93_HAS_PALETTE 0x01
+#define C93_FIRST_FRAME 0x02
+
+static int read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = s->pb;
+ C93DemuxContext *c93 = s->priv_data;
+ C93BlockRecord *br = &c93->block_records[c93->current_block];
+ int datasize;
+ int ret, i;
+
+ if (c93->next_pkt_is_audio) {
+ c93->current_frame++;
+ c93->next_pkt_is_audio = 0;
+ datasize = get_le16(pb);
+ if (datasize > 42) {
+ if (!c93->audio) {
+ c93->audio = av_new_stream(s, 1);
+ if (!c93->audio)
+ return AVERROR(ENOMEM);
+ c93->audio->codec->codec_type = CODEC_TYPE_AUDIO;
+ }
+ url_fskip(pb, 26); /* VOC header */
+ ret = voc_get_packet(s, pkt, c93->audio, datasize - 26);
+ if (ret > 0) {
+ pkt->stream_index = 1;
+ pkt->flags |= PKT_FLAG_KEY;
+ return ret;
+ }
+ }
+ }
+ if (c93->current_frame >= br->frames) {
+ if (c93->current_block >= 511 || !br[1].length)
+ return AVERROR(EIO);
+ br++;
+ c93->current_block++;
+ c93->current_frame = 0;
+ }
+
+ if (c93->current_frame == 0) {
+ url_fseek(pb, br->index * 2048, SEEK_SET);
+ for (i = 0; i < 32; i++) {
+ c93->frame_offsets[i] = get_le32(pb);
+ }
+ }
+
+ url_fseek(pb,br->index * 2048 +
+ c93->frame_offsets[c93->current_frame], SEEK_SET);
+ datasize = get_le16(pb); /* video frame size */
+
+ ret = av_new_packet(pkt, datasize + 768 + 1);
+ if (ret < 0)
+ return ret;
+ pkt->data[0] = 0;
+ pkt->size = datasize + 1;
+
+ ret = get_buffer(pb, pkt->data + 1, datasize);
+ if (ret < datasize) {
+ ret = AVERROR(EIO);
+ goto fail;
+ }
+
+ datasize = get_le16(pb); /* palette size */
+ if (datasize) {
+ if (datasize != 768) {
+ av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ pkt->data[0] |= C93_HAS_PALETTE;
+ ret = get_buffer(pb, pkt->data + pkt->size, datasize);
+ if (ret < datasize) {
+ ret = AVERROR(EIO);
+ goto fail;
+ }
+ pkt->size += 768;
+ }
+ pkt->stream_index = 0;
+ c93->next_pkt_is_audio = 1;
+
+ /* only the first frame is guaranteed to not reference previous frames */
+ if (c93->current_block == 0 && c93->current_frame == 0) {
+ pkt->flags |= PKT_FLAG_KEY;
+ pkt->data[0] |= C93_FIRST_FRAME;
+ }
+ return 0;
+
+ fail:
+ av_free_packet(pkt);
+ return ret;
+}
+
+AVInputFormat c93_demuxer = {
+ "c93",
+ "Interplay C93",
+ sizeof(C93DemuxContext),
+ probe,
+ read_header,
+ read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/crc.c b/contrib/ffmpeg/libavformat/crcenc.c
index bdbe8bcff..dd8803161 100644
--- a/contrib/ffmpeg/libavformat/crc.c
+++ b/contrib/ffmpeg/libavformat/crcenc.c
@@ -1,5 +1,5 @@
/*
- * CRC decoder (for codec/format testing)
+ * CRC encoder (for codec/format testing)
* Copyright (c) 2002 Fabrice Bellard.
*
* This file is part of FFmpeg.
@@ -21,7 +21,6 @@
#include "avformat.h"
#include "adler32.h"
-#ifdef CONFIG_CRC_MUXER
typedef struct CRCState {
uint32_t crcval;
} CRCState;
@@ -49,26 +48,11 @@ static int crc_write_trailer(struct AVFormatContext *s)
char buf[64];
snprintf(buf, sizeof(buf), "CRC=0x%08x\n", crc->crcval);
- put_buffer(&s->pb, buf, strlen(buf));
- put_flush_packet(&s->pb);
+ put_buffer(s->pb, buf, strlen(buf));
+ put_flush_packet(s->pb);
return 0;
}
-#endif
-#ifdef CONFIG_FRAMECRC_MUXER
-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, %"PRId64", %d, 0x%08x\n", pkt->stream_index, pkt->dts, pkt->size, crc);
- put_buffer(&s->pb, buf, strlen(buf));
- put_flush_packet(&s->pb);
- return 0;
-}
-#endif
-
-#ifdef CONFIG_CRC_MUXER
AVOutputFormat crc_muxer = {
"crc",
"crc testing format",
@@ -81,18 +65,3 @@ AVOutputFormat crc_muxer = {
crc_write_packet,
crc_write_trailer,
};
-#endif
-#ifdef CONFIG_FRAMECRC_MUXER
-AVOutputFormat framecrc_muxer = {
- "framecrc",
- "framecrc testing format",
- NULL,
- "",
- 0,
- CODEC_ID_PCM_S16LE,
- CODEC_ID_RAWVIDEO,
- NULL,
- framecrc_write_packet,
- NULL,
-};
-#endif
diff --git a/contrib/ffmpeg/libavformat/cutils.c b/contrib/ffmpeg/libavformat/cutils.c
index 45959ec39..06c941112 100644
--- a/contrib/ffmpeg/libavformat/cutils.c
+++ b/contrib/ffmpeg/libavformat/cutils.c
@@ -20,96 +20,6 @@
*/
#include "avformat.h"
-#if !defined(CONFIG_NOCUTILS)
-/**
- * Return TRUE if val is a prefix of str. If it returns TRUE, ptr is
- * set to the next character in 'str' after the prefix.
- *
- * @param str input string
- * @param val prefix to test
- * @param ptr updated after the prefix in str in there is a match
- * @return TRUE if there is a match
- */
-int strstart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
-/**
- * Return TRUE if val is a prefix of str (case independent). If it
- * returns TRUE, ptr is set to the next character in 'str' after the
- * prefix.
- *
- * @param str input string
- * @param val prefix to test
- * @param ptr updated after the prefix in str in there is a match
- * @return TRUE if there is a match */
-int stristart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (toupper(*(const unsigned char *)p) != toupper(*(const unsigned char *)q))
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
-/**
- * Copy the string str to buf. If str length is bigger than buf_size -
- * 1 then it is clamped to buf_size - 1.
- * NOTE: this function does what strncpy should have done to be
- * useful. NEVER use strncpy.
- *
- * @param buf destination buffer
- * @param buf_size size of destination buffer
- * @param str source string
- */
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
- int c;
- char *q = buf;
-
- if (buf_size <= 0)
- return;
-
- for(;;) {
- c = *str++;
- if (c == 0 || q >= buf + buf_size - 1)
- break;
- *q++ = c;
- }
- *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
- int len;
- len = strlen(buf);
- if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
- return buf;
-}
-
-#endif
-
/* add one element to a dynamic array */
void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem)
{
@@ -152,7 +62,7 @@ time_t mktimegm(struct tm *tm)
#define ISLEAP(y) (((y) % 4 == 0) && (((y) % 100) != 0 || ((y) % 400) == 0))
#define LEAPS_COUNT(y) ((y)/4 - (y)/100 + (y)/400)
-/* this is our own gmtime_r. it differs from its POSIX counterpart in a
+/* This is our own gmtime_r. It differs from its POSIX counterpart in a
couple of places, though. */
struct tm *brktimegm(time_t secs, struct tm *tm)
{
diff --git a/contrib/ffmpeg/libavformat/daud.c b/contrib/ffmpeg/libavformat/daud.c
index ec81b7b1c..ff74d0502 100644
--- a/contrib/ffmpeg/libavformat/daud.c
+++ b/contrib/ffmpeg/libavformat/daud.c
@@ -1,6 +1,6 @@
/*
* D-Cinema audio demuxer
- * Copyright (c) 2005 Reimar Döffinger.
+ * Copyright (c) 2005 Reimar Döffinger
*
* This file is part of FFmpeg.
*
@@ -34,10 +34,10 @@ static int daud_header(AVFormatContext *s, AVFormatParameters *ap) {
}
static int daud_packet(AVFormatContext *s, AVPacket *pkt) {
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int ret, size;
if (url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
size = get_be16(pb);
get_be16(pb); // unknown
ret = av_get_packet(pb, pkt, size);
diff --git a/contrib/ffmpeg/libavformat/dc1394.c b/contrib/ffmpeg/libavformat/dc1394.c
deleted file mode 100644
index bf140c466..000000000
--- a/contrib/ffmpeg/libavformat/dc1394.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * IIDC1394 grab interface (uses libdc1394 and libraw1394)
- * Copyright (c) 2004 Roman Shaposhnik
- *
- * 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 "avformat.h"
-
-#include <libraw1394/raw1394.h>
-#include <libdc1394/dc1394_control.h>
-
-#undef free
-
-typedef struct dc1394_data {
- raw1394handle_t handle;
- dc1394_cameracapture camera;
- int current_frame;
- int fps;
-
- AVPacket packet;
-} dc1394_data;
-
-struct dc1394_frame_format {
- int width;
- int height;
- enum PixelFormat pix_fmt;
- int frame_size_id;
-} dc1394_frame_formats[] = {
- { 320, 240, PIX_FMT_UYVY422, MODE_320x240_YUV422 },
- { 640, 480, PIX_FMT_UYYVYY411, MODE_640x480_YUV411 },
- { 640, 480, PIX_FMT_UYVY422, MODE_640x480_YUV422 },
- { 0, 0, 0, MODE_320x240_YUV422 } /* default -- gotta be the last one */
-};
-
-struct dc1394_frame_rate {
- int frame_rate;
- int frame_rate_id;
-} dc1394_frame_rates[] = {
- { 1875, FRAMERATE_1_875 },
- { 3750, FRAMERATE_3_75 },
- { 7500, FRAMERATE_7_5 },
- { 15000, FRAMERATE_15 },
- { 30000, FRAMERATE_30 },
- { 60000, FRAMERATE_60 },
- { 0, FRAMERATE_30 } /* default -- gotta be the last one */
-};
-
-static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap)
-{
- dc1394_data* dc1394 = c->priv_data;
- AVStream* vst;
- nodeid_t* camera_nodes;
- int res;
- struct dc1394_frame_format *fmt;
- struct dc1394_frame_rate *fps;
-
- for (fmt = dc1394_frame_formats; fmt->width; fmt++)
- if (fmt->pix_fmt == ap->pix_fmt && fmt->width == ap->width && fmt->height == ap->height)
- break;
-
- for (fps = dc1394_frame_rates; fps->frame_rate; fps++)
- if (fps->frame_rate == av_rescale(1000, ap->time_base.den, ap->time_base.num))
- break;
-
- /* create a video stream */
- vst = av_new_stream(c, 0);
- if (!vst)
- return -1;
- av_set_pts_info(vst, 64, 1, 1000);
- vst->codec->codec_type = CODEC_TYPE_VIDEO;
- vst->codec->codec_id = CODEC_ID_RAWVIDEO;
- vst->codec->time_base.den = fps->frame_rate;
- vst->codec->time_base.num = 1000;
- vst->codec->width = fmt->width;
- vst->codec->height = fmt->height;
- vst->codec->pix_fmt = fmt->pix_fmt;
-
- /* packet init */
- av_init_packet(&dc1394->packet);
- dc1394->packet.size = avpicture_get_size(fmt->pix_fmt, fmt->width, fmt->height);
- dc1394->packet.stream_index = vst->index;
- dc1394->packet.flags |= PKT_FLAG_KEY;
-
- dc1394->current_frame = 0;
- dc1394->fps = fps->frame_rate;
-
- vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000);
-
- /* Now lets prep the hardware */
- dc1394->handle = dc1394_create_handle(0); /* FIXME: gotta have ap->port */
- if (!dc1394->handle) {
- av_log(c, AV_LOG_ERROR, "Can't acquire dc1394 handle on port %d\n", 0 /* ap->port */);
- goto out;
- }
- camera_nodes = dc1394_get_camera_nodes(dc1394->handle, &res, 1);
- if (!camera_nodes || camera_nodes[ap->channel] == DC1394_NO_CAMERA) {
- av_log(c, AV_LOG_ERROR, "There's no IIDC camera on the channel %d\n", ap->channel);
- goto out_handle;
- }
- res = dc1394_dma_setup_capture(dc1394->handle, camera_nodes[ap->channel],
- 0,
- FORMAT_VGA_NONCOMPRESSED,
- fmt->frame_size_id,
- SPEED_400,
- fps->frame_rate_id, 8, 1,
- c->filename,
- &dc1394->camera);
- dc1394_free_camera_nodes(camera_nodes);
- if (res != DC1394_SUCCESS) {
- av_log(c, AV_LOG_ERROR, "Can't prepare camera for the DMA capture\n");
- goto out_handle;
- }
-
- res = dc1394_start_iso_transmission(dc1394->handle, dc1394->camera.node);
- if (res != DC1394_SUCCESS) {
- av_log(c, AV_LOG_ERROR, "Can't start isochronous transmission\n");
- goto out_handle_dma;
- }
-
- return 0;
-
-out_handle_dma:
- dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
- dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
-out_handle:
- dc1394_destroy_handle(dc1394->handle);
-out:
- return -1;
-}
-
-static int dc1394_read_packet(AVFormatContext *c, AVPacket *pkt)
-{
- struct dc1394_data *dc1394 = c->priv_data;
- int res;
-
- /* discard stale frame */
- if (dc1394->current_frame++) {
- if (dc1394_dma_done_with_buffer(&dc1394->camera) != DC1394_SUCCESS)
- av_log(c, AV_LOG_ERROR, "failed to release %d frame\n", dc1394->current_frame);
- }
-
- res = dc1394_dma_single_capture(&dc1394->camera);
-
- if (res == DC1394_SUCCESS) {
- dc1394->packet.data = (uint8_t *)(dc1394->camera.capture_buffer);
- dc1394->packet.pts = (dc1394->current_frame * 1000000) / dc1394->fps;
- res = dc1394->packet.size;
- } else {
- av_log(c, AV_LOG_ERROR, "DMA capture failed\n");
- dc1394->packet.data = NULL;
- res = -1;
- }
-
- *pkt = dc1394->packet;
- return res;
-}
-
-static int dc1394_close(AVFormatContext * context)
-{
- struct dc1394_data *dc1394 = context->priv_data;
-
- dc1394_stop_iso_transmission(dc1394->handle, dc1394->camera.node);
- dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
- dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
- dc1394_destroy_handle(dc1394->handle);
-
- return 0;
-}
-
-AVInputFormat dc1394_demuxer = {
- .name = "dc1394",
- .long_name = "dc1394 A/V grab",
- .priv_data_size = sizeof(struct dc1394_data),
- .read_header = dc1394_read_header,
- .read_packet = dc1394_read_packet,
- .read_close = dc1394_close,
- .flags = AVFMT_NOFILE
-};
diff --git a/contrib/ffmpeg/libavformat/dsicin.c b/contrib/ffmpeg/libavformat/dsicin.c
index fb9cb50df..14f2be8af 100644
--- a/contrib/ffmpeg/libavformat/dsicin.c
+++ b/contrib/ffmpeg/libavformat/dsicin.c
@@ -58,9 +58,6 @@ typedef struct CinDemuxContext {
static int cin_probe(AVProbeData *p)
{
- if (p->buf_size < 18)
- return 0;
-
/* header starts with this special marker */
if (AV_RL32(&p->buf[0]) != 0x55AA0000)
return 0;
@@ -95,9 +92,9 @@ static int cin_read_file_header(CinDemuxContext *cin, ByteIOContext *pb) {
static int cin_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
int rc;
- CinDemuxContext *cin = (CinDemuxContext *)s->priv_data;
+ CinDemuxContext *cin = s->priv_data;
CinFileHeader *hdr = &cin->file_header;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
rc = cin_read_file_header(cin, pb);
@@ -111,7 +108,7 @@ static int cin_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* initialize the video decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 32, 1, 12);
cin->video_stream_index = st->index;
@@ -124,7 +121,7 @@ static int cin_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* initialize the audio decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 32, 1, 22050);
cin->audio_stream_index = st->index;
@@ -150,7 +147,7 @@ static int cin_read_frame_header(CinDemuxContext *cin, ByteIOContext *pb) {
hdr->audio_frame_size = get_le32(pb);
if (url_feof(pb) || url_ferror(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
if (get_le32(pb) != 0xAA55AA55)
return AVERROR_INVALIDDATA;
@@ -160,8 +157,8 @@ static int cin_read_frame_header(CinDemuxContext *cin, ByteIOContext *pb) {
static int cin_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- CinDemuxContext *cin = (CinDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ CinDemuxContext *cin = s->priv_data;
+ ByteIOContext *pb = s->pb;
CinFrameHeader *hdr = &cin->frame_header;
int rc, palette_type, pkt_size;
@@ -181,7 +178,7 @@ static int cin_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt_size = (palette_type + 3) * hdr->pal_colors_count + hdr->video_frame_size;
if (av_new_packet(pkt, 4 + pkt_size))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
pkt->stream_index = cin->video_stream_index;
pkt->pts = cin->video_stream_pts++;
@@ -192,7 +189,7 @@ static int cin_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->data[3] = hdr->video_frame_type;
if (get_buffer(pb, &pkt->data[4], pkt_size) != pkt_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* sound buffer will be processed on next read_packet() call */
cin->audio_buffer_size = hdr->audio_frame_size;
@@ -201,14 +198,14 @@ static int cin_read_packet(AVFormatContext *s, AVPacket *pkt)
/* audio packet */
if (av_new_packet(pkt, cin->audio_buffer_size))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
pkt->stream_index = cin->audio_stream_index;
pkt->pts = cin->audio_stream_pts;
cin->audio_stream_pts += cin->audio_buffer_size * 2 / cin->file_header.audio_frame_size;
if (get_buffer(pb, pkt->data, cin->audio_buffer_size) != cin->audio_buffer_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
cin->audio_buffer_size = 0;
return 0;
diff --git a/contrib/ffmpeg/libavformat/dv.c b/contrib/ffmpeg/libavformat/dv.c
index 10a306260..6fb27bfe0 100644
--- a/contrib/ffmpeg/libavformat/dv.c
+++ b/contrib/ffmpeg/libavformat/dv.c
@@ -347,7 +347,7 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
// FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
const DVprofile* sys = dv_codec_profile(c->vst->codec);
int64_t offset;
- int64_t size = url_fsize(&s->pb);
+ int64_t size = url_fsize(s->pb);
int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
offset = sys->frame_size * timestamp;
@@ -386,9 +386,9 @@ static int dv_read_header(AVFormatContext *s,
if (!c->dv_demux)
return -1;
- if (get_buffer(&s->pb, c->buf, DV_PROFILE_BYTES) <= 0 ||
- url_fseek(&s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
- return AVERROR_IO;
+ if (get_buffer(s->pb, c->buf, DV_PROFILE_BYTES) <= 0 ||
+ url_fseek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
+ return AVERROR(EIO);
c->dv_demux->sys = dv_frame_profile(c->buf);
s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8,
@@ -408,8 +408,8 @@ static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
if (size < 0) {
size = c->dv_demux->sys->frame_size;
- if (get_buffer(&s->pb, c->buf, size) <= 0)
- return AVERROR_IO;
+ if (get_buffer(s->pb, c->buf, size) <= 0)
+ return AVERROR(EIO);
size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
}
@@ -426,7 +426,8 @@ static int dv_read_seek(AVFormatContext *s, int stream_index,
dv_offset_reset(c, offset / c->sys->frame_size);
- return url_fseek(&s->pb, offset, SEEK_SET);
+ offset = url_fseek(s->pb, offset, SEEK_SET);
+ return (offset < 0)?offset:0;
}
static int dv_read_close(AVFormatContext *s)
diff --git a/contrib/ffmpeg/libavformat/dv.h b/contrib/ffmpeg/libavformat/dv.h
index 2fa30036c..cfe93533a 100644
--- a/contrib/ffmpeg/libavformat/dv.h
+++ b/contrib/ffmpeg/libavformat/dv.h
@@ -25,6 +25,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef FFMPEG_DV_H
+#define FFMPEG_DV_H
+
+#include "avformat.h"
+
typedef struct DVDemuxContext DVDemuxContext;
DVDemuxContext* dv_init_demux(AVFormatContext* s);
int dv_get_packet(DVDemuxContext*, AVPacket *);
@@ -35,3 +40,5 @@ typedef struct DVMuxContext DVMuxContext;
DVMuxContext* dv_init_mux(AVFormatContext* s);
int dv_assemble_frame(DVMuxContext *c, AVStream*, const uint8_t*, int, uint8_t**);
void dv_delete_mux(DVMuxContext*);
+
+#endif /* FFMPEG_DV_H */
diff --git a/contrib/ffmpeg/libavformat/dv1394.c b/contrib/ffmpeg/libavformat/dv1394.c
deleted file mode 100644
index 3a5f479c8..000000000
--- a/contrib/ffmpeg/libavformat/dv1394.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Linux DV1394 interface
- * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include "avformat.h"
-
-#undef DV1394_DEBUG
-
-#include "dv1394.h"
-#include "dv.h"
-
-struct dv1394_data {
- int fd;
- int channel;
- int format;
-
- uint8_t *ring; /* Ring buffer */
- int index; /* Current frame index */
- int avail; /* Number of frames available for reading */
- int done; /* Number of completed frames */
-
- DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */
-};
-
-/*
- * The trick here is to kludge around well known problem with kernel Ooopsing
- * when you try to capture PAL on a device node configure for NTSC. That's
- * why we have to configure the device node for PAL, and then read only NTSC
- * amount of data.
- */
-static int dv1394_reset(struct dv1394_data *dv)
-{
- struct dv1394_init init;
-
- init.channel = dv->channel;
- init.api_version = DV1394_API_VERSION;
- init.n_frames = DV1394_RING_FRAMES;
- init.format = DV1394_PAL;
-
- if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
- return -1;
-
- dv->avail = dv->done = 0;
- return 0;
-}
-
-static int dv1394_start(struct dv1394_data *dv)
-{
- /* Tell DV1394 driver to enable receiver */
- if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) {
- perror("Failed to start receiver");
- return -1;
- }
- return 0;
-}
-
-static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap)
-{
- struct dv1394_data *dv = context->priv_data;
-
- dv->dv_demux = dv_init_demux(context);
- if (!dv->dv_demux)
- goto failed;
-
- if (ap->standard && !strcasecmp(ap->standard, "pal"))
- dv->format = DV1394_PAL;
- else
- dv->format = DV1394_NTSC;
-
- if (ap->channel)
- dv->channel = ap->channel;
- else
- dv->channel = DV1394_DEFAULT_CHANNEL;
-
- /* Open and initialize DV1394 device */
- dv->fd = open(context->filename, O_RDONLY);
- if (dv->fd < 0) {
- perror("Failed to open DV interface");
- goto failed;
- }
-
- if (dv1394_reset(dv) < 0) {
- perror("Failed to initialize DV interface");
- goto failed;
- }
-
- dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES,
- PROT_READ, MAP_PRIVATE, dv->fd, 0);
- if (dv->ring == MAP_FAILED) {
- perror("Failed to mmap DV ring buffer");
- goto failed;
- }
-
- if (dv1394_start(dv) < 0)
- goto failed;
-
- return 0;
-
-failed:
- close(dv->fd);
- return AVERROR_IO;
-}
-
-static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
-{
- struct dv1394_data *dv = context->priv_data;
- int size;
-
- size = dv_get_packet(dv->dv_demux, pkt);
- if (size > 0)
- return size;
-
- if (!dv->avail) {
- struct dv1394_status s;
- struct pollfd p;
-
- if (dv->done) {
- /* Request more frames */
- if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
- /* This usually means that ring buffer overflowed.
- * We have to reset :(.
- */
-
- av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n");
-
- dv1394_reset(dv);
- dv1394_start(dv);
- }
- dv->done = 0;
- }
-
- /* Wait until more frames are available */
-restart_poll:
- p.fd = dv->fd;
- p.events = POLLIN | POLLERR | POLLHUP;
- if (poll(&p, 1, -1) < 0) {
- if (errno == EAGAIN || errno == EINTR)
- goto restart_poll;
- perror("Poll failed");
- return AVERROR_IO;
- }
-
- if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) {
- perror("Failed to get status");
- return AVERROR_IO;
- }
-#ifdef DV1394_DEBUG
- av_log(context, AV_LOG_DEBUG, "DV1394: status\n"
- "\tactive_frame\t%d\n"
- "\tfirst_clear_frame\t%d\n"
- "\tn_clear_frames\t%d\n"
- "\tdropped_frames\t%d\n",
- s.active_frame, s.first_clear_frame,
- s.n_clear_frames, s.dropped_frames);
-#endif
-
- dv->avail = s.n_clear_frames;
- dv->index = s.first_clear_frame;
- dv->done = 0;
-
- if (s.dropped_frames) {
- av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n",
- s.dropped_frames);
-
- dv1394_reset(dv);
- dv1394_start(dv);
- }
- }
-
-#ifdef DV1394_DEBUG
- av_log(context, AV_LOG_DEBUG, "index %d, avail %d, done %d\n", dv->index, dv->avail,
- dv->done);
-#endif
-
- size = dv_produce_packet(dv->dv_demux, pkt,
- dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE),
- DV1394_PAL_FRAME_SIZE);
- dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
- dv->done++; dv->avail--;
-
- return size;
-}
-
-static int dv1394_close(AVFormatContext * context)
-{
- struct dv1394_data *dv = context->priv_data;
-
- /* Shutdown DV1394 receiver */
- if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0)
- perror("Failed to shutdown DV1394");
-
- /* Unmap ring buffer */
- if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0)
- perror("Failed to munmap DV1394 ring buffer");
-
- close(dv->fd);
- av_free(dv->dv_demux);
-
- return 0;
-}
-
-AVInputFormat dv1394_demuxer = {
- .name = "dv1394",
- .long_name = "dv1394 A/V grab",
- .priv_data_size = sizeof(struct dv1394_data),
- .read_header = dv1394_read_header,
- .read_packet = dv1394_read_packet,
- .read_close = dv1394_close,
- .flags = AVFMT_NOFILE
-};
diff --git a/contrib/ffmpeg/libavformat/dv1394.h b/contrib/ffmpeg/libavformat/dv1394.h
deleted file mode 100644
index f7db40108..000000000
--- a/contrib/ffmpeg/libavformat/dv1394.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * dv1394.h - DV input/output over IEEE 1394 on OHCI chips
- * Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- * video1394.h - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- * Peter Schlaile <udbz@rz.uni-karlsruhe.de>
- *
- * 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 _DV_1394_H
-#define _DV_1394_H
-
-#define DV1394_DEFAULT_CHANNEL 63
-#define DV1394_DEFAULT_CARD 0
-#define DV1394_RING_FRAMES 20
-
-#define DV1394_WIDTH 720
-#define DV1394_NTSC_HEIGHT 480
-#define DV1394_PAL_HEIGHT 576
-
-/* This is the public user-space interface. Try not to break it. */
-
-#define DV1394_API_VERSION 0x20011127
-
-/* ********************
- ** **
- ** DV1394 API **
- ** **
- ********************
-
- There are two methods of operating the DV1394 DV output device.
-
- 1)
-
- The simplest is an interface based on write(): simply write
- full DV frames of data to the device, and they will be transmitted
- as quickly as possible. The FD may be set for non-blocking I/O,
- in which case you can use select() or poll() to wait for output
- buffer space.
-
- To set the DV output parameters (e.g. whether you want NTSC or PAL
- video), use the DV1394_INIT ioctl, passing in the parameters you
- want in a struct dv1394_init.
-
- Example 1:
- To play a raw .DV file: cat foo.DV > /dev/dv1394
- (cat will use write() internally)
-
- Example 2:
- static struct dv1394_init init = {
- 0x63, (broadcast channel)
- 4, (four-frame ringbuffer)
- DV1394_NTSC, (send NTSC video)
- 0, 0 (default empty packet rate)
- }
-
- ioctl(fd, DV1394_INIT, &init);
-
- while(1) {
- read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
- write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
- }
-
- 2)
-
- For more control over buffering, and to avoid unnecessary copies
- of the DV data, you can use the more sophisticated the mmap() interface.
- First, call the DV1394_INIT ioctl to specify your parameters,
- including the number of frames in the ringbuffer. Then, calling mmap()
- on the dv1394 device will give you direct access to the ringbuffer
- from which the DV card reads your frame data.
-
- The ringbuffer is simply one large, contiguous region of memory
- containing two or more frames of packed DV data. Each frame of DV data
- is 120000 bytes (NTSC) or 144000 bytes (PAL).
-
- Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
- ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
- or select()/poll() to wait until the frames are transmitted. Next, you'll
- need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
- frames are clear (ready to be filled with new DV data). Finally, use
- DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
-
-
- Example: here is what a four-frame ringbuffer might look like
- during DV transmission:
-
-
- frame 0 frame 1 frame 2 frame 3
-
- *--------------------------------------*
- | CLEAR | DV data | DV data | CLEAR |
- *--------------------------------------*
- <ACTIVE>
-
- transmission goes in this direction --->>>
-
-
- The DV hardware is currently transmitting the data in frame 1.
- Once frame 1 is finished, it will automatically transmit frame 2.
- (if frame 2 finishes before frame 3 is submitted, the device
- will continue to transmit frame 2, and will increase the dropped_frames
- counter each time it repeats the transmission).
-
-
- If you called DV1394_GET_STATUS at this instant, you would
- receive the following values:
-
- n_frames = 4
- active_frame = 1
- first_clear_frame = 3
- n_clear_frames = 2
-
- At this point, you should write new DV data into frame 3 and optionally
- frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
- it may transmit the new frames.
-
- ERROR HANDLING
-
- An error (buffer underflow/overflow or a break in the DV stream due
- to a 1394 bus reset) can be detected by checking the dropped_frames
- field of struct dv1394_status (obtained through the
- DV1394_GET_STATUS ioctl).
-
- The best way to recover from such an error is to re-initialize
- dv1394, either by using the DV1394_INIT ioctl call, or closing the
- file descriptor and opening it again. (note that you must unmap all
- ringbuffer mappings when closing the file descriptor, or else
- dv1394 will still be considered 'in use').
-
- MAIN LOOP
-
- For maximum efficiency and robustness against bus errors, you are
- advised to model the main loop of your application after the
- following pseudo-code example:
-
- (checks of system call return values omitted for brevity; always
- check return values in your code!)
-
- while( frames left ) {
-
- struct pollfd *pfd = ...;
-
- pfd->fd = dv1394_fd;
- pfd->revents = 0;
- pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
-
- (add other sources of I/O here)
-
- poll(pfd, 1, -1); (or select(); add a timeout if you want)
-
- if(pfd->revents) {
- struct dv1394_status status;
-
- ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
-
- if(status.dropped_frames > 0) {
- reset_dv1394();
- } else {
- for(int i = 0; i < status.n_clear_frames; i++) {
- copy_DV_frame();
- }
- }
- }
- }
-
- where copy_DV_frame() reads or writes on the dv1394 file descriptor
- (read/write mode) or copies data to/from the mmap ringbuffer and
- then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
- frames are availble (mmap mode).
-
- reset_dv1394() is called in the event of a buffer
- underflow/overflow or a halt in the DV stream (e.g. due to a 1394
- bus reset). To guarantee recovery from the error, this function
- should close the dv1394 file descriptor (and munmap() all
- ringbuffer mappings, if you are using them), then re-open the
- dv1394 device (and re-map the ringbuffer).
-
-*/
-
-
-/* maximum number of frames in the ringbuffer */
-#define DV1394_MAX_FRAMES 32
-
-/* number of *full* isochronous packets per DV frame */
-#define DV1394_NTSC_PACKETS_PER_FRAME 250
-#define DV1394_PAL_PACKETS_PER_FRAME 300
-
-/* size of one frame's worth of DV data, in bytes */
-#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
-#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME)
-
-
-/* ioctl() commands */
-
-enum {
- /* I don't like using 0 as a valid ioctl() */
- DV1394_INVALID = 0,
-
-
- /* get the driver ready to transmit video.
- pass a struct dv1394_init* as the parameter (see below),
- or NULL to get default parameters */
- DV1394_INIT,
-
-
- /* stop transmitting video and free the ringbuffer */
- DV1394_SHUTDOWN,
-
-
- /* submit N new frames to be transmitted, where
- the index of the first new frame is first_clear_buffer,
- and the index of the last new frame is
- (first_clear_buffer + N) % n_frames */
- DV1394_SUBMIT_FRAMES,
-
-
- /* block until N buffers are clear (pass N as the parameter)
- Because we re-transmit the last frame on underrun, there
- will at most be n_frames - 1 clear frames at any time */
- DV1394_WAIT_FRAMES,
-
- /* capture new frames that have been received, where
- the index of the first new frame is first_clear_buffer,
- and the index of the last new frame is
- (first_clear_buffer + N) % n_frames */
- DV1394_RECEIVE_FRAMES,
-
-
- DV1394_START_RECEIVE,
-
-
- /* pass a struct dv1394_status* as the parameter (see below) */
- DV1394_GET_STATUS,
-};
-
-
-
-enum pal_or_ntsc {
- DV1394_NTSC = 0,
- DV1394_PAL
-};
-
-
-
-
-/* this is the argument to DV1394_INIT */
-struct dv1394_init {
- /* DV1394_API_VERSION */
- unsigned int api_version;
-
- /* isochronous transmission channel to use */
- unsigned int channel;
-
- /* number of frames in the ringbuffer. Must be at least 2
- and at most DV1394_MAX_FRAMES. */
- unsigned int n_frames;
-
- /* send/receive PAL or NTSC video format */
- enum pal_or_ntsc format;
-
- /* the following are used only for transmission */
-
- /* set these to zero unless you want a
- non-default empty packet rate (see below) */
- unsigned long cip_n;
- unsigned long cip_d;
-
- /* set this to zero unless you want a
- non-default SYT cycle offset (default = 3 cycles) */
- unsigned int syt_offset;
-};
-
-/* NOTE: you may only allocate the DV frame ringbuffer once each time
- you open the dv1394 device. DV1394_INIT will fail if you call it a
- second time with different 'n_frames' or 'format' arguments (which
- would imply a different size for the ringbuffer). If you need a
- different buffer size, simply close and re-open the device, then
- initialize it with your new settings. */
-
-/* Q: What are cip_n and cip_d? */
-
-/*
- A: DV video streams do not utilize 100% of the potential bandwidth offered
- by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
- DV devices must periodically insert empty packets into the 1394 data stream.
- Typically there is one empty packet per 14-16 data-carrying packets.
-
- Some DV devices will accept a wide range of empty packet rates, while others
- require a precise rate. If the dv1394 driver produces empty packets at
- a rate that your device does not accept, you may see ugly patterns on the
- DV output, or even no output at all.
-
- The default empty packet insertion rate seems to work for many people; if
- your DV output is stable, you can simply ignore this discussion. However,
- we have exposed the empty packet rate as a parameter to support devices that
- do not work with the default rate.
-
- The decision to insert an empty packet is made with a numerator/denominator
- algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
- You can alter the empty packet rate by passing non-zero values for cip_n
- and cip_d to the INIT ioctl.
-
- */
-
-
-
-struct dv1394_status {
- /* this embedded init struct returns the current dv1394
- parameters in use */
- struct dv1394_init init;
-
- /* the ringbuffer frame that is currently being
- displayed. (-1 if the device is not transmitting anything) */
- int active_frame;
-
- /* index of the first buffer (ahead of active_frame) that
- is ready to be filled with data */
- unsigned int first_clear_frame;
-
- /* how many buffers, including first_clear_buffer, are
- ready to be filled with data */
- unsigned int n_clear_frames;
-
- /* how many times the DV stream has underflowed, overflowed,
- or otherwise encountered an error, since the previous call
- to DV1394_GET_STATUS */
- unsigned int dropped_frames;
-
- /* N.B. The dropped_frames counter is only a lower bound on the actual
- number of dropped frames, with the special case that if dropped_frames
- is zero, then it is guaranteed that NO frames have been dropped
- since the last call to DV1394_GET_STATUS.
- */
-};
-
-
-#endif /* _DV_1394_H */
diff --git a/contrib/ffmpeg/libavformat/dvenc.c b/contrib/ffmpeg/libavformat/dvenc.c
index bdac43784..0d6002818 100644
--- a/contrib/ffmpeg/libavformat/dvenc.c
+++ b/contrib/ffmpeg/libavformat/dvenc.c
@@ -77,100 +77,100 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
buf[0] = (uint8_t)pack_id;
switch (pack_id) {
case dv_timecode:
- ct = (time_t)(c->frames / ((float)c->sys->frame_rate /
- (float)c->sys->frame_rate_base));
- brktimegm(ct, &tc);
- /*
- * LTC drop-frame frame counter drops two frames (0 and 1) every
- * minute, unless it is exactly divisible by 10
- */
- ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor;
- buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */
- (1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */
- ((ltc_frame / 10) << 4) | /* Tens of frames */
- (ltc_frame % 10); /* Units of frames */
- buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */
- ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
- (tc.tm_sec % 10); /* Units of seconds */
- buf[3] = (1 << 7) | /* Binary group flag BGF0 */
- ((tc.tm_min / 10) << 4) | /* Tens of minutes */
- (tc.tm_min % 10); /* Units of minutes */
- buf[4] = (1 << 7) | /* Binary group flag BGF2 */
- (1 << 6) | /* Binary group flag BGF1 */
- ((tc.tm_hour / 10) << 4) | /* Tens of hours */
- (tc.tm_hour % 10); /* Units of hours */
- break;
+ ct = (time_t)(c->frames / ((float)c->sys->frame_rate /
+ (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ /*
+ * LTC drop-frame frame counter drops two frames (0 and 1) every
+ * minute, unless it is exactly divisible by 10
+ */
+ ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor;
+ buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */
+ (1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */
+ ((ltc_frame / 10) << 4) | /* Tens of frames */
+ (ltc_frame % 10); /* Units of frames */
+ buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */
+ ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
+ (tc.tm_sec % 10); /* Units of seconds */
+ buf[3] = (1 << 7) | /* Binary group flag BGF0 */
+ ((tc.tm_min / 10) << 4) | /* Tens of minutes */
+ (tc.tm_min % 10); /* Units of minutes */
+ buf[4] = (1 << 7) | /* Binary group flag BGF2 */
+ (1 << 6) | /* Binary group flag BGF1 */
+ ((tc.tm_hour / 10) << 4) | /* Tens of hours */
+ (tc.tm_hour % 10); /* Units of hours */
+ break;
case dv_audio_source: /* AAUX source pack */
- va_start(ap, buf);
- buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */
- (1 << 6) | /* reserved -- always 1 */
- (dv_audio_frame_size(c->sys, c->frames) -
- c->sys->audio_min_samples[0]);
- /* # of samples */
- buf[2] = (0 << 7) | /* multi-stereo */
- (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */
- (0 << 4) | /* pair bit: 0 -- one pair of channels */
- !!va_arg(ap, int); /* audio mode */
- buf[3] = (1 << 7) | /* res */
- (1 << 6) | /* multi-language flag */
- (c->sys->dsf << 5) | /* system: 60fields/50fields */
- (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */
- buf[4] = (1 << 7) | /* emphasis: 1 -- off */
- (0 << 6) | /* emphasis time constant: 0 -- reserved */
- (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */
- 0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
- va_end(ap);
- break;
+ va_start(ap, buf);
+ buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */
+ (1 << 6) | /* reserved -- always 1 */
+ (dv_audio_frame_size(c->sys, c->frames) -
+ c->sys->audio_min_samples[0]);
+ /* # of samples */
+ buf[2] = (0 << 7) | /* multi-stereo */
+ (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */
+ (0 << 4) | /* pair bit: 0 -- one pair of channels */
+ !!va_arg(ap, int); /* audio mode */
+ buf[3] = (1 << 7) | /* res */
+ (1 << 6) | /* multi-language flag */
+ (c->sys->dsf << 5) | /* system: 60fields/50fields */
+ (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */
+ buf[4] = (1 << 7) | /* emphasis: 1 -- off */
+ (0 << 6) | /* emphasis time constant: 0 -- reserved */
+ (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */
+ 0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
+ va_end(ap);
+ break;
case dv_audio_control:
- buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */
- (1 << 4) | /* input source: 1 -- digital input */
- (3 << 2) | /* compression: 3 -- no information */
- 0; /* misc. info/SMPTE emphasis off */
- buf[2] = (1 << 7) | /* recording start point: 1 -- no */
- (1 << 6) | /* recording end point: 1 -- no */
- (1 << 3) | /* recording mode: 1 -- original */
- 7;
- buf[3] = (1 << 7) | /* direction: 1 -- forward */
- (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0x20 : /* speed */
- c->sys->ltc_divisor*4);
- buf[4] = (1 << 7) | /* reserved -- always 1 */
- 0x7f; /* genre category */
- break;
+ buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */
+ (1 << 4) | /* input source: 1 -- digital input */
+ (3 << 2) | /* compression: 3 -- no information */
+ 0; /* misc. info/SMPTE emphasis off */
+ buf[2] = (1 << 7) | /* recording start point: 1 -- no */
+ (1 << 6) | /* recording end point: 1 -- no */
+ (1 << 3) | /* recording mode: 1 -- original */
+ 7;
+ buf[3] = (1 << 7) | /* direction: 1 -- forward */
+ (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0x20 : /* speed */
+ c->sys->ltc_divisor*4);
+ buf[4] = (1 << 7) | /* reserved -- always 1 */
+ 0x7f; /* genre category */
+ break;
case dv_audio_recdate:
case dv_video_recdate: /* VAUX recording date */
- ct = c->start_time + (time_t)(c->frames /
- ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
- brktimegm(ct, &tc);
- buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */
- /* 0xff is very likely to be "unknown" */
- buf[2] = (3 << 6) | /* reserved -- always 1 */
- ((tc.tm_mday / 10) << 4) | /* Tens of day */
- (tc.tm_mday % 10); /* Units of day */
- buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */
- ((tc.tm_mon / 10) << 4) | /* Tens of month */
- (tc.tm_mon % 10); /* Units of month */
- buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */
- (tc.tm_year % 10); /* Units of year */
- break;
+ ct = c->start_time + (time_t)(c->frames /
+ ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */
+ /* 0xff is very likely to be "unknown" */
+ buf[2] = (3 << 6) | /* reserved -- always 1 */
+ ((tc.tm_mday / 10) << 4) | /* Tens of day */
+ (tc.tm_mday % 10); /* Units of day */
+ buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */
+ ((tc.tm_mon / 10) << 4) | /* Tens of month */
+ (tc.tm_mon % 10); /* Units of month */
+ buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */
+ (tc.tm_year % 10); /* Units of year */
+ break;
case dv_audio_rectime: /* AAUX recording time */
case dv_video_rectime: /* VAUX recording time */
- ct = c->start_time + (time_t)(c->frames /
- ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
- brktimegm(ct, &tc);
- buf[1] = (3 << 6) | /* reserved -- always 1 */
- 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */
- buf[2] = (1 << 7) | /* reserved -- always 1 */
- ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
- (tc.tm_sec % 10); /* Units of seconds */
- buf[3] = (1 << 7) | /* reserved -- always 1 */
- ((tc.tm_min / 10) << 4) | /* Tens of minutes */
- (tc.tm_min % 10); /* Units of minutes */
- buf[4] = (3 << 6) | /* reserved -- always 1 */
- ((tc.tm_hour / 10) << 4) | /* Tens of hours */
- (tc.tm_hour % 10); /* Units of hours */
- break;
+ ct = c->start_time + (time_t)(c->frames /
+ ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ buf[1] = (3 << 6) | /* reserved -- always 1 */
+ 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */
+ buf[2] = (1 << 7) | /* reserved -- always 1 */
+ ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
+ (tc.tm_sec % 10); /* Units of seconds */
+ buf[3] = (1 << 7) | /* reserved -- always 1 */
+ ((tc.tm_min / 10) << 4) | /* Tens of minutes */
+ (tc.tm_min % 10); /* Units of minutes */
+ buf[4] = (3 << 6) | /* reserved -- always 1 */
+ ((tc.tm_hour / 10) << 4) | /* Tens of hours */
+ (tc.tm_hour % 10); /* Units of hours */
+ break;
default:
- buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
+ buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
}
return 5;
}
@@ -181,19 +181,19 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr)
size = 4 * dv_audio_frame_size(c->sys, c->frames);
frame_ptr += channel * c->sys->difseg_size * 150 * 80;
for (i = 0; i < c->sys->difseg_size; i++) {
- frame_ptr += 6 * 80; /* skip DIF segment header */
- for (j = 0; j < 9; j++) {
- dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i >= c->sys->difseg_size/2);
- for (d = 8; d < 80; d+=2) {
- of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;
- if (of*2 >= size)
- continue;
-
- frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit
- frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM
- }
- frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
- }
+ frame_ptr += 6 * 80; /* skip DIF segment header */
+ for (j = 0; j < 9; j++) {
+ dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i >= c->sys->difseg_size/2);
+ for (d = 8; d < 80; d+=2) {
+ of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;
+ if (of*2 >= size)
+ continue;
+
+ frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit
+ frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM
+ }
+ frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
+ }
}
}
@@ -240,39 +240,41 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st,
switch (st->codec->codec_type) {
case CODEC_TYPE_VIDEO:
- /* FIXME: we have to have more sensible approach than this one */
- if (c->has_video)
- av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
+ /* FIXME: we have to have more sensible approach than this one */
+ if (c->has_video)
+ av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
- memcpy(*frame, data, c->sys->frame_size);
- c->has_video = 1;
- break;
+ memcpy(*frame, data, c->sys->frame_size);
+ c->has_video = 1;
+ break;
case CODEC_TYPE_AUDIO:
- for (i = 0; i < c->n_ast && st != c->ast[i]; i++);
+ for (i = 0; i < c->n_ast && st != c->ast[i]; i++);
/* FIXME: we have to have more sensible approach than this one */
- if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE)
- av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
- av_fifo_write(&c->audio_data[i], data, data_size);
+ if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE)
+ av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
+ av_fifo_write(&c->audio_data[i], data, data_size);
- /* Lets see if we've got enough audio for one DV frame */
- c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i);
+ /* Lets see if we've got enough audio for one DV frame */
+ c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i);
- break;
+ break;
default:
- break;
+ break;
}
/* Lets see if we have enough data to construct one DV frame */
if (c->has_video == 1 && c->has_audio + 1 == 1<<c->n_ast) {
dv_inject_metadata(c, *frame);
+ c->has_audio = 0;
for (i=0; i<c->n_ast; i++) {
- dv_inject_audio(c, i, *frame);
- av_fifo_drain(&c->audio_data[i], reqasize);
+ dv_inject_audio(c, i, *frame);
+ av_fifo_drain(&c->audio_data[i], reqasize);
+ c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i);
}
c->has_video = 0;
- c->has_audio = 0;
+
c->frames++;
return c->sys->frame_size;
@@ -283,7 +285,7 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st,
DVMuxContext* dv_init_mux(AVFormatContext* s)
{
- DVMuxContext *c = (DVMuxContext *)s->priv_data;
+ DVMuxContext *c = s->priv_data;
AVStream *vst = NULL;
int i;
@@ -296,16 +298,18 @@ DVMuxContext* dv_init_mux(AVFormatContext* s)
/* We have to sort out where audio and where video stream is */
for (i=0; i<s->nb_streams; i++) {
- switch (s->streams[i]->codec->codec_type) {
- case CODEC_TYPE_VIDEO:
- vst = s->streams[i];
- break;
- case CODEC_TYPE_AUDIO:
- c->ast[c->n_ast++] = s->streams[i];
- break;
- default:
- goto bail_out;
- }
+ switch (s->streams[i]->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ if (vst) return NULL;
+ vst = s->streams[i];
+ break;
+ case CODEC_TYPE_AUDIO:
+ if (c->n_ast > 1) return NULL;
+ c->ast[c->n_ast++] = s->streams[i];
+ break;
+ default:
+ goto bail_out;
+ }
}
/* Some checks -- DV format is very picky about its incoming streams */
@@ -373,11 +377,11 @@ static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
uint8_t* frame;
int fsize;
- fsize = dv_assemble_frame((DVMuxContext *)s->priv_data, s->streams[pkt->stream_index],
+ fsize = dv_assemble_frame(s->priv_data, s->streams[pkt->stream_index],
pkt->data, pkt->size, &frame);
if (fsize > 0) {
- put_buffer(&s->pb, frame, fsize);
- put_flush_packet(&s->pb);
+ put_buffer(s->pb, frame, fsize);
+ put_flush_packet(s->pb);
}
return 0;
}
@@ -390,7 +394,7 @@ static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
*/
static int dv_write_trailer(struct AVFormatContext *s)
{
- dv_delete_mux((DVMuxContext *)s->priv_data);
+ dv_delete_mux(s->priv_data);
return 0;
}
#endif /* CONFIG_MUXERS */
diff --git a/contrib/ffmpeg/libavformat/dxa.c b/contrib/ffmpeg/libavformat/dxa.c
index f49d3d4ac..2df73c7dd 100644
--- a/contrib/ffmpeg/libavformat/dxa.c
+++ b/contrib/ffmpeg/libavformat/dxa.c
@@ -36,8 +36,6 @@ typedef struct{
static int dxa_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size <= 4)
- return 0;
if (p->buf[0] == 'D' && p->buf[1] == 'E' &&
p->buf[2] == 'X' && p->buf[3] == 'A')
return AVPROBE_SCORE_MAX;
@@ -47,7 +45,7 @@ static int dxa_probe(AVProbeData *p)
static int dxa_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
DXAContext *c = s->priv_data;
AVStream *st, *ast;
uint32_t tag;
@@ -146,54 +144,54 @@ static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt)
if(!c->readvid && c->has_sound && c->bytes_left){
c->readvid = 1;
- url_fseek(&s->pb, c->wavpos, SEEK_SET);
+ url_fseek(s->pb, c->wavpos, SEEK_SET);
size = FFMIN(c->bytes_left, c->bpc);
- ret = av_get_packet(&s->pb, pkt, size);
+ ret = av_get_packet(s->pb, pkt, size);
pkt->stream_index = 1;
if(ret != size)
- return AVERROR_IO;
+ return AVERROR(EIO);
c->bytes_left -= size;
- c->wavpos = url_ftell(&s->pb);
+ c->wavpos = url_ftell(s->pb);
return 0;
}
- url_fseek(&s->pb, c->vidpos, SEEK_SET);
- while(!url_feof(&s->pb) && c->frames){
- get_buffer(&s->pb, buf, 4);
+ url_fseek(s->pb, c->vidpos, SEEK_SET);
+ while(!url_feof(s->pb) && c->frames){
+ get_buffer(s->pb, buf, 4);
switch(AV_RL32(buf)){
case MKTAG('N', 'U', 'L', 'L'):
if(av_new_packet(pkt, 4 + pal_size) < 0)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
pkt->stream_index = 0;
if(pal_size) memcpy(pkt->data, pal, pal_size);
memcpy(pkt->data + pal_size, buf, 4);
c->frames--;
- c->vidpos = url_ftell(&s->pb);
+ c->vidpos = url_ftell(s->pb);
c->readvid = 0;
return 0;
case MKTAG('C', 'M', 'A', 'P'):
pal_size = 768+4;
memcpy(pal, buf, 4);
- get_buffer(&s->pb, pal + 4, 768);
+ get_buffer(s->pb, pal + 4, 768);
break;
case MKTAG('F', 'R', 'A', 'M'):
- get_buffer(&s->pb, buf + 4, DXA_EXTRA_SIZE - 4);
+ get_buffer(s->pb, buf + 4, DXA_EXTRA_SIZE - 4);
size = AV_RB32(buf + 5);
if(size > 0xFFFFFF){
av_log(s, AV_LOG_ERROR, "Frame size is too big: %d\n", size);
return -1;
}
if(av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size) < 0)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
memcpy(pkt->data + pal_size, buf, DXA_EXTRA_SIZE);
- ret = get_buffer(&s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size);
+ ret = get_buffer(s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size);
if(ret != size){
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
if(pal_size) memcpy(pkt->data, pal, pal_size);
pkt->stream_index = 0;
c->frames--;
- c->vidpos = url_ftell(&s->pb);
+ c->vidpos = url_ftell(s->pb);
c->readvid = 0;
return 0;
default:
diff --git a/contrib/ffmpeg/libavformat/eacdata.c b/contrib/ffmpeg/libavformat/eacdata.c
new file mode 100644
index 000000000..ffaf85e0e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/eacdata.c
@@ -0,0 +1,100 @@
+/*
+ * Electronic Arts .cdata file Demuxer
+ * Copyright (c) 2007 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 eacdata.c
+ * Electronic Arts cdata Format Demuxer
+ * by Peter Ross (suxen_drol at hotmail dot com)
+ *
+ * Technical details here:
+ * http://wiki.multimedia.cx/index.php?title=EA_Command_And_Conquer_3_Audio_Codec
+ */
+
+#include "avformat.h"
+
+typedef struct {
+ unsigned int channels;
+ unsigned int audio_pts;
+} CdataDemuxContext;
+
+static int cdata_probe(AVProbeData *p)
+{
+ const uint8_t *b = p->buf;
+
+ if (b[0] == 0x04 && (b[1] == 0x00 || b[1] == 0x04 || b[1] == 0x0C))
+ return AVPROBE_SCORE_MAX/8;
+ return 0;
+}
+
+static int cdata_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ CdataDemuxContext *cdata = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ unsigned int sample_rate, header;
+ AVStream *st;
+
+ header = get_be16(pb);
+ switch (header) {
+ case 0x0400: cdata->channels = 1; break;
+ case 0x0404: cdata->channels = 2; break;
+ case 0x040C: cdata->channels = 4; break;
+ default:
+ av_log(s, AV_LOG_INFO, "unknown header 0x%04x\n", header);
+ return -1;
+ };
+
+ sample_rate = get_be16(pb);
+ url_fskip(pb, 12);
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->codec_id = CODEC_ID_ADPCM_EA_XAS;
+ st->codec->channels = cdata->channels;
+ st->codec->sample_rate = sample_rate;
+ av_set_pts_info(st, 64, 1, sample_rate);
+
+ cdata->audio_pts = 0;
+ return 0;
+}
+
+static int cdata_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ CdataDemuxContext *cdata = s->priv_data;
+ int packet_size = 76*cdata->channels;
+
+ if (av_get_packet(s->pb, pkt, packet_size) != packet_size)
+ return AVERROR(EIO);
+ pkt->pts = cdata->audio_pts++;
+ return 1;
+}
+
+AVInputFormat ea_cdata_demuxer = {
+ "ea_cdata",
+ "Electronic Arts cdata",
+ sizeof(CdataDemuxContext),
+ cdata_probe,
+ cdata_read_header,
+ cdata_read_packet,
+ .extensions = "cdata",
+};
diff --git a/contrib/ffmpeg/libavformat/electronicarts.c b/contrib/ffmpeg/libavformat/electronicarts.c
index 762d658ab..0201e8200 100644
--- a/contrib/ffmpeg/libavformat/electronicarts.c
+++ b/contrib/ffmpeg/libavformat/electronicarts.c
@@ -27,33 +27,42 @@
#include "avformat.h"
#define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
+#define SEAD_TAG MKTAG('S', 'E', 'A', 'D') /* Sxxx header */
+#define SNDC_TAG MKTAG('S', 'N', 'D', 'C') /* Sxxx data */
+#define SEND_TAG MKTAG('S', 'E', 'N', 'D') /* Sxxx end */
+#define ISNh_TAG MKTAG('1', 'S', 'N', 'h') /* 1SNx header */
+#define EACS_TAG MKTAG('E', 'A', 'C', 'S')
+#define ISNd_TAG MKTAG('1', 'S', 'N', 'd') /* 1SNx data */
+#define ISNe_TAG MKTAG('1', 'S', 'N', 'e') /* 1SNx end */
#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
+#define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
-#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T')
#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
-#define _TAG MKTAG('', '', '', '')
-
-#define EA_SAMPLE_RATE 22050
-#define EA_BITS_PER_SAMPLE 16
-#define EA_PREAMBLE_SIZE 8
+#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') /* TGV i-frame */
+#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */
+#define MPCh_TAG MKTAG('M', 'P', 'C', 'h') /* MPEG2 */
+#define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
+#define MV0K_TAG MKTAG('M', 'V', '0', 'K')
+#define MV0F_TAG MKTAG('M', 'V', '0', 'F')
+#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */
typedef struct EaDemuxContext {
- int width;
- int height;
+ int big_endian;
+
+ int video_codec;
+ AVRational time_base;
int video_stream_index;
- int track_count;
+ int audio_codec;
int audio_stream_index;
int audio_frame_counter;
int64_t audio_pts;
- int64_t video_pts;
- int video_pts_inc;
- float fps;
+ int bytes;
+ int sample_rate;
int num_channels;
int num_samples;
- int compression_type;
} EaDemuxContext;
static uint32_t read_arbitary(ByteIOContext *pb) {
@@ -74,40 +83,24 @@ static uint32_t read_arbitary(ByteIOContext *pb) {
}
/*
- * Process WVE file header
- * Returns 1 if the WVE file is valid and successfully opened, 0 otherwise
+ * Process PT/GSTR sound header
+ * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
*/
-static int process_ea_header(AVFormatContext *s) {
- int inHeader;
- uint32_t blockid, size;
- EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
-
- if (get_buffer(pb, (void*)&blockid, 4) != 4) {
- return 0;
- }
- if (le2me_32(blockid) != SCHl_TAG) {
- return 0;
- }
-
- if (get_buffer(pb, (void*)&size, 4) != 4) {
- return 0;
- }
- size = le2me_32(size);
+static int process_audio_header_elements(AVFormatContext *s)
+{
+ int inHeader = 1;
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int compression_type = -1, revision = -1, revision2 = -1;
- if (get_buffer(pb, (void*)&blockid, 4) != 4) {
- return 0;
- }
- if (le2me_32(blockid) != PT00_TAG) {
- av_log (s, AV_LOG_ERROR, "PT header missing\n");
- return 0;
- }
+ ea->bytes = 2;
+ ea->sample_rate = -1;
+ ea->num_channels = 1;
- inHeader = 1;
while (inHeader) {
int inSubheader;
uint8_t byte;
- byte = get_byte(pb) & 0xFF;
+ byte = get_byte(pb);
switch (byte) {
case 0xFD:
@@ -115,16 +108,24 @@ static int process_ea_header(AVFormatContext *s) {
inSubheader = 1;
while (inSubheader) {
uint8_t subbyte;
- subbyte = get_byte(pb) & 0xFF;
+ subbyte = get_byte(pb);
switch (subbyte) {
+ case 0x80:
+ revision = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "revision (element 0x80) set to 0x%08x\n", revision);
+ break;
case 0x82:
ea->num_channels = read_arbitary(pb);
av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
break;
case 0x83:
- ea->compression_type = read_arbitary(pb);
- av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", ea->compression_type);
+ compression_type = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", compression_type);
+ break;
+ case 0x84:
+ ea->sample_rate = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "sample_rate (element 0x84) set to %i\n", ea->sample_rate);
break;
case 0x85:
ea->num_samples = read_arbitary(pb);
@@ -135,6 +136,15 @@ static int process_ea_header(AVFormatContext *s) {
av_log (s, AV_LOG_INFO, "exited audio subheader\n");
inSubheader = 0;
break;
+ case 0xA0:
+ revision2 = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "revision2 (element 0xA0) set to 0x%08x\n", revision2);
+ break;
+ case 0xFF:
+ av_log (s, AV_LOG_INFO, "end of header block reached (within audio subheader)\n");
+ inSubheader = 0;
+ inHeader = 0;
+ break;
default:
av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
break;
@@ -151,67 +161,218 @@ static int process_ea_header(AVFormatContext *s) {
}
}
- if ((ea->num_channels != 2) || (ea->compression_type != 7)) {
- av_log (s, AV_LOG_ERROR, "unsupported stream type\n");
+ switch (compression_type) {
+ case 0: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
+ case 7: ea->audio_codec = CODEC_ID_ADPCM_EA; break;
+ case -1:
+ switch (revision) {
+ case 1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break;
+ case 2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break;
+ case 3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break;
+ case -1: break;
+ default:
+ av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
+ return 0;
+ }
+ switch (revision2) {
+ case 8: ea->audio_codec = CODEC_ID_PCM_S16LE_PLANAR; break;
+ default:
+ av_log(s, AV_LOG_ERROR, "unsupported stream type; revision2=%i\n", revision2);
+ return 0;
+ }
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
return 0;
}
- /* skip to the start of the data */
- url_fseek(pb, size, SEEK_SET);
+ if (ea->sample_rate == -1)
+ ea->sample_rate = revision==3 ? 48000 : 22050;
return 1;
}
+/*
+ * Process EACS sound header
+ * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
+ */
+static int process_audio_header_eacs(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int compression_type;
-static int ea_probe(AVProbeData *p)
+ ea->sample_rate = ea->big_endian ? get_be32(pb) : get_le32(pb);
+ ea->bytes = get_byte(pb); /* 1=8-bit, 2=16-bit */
+ ea->num_channels = get_byte(pb);
+ compression_type = get_byte(pb);
+ url_fskip(pb, 13);
+
+ switch (compression_type) {
+ case 0:
+ switch (ea->bytes) {
+ case 1: ea->audio_codec = CODEC_ID_PCM_S8; break;
+ case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
+ }
+ break;
+ case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
+ case 2: ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_EACS; break;
+ default:
+ av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
+ }
+
+ return 1;
+}
+
+/*
+ * Process SEAD sound header
+ * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
+ */
+static int process_audio_header_sead(AVFormatContext *s)
{
- if (p->buf_size < 4)
- return 0;
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
- if (AV_RL32(&p->buf[0]) != SCHl_TAG)
- return 0;
+ ea->sample_rate = get_le32(pb);
+ ea->bytes = get_le32(pb); /* 1=8-bit, 2=16-bit */
+ ea->num_channels = get_le32(pb);
+ ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_SEAD;
+
+ return 1;
+}
+
+static int process_video_header_vp6(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
- return AVPROBE_SCORE_MAX;
+ url_fskip(pb, 16);
+ ea->time_base.den = get_le32(pb);
+ ea->time_base.num = get_le32(pb);
+ ea->video_codec = CODEC_ID_VP6;
+
+ return 1;
+}
+
+/*
+ * Process EA file header
+ * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
+ */
+static int process_ea_header(AVFormatContext *s) {
+ uint32_t blockid, size = 0;
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int i;
+
+ for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) {
+ unsigned int startpos = url_ftell(pb);
+ int err = 0;
+
+ blockid = get_le32(pb);
+ size = get_le32(pb);
+ if (i == 0)
+ ea->big_endian = size > 0x000FFFFF;
+ if (ea->big_endian)
+ size = bswap_32(size);
+
+ switch (blockid) {
+ case ISNh_TAG:
+ if (get_le32(pb) != EACS_TAG) {
+ av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
+ return 0;
+ }
+ err = process_audio_header_eacs(s);
+ break;
+
+ case SCHl_TAG :
+ blockid = get_le32(pb);
+ if (blockid == GSTR_TAG) {
+ url_fskip(pb, 4);
+ } else if (blockid != PT00_TAG) {
+ av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
+ return 0;
+ }
+ err = process_audio_header_elements(s);
+ break;
+
+ case SEAD_TAG:
+ err = process_audio_header_sead(s);
+ break;
+
+ case MVhd_TAG :
+ err = process_video_header_vp6(s);
+ break;
+ }
+
+ if (err < 0) {
+ av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
+ return err;
+ }
+
+ url_fseek(pb, startpos + size, SEEK_SET);
+ }
+
+ url_fseek(pb, 0, SEEK_SET);
+
+ return 1;
+}
+
+
+static int ea_probe(AVProbeData *p)
+{
+ switch (AV_RL32(&p->buf[0])) {
+ case ISNh_TAG:
+ case SCHl_TAG:
+ case SEAD_TAG:
+ case kVGT_TAG:
+ case MADk_TAG:
+ case MPCh_TAG:
+ case MVhd_TAG:
+ case MVIh_TAG:
+ return AVPROBE_SCORE_MAX;
+ }
+ return 0;
}
static int ea_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
+ EaDemuxContext *ea = s->priv_data;
AVStream *st;
if (!process_ea_header(s))
- return AVERROR_IO;
-
-#if 0
- /* initialize the video decoder stream */
- st = av_new_stream(s, 0);
- if (!st)
- return AVERROR_NOMEM;
- av_set_pts_info(st, 33, 1, 90000);
- ea->video_stream_index = st->index;
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = CODEC_ID_EA_MJPEG;
- st->codec->codec_tag = 0; /* no fourcc */
-#endif
-
- /* initialize the audio decoder stream */
- st = av_new_stream(s, 0);
- if (!st)
- return AVERROR_NOMEM;
- av_set_pts_info(st, 33, 1, EA_SAMPLE_RATE);
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = CODEC_ID_ADPCM_EA;
- st->codec->codec_tag = 0; /* no tag */
- st->codec->channels = ea->num_channels;
- st->codec->sample_rate = EA_SAMPLE_RATE;
- st->codec->bits_per_sample = EA_BITS_PER_SAMPLE;
- st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
- st->codec->bits_per_sample / 4;
- st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
-
- ea->audio_stream_index = st->index;
- ea->audio_frame_counter = 0;
+ return AVERROR(EIO);
+
+ if (ea->video_codec) {
+ /* initialize the video decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ ea->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = ea->video_codec;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->time_base = ea->time_base;
+ }
+
+ if (ea->audio_codec) {
+ /* initialize the audio decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ av_set_pts_info(st, 33, 1, ea->sample_rate);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = ea->audio_codec;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = ea->num_channels;
+ st->codec->sample_rate = ea->sample_rate;
+ st->codec->bits_per_sample = ea->bytes * 8;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample / 4;
+ st->codec->block_align = st->codec->channels*st->codec->bits_per_sample;
+ ea->audio_stream_index = st->index;
+ ea->audio_frame_counter = 0;
+ }
return 1;
}
@@ -220,43 +381,76 @@ static int ea_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
EaDemuxContext *ea = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int ret = 0;
int packet_read = 0;
- unsigned char preamble[EA_PREAMBLE_SIZE];
unsigned int chunk_type, chunk_size;
+ int key = 0;
while (!packet_read) {
-
- if (get_buffer(pb, preamble, EA_PREAMBLE_SIZE) != EA_PREAMBLE_SIZE)
- return AVERROR_IO;
- chunk_type = AV_RL32(&preamble[0]);
- chunk_size = AV_RL32(&preamble[4]) - EA_PREAMBLE_SIZE;
+ chunk_type = get_le32(pb);
+ chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8;
switch (chunk_type) {
/* audio data */
+ case ISNh_TAG:
+ /* header chunk also contains data; skip over the header portion*/
+ url_fskip(pb, 32);
+ chunk_size -= 32;
+ case ISNd_TAG:
case SCDl_TAG:
+ case SNDC_TAG:
+ if (!ea->audio_codec) {
+ url_fskip(pb, chunk_size);
+ break;
+ } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR) {
+ url_fskip(pb, 12); /* planar header */
+ chunk_size -= 12;
+ }
ret = av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
else {
pkt->stream_index = ea->audio_stream_index;
pkt->pts = 90000;
pkt->pts *= ea->audio_frame_counter;
- pkt->pts /= EA_SAMPLE_RATE;
+ pkt->pts /= ea->sample_rate;
+ switch (ea->audio_codec) {
+ case CODEC_ID_ADPCM_EA:
/* 2 samples/byte, 1 or 2 samples per frame depending
* on stereo; chunk also has 12-byte header */
ea->audio_frame_counter += ((chunk_size - 12) * 2) /
ea->num_channels;
+ break;
+ default:
+ ea->audio_frame_counter += chunk_size /
+ (ea->bytes * ea->num_channels);
+ }
}
packet_read = 1;
break;
/* ending tag */
+ case 0:
+ case ISNe_TAG:
case SCEl_TAG:
- ret = AVERROR_IO;
+ case SEND_TAG:
+ ret = AVERROR(EIO);
+ packet_read = 1;
+ break;
+
+ case MV0K_TAG:
+ key = PKT_FLAG_KEY;
+ case MV0F_TAG:
+ ret = av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ ret = AVERROR_IO;
+ else {
+ pkt->stream_index = ea->video_stream_index;
+ pkt->flags |= key;
+ }
packet_read = 1;
break;
@@ -264,22 +458,11 @@ static int ea_read_packet(AVFormatContext *s,
url_fseek(pb, chunk_size, SEEK_CUR);
break;
}
-
- /* ending packet */
- if (chunk_type == SCEl_TAG) {
- }
}
return ret;
}
-static int ea_read_close(AVFormatContext *s)
-{
-// EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
-
- return 0;
-}
-
AVInputFormat ea_demuxer = {
"ea",
"Electronic Arts Multimedia Format",
@@ -287,5 +470,4 @@ AVInputFormat ea_demuxer = {
ea_probe,
ea_read_header,
ea_read_packet,
- ea_read_close,
};
diff --git a/contrib/ffmpeg/libavformat/ffm.c b/contrib/ffmpeg/libavformat/ffm.c
index a2970ae42..872e6f0ba 100644
--- a/contrib/ffmpeg/libavformat/ffm.c
+++ b/contrib/ffmpeg/libavformat/ffm.c
@@ -64,7 +64,7 @@ static void flush_packet(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
int fill_size, h;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
fill_size = ffm->packet_end - ffm->packet_ptr;
memset(ffm->packet_ptr, 0, fill_size);
@@ -128,7 +128,7 @@ static int ffm_write_header(AVFormatContext *s)
FFMContext *ffm = s->priv_data;
AVStream *st;
FFMStream *fst;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *codec;
int bit_rate, i;
@@ -278,7 +278,7 @@ static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt)
static int ffm_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
FFMContext *ffm = s->priv_data;
/* flush packets */
@@ -314,7 +314,7 @@ static int ffm_is_avail_data(AVFormatContext *s, int size)
if (size <= len)
return 1;
}
- pos = url_ftell(&s->pb);
+ pos = url_ftell(s->pb);
if (pos == ffm->write_index) {
/* exactly at the end of stream */
return 0;
@@ -335,7 +335,7 @@ static int ffm_read_data(AVFormatContext *s,
uint8_t *buf, int size, int first)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int len, fill_size, size1, frame_offset;
size1 = size;
@@ -393,7 +393,7 @@ static int ffm_read_data(AVFormatContext *s,
static void adjust_write_index(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int64_t pts;
//offset_t orig_write_index = ffm->write_index;
offset_t pos_min, pos_max;
@@ -452,7 +452,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
FFMContext *ffm = s->priv_data;
AVStream *st;
FFMStream *fst;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *codec;
int i, nb_streams;
uint32_t tag;
@@ -585,7 +585,7 @@ static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
}
#if 0
printf("pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
- url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
+ url_ftell(s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
#endif
if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
FRAME_HEADER_SIZE)
@@ -601,16 +601,16 @@ static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
ffm->read_state = READ_DATA;
/* fall thru */
case READ_DATA:
- size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
+ size = AV_RB24(ffm->header + 2);
if (!ffm_is_avail_data(s, size)) {
return AVERROR(EAGAIN);
}
- duration = (ffm->header[5] << 16) | (ffm->header[6] << 8) | ffm->header[7];
+ duration = AV_RB24(ffm->header + 5);
av_new_packet(pkt, size);
pkt->stream_index = ffm->header[0];
- pkt->pos = url_ftell(&s->pb);
+ pkt->pos = url_ftell(s->pb);
if (ffm->header[1] & FLAG_KEY_FRAME)
pkt->flags |= PKT_FLAG_KEY;
@@ -638,7 +638,7 @@ static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
static void ffm_seek1(AVFormatContext *s, offset_t pos1)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t pos;
pos = pos1 + ffm->write_index;
@@ -652,7 +652,7 @@ static void ffm_seek1(AVFormatContext *s, offset_t pos1)
static int64_t get_pts(AVFormatContext *s, offset_t pos)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int64_t pts;
ffm_seek1(s, pos);
@@ -665,7 +665,7 @@ static int64_t get_pts(AVFormatContext *s, offset_t pos)
}
/* seek to a given time in the file. The file read pointer is
- positionned at or before pts. XXX: the following code is quite
+ positioned at or before pts. XXX: the following code is quite
approximative */
static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
{
@@ -714,15 +714,10 @@ static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, in
offset_t ffm_read_write_index(int fd)
{
uint8_t buf[8];
- offset_t pos;
- int i;
lseek(fd, 8, SEEK_SET);
read(fd, buf, 8);
- pos = 0;
- for(i=0;i<8;i++)
- pos |= (int64_t)buf[i] << (56 - i * 8);
- return pos;
+ return AV_RB64(buf);
}
void ffm_write_write_index(int fd, offset_t pos)
@@ -758,7 +753,7 @@ static int ffm_read_close(AVFormatContext *s)
static int ffm_probe(AVProbeData *p)
{
- if (p->buf_size >= 4 &&
+ if (
p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
p->buf[3] == '1')
return AVPROBE_SCORE_MAX + 1;
diff --git a/contrib/ffmpeg/libavformat/file.c b/contrib/ffmpeg/libavformat/file.c
index 3caf80a61..6285c1bba 100644
--- a/contrib/ffmpeg/libavformat/file.c
+++ b/contrib/ffmpeg/libavformat/file.c
@@ -19,9 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
+#include "avstring.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
+#include <stdlib.h>
+#include "os_support.h"
/* standard file protocol */
@@ -31,7 +34,7 @@ static int file_open(URLContext *h, const char *filename, int flags)
int access;
int fd;
- strstart(filename, "file:", &filename);
+ av_strstart(filename, "file:", &filename);
if (flags & URL_RDWR) {
access = O_CREAT | O_TRUNC | O_RDWR;
@@ -40,7 +43,7 @@ static int file_open(URLContext *h, const char *filename, int flags)
} else {
access = O_RDONLY;
}
-#if defined(__MINGW32__) || defined(CONFIG_OS2) || defined(__CYGWIN__)
+#ifdef O_BINARY
access |= O_BINARY;
#endif
fd = open(filename, access, 0666);
@@ -89,13 +92,18 @@ URLProtocol file_protocol = {
static int pipe_open(URLContext *h, const char *filename, int flags)
{
int fd;
-
- if (flags & URL_WRONLY) {
- fd = 1;
- } else {
- fd = 0;
+ const char * final;
+ av_strstart(filename, "pipe:", &filename);
+
+ fd = strtol(filename, &final, 10);
+ if((filename == final) || *final ) {/* No digits found, or something like 10ab */
+ if (flags & URL_WRONLY) {
+ fd = 1;
+ } else {
+ fd = 0;
+ }
}
-#if defined(__MINGW32__) || defined(CONFIG_OS2) || defined(__CYGWIN__)
+#ifdef O_BINARY
setmode(fd, O_BINARY);
#endif
h->priv_data = (void *)(size_t)fd;
@@ -103,28 +111,9 @@ static int pipe_open(URLContext *h, const char *filename, int flags)
return 0;
}
-static int pipe_read(URLContext *h, unsigned char *buf, int size)
-{
- int fd = (size_t)h->priv_data;
- return read(fd, buf, size);
-}
-
-static int pipe_write(URLContext *h, unsigned char *buf, int size)
-{
- int fd = (size_t)h->priv_data;
- return write(fd, buf, size);
-}
-
-static int pipe_close(URLContext *h)
-{
- return 0;
-}
-
URLProtocol pipe_protocol = {
"pipe",
pipe_open,
- pipe_read,
- pipe_write,
- NULL,
- pipe_close,
+ file_read,
+ file_write,
};
diff --git a/contrib/ffmpeg/libavformat/flic.c b/contrib/ffmpeg/libavformat/flic.c
index 0c3a7f01f..b422fb09a 100644
--- a/contrib/ffmpeg/libavformat/flic.c
+++ b/contrib/ffmpeg/libavformat/flic.c
@@ -39,25 +39,21 @@
originated in Dave's Targa Animator (DTA) */
#define FLIC_CHUNK_MAGIC_1 0xF1FA
#define FLIC_CHUNK_MAGIC_2 0xF5FA
-#define FLIC_MC_PTS_INC 6000 /* pts increment for Magic Carpet game FLIs */
-#define FLIC_DEFAULT_PTS_INC 6000 /* for FLIs that have 0 speed */
+#define FLIC_MC_SPEED 5 /* speed for Magic Carpet game FLIs */
+#define FLIC_DEFAULT_SPEED 5 /* for FLIs that have 0 speed */
#define FLIC_HEADER_SIZE 128
#define FLIC_PREAMBLE_SIZE 6
typedef struct FlicDemuxContext {
- int frame_pts_inc;
- int64_t pts;
int video_stream_index;
+ int frame_number;
} FlicDemuxContext;
static int flic_probe(AVProbeData *p)
{
int magic_number;
- if (p->buf_size < 6)
- return 0;
-
magic_number = AV_RL16(&p->buf[4]);
if ((magic_number != FLIC_FILE_MAGIC_1) &&
(magic_number != FLIC_FILE_MAGIC_2) &&
@@ -70,26 +66,28 @@ static int flic_probe(AVProbeData *p)
static int flic_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ FlicDemuxContext *flic = s->priv_data;
+ ByteIOContext *pb = s->pb;
unsigned char header[FLIC_HEADER_SIZE];
AVStream *st;
int speed;
int magic_number;
- flic->pts = 0;
+ flic->frame_number = 0;
/* load the whole header and pull out the width and height */
if (get_buffer(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
magic_number = AV_RL16(&header[4]);
speed = AV_RL32(&header[0x10]);
+ if (speed == 0)
+ speed = FLIC_DEFAULT_SPEED;
/* initialize the decoder streams */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
flic->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_FLIC;
@@ -97,22 +95,26 @@ static int flic_read_header(AVFormatContext *s,
st->codec->width = AV_RL16(&header[0x08]);
st->codec->height = AV_RL16(&header[0x0A]);
- if (!st->codec->width || !st->codec->height)
- return AVERROR_INVALIDDATA;
+ if (!st->codec->width || !st->codec->height) {
+ /* Ugly hack needed for the following sample: */
+ /* http://samples.mplayerhq.hu/fli-flc/fli-bugs/specular.flc */
+ av_log(s, AV_LOG_WARNING,
+ "File with no specified width/height. Trying 640x480.\n");
+ st->codec->width = 640;
+ st->codec->height = 480;
+ }
/* send over the whole 128-byte FLIC header */
st->codec->extradata_size = FLIC_HEADER_SIZE;
st->codec->extradata = av_malloc(FLIC_HEADER_SIZE);
memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE);
- av_set_pts_info(st, 33, 1, 90000);
-
/* Time to figure out the framerate: If there is a FLIC chunk magic
* number at offset 0x10, assume this is from the Bullfrog game,
* Magic Carpet. */
if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
- flic->frame_pts_inc = FLIC_MC_PTS_INC;
+ av_set_pts_info(st, 64, FLIC_MC_SPEED, 70);
/* rewind the stream since the first chunk is at offset 12 */
url_fseek(pb, 12, SEEK_SET);
@@ -124,44 +126,23 @@ static int flic_read_header(AVFormatContext *s,
memcpy(st->codec->extradata, header, 12);
} else if (magic_number == FLIC_FILE_MAGIC_1) {
- /*
- * in this case, the speed (n) is number of 1/70s ticks between frames:
- *
- * pts n * frame #
- * -------- = ----------- => pts = n * (90000/70) * frame #
- * 90000 70
- *
- * therefore, the frame pts increment = n * 1285.7
- */
- flic->frame_pts_inc = speed * 1285.7;
+ av_set_pts_info(st, 64, speed, 70);
} else if ((magic_number == FLIC_FILE_MAGIC_2) ||
(magic_number == FLIC_FILE_MAGIC_3)) {
- /*
- * in this case, the speed (n) is number of milliseconds between frames:
- *
- * pts n * frame #
- * -------- = ----------- => pts = n * 90 * frame #
- * 90000 1000
- *
- * therefore, the frame pts increment = n * 90
- */
- flic->frame_pts_inc = speed * 90;
+ av_set_pts_info(st, 64, speed, 1000);
} else {
av_log(s, AV_LOG_INFO, "Invalid or unsupported magic chunk in file\n");
return AVERROR_INVALIDDATA;
}
- if (flic->frame_pts_inc == 0)
- flic->frame_pts_inc = FLIC_DEFAULT_PTS_INC;
-
return 0;
}
static int flic_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ FlicDemuxContext *flic = s->priv_data;
+ ByteIOContext *pb = s->pb;
int packet_read = 0;
unsigned int size;
int magic;
@@ -172,7 +153,7 @@ static int flic_read_packet(AVFormatContext *s,
if ((ret = get_buffer(pb, preamble, FLIC_PREAMBLE_SIZE)) !=
FLIC_PREAMBLE_SIZE) {
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
break;
}
@@ -181,20 +162,19 @@ static int flic_read_packet(AVFormatContext *s,
if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) {
if (av_new_packet(pkt, size)) {
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
break;
}
pkt->stream_index = flic->video_stream_index;
- pkt->pts = flic->pts;
+ pkt->pts = flic->frame_number++;
pkt->pos = url_ftell(pb);
memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE);
ret = get_buffer(pb, pkt->data + FLIC_PREAMBLE_SIZE,
size - FLIC_PREAMBLE_SIZE);
if (ret != size - FLIC_PREAMBLE_SIZE) {
av_free_packet(pkt);
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
}
- flic->pts += flic->frame_pts_inc;
packet_read = 1;
} else {
/* not interested in this chunk */
@@ -207,7 +187,7 @@ static int flic_read_packet(AVFormatContext *s,
static int flic_read_close(AVFormatContext *s)
{
-// FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
+// FlicDemuxContext *flic = s->priv_data;
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/flv.h b/contrib/ffmpeg/libavformat/flv.h
index 1484ac15d..4501527aa 100644
--- a/contrib/ffmpeg/libavformat/flv.h
+++ b/contrib/ffmpeg/libavformat/flv.h
@@ -21,8 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef FLV_H
-#define FLV_H
+#ifndef FFMPEG_FLV_H
+#define FFMPEG_FLV_H
/* offsets for packed values */
#define FLV_AUDIO_SAMPLESSIZE_OFFSET 1
@@ -71,7 +71,7 @@ enum {
};
enum {
- FLV_CODECID_PCM_BE = 0,
+ FLV_CODECID_PCM = 0,
FLV_CODECID_ADPCM = 1 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_MP3 = 2 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_PCM_LE = 3 << FLV_AUDIO_CODECID_OFFSET,
@@ -107,4 +107,4 @@ typedef enum {
AMF_DATA_TYPE_UNSUPPORTED = 0x0d,
} AMFDataType;
-#endif /* FLV_H */
+#endif /* FFMPEG_FLV_H */
diff --git a/contrib/ffmpeg/libavformat/flvdec.c b/contrib/ffmpeg/libavformat/flvdec.c
index bf91fbbc7..f21f35296 100644
--- a/contrib/ffmpeg/libavformat/flvdec.c
+++ b/contrib/ffmpeg/libavformat/flvdec.c
@@ -2,6 +2,11 @@
* FLV demuxer
* Copyright (c) 2003 The FFmpeg Project.
*
+ * This demuxer will generate a 1 byte extradata for VP6F content.
+ * It is composed of:
+ * - upper 4bits: difference between encoded width and visible width
+ * - lower 4bits: difference between encoded height and visible height
+ *
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
@@ -17,12 +22,6 @@
* 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
- *
- *
- * This demuxer will generate a 1 byte extradata for VP6F content.
- * It is composed of:
- * - upper 4bits: difference between encoded width and visible width
- * - lower 4bits: difference between encoded height and visible height
*/
#include "avformat.h"
#include "flv.h"
@@ -31,8 +30,6 @@ static int flv_probe(AVProbeData *p)
{
const uint8_t *d;
- if (p->buf_size < 6)
- return 0;
d = p->buf;
if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5]==0) {
return AVPROBE_SCORE_MAX;
@@ -44,15 +41,23 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_c
AVCodecContext *acodec = astream->codec;
switch(flv_codecid) {
//no distinction between S16 and S8 PCM codec flags
- case FLV_CODECID_PCM_BE:
- acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 : CODEC_ID_PCM_S16BE; break;
+ case FLV_CODECID_PCM:
+ acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 :
+#ifdef WORDS_BIGENDIAN
+ CODEC_ID_PCM_S16BE;
+#else
+ CODEC_ID_PCM_S16LE;
+#endif
+ break;
case FLV_CODECID_PCM_LE:
acodec->codec_id = acodec->bits_per_sample == 8 ? CODEC_ID_PCM_S8 : CODEC_ID_PCM_S16LE; break;
case FLV_CODECID_ADPCM: acodec->codec_id = CODEC_ID_ADPCM_SWF; break;
- case FLV_CODECID_MP3 : acodec->codec_id = CODEC_ID_MP3 ; astream->need_parsing = 1 ; break;
+ case FLV_CODECID_MP3 : acodec->codec_id = CODEC_ID_MP3 ; astream->need_parsing = AVSTREAM_PARSE_FULL; break;
case FLV_CODECID_NELLYMOSER_8HZ_MONO:
acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate
case FLV_CODECID_NELLYMOSER:
+ acodec->codec_id = CODEC_ID_NELLYMOSER;
+ break;
default:
av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
@@ -65,11 +70,14 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_co
case FLV_CODECID_H263 : vcodec->codec_id = CODEC_ID_FLV1 ; break;
case FLV_CODECID_SCREEN: vcodec->codec_id = CODEC_ID_FLASHSV; break;
case FLV_CODECID_VP6 : vcodec->codec_id = CODEC_ID_VP6F ;
+ case FLV_CODECID_VP6A :
+ if(flv_codecid == FLV_CODECID_VP6A)
+ vcodec->codec_id = CODEC_ID_VP6A;
if(vcodec->extradata_size != 1) {
vcodec->extradata_size = 1;
vcodec->extradata = av_malloc(1);
}
- vcodec->extradata[0] = get_byte(&s->pb);
+ vcodec->extradata[0] = get_byte(s->pb);
return 1; // 1 byte body size adjustment for flv_read_packet()
default:
av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid);
@@ -101,7 +109,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
double num_val;
num_val = 0;
- ioc = &s->pb;
+ ioc = s->pb;
amf_type = get_byte(ioc);
@@ -177,12 +185,14 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
}
else if(!strcmp(key, "audiosamplerate") && acodec && num_val >= 0) {
//some tools, like FLVTool2, write consistently approximate metadata sample rates
- switch((int)num_val) {
- case 44000: acodec->sample_rate = 44100 ; break;
- case 22000: acodec->sample_rate = 22050 ; break;
- case 11000: acodec->sample_rate = 11025 ; break;
- case 5000 : acodec->sample_rate = 5512 ; break;
- default : acodec->sample_rate = num_val;
+ if (!acodec->sample_rate) {
+ switch((int)num_val) {
+ case 44000: acodec->sample_rate = 44100 ; break;
+ case 22000: acodec->sample_rate = 22050 ; break;
+ case 11000: acodec->sample_rate = 11025 ; break;
+ case 5000 : acodec->sample_rate = 5512 ; break;
+ default : acodec->sample_rate = num_val;
+ }
}
}
}
@@ -201,7 +211,7 @@ static int flv_read_metabody(AVFormatContext *s, unsigned int next_pos) {
astream = NULL;
vstream = NULL;
keylen = 0;
- ioc = &s->pb;
+ ioc = s->pb;
//first object needs to be "onMetaData" string
type = get_byte(ioc);
@@ -222,14 +232,22 @@ static int flv_read_metabody(AVFormatContext *s, unsigned int next_pos) {
return 0;
}
+static AVStream *create_stream(AVFormatContext *s, int is_audio){
+ AVStream *st = av_new_stream(s, is_audio);
+ if (!st)
+ return NULL;
+ st->codec->codec_type = is_audio ? CODEC_TYPE_AUDIO : CODEC_TYPE_VIDEO;
+ av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */
+ return st;
+}
+
static int flv_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
int offset, flags;
- AVStream *st;
- url_fskip(&s->pb, 4);
- flags = get_byte(&s->pb);
+ url_fskip(s->pb, 4);
+ flags = get_byte(s->pb);
/* old flvtool cleared this field */
/* FIXME: better fix needed */
if (!flags) {
@@ -238,22 +256,16 @@ static int flv_read_header(AVFormatContext *s,
}
if(flags & FLV_HEADER_FLAG_HASVIDEO){
- st = av_new_stream(s, 0);
- if (!st)
- return AVERROR_NOMEM;
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */
+ if(!create_stream(s, 0))
+ return AVERROR(ENOMEM);
}
if(flags & FLV_HEADER_FLAG_HASAUDIO){
- st = av_new_stream(s, 1);
- if (!st)
- return AVERROR_NOMEM;
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */
+ if(!create_stream(s, 1))
+ return AVERROR(ENOMEM);
}
- offset = get_be32(&s->pb);
- url_fseek(&s->pb, offset, SEEK_SET);
+ offset = get_be32(s->pb);
+ url_fseek(s->pb, offset, SEEK_SET);
s->start_time = 0;
@@ -266,34 +278,35 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *st = NULL;
for(;;){
- pos = url_ftell(&s->pb);
- url_fskip(&s->pb, 4); /* size of previous packet */
- type = get_byte(&s->pb);
- size = get_be24(&s->pb);
- pts = get_be24(&s->pb);
+ pos = url_ftell(s->pb);
+ url_fskip(s->pb, 4); /* size of previous packet */
+ type = get_byte(s->pb);
+ size = get_be24(s->pb);
+ pts = get_be24(s->pb);
+ pts |= get_byte(s->pb) << 24;
// av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts);
- if (url_feof(&s->pb))
- return AVERROR_IO;
- url_fskip(&s->pb, 4); /* reserved */
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
+ url_fskip(s->pb, 3); /* stream id, always 0 */
flags = 0;
if(size == 0)
continue;
- next= size + url_ftell(&s->pb);
+ next= size + url_ftell(s->pb);
if (type == FLV_TAG_TYPE_AUDIO) {
is_audio=1;
- flags = get_byte(&s->pb);
+ flags = get_byte(s->pb);
} else if (type == FLV_TAG_TYPE_VIDEO) {
is_audio=0;
- flags = get_byte(&s->pb);
+ flags = get_byte(s->pb);
} else {
if (type == FLV_TAG_TYPE_META && size > 13+1+4)
flv_read_metabody(s, next);
else /* skip packet */
av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags);
- url_fseek(&s->pb, next, SEEK_SET);
+ url_fseek(s->pb, next, SEEK_SET);
continue;
}
@@ -305,15 +318,14 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
if(i == s->nb_streams){
av_log(NULL, AV_LOG_ERROR, "invalid stream\n");
- url_fseek(&s->pb, next, SEEK_SET);
- continue;
+ st= create_stream(s, is_audio);
}
// av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard);
if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio))
||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio))
|| st->discard >= AVDISCARD_ALL
){
- url_fseek(&s->pb, next, SEEK_SET);
+ url_fseek(s->pb, next, SEEK_SET);
continue;
}
if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)
@@ -322,17 +334,17 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
// if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
- if(!url_is_streamed(&s->pb) && s->duration==AV_NOPTS_VALUE){
+ if(!url_is_streamed(s->pb) && s->duration==AV_NOPTS_VALUE){
int size;
- const int pos= url_ftell(&s->pb);
- const int fsize= url_fsize(&s->pb);
- url_fseek(&s->pb, fsize-4, SEEK_SET);
- size= get_be32(&s->pb);
- url_fseek(&s->pb, fsize-3-size, SEEK_SET);
- if(size == get_be24(&s->pb) + 11){
- s->duration= get_be24(&s->pb) * (int64_t)AV_TIME_BASE / 1000;
+ const int pos= url_ftell(s->pb);
+ const int fsize= url_fsize(s->pb);
+ url_fseek(s->pb, fsize-4, SEEK_SET);
+ size= get_be32(s->pb);
+ url_fseek(s->pb, fsize-3-size, SEEK_SET);
+ if(size == get_be24(s->pb) + 11){
+ s->duration= get_be24(s->pb) * (int64_t)AV_TIME_BASE / 1000;
}
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
}
if(is_audio){
@@ -349,9 +361,9 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK);
}
- ret= av_get_packet(&s->pb, pkt, size - 1);
+ ret= av_get_packet(s->pb, pkt, size - 1);
if (ret <= 0) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
/* note: we need to modify the packet size here to handle the last
packet */
@@ -376,7 +388,7 @@ static int flv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
int index = av_index_search_timestamp(st, timestamp, flags);
if (index < 0)
return -1;
- url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
+ url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/flvenc.c b/contrib/ffmpeg/libavformat/flvenc.c
index ece585d77..e5270ca32 100644
--- a/contrib/ffmpeg/libavformat/flvenc.c
+++ b/contrib/ffmpeg/libavformat/flvenc.c
@@ -35,8 +35,8 @@ static const AVCodecTag flv_video_codec_ids[] = {
static const AVCodecTag flv_audio_codec_ids[] = {
{CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET},
- {CODEC_ID_PCM_S8, FLV_CODECID_PCM_BE >> FLV_AUDIO_CODECID_OFFSET},
- {CODEC_ID_PCM_S16BE, FLV_CODECID_PCM_BE >> FLV_AUDIO_CODECID_OFFSET},
+ {CODEC_ID_PCM_S8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET},
+ {CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_NONE, 0}
@@ -66,10 +66,12 @@ static int get_audio_flags(AVCodecContext *enc){
break;
case 8000: //nellymoser only
case 5512: //not mp3
- flags |= FLV_SAMPLERATE_SPECIAL;
- break;
+ if(enc->codec_id != CODEC_ID_MP3){
+ flags |= FLV_SAMPLERATE_SPECIAL;
+ break;
+ }
default:
- av_log(enc, AV_LOG_ERROR, "flv doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
+ av_log(enc, AV_LOG_ERROR, "flv does not support that sample rate, choose from (44100, 22050, 11025).\n");
return -1;
}
@@ -82,10 +84,10 @@ static int get_audio_flags(AVCodecContext *enc){
flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_PCM_S8:
- flags |= FLV_CODECID_PCM_BE | FLV_SAMPLESSIZE_8BIT;
+ flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_8BIT;
break;
case CODEC_ID_PCM_S16BE:
- flags |= FLV_CODECID_PCM_BE | FLV_SAMPLESSIZE_16BIT;
+ flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_PCM_S16LE:
flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;
@@ -124,7 +126,7 @@ static void put_amf_bool(ByteIOContext *pb, int b) {
static int flv_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
FLVContext *flv = s->priv_data;
int i, width, height, samplerate, samplesize, channels, audiocodecid, videocodecid;
double framerate = 0.0;
@@ -254,7 +256,7 @@ static int flv_write_trailer(AVFormatContext *s)
{
int64_t file_size;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
FLVContext *flv = s->priv_data;
file_size = url_ftell(pb);
@@ -271,14 +273,19 @@ static int flv_write_trailer(AVFormatContext *s)
static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
FLVContext *flv = s->priv_data;
int size= pkt->size;
- int flags;
+ int flags, flags_size;
// av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n", enc->codec_type, timestamp, size);
+ if(enc->codec_id == CODEC_ID_VP6 || enc->codec_id == CODEC_ID_VP6F)
+ flags_size= 2;
+ else
+ flags_size= 1;
+
if (enc->codec_type == CODEC_TYPE_VIDEO) {
put_byte(pb, FLV_TAG_TYPE_VIDEO);
@@ -298,19 +305,17 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
put_byte(pb, FLV_TAG_TYPE_AUDIO);
}
- if ((enc->codec_id == CODEC_ID_VP6) || (enc->codec_id == CODEC_ID_VP6F))
- put_be24(pb,size+2); // include the extra byte needed for VP6 in flv and flags
- else
- put_be24(pb,size+1); // include flags
+ put_be24(pb,size + flags_size);
put_be24(pb,pkt->pts);
- put_be32(pb,flv->reserved);
+ put_byte(pb,pkt->pts >> 24);
+ put_be24(pb,flv->reserved);
put_byte(pb,flags);
if (enc->codec_id == CODEC_ID_VP6)
put_byte(pb,0);
if (enc->codec_id == CODEC_ID_VP6F)
put_byte(pb, enc->extradata_size ? enc->extradata[0] : 0);
put_buffer(pb, pkt->data, size);
- put_be32(pb,size+1+11); // previous tag size
+ put_be32(pb,size+flags_size+11); // previous tag size
flv->duration = pkt->pts + pkt->duration;
put_flush_packet(pb);
@@ -326,7 +331,7 @@ AVOutputFormat flv_muxer = {
#ifdef CONFIG_LIBMP3LAME
CODEC_ID_MP3,
#else // CONFIG_LIBMP3LAME
- CODEC_ID_NONE,
+ CODEC_ID_ADPCM_SWF,
#endif // CONFIG_LIBMP3LAME
CODEC_ID_FLV1,
flv_write_header,
diff --git a/contrib/ffmpeg/libavformat/framecrcenc.c b/contrib/ffmpeg/libavformat/framecrcenc.c
new file mode 100644
index 000000000..c0133017c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/framecrcenc.c
@@ -0,0 +1,46 @@
+/*
+ * frame CRC encoder (for codec/format testing)
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "adler32.h"
+
+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, %"PRId64", %d, 0x%08x\n", pkt->stream_index, pkt->dts, pkt->size, crc);
+ put_buffer(s->pb, buf, strlen(buf));
+ put_flush_packet(s->pb);
+ return 0;
+}
+
+AVOutputFormat framecrc_muxer = {
+ "framecrc",
+ "framecrc testing format",
+ NULL,
+ "",
+ 0,
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_RAWVIDEO,
+ NULL,
+ framecrc_write_packet,
+ NULL,
+};
diff --git a/contrib/ffmpeg/libavformat/framehook.c b/contrib/ffmpeg/libavformat/framehook.c
index 8738f8030..eb5184f02 100644
--- a/contrib/ffmpeg/libavformat/framehook.c
+++ b/contrib/ffmpeg/libavformat/framehook.c
@@ -28,8 +28,8 @@
#endif
-typedef struct _FrameHookEntry {
- struct _FrameHookEntry *next;
+typedef struct FrameHookEntry {
+ struct FrameHookEntry *next;
FrameHookConfigureFn Configure;
FrameHookProcessFn Process;
FrameHookReleaseFn Release;
diff --git a/contrib/ffmpeg/libavformat/framehook.h b/contrib/ffmpeg/libavformat/framehook.h
index 06ed4f889..5568c138e 100644
--- a/contrib/ffmpeg/libavformat/framehook.h
+++ b/contrib/ffmpeg/libavformat/framehook.h
@@ -19,10 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef _FRAMEHOOK_H
-#define _FRAMEHOOK_H
+#ifndef FFMPEG_FRAMEHOOK_H
+#define FFMPEG_FRAMEHOOK_H
-#warning VHOOK is deprecated please help porting libmpcodecs or a better filter system to ffmpeg instead of wasting your time writing new fiters for this crappy one
+#warning VHOOK is deprecated. Please help finishing libavfilter instead of wasting your time writing new filters for this crappy filter system.
/*
* Prototypes for interface to .so that implement a video processing hook
@@ -49,4 +49,4 @@ extern int frame_hook_add(int argc, char *argv[]);
extern void frame_hook_process(struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts);
extern void frame_hook_release(void);
-#endif
+#endif /* FFMPEG_FRAMEHOOK_H */
diff --git a/contrib/ffmpeg/libavformat/gif.c b/contrib/ffmpeg/libavformat/gif.c
index 1083710d5..7b71faea9 100644
--- a/contrib/ffmpeg/libavformat/gif.c
+++ b/contrib/ffmpeg/libavformat/gif.c
@@ -137,7 +137,7 @@ static void gif_put_bits_rev(PutBitContext *s, int n, unsigned int value)
//printf("bitbuf = %08x\n", bit_buf);
s->buf_ptr+=4;
if (s->buf_ptr >= s->buf_end)
- puts("bit buffer overflow !!"); // should never happen ! who got rid of the callback ???
+ abort();
// flush_buffer_rev(s);
bit_cnt=bit_cnt + n - 32;
if (bit_cnt == 0) {
@@ -313,7 +313,7 @@ typedef struct {
static int gif_write_header(AVFormatContext *s)
{
GIFContext *gif = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc, *video_enc;
int i, width, height, loop_count /*, rate*/;
@@ -343,19 +343,19 @@ static int gif_write_header(AVFormatContext *s)
if (video_enc->pix_fmt != PIX_FMT_RGB24) {
av_log(s, AV_LOG_ERROR, "ERROR: gif only handles the rgb24 pixel format. Use -pix_fmt rgb24.\n");
- return AVERROR_IO;
+ return AVERROR(EIO);
}
gif_image_write_header(pb, width, height, loop_count, NULL);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
}
static int gif_write_video(AVFormatContext *s,
AVCodecContext *enc, const uint8_t *buf, int size)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
GIFContext *gif = s->priv_data;
int jiffies;
int64_t delay;
@@ -383,7 +383,7 @@ static int gif_write_video(AVFormatContext *s,
gif_image_write_image(pb, 0, 0, enc->width, enc->height,
buf, enc->width * 3, PIX_FMT_RGB24);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
}
@@ -398,10 +398,10 @@ static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
static int gif_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
put_byte(pb, 0x3b);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/gifdec.c b/contrib/ffmpeg/libavformat/gifdec.c
index 1d31211f6..5803e5e5d 100644
--- a/contrib/ffmpeg/libavformat/gifdec.c
+++ b/contrib/ffmpeg/libavformat/gifdec.c
@@ -500,21 +500,21 @@ static int gif_parse_next_image(GifState *s)
switch (code) {
case ',':
if (gif_read_image(s) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
ret = 0;
goto the_end;
case ';':
/* end of image */
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
goto the_end;
case '!':
if (gif_read_extension(s) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
break;
case EOF:
default:
/* error or errneous EOF */
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
goto the_end;
}
}
@@ -526,7 +526,7 @@ static int gif_read_header(AVFormatContext * s1,
AVFormatParameters * ap)
{
GifState *s = s1->priv_data;
- ByteIOContext *f = &s1->pb;
+ ByteIOContext *f = s1->pb;
AVStream *st;
s->f = f;
@@ -567,7 +567,7 @@ static int gif_read_packet(AVFormatContext * s1,
/* XXX: avoid copying */
if (av_new_packet(pkt, s->screen_width * s->screen_height * 3)) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->stream_index = 0;
memcpy(pkt->data, s->image_buf, s->screen_width * s->screen_height * 3);
diff --git a/contrib/ffmpeg/libavformat/grab.c b/contrib/ffmpeg/libavformat/grab.c
deleted file mode 100644
index 5e778ecc0..000000000
--- a/contrib/ffmpeg/libavformat/grab.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Linux video grab interface
- * Copyright (c) 2000,2001 Fabrice Bellard.
- *
- * 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 "avformat.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#define _LINUX_TIME_H 1
-#include <linux/videodev.h>
-#include <time.h>
-
-typedef struct {
- int fd;
- int frame_format; /* see VIDEO_PALETTE_xxx */
- int use_mmap;
- int width, height;
- int frame_rate;
- int frame_rate_base;
- int64_t time_frame;
- int frame_size;
- struct video_capability video_cap;
- struct video_audio audio_saved;
- uint8_t *video_buf;
- struct video_mbuf gb_buffers;
- struct video_mmap gb_buf;
- int gb_frame;
-
- /* ATI All In Wonder specific stuff */
- /* XXX: remove and merge in libavcodec/imgconvert.c */
- int aiw_enabled;
- int deint;
- int halfw;
- uint8_t *src_mem;
- uint8_t *lum_m4_mem;
-} VideoData;
-
-static int aiw_init(VideoData *s);
-static int aiw_read_picture(VideoData *s, uint8_t *data);
-static int aiw_close(VideoData *s);
-
-static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- VideoData *s = s1->priv_data;
- AVStream *st;
- int width, height;
- int video_fd, frame_size;
- int ret, frame_rate, frame_rate_base;
- int desired_palette, desired_depth;
- struct video_tuner tuner;
- struct video_audio audio;
- struct video_picture pict;
- int j;
-
- if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
- av_log(s1, AV_LOG_ERROR, "Bad capture size (%dx%d) or wrong time base (%d)\n",
- ap->width, ap->height, ap->time_base.den);
-
- return -1;
- }
-
- width = ap->width;
- height = ap->height;
- frame_rate = ap->time_base.den;
- frame_rate_base = ap->time_base.num;
-
- if((unsigned)width > 32767 || (unsigned)height > 32767) {
- av_log(s1, AV_LOG_ERROR, "Capture size is out of range: %dx%d\n",
- width, height);
-
- return -1;
- }
-
- st = av_new_stream(s1, 0);
- if (!st)
- return AVERROR(ENOMEM);
- av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
-
- s->width = width;
- s->height = height;
- s->frame_rate = frame_rate;
- s->frame_rate_base = frame_rate_base;
-
- video_fd = open(s1->filename, O_RDWR);
- if (video_fd < 0) {
- perror(s1->filename);
- goto fail;
- }
-
- if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) {
- perror("VIDIOCGCAP");
- goto fail;
- }
-
- if (!(s->video_cap.type & VID_TYPE_CAPTURE)) {
- av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n");
- goto fail;
- }
-
- desired_palette = -1;
- desired_depth = -1;
- if (ap->pix_fmt == PIX_FMT_YUV420P) {
- desired_palette = VIDEO_PALETTE_YUV420P;
- desired_depth = 12;
- } else if (ap->pix_fmt == PIX_FMT_YUYV422) {
- desired_palette = VIDEO_PALETTE_YUV422;
- desired_depth = 16;
- } else if (ap->pix_fmt == PIX_FMT_BGR24) {
- desired_palette = VIDEO_PALETTE_RGB24;
- desired_depth = 24;
- }
-
- /* set tv standard */
- if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) {
- if (!strcasecmp(ap->standard, "pal"))
- tuner.mode = VIDEO_MODE_PAL;
- else if (!strcasecmp(ap->standard, "secam"))
- tuner.mode = VIDEO_MODE_SECAM;
- else
- tuner.mode = VIDEO_MODE_NTSC;
- ioctl(video_fd, VIDIOCSTUNER, &tuner);
- }
-
- /* unmute audio */
- audio.audio = 0;
- ioctl(video_fd, VIDIOCGAUDIO, &audio);
- memcpy(&s->audio_saved, &audio, sizeof(audio));
- audio.flags &= ~VIDEO_AUDIO_MUTE;
- ioctl(video_fd, VIDIOCSAUDIO, &audio);
-
- ioctl(video_fd, VIDIOCGPICT, &pict);
-#if 0
- printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
- pict.colour,
- pict.hue,
- pict.brightness,
- pict.contrast,
- pict.whiteness);
-#endif
- /* try to choose a suitable video format */
- pict.palette = desired_palette;
- pict.depth= desired_depth;
- if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) {
- pict.palette=VIDEO_PALETTE_YUV420P;
- pict.depth=12;
- ret = ioctl(video_fd, VIDIOCSPICT, &pict);
- if (ret < 0) {
- pict.palette=VIDEO_PALETTE_YUV422;
- pict.depth=16;
- ret = ioctl(video_fd, VIDIOCSPICT, &pict);
- if (ret < 0) {
- pict.palette=VIDEO_PALETTE_RGB24;
- pict.depth=24;
- ret = ioctl(video_fd, VIDIOCSPICT, &pict);
- if (ret < 0) {
- pict.palette=VIDEO_PALETTE_GREY;
- pict.depth=8;
- ret = ioctl(video_fd, VIDIOCSPICT, &pict);
- if (ret < 0)
- goto fail1;
- }
- }
- }
- }
-
- ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers);
- if (ret < 0) {
- /* try to use read based access */
- struct video_window win;
- int val;
-
- win.x = 0;
- win.y = 0;
- win.width = width;
- win.height = height;
- win.chromakey = -1;
- win.flags = 0;
-
- ioctl(video_fd, VIDIOCSWIN, &win);
-
- s->frame_format = pict.palette;
-
- val = 1;
- ioctl(video_fd, VIDIOCCAPTURE, &val);
-
- s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
- s->use_mmap = 0;
-
- /* ATI All In Wonder automatic activation */
- if (!strcmp(s->video_cap.name, "Km")) {
- if (aiw_init(s) < 0)
- goto fail;
- s->aiw_enabled = 1;
- /* force 420P format because convertion from YUV422 to YUV420P
- is done in this driver (ugly) */
- s->frame_format = VIDEO_PALETTE_YUV420P;
- }
- } else {
- s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
- if ((unsigned char*)-1 == s->video_buf) {
- s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_PRIVATE,video_fd,0);
- if ((unsigned char*)-1 == s->video_buf) {
- perror("mmap");
- goto fail;
- }
- }
- s->gb_frame = 0;
- s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
-
- /* start to grab the first frame */
- s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames;
- s->gb_buf.height = height;
- s->gb_buf.width = width;
- s->gb_buf.format = pict.palette;
-
- ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
- if (ret < 0) {
- if (errno != EAGAIN) {
- fail1:
- av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not support suitable format\n");
- } else {
- av_log(s1, AV_LOG_ERROR,"Fatal: grab device does not receive any video signal\n");
- }
- goto fail;
- }
- for (j = 1; j < s->gb_buffers.frames; j++) {
- s->gb_buf.frame = j;
- ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
- }
- s->frame_format = s->gb_buf.format;
- s->use_mmap = 1;
- }
-
- switch(s->frame_format) {
- case VIDEO_PALETTE_YUV420P:
- frame_size = (width * height * 3) / 2;
- st->codec->pix_fmt = PIX_FMT_YUV420P;
- break;
- case VIDEO_PALETTE_YUV422:
- frame_size = width * height * 2;
- st->codec->pix_fmt = PIX_FMT_YUYV422;
- break;
- case VIDEO_PALETTE_RGB24:
- frame_size = width * height * 3;
- st->codec->pix_fmt = PIX_FMT_BGR24; /* NOTE: v4l uses BGR24, not RGB24 ! */
- break;
- case VIDEO_PALETTE_GREY:
- frame_size = width * height * 1;
- st->codec->pix_fmt = PIX_FMT_GRAY8;
- break;
- default:
- goto fail;
- }
- s->fd = video_fd;
- s->frame_size = frame_size;
-
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = CODEC_ID_RAWVIDEO;
- st->codec->width = width;
- st->codec->height = height;
- st->codec->time_base.den = frame_rate;
- st->codec->time_base.num = frame_rate_base;
- st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8;
-
- return 0;
- fail:
- if (video_fd >= 0)
- close(video_fd);
- av_free(st);
- return AVERROR_IO;
-}
-
-static int v4l_mm_read_picture(VideoData *s, uint8_t *buf)
-{
- uint8_t *ptr;
-
- while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 &&
- (errno == EAGAIN || errno == EINTR));
-
- ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame];
- memcpy(buf, ptr, s->frame_size);
-
- /* Setup to capture the next frame */
- s->gb_buf.frame = s->gb_frame;
- if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
- if (errno == EAGAIN)
- av_log(NULL, AV_LOG_ERROR, "Cannot Sync\n");
- else
- perror("VIDIOCMCAPTURE");
- return AVERROR_IO;
- }
-
- /* This is now the grabbing frame */
- s->gb_frame = (s->gb_frame + 1) % s->gb_buffers.frames;
-
- return s->frame_size;
-}
-
-static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- VideoData *s = s1->priv_data;
- int64_t curtime, delay;
- struct timespec ts;
-
- /* Calculate the time of the next frame */
- s->time_frame += INT64_C(1000000);
-
- /* wait based on the frame rate */
- for(;;) {
- curtime = av_gettime();
- delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime;
- if (delay <= 0) {
- if (delay < INT64_C(-1000000) * s->frame_rate_base / s->frame_rate) {
- /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */
- s->time_frame += INT64_C(1000000);
- }
- break;
- }
- ts.tv_sec = delay / 1000000;
- ts.tv_nsec = (delay % 1000000) * 1000;
- nanosleep(&ts, NULL);
- }
-
- if (av_new_packet(pkt, s->frame_size) < 0)
- return AVERROR_IO;
-
- pkt->pts = curtime;
-
- /* read one frame */
- if (s->aiw_enabled) {
- return aiw_read_picture(s, pkt->data);
- } else if (s->use_mmap) {
- return v4l_mm_read_picture(s, pkt->data);
- } else {
- if (read(s->fd, pkt->data, pkt->size) != pkt->size)
- return AVERROR_IO;
- return s->frame_size;
- }
-}
-
-static int grab_read_close(AVFormatContext *s1)
-{
- VideoData *s = s1->priv_data;
-
- if (s->aiw_enabled)
- aiw_close(s);
-
- if (s->use_mmap)
- munmap(s->video_buf, s->gb_buffers.size);
-
- /* mute audio. we must force it because the BTTV driver does not
- return its state correctly */
- s->audio_saved.flags |= VIDEO_AUDIO_MUTE;
- ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved);
-
- close(s->fd);
- return 0;
-}
-
-AVInputFormat video_grab_device_demuxer = {
- "video4linux",
- "video grab",
- sizeof(VideoData),
- NULL,
- grab_read_header,
- grab_read_packet,
- grab_read_close,
- .flags = AVFMT_NOFILE,
-};
-
-/* All in Wonder specific stuff */
-/* XXX: remove and merge in libavcodec/imgconvert.c */
-
-static int aiw_init(VideoData *s)
-{
- int width, height;
-
- width = s->width;
- height = s->height;
-
- if ((width == s->video_cap.maxwidth && height == s->video_cap.maxheight) ||
- (width == s->video_cap.maxwidth && height == s->video_cap.maxheight*2) ||
- (width == s->video_cap.maxwidth/2 && height == s->video_cap.maxheight)) {
-
- s->deint=0;
- s->halfw=0;
- if (height == s->video_cap.maxheight*2) s->deint=1;
- if (width == s->video_cap.maxwidth/2) s->halfw=1;
- } else {
- av_log(NULL, AV_LOG_ERROR, "\nIncorrect Grab Size Supplied - Supported Sizes Are:\n");
- av_log(NULL, AV_LOG_ERROR, " %dx%d %dx%d %dx%d\n\n",
- s->video_cap.maxwidth,s->video_cap.maxheight,
- s->video_cap.maxwidth,s->video_cap.maxheight*2,
- s->video_cap.maxwidth/2,s->video_cap.maxheight);
- goto fail;
- }
-
- if (s->halfw == 0) {
- s->src_mem = av_malloc(s->width*2);
- } else {
- s->src_mem = av_malloc(s->width*4);
- }
- if (!s->src_mem) goto fail;
-
- s->lum_m4_mem = av_malloc(s->width);
- if (!s->lum_m4_mem)
- goto fail;
- return 0;
- fail:
- av_freep(&s->src_mem);
- av_freep(&s->lum_m4_mem);
- return -1;
-}
-
-#ifdef HAVE_MMX
-#include "libavcodec/i386/mmx.h"
-
-#define LINE_WITH_UV \
- movq_m2r(ptr[0],mm0); \
- movq_m2r(ptr[8],mm1); \
- movq_r2r(mm0, mm4); \
- punpcklbw_r2r(mm1,mm0); \
- punpckhbw_r2r(mm1,mm4); \
- movq_r2r(mm0,mm5); \
- punpcklbw_r2r(mm4,mm0); \
- punpckhbw_r2r(mm4,mm5); \
- movq_r2r(mm0,mm1); \
- punpcklbw_r2r(mm5,mm1); \
- movq_r2m(mm1,lum[0]); \
- movq_m2r(ptr[16],mm2); \
- movq_m2r(ptr[24],mm1); \
- movq_r2r(mm2,mm4); \
- punpcklbw_r2r(mm1,mm2); \
- punpckhbw_r2r(mm1,mm4); \
- movq_r2r(mm2,mm3); \
- punpcklbw_r2r(mm4,mm2); \
- punpckhbw_r2r(mm4,mm3); \
- movq_r2r(mm2,mm1); \
- punpcklbw_r2r(mm3,mm1); \
- movq_r2m(mm1,lum[8]); \
- punpckhdq_r2r(mm2,mm0); \
- punpckhdq_r2r(mm3,mm5); \
- movq_r2m(mm0,cb[0]); \
- movq_r2m(mm5,cr[0]);
-
-#define LINE_NO_UV \
- movq_m2r(ptr[0],mm0);\
- movq_m2r(ptr[8],mm1);\
- movq_r2r(mm0, mm4);\
- punpcklbw_r2r(mm1,mm0); \
- punpckhbw_r2r(mm1,mm4);\
- movq_r2r(mm0,mm5);\
- punpcklbw_r2r(mm4,mm0);\
- punpckhbw_r2r(mm4,mm5);\
- movq_r2r(mm0,mm1);\
- punpcklbw_r2r(mm5,mm1);\
- movq_r2m(mm1,lum[0]);\
- movq_m2r(ptr[16],mm2);\
- movq_m2r(ptr[24],mm1);\
- movq_r2r(mm2,mm4);\
- punpcklbw_r2r(mm1,mm2);\
- punpckhbw_r2r(mm1,mm4);\
- movq_r2r(mm2,mm3);\
- punpcklbw_r2r(mm4,mm2);\
- punpckhbw_r2r(mm4,mm3);\
- movq_r2r(mm2,mm1);\
- punpcklbw_r2r(mm3,mm1);\
- movq_r2m(mm1,lum[8]);
-
-#define LINE_WITHUV_AVG \
- movq_m2r(ptr[0], mm0);\
- movq_m2r(ptr[8], mm1);\
- movq_r2r(mm0, mm4);\
- punpcklbw_r2r(mm1,mm0);\
- punpckhbw_r2r(mm1,mm4);\
- movq_r2r(mm0,mm5);\
- punpcklbw_r2r(mm4,mm0);\
- punpckhbw_r2r(mm4,mm5);\
- movq_r2r(mm0,mm1);\
- movq_r2r(mm5,mm2);\
- punpcklbw_r2r(mm7,mm1);\
- punpcklbw_r2r(mm7,mm2);\
- paddw_r2r(mm6,mm1);\
- paddw_r2r(mm2,mm1);\
- psraw_i2r(1,mm1);\
- packuswb_r2r(mm7,mm1);\
- movd_r2m(mm1,lum[0]);\
- movq_m2r(ptr[16],mm2);\
- movq_m2r(ptr[24],mm1);\
- movq_r2r(mm2,mm4);\
- punpcklbw_r2r(mm1,mm2);\
- punpckhbw_r2r(mm1,mm4);\
- movq_r2r(mm2,mm3);\
- punpcklbw_r2r(mm4,mm2);\
- punpckhbw_r2r(mm4,mm3);\
- movq_r2r(mm2,mm1);\
- movq_r2r(mm3,mm4);\
- punpcklbw_r2r(mm7,mm1);\
- punpcklbw_r2r(mm7,mm4);\
- paddw_r2r(mm6,mm1);\
- paddw_r2r(mm4,mm1);\
- psraw_i2r(1,mm1);\
- packuswb_r2r(mm7,mm1);\
- movd_r2m(mm1,lum[4]);\
- punpckhbw_r2r(mm7,mm0);\
- punpckhbw_r2r(mm7,mm2);\
- paddw_r2r(mm6,mm0);\
- paddw_r2r(mm2,mm0);\
- psraw_i2r(1,mm0);\
- packuswb_r2r(mm7,mm0);\
- punpckhbw_r2r(mm7,mm5);\
- punpckhbw_r2r(mm7,mm3);\
- paddw_r2r(mm6,mm5);\
- paddw_r2r(mm3,mm5);\
- psraw_i2r(1,mm5);\
- packuswb_r2r(mm7,mm5);\
- movd_r2m(mm0,cb[0]);\
- movd_r2m(mm5,cr[0]);
-
-#define LINE_NOUV_AVG \
- movq_m2r(ptr[0],mm0);\
- movq_m2r(ptr[8],mm1);\
- pand_r2r(mm5,mm0);\
- pand_r2r(mm5,mm1);\
- pmaddwd_r2r(mm6,mm0);\
- pmaddwd_r2r(mm6,mm1);\
- packssdw_r2r(mm1,mm0);\
- paddw_r2r(mm6,mm0);\
- psraw_i2r(1,mm0);\
- movq_m2r(ptr[16],mm2);\
- movq_m2r(ptr[24],mm3);\
- pand_r2r(mm5,mm2);\
- pand_r2r(mm5,mm3);\
- pmaddwd_r2r(mm6,mm2);\
- pmaddwd_r2r(mm6,mm3);\
- packssdw_r2r(mm3,mm2);\
- paddw_r2r(mm6,mm2);\
- psraw_i2r(1,mm2);\
- packuswb_r2r(mm2,mm0);\
- movq_r2m(mm0,lum[0]);
-
-#define DEINT_LINE_LUM(ptroff) \
- movd_m2r(lum_m4[(ptroff)],mm0);\
- movd_m2r(lum_m3[(ptroff)],mm1);\
- movd_m2r(lum_m2[(ptroff)],mm2);\
- movd_m2r(lum_m1[(ptroff)],mm3);\
- movd_m2r(lum[(ptroff)],mm4);\
- punpcklbw_r2r(mm7,mm0);\
- movd_r2m(mm2,lum_m4[(ptroff)]);\
- punpcklbw_r2r(mm7,mm1);\
- punpcklbw_r2r(mm7,mm2);\
- punpcklbw_r2r(mm7,mm3);\
- punpcklbw_r2r(mm7,mm4);\
- psllw_i2r(2,mm1);\
- psllw_i2r(1,mm2);\
- paddw_r2r(mm6,mm1);\
- psllw_i2r(2,mm3);\
- paddw_r2r(mm2,mm1);\
- paddw_r2r(mm4,mm0);\
- paddw_r2r(mm3,mm1);\
- psubusw_r2r(mm0,mm1);\
- psrlw_i2r(3,mm1);\
- packuswb_r2r(mm7,mm1);\
- movd_r2m(mm1,lum_m2[(ptroff)]);
-
-#else
-#include "libavcodec/dsputil.h"
-
-#define LINE_WITH_UV \
- lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
- cb[0]=ptr[1];cb[1]=ptr[5];\
- cr[0]=ptr[3];cr[1]=ptr[7];\
- lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
- cb[2]=ptr[9];cb[3]=ptr[13];\
- cr[2]=ptr[11];cr[3]=ptr[15];\
- lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
- cb[4]=ptr[17];cb[5]=ptr[21];\
- cr[4]=ptr[19];cr[5]=ptr[23];\
- lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];\
- cb[6]=ptr[25];cb[7]=ptr[29];\
- cr[6]=ptr[27];cr[7]=ptr[31];
-
-#define LINE_NO_UV \
- lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
- lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
- lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
- lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];
-
-#define LINE_WITHUV_AVG \
- sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
- sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
- sum=(ptr[1]+ptr[5]+1) >> 1;cb[0]=sum; \
- sum=(ptr[3]+ptr[7]+1) >> 1;cr[0]=sum; \
- sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
- sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
- sum=(ptr[9]+ptr[13]+1) >> 1;cb[1]=sum; \
- sum=(ptr[11]+ptr[15]+1) >> 1;cr[1]=sum; \
- sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
- sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
- sum=(ptr[17]+ptr[21]+1) >> 1;cb[2]=sum; \
- sum=(ptr[19]+ptr[23]+1) >> 1;cr[2]=sum; \
- sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
- sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum; \
- sum=(ptr[25]+ptr[29]+1) >> 1;cb[3]=sum; \
- sum=(ptr[27]+ptr[31]+1) >> 1;cr[3]=sum;
-
-#define LINE_NOUV_AVG \
- sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
- sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
- sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
- sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
- sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
- sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
- sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
- sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum;
-
-#define DEINT_LINE_LUM(ptroff) \
- sum=(-lum_m4[(ptroff)]+(lum_m3[(ptroff)]<<2)+(lum_m2[(ptroff)]<<1)+(lum_m1[(ptroff)]<<2)-lum[(ptroff)]); \
- lum_m4[(ptroff)]=lum_m2[(ptroff)];\
- lum_m2[(ptroff)]=cm[(sum+4)>>3];\
- sum=(-lum_m4[(ptroff)+1]+(lum_m3[(ptroff)+1]<<2)+(lum_m2[(ptroff)+1]<<1)+(lum_m1[(ptroff)+1]<<2)-lum[(ptroff)+1]); \
- lum_m4[(ptroff)+1]=lum_m2[(ptroff)+1];\
- lum_m2[(ptroff)+1]=cm[(sum+4)>>3];\
- sum=(-lum_m4[(ptroff)+2]+(lum_m3[(ptroff)+2]<<2)+(lum_m2[(ptroff)+2]<<1)+(lum_m1[(ptroff)+2]<<2)-lum[(ptroff)+2]); \
- lum_m4[(ptroff)+2]=lum_m2[(ptroff)+2];\
- lum_m2[(ptroff)+2]=cm[(sum+4)>>3];\
- sum=(-lum_m4[(ptroff)+3]+(lum_m3[(ptroff)+3]<<2)+(lum_m2[(ptroff)+3]<<1)+(lum_m1[(ptroff)+3]<<2)-lum[(ptroff)+3]); \
- lum_m4[(ptroff)+3]=lum_m2[(ptroff)+3];\
- lum_m2[(ptroff)+3]=cm[(sum+4)>>3];
-
-#endif
-
-
-/* Read two fields separately. */
-static int aiw_read_picture(VideoData *s, uint8_t *data)
-{
- uint8_t *ptr, *lum, *cb, *cr;
- int h;
-#ifndef HAVE_MMX
- int sum;
-#endif
- uint8_t* src = s->src_mem;
- uint8_t *ptrend = &src[s->width*2];
- lum=data;
- cb=&lum[s->width*s->height];
- cr=&cb[(s->width*s->height)/4];
- if (s->deint == 0 && s->halfw == 0) {
- while (read(s->fd,src,s->width*2) < 0) {
- usleep(100);
- }
- for (h = 0; h < s->height-2; h+=2) {
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- read(s->fd,src,s->width*2);
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
- LINE_NO_UV
- }
- read(s->fd,src,s->width*2);
- }
- /*
- * Do last two lines
- */
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- read(s->fd,src,s->width*2);
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
- LINE_NO_UV
- }
- /* drop second field */
- while (read(s->fd,src,s->width*2) < 0) {
- usleep(100);
- }
- for (h = 0; h < s->height - 1; h++) {
- read(s->fd,src,s->width*2);
- }
- } else if (s->halfw == 1) {
-#ifdef HAVE_MMX
- mmx_t rounder;
- mmx_t masker;
- rounder.uw[0]=1;
- rounder.uw[1]=1;
- rounder.uw[2]=1;
- rounder.uw[3]=1;
- masker.ub[0]=0xff;
- masker.ub[1]=0;
- masker.ub[2]=0xff;
- masker.ub[3]=0;
- masker.ub[4]=0xff;
- masker.ub[5]=0;
- masker.ub[6]=0xff;
- masker.ub[7]=0;
- pxor_r2r(mm7,mm7);
- movq_m2r(rounder,mm6);
-#endif
- while (read(s->fd,src,s->width*4) < 0) {
- usleep(100);
- }
- ptrend = &src[s->width*4];
- for (h = 0; h < s->height-2; h+=2) {
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
- LINE_WITHUV_AVG
- }
- read(s->fd,src,s->width*4);
-#ifdef HAVE_MMX
- movq_m2r(masker,mm5);
-#endif
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
- LINE_NOUV_AVG
- }
- read(s->fd,src,s->width*4);
- }
- /*
- * Do last two lines
- */
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
- LINE_WITHUV_AVG
- }
- read(s->fd,src,s->width*4);
-#ifdef HAVE_MMX
- movq_m2r(masker,mm5);
-#endif
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
- LINE_NOUV_AVG
- }
- /* drop second field */
- while (read(s->fd,src,s->width*4) < 0) {
- usleep(100);
- }
- for (h = 0; h < s->height - 1; h++) {
- read(s->fd,src,s->width*4);
- }
- } else {
- uint8_t *lum_m1, *lum_m2, *lum_m3, *lum_m4;
-#ifdef HAVE_MMX
- mmx_t rounder;
- rounder.uw[0]=4;
- rounder.uw[1]=4;
- rounder.uw[2]=4;
- rounder.uw[3]=4;
- movq_m2r(rounder,mm6);
- pxor_r2r(mm7,mm7);
-#else
- uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
-#endif
-
- /* read two fields and deinterlace them */
- while (read(s->fd,src,s->width*2) < 0) {
- usleep(100);
- }
- for (h = 0; h < (s->height/2)-2; h+=2) {
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- read(s->fd,src,s->width*2);
- /* skip a luminance line - will be filled in later */
- lum += s->width;
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- /* skip a luminance line - will be filled in later */
- lum += s->width;
- read(s->fd,src,s->width*2);
- }
- /*
- * Do last two lines
- */
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- /* skip a luminance line - will be filled in later */
- lum += s->width;
- read(s->fd,src,s->width*2);
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
- LINE_WITH_UV
- }
- /*
- *
- * SECOND FIELD
- *
- */
- lum=&data[s->width];
- while (read(s->fd,src,s->width*2) < 0) {
- usleep(10);
- }
- /* First (and last) two lines not interlaced */
- for (h = 0; h < 2; h++) {
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
- LINE_NO_UV
- }
- read(s->fd,src,s->width*2);
- /* skip a luminance line */
- lum += s->width;
- }
- lum_m1=&lum[-s->width];
- lum_m2=&lum_m1[-s->width];
- lum_m3=&lum_m2[-s->width];
- memmove(s->lum_m4_mem,&lum_m3[-s->width],s->width);
- for (; h < (s->height/2)-1; h++) {
- lum_m4=s->lum_m4_mem;
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16,lum_m1+=16,lum_m2+=16,lum_m3+=16,lum_m4+=16) {
- LINE_NO_UV
-
- DEINT_LINE_LUM(0)
- DEINT_LINE_LUM(4)
- DEINT_LINE_LUM(8)
- DEINT_LINE_LUM(12)
- }
- read(s->fd,src,s->width*2);
- /* skip a luminance line */
- lum += s->width;
- lum_m1 += s->width;
- lum_m2 += s->width;
- lum_m3 += s->width;
- // lum_m4 += s->width;
- }
- /*
- * Do last line
- */
- lum_m4=s->lum_m4_mem;
- for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, lum_m1+=16, lum_m2+=16, lum_m3+=16, lum_m4+=16) {
- LINE_NO_UV
-
- DEINT_LINE_LUM(0)
- DEINT_LINE_LUM(4)
- DEINT_LINE_LUM(8)
- DEINT_LINE_LUM(12)
- }
- }
-#ifdef HAVE_MMX
- emms();
-#endif
- return s->frame_size;
-}
-
-static int aiw_close(VideoData *s)
-{
- av_freep(&s->lum_m4_mem);
- av_freep(&s->src_mem);
- return 0;
-}
diff --git a/contrib/ffmpeg/libavformat/grab_bktr.c b/contrib/ffmpeg/libavformat/grab_bktr.c
deleted file mode 100644
index 100653db7..000000000
--- a/contrib/ffmpeg/libavformat/grab_bktr.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * *BSD video grab interface
- * Copyright (c) 2002 Steve O'Hara-Smith
- * based on
- * Linux video grab interface
- * Copyright (c) 2000,2001 Gerard Lantau.
- * and
- * simple_grab.c Copyright (c) 1999 Roger Hardiman
- *
- * 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 "avformat.h"
-#if defined (HAVE_DEV_BKTR_IOCTL_METEOR_H) && defined (HAVE_DEV_BKTR_IOCTL_BT848_H)
-# include <dev/bktr/ioctl_meteor.h>
-# include <dev/bktr/ioctl_bt848.h>
-#elif defined (HAVE_MACHINE_IOCTL_METEOR_H) && defined (HAVE_MACHINE_IOCTL_BT848_H)
-# include <machine/ioctl_meteor.h>
-# include <machine/ioctl_bt848.h>
-#elif defined (HAVE_DEV_VIDEO_METEOR_IOCTL_METEOR_H) && defined (HAVE_DEV_VIDEO_METEOR_IOCTL_BT848_H)
-# include <dev/video/meteor/ioctl_meteor.h>
-# include <dev/video/bktr/ioctl_bt848.h>
-#elif HAVE_DEV_IC_BT8XX_H
-# include <dev/ic/bt8xx.h>
-#endif
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <signal.h>
-
-typedef struct {
- int video_fd;
- int tuner_fd;
- int width, height;
- int frame_rate;
- int frame_rate_base;
- u_int64_t per_frame;
-} VideoData;
-
-
-#define PAL 1
-#define PALBDGHI 1
-#define NTSC 2
-#define NTSCM 2
-#define SECAM 3
-#define PALN 4
-#define PALM 5
-#define NTSCJ 6
-
-/* PAL is 768 x 576. NTSC is 640 x 480 */
-#define PAL_HEIGHT 576
-#define SECAM_HEIGHT 576
-#define NTSC_HEIGHT 480
-
-#ifndef VIDEO_FORMAT
-#define VIDEO_FORMAT NTSC
-#endif
-
-static int bktr_dev[] = { METEOR_DEV0, METEOR_DEV1, METEOR_DEV2,
- METEOR_DEV3, METEOR_DEV_SVIDEO };
-
-uint8_t *video_buf;
-size_t video_buf_size;
-u_int64_t last_frame_time;
-volatile sig_atomic_t nsignals;
-
-
-static void catchsignal(int signal)
-{
- nsignals++;
- return;
-}
-
-static int bktr_init(const char *video_device, int width, int height,
- int format, int *video_fd, int *tuner_fd, int idev, double frequency)
-{
- struct meteor_geomet geo;
- int h_max;
- long ioctl_frequency;
- char *arg;
- int c;
- struct sigaction act, old;
-
- if (idev < 0 || idev > 4)
- {
- arg = getenv ("BKTR_DEV");
- if (arg)
- idev = atoi (arg);
- if (idev < 0 || idev > 4)
- idev = 1;
- }
-
- if (format < 1 || format > 6)
- {
- arg = getenv ("BKTR_FORMAT");
- if (arg)
- format = atoi (arg);
- if (format < 1 || format > 6)
- format = VIDEO_FORMAT;
- }
-
- if (frequency <= 0)
- {
- arg = getenv ("BKTR_FREQUENCY");
- if (arg)
- frequency = atof (arg);
- if (frequency <= 0)
- frequency = 0.0;
- }
-
- memset(&act, 0, sizeof(act));
- sigemptyset(&act.sa_mask);
- act.sa_handler = catchsignal;
- sigaction(SIGUSR1, &act, &old);
-
- *tuner_fd = open("/dev/tuner0", O_RDONLY);
- if (*tuner_fd < 0)
- perror("Warning: Tuner not opened, continuing");
-
- *video_fd = open(video_device, O_RDONLY);
- if (*video_fd < 0) {
- perror(video_device);
- return -1;
- }
-
- geo.rows = height;
- geo.columns = width;
- geo.frames = 1;
- geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12;
-
- switch (format) {
- case PAL: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
- case PALN: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALN; break;
- case PALM: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALM; break;
- case SECAM: h_max = SECAM_HEIGHT; c = BT848_IFORM_F_SECAM; break;
- case NTSC: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCM; break;
- case NTSCJ: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCJ; break;
- default: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
- }
-
- if (height <= h_max / 2)
- geo.oformat |= METEOR_GEO_EVEN_ONLY;
-
- if (ioctl(*video_fd, METEORSETGEO, &geo) < 0) {
- perror("METEORSETGEO");
- return -1;
- }
-
- if (ioctl(*video_fd, BT848SFMT, &c) < 0) {
- perror("BT848SFMT");
- return -1;
- }
-
- c = bktr_dev[idev];
- if (ioctl(*video_fd, METEORSINPUT, &c) < 0) {
- perror("METEORSINPUT");
- return -1;
- }
-
- video_buf_size = width * height * 12 / 8;
-
- video_buf = (uint8_t *)mmap((caddr_t)0, video_buf_size,
- PROT_READ, MAP_SHARED, *video_fd, (off_t)0);
- if (video_buf == MAP_FAILED) {
- perror("mmap");
- return -1;
- }
-
- if (frequency != 0.0) {
- ioctl_frequency = (unsigned long)(frequency*16);
- if (ioctl(*tuner_fd, TVTUNER_SETFREQ, &ioctl_frequency) < 0)
- perror("TVTUNER_SETFREQ");
- }
-
- c = AUDIO_UNMUTE;
- if (ioctl(*tuner_fd, BT848_SAUDIO, &c) < 0)
- perror("TVTUNER_SAUDIO");
-
- c = METEOR_CAP_CONTINOUS;
- ioctl(*video_fd, METEORCAPTUR, &c);
-
- c = SIGUSR1;
- ioctl(*video_fd, METEORSSIGNAL, &c);
-
- return 0;
-}
-
-static void bktr_getframe(u_int64_t per_frame)
-{
- u_int64_t curtime;
-
- curtime = av_gettime();
- if (!last_frame_time
- || ((last_frame_time + per_frame) > curtime)) {
- if (!usleep(last_frame_time + per_frame + per_frame / 8 - curtime)) {
- if (!nsignals)
- av_log(NULL, AV_LOG_INFO,
- "SLEPT NO signals - %d microseconds late\n",
- (int)(av_gettime() - last_frame_time - per_frame));
- }
- }
- nsignals = 0;
- last_frame_time = curtime;
-}
-
-
-/* note: we support only one picture read at a time */
-static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- VideoData *s = s1->priv_data;
-
- if (av_new_packet(pkt, video_buf_size) < 0)
- return AVERROR(EIO);
-
- bktr_getframe(s->per_frame);
-
- pkt->pts = av_gettime();
- memcpy(pkt->data, video_buf, video_buf_size);
-
- return video_buf_size;
-}
-
-static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- VideoData *s = s1->priv_data;
- AVStream *st;
- int width, height;
- int frame_rate;
- int frame_rate_base;
- int format = -1;
-
- if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0)
- return -1;
-
- width = ap->width;
- height = ap->height;
- frame_rate = ap->time_base.den;
- frame_rate_base = ap->time_base.num;
-
- st = av_new_stream(s1, 0);
- if (!st)
- return AVERROR(ENOMEM);
- av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in use */
-
- s->width = width;
- s->height = height;
- s->frame_rate = frame_rate;
- s->frame_rate_base = frame_rate_base;
- s->per_frame = ((u_int64_t)1000000 * s->frame_rate_base) / s->frame_rate;
-
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->pix_fmt = PIX_FMT_YUV420P;
- st->codec->codec_id = CODEC_ID_RAWVIDEO;
- st->codec->width = width;
- st->codec->height = height;
- st->codec->time_base.den = frame_rate;
- st->codec->time_base.num = frame_rate_base;
-
- if (ap->standard) {
- if (!strcasecmp(ap->standard, "pal"))
- format = PAL;
- else if (!strcasecmp(ap->standard, "secam"))
- format = SECAM;
- else if (!strcasecmp(ap->standard, "ntsc"))
- format = NTSC;
- }
-
- if (bktr_init(s1->filename, width, height, format,
- &(s->video_fd), &(s->tuner_fd), -1, 0.0) < 0)
- return AVERROR(EIO);
-
- nsignals = 0;
- last_frame_time = 0;
-
- return 0;
-}
-
-static int grab_read_close(AVFormatContext *s1)
-{
- VideoData *s = s1->priv_data;
- int c;
-
- c = METEOR_CAP_STOP_CONT;
- ioctl(s->video_fd, METEORCAPTUR, &c);
- close(s->video_fd);
-
- c = AUDIO_MUTE;
- ioctl(s->tuner_fd, BT848_SAUDIO, &c);
- close(s->tuner_fd);
-
- munmap((caddr_t)video_buf, video_buf_size);
-
- return 0;
-}
-
-AVInputFormat video_grab_device_demuxer = {
- "bktr",
- "video grab",
- sizeof(VideoData),
- NULL,
- grab_read_header,
- grab_read_packet,
- grab_read_close,
- .flags = AVFMT_NOFILE,
-};
diff --git a/contrib/ffmpeg/libavformat/gxf.c b/contrib/ffmpeg/libavformat/gxf.c
index ba2463ead..d4bf6f43b 100644
--- a/contrib/ffmpeg/libavformat/gxf.c
+++ b/contrib/ffmpeg/libavformat/gxf.c
@@ -20,33 +20,7 @@
*/
#include "avformat.h"
#include "common.h"
-
-typedef enum {
- PKT_MAP = 0xbc,
- PKT_MEDIA = 0xbf,
- PKT_EOS = 0xfb,
- PKT_FLT = 0xfc,
- PKT_UMF = 0xfd
-} pkt_type_t;
-
-typedef enum {
- MAT_NAME = 0x40,
- MAT_FIRST_FIELD = 0x41,
- MAT_LAST_FIELD = 0x42,
- MAT_MARK_IN = 0x43,
- MAT_MARK_OUT = 0x44,
- MAT_SIZE = 0x45
-} mat_tag_t;
-
-typedef enum {
- TRACK_NAME = 0x4c,
- TRACK_AUX = 0x4d,
- TRACK_VER = 0x4e,
- TRACK_MPG_AUX = 0x4f,
- TRACK_FPS = 0x50,
- TRACK_LINES = 0x51,
- TRACK_FPF = 0x52
-} track_tag_t;
+#include "gxf.h"
typedef struct {
int64_t first_field;
@@ -87,8 +61,6 @@ static int parse_packet_header(ByteIOContext *pb, pkt_type_t *type, int *length)
static int gxf_probe(AVProbeData *p) {
static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
- if (p->buf_size < 16)
- return 0;
if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
!memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
return AVPROBE_SCORE_MAX;
@@ -130,13 +102,13 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
case 20:
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
- st->need_parsing = 2; // get keyframe flag etc.
+ st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
break;
case 22:
case 23:
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_MPEG1VIDEO;
- st->need_parsing = 2; // get keyframe flag etc.
+ st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
break;
case 9:
st->codec->codec_type = CODEC_TYPE_AUDIO;
@@ -179,7 +151,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
/**
* \brief filters out interesting tags from material information.
- * \param len lenght of tag section, will be adjusted to contain remaining bytes
+ * \param len length of tag section, will be adjusted to contain remaining bytes
* \param si struct to store collected information into
*/
static void gxf_material_tags(ByteIOContext *pb, int *len, st_info_t *si) {
@@ -256,7 +228,7 @@ static void gxf_track_tags(ByteIOContext *pb, int *len, st_info_t *si) {
* \brief read index from FLT packet into stream 0 av_index
*/
static void gxf_read_index(AVFormatContext *s, int pkt_len) {
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st = s->streams[0];
uint32_t fields_per_map = get_le32(pb);
uint32_t map_cnt = get_le32(pb);
@@ -280,7 +252,7 @@ static void gxf_read_index(AVFormatContext *s, int pkt_len) {
}
static int gxf_header(AVFormatContext *s, AVFormatParameters *ap) {
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
pkt_type_t pkt_type;
int map_len;
int len;
@@ -406,7 +378,7 @@ static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int t
int cur_track;
int64_t cur_timestamp = AV_NOPTS_VALUE;
int len;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
pkt_type_t type;
tmp = get_be32(pb);
start:
@@ -436,7 +408,7 @@ out:
}
static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
pkt_type_t pkt_type;
int pkt_len;
while (!url_feof(pb)) {
@@ -475,7 +447,7 @@ static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
pkt->dts = field_nr;
return ret;
}
- return AVERROR_IO;
+ return AVERROR(EIO);
}
static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
@@ -494,7 +466,7 @@ static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int
if (idx < st->nb_index_entries - 2)
maxlen = st->index_entries[idx + 2].pos - pos;
maxlen = FFMAX(maxlen, 200 * 1024);
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
found = gxf_resync_media(s, maxlen, -1, timestamp);
if (FFABS(found - timestamp) > 4)
return -1;
@@ -503,7 +475,7 @@ static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int
static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
int64_t *pos, int64_t pos_limit) {
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int64_t res;
url_fseek(pb, *pos, SEEK_SET);
res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
diff --git a/contrib/ffmpeg/libavformat/gxf.h b/contrib/ffmpeg/libavformat/gxf.h
index 0e2a31ca4..ab37cb97f 100644
--- a/contrib/ffmpeg/libavformat/gxf.h
+++ b/contrib/ffmpeg/libavformat/gxf.h
@@ -24,11 +24,30 @@
/* gxf.c */
typedef enum {
- PKT_MAP = 0xbc,
- PKT_MEDIA = 0xbf,
- PKT_EOS = 0xfb,
- PKT_FLT = 0xfc,
- PKT_UMF = 0xfd
+ PKT_MAP = 0xbc,
+ PKT_MEDIA = 0xbf,
+ PKT_EOS = 0xfb,
+ PKT_FLT = 0xfc,
+ PKT_UMF = 0xfd,
} pkt_type_t;
+typedef enum {
+ MAT_NAME = 0x40,
+ MAT_FIRST_FIELD = 0x41,
+ MAT_LAST_FIELD = 0x42,
+ MAT_MARK_IN = 0x43,
+ MAT_MARK_OUT = 0x44,
+ MAT_SIZE = 0x45,
+} mat_tag_t;
+
+typedef enum {
+ TRACK_NAME = 0x4c,
+ TRACK_AUX = 0x4d,
+ TRACK_VER = 0x4e,
+ TRACK_MPG_AUX = 0x4f,
+ TRACK_FPS = 0x50,
+ TRACK_LINES = 0x51,
+ TRACK_FPF = 0x52,
+} track_tag_t;
+
#endif /* FFMPEG_GXF_H */
diff --git a/contrib/ffmpeg/libavformat/gxfenc.c b/contrib/ffmpeg/libavformat/gxfenc.c
index 39b9ed3e1..469105de5 100644
--- a/contrib/ffmpeg/libavformat/gxfenc.c
+++ b/contrib/ffmpeg/libavformat/gxfenc.c
@@ -4,18 +4,18 @@
*
* This file is part of FFmpeg.
*
- * FFmpeg is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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 General Public License for more details.
+ * 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 General Public License
- * along with FFmpeg; if not, write to the Free Software
+ * 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
*/
@@ -187,7 +187,7 @@ static int gxf_write_mpeg_auxiliary(ByteIOContext *pb, GXFStreamContext *ctx)
(float)ctx->codec->bit_rate, ctx->p_per_gop, ctx->b_per_gop,
ctx->codec->pix_fmt == PIX_FMT_YUV422P ? 2 : 1, ctx->first_gop_closed == 1,
ctx->codec->height / 16);
- put_byte(pb, 0x4F);
+ put_byte(pb, TRACK_MPG_AUX);
put_byte(pb, size + 1);
put_buffer(pb, (uint8_t *)buffer, size + 1);
return size + 3;
@@ -217,7 +217,7 @@ static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stre
put_be16(pb, 0); /* size */
/* media file name */
- put_byte(pb, 0x4C);
+ put_byte(pb, TRACK_NAME);
put_byte(pb, strlen(ES_NAME_PATTERN) + 3);
put_tag(pb, ES_NAME_PATTERN);
put_be16(pb, stream->media_info);
@@ -225,7 +225,7 @@ static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stre
if (stream->codec->codec_id != CODEC_ID_MPEG2VIDEO) {
/* auxiliary information */
- put_byte(pb, 0x4D);
+ put_byte(pb, TRACK_AUX);
put_byte(pb, 8);
if (stream->codec->codec_id == CODEC_ID_NONE)
gxf_write_timecode_auxiliary(pb, stream);
@@ -234,7 +234,7 @@ static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stre
}
/* file system version */
- put_byte(pb, 0x4E);
+ put_byte(pb, TRACK_VER);
put_byte(pb, 4);
put_be32(pb, 0);
@@ -242,17 +242,17 @@ static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stre
gxf_write_mpeg_auxiliary(pb, stream);
/* frame rate */
- put_byte(pb, 0x50);
+ put_byte(pb, TRACK_FPS);
put_byte(pb, 4);
put_be32(pb, stream->frame_rate_index);
/* lines per frame */
- put_byte(pb, 0x51);
+ put_byte(pb, TRACK_LINES);
put_byte(pb, 4);
put_be32(pb, stream->lines_index);
/* fields per frame */
- put_byte(pb, 0x52);
+ put_byte(pb, TRACK_FPF);
put_byte(pb, 4);
put_be32(pb, stream->fields);
@@ -272,33 +272,33 @@ static int gxf_write_material_data_section(ByteIOContext *pb, GXFContext *ctx)
filename++;
else
filename = ctx->fc->filename;
- put_byte(pb, 0x40);
+ put_byte(pb, MAT_NAME);
put_byte(pb, strlen(SERVER_PATH) + strlen(filename) + 1);
put_tag(pb, SERVER_PATH);
put_tag(pb, filename);
put_byte(pb, 0);
/* first field */
- put_byte(pb, 0x41);
+ put_byte(pb, MAT_FIRST_FIELD);
put_byte(pb, 4);
put_be32(pb, 0);
/* last field */
- put_byte(pb, 0x42);
+ put_byte(pb, MAT_LAST_FIELD);
put_byte(pb, 4);
put_be32(pb, ctx->nb_frames);
/* reserved */
- put_byte(pb, 0x43);
+ put_byte(pb, MAT_MARK_IN);
put_byte(pb, 4);
put_be32(pb, 0);
- put_byte(pb, 0x44);
+ put_byte(pb, MAT_MARK_OUT);
put_byte(pb, 4);
put_be32(pb, ctx->nb_frames);
/* estimated size */
- put_byte(pb, 0x45);
+ put_byte(pb, MAT_SIZE);
put_byte(pb, 4);
put_be32(pb, url_fsize(pb) / 1024);
@@ -576,7 +576,7 @@ static int gxf_write_umf_packet(ByteIOContext *pb, GXFContext *ctx)
static int gxf_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
GXFContext *gxf = s->priv_data;
int i;
@@ -671,7 +671,7 @@ static int gxf_write_eos_packet(ByteIOContext *pb, GXFContext *ctx)
static int gxf_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
GXFContext *gxf = s->priv_data;
offset_t end;
int i;
@@ -679,9 +679,9 @@ static int gxf_write_trailer(AVFormatContext *s)
for (i = 0; i < s->nb_streams; ++i) {
if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
av_fifo_free(&gxf->streams[i].audio_buffer);
- }
- if (s->streams[i]->codec->frame_number > gxf->nb_frames)
+ } else if (s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
gxf->nb_frames = 2 * s->streams[i]->codec->frame_number;
+ }
}
gxf_write_eos_packet(pb, gxf);
@@ -710,7 +710,7 @@ static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int si
static int gxf_write_media_preamble(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt, int size)
{
GXFStreamContext *sc = &ctx->streams[pkt->stream_index];
- int64_t dts = av_rescale(pkt->dts, ctx->sample_rate, sc->codec->time_base.den);
+ int64_t dts = av_rescale_rnd(pkt->dts, ctx->sample_rate, sc->codec->time_base.den, AV_ROUND_UP);
put_byte(pb, sc->media_type);
put_byte(pb, sc->index);
@@ -763,8 +763,8 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
{
GXFContext *gxf = s->priv_data;
- gxf_write_media_packet(&s->pb, gxf, pkt);
- put_flush_packet(&s->pb);
+ gxf_write_media_packet(s->pb, gxf, pkt);
+ put_flush_packet(s->pb);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/http.c b/contrib/ffmpeg/libavformat/http.c
index e057d6efe..1d542061b 100644
--- a/contrib/ffmpeg/libavformat/http.c
+++ b/contrib/ffmpeg/libavformat/http.c
@@ -21,11 +21,13 @@
#include "avformat.h"
#include <unistd.h>
#include "network.h"
+#include "os_support.h"
#include "base64.h"
+#include "avstring.h"
-/* XXX: POST protocol is not completly implemented because ffmpeg use
- only a subset of it */
+/* XXX: POST protocol is not completely implemented because ffmpeg uses
+ only a subset of it. */
//#define DEBUG
@@ -62,7 +64,7 @@ static int http_open_cnx(URLContext *h)
proxy_path = getenv("http_proxy");
use_proxy = (proxy_path != NULL) && !getenv("no_proxy") &&
- strstart(proxy_path, "http://", NULL);
+ av_strstart(proxy_path, "http://", NULL);
/* fill the dest addr */
redo:
@@ -72,7 +74,7 @@ static int http_open_cnx(URLContext *h)
if (port > 0) {
snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port);
} else {
- pstrcpy(hoststr, sizeof(hoststr), hostname);
+ av_strlcpy(hoststr, hostname, sizeof(hoststr));
}
if (use_proxy) {
@@ -100,7 +102,7 @@ static int http_open_cnx(URLContext *h)
/* url moved, get next */
url_close(hd);
if (redirects++ >= MAX_REDIRECTS)
- return AVERROR_IO;
+ return AVERROR(EIO);
location_changed = 0;
goto redo;
}
@@ -108,7 +110,7 @@ static int http_open_cnx(URLContext *h)
fail:
if (hd)
url_close(hd);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
static int http_open(URLContext *h, const char *uri, int flags)
@@ -125,7 +127,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
h->priv_data = s;
s->filesize = -1;
s->off = 0;
- pstrcpy (s->location, URL_SIZE, uri);
+ av_strlcpy(s->location, uri, URL_SIZE);
ret = http_open_cnx(h);
if (ret != 0)
@@ -138,7 +140,7 @@ static int http_getc(HTTPContext *s)
if (s->buf_ptr >= s->buf_end) {
len = url_read(s->hd, s->buffer, BUFFER_SIZE);
if (len < 0) {
- return AVERROR_IO;
+ return AVERROR(EIO);
} else if (len == 0) {
return -1;
} else {
@@ -217,7 +219,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr,
/* send http header */
post = h->flags & URL_WRONLY;
auth_b64 = av_malloc(auth_b64_len);
- av_base64_encode(auth_b64, auth_b64_len, (uint8_t *)auth, strlen(auth));
+ av_base64_encode(auth_b64, auth_b64_len, auth, strlen(auth));
snprintf(s->buffer, sizeof(s->buffer),
"%s %s HTTP/1.1\r\n"
"User-Agent: %s\r\n"
@@ -236,7 +238,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr,
av_freep(&auth_b64);
if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* init input buffer */
s->buf_ptr = s->buffer;
@@ -245,7 +247,6 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr,
s->off = 0;
s->filesize = -1;
if (post) {
- sleep(1);
return 0;
}
@@ -254,7 +255,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr,
for(;;) {
ch = http_getc(s);
if (ch < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (ch == '\n') {
/* process line */
if (q > line && q[-1] == '\r')
diff --git a/contrib/ffmpeg/libavformat/idcin.c b/contrib/ffmpeg/libavformat/idcin.c
index e2c92f3b4..914a3532a 100644
--- a/contrib/ffmpeg/libavformat/idcin.c
+++ b/contrib/ffmpeg/libavformat/idcin.c
@@ -71,7 +71,7 @@
#include "avformat.h"
#define HUFFMAN_TABLE_SIZE (64 * 1024)
-#define FRAME_PTS_INC (90000 / 14)
+#define IDCIN_FPS 14
typedef struct IdcinDemuxContext {
int video_stream_index;
@@ -104,10 +104,6 @@ static int idcin_probe(AVProbeData *p)
* audio channels: 0 for no audio, or 1 or 2
*/
- /* cannot proceed without 20 bytes */
- if (p->buf_size < 20)
- return 0;
-
/* check the video width */
number = AV_RL32(&p->buf[0]);
if ((number == 0) || (number > 1024))
@@ -140,8 +136,8 @@ static int idcin_probe(AVProbeData *p)
static int idcin_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
- IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data;
+ ByteIOContext *pb = s->pb;
+ IdcinDemuxContext *idcin = s->priv_data;
AVStream *st;
unsigned int width, height;
unsigned int sample_rate, bytes_per_sample, channels;
@@ -155,8 +151,8 @@ static int idcin_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
- av_set_pts_info(st, 33, 1, 90000);
+ return AVERROR(ENOMEM);
+ av_set_pts_info(st, 33, 1, IDCIN_FPS);
idcin->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_IDCIN;
@@ -169,7 +165,7 @@ static int idcin_read_header(AVFormatContext *s,
st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE);
if (get_buffer(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) !=
HUFFMAN_TABLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* save a reference in order to transport the palette */
st->codec->palctrl = &idcin->palctrl;
@@ -178,8 +174,8 @@ static int idcin_read_header(AVFormatContext *s,
idcin->audio_present = 1;
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
- av_set_pts_info(st, 33, 1, 90000);
+ return AVERROR(ENOMEM);
+ av_set_pts_info(st, 33, 1, IDCIN_FPS);
idcin->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_tag = 1;
@@ -218,25 +214,25 @@ static int idcin_read_packet(AVFormatContext *s,
int ret;
unsigned int command;
unsigned int chunk_size;
- IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ IdcinDemuxContext *idcin = s->priv_data;
+ ByteIOContext *pb = s->pb;
int i;
int palette_scale;
unsigned char r, g, b;
unsigned char palette_buffer[768];
- if (url_feof(&s->pb))
- return AVERROR_IO;
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
if (idcin->next_chunk_is_video) {
command = get_le32(pb);
if (command == 2) {
- return AVERROR_IO;
+ return AVERROR(EIO);
} else if (command == 1) {
/* trigger a palette change */
idcin->palctrl.palette_changed = 1;
if (get_buffer(pb, palette_buffer, 768) != 768)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* scale the palette as necessary */
palette_scale = 2;
for (i = 0; i < 768; i++)
@@ -259,7 +255,7 @@ static int idcin_read_packet(AVFormatContext *s,
chunk_size -= 4;
ret= av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = idcin->video_stream_index;
pkt->pts = idcin->pts;
} else {
@@ -270,12 +266,12 @@ static int idcin_read_packet(AVFormatContext *s,
chunk_size = idcin->audio_chunk_size1;
ret= av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = idcin->audio_stream_index;
pkt->pts = idcin->pts;
idcin->current_audio_chunk ^= 1;
- idcin->pts += FRAME_PTS_INC;
+ idcin->pts++;
}
if (idcin->audio_present)
diff --git a/contrib/ffmpeg/libavformat/idroq.c b/contrib/ffmpeg/libavformat/idroq.c
index b8ee176ab..394697fcd 100644
--- a/contrib/ffmpeg/libavformat/idroq.c
+++ b/contrib/ffmpeg/libavformat/idroq.c
@@ -58,9 +58,6 @@ typedef struct RoqDemuxContext {
static int roq_probe(AVProbeData *p)
{
- if (p->buf_size < 6)
- return 0;
-
if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
(AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
return 0;
@@ -72,7 +69,7 @@ static int roq_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
RoqDemuxContext *roq = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
int i;
@@ -82,7 +79,7 @@ static int roq_read_header(AVFormatContext *s,
/* get the main header */
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
roq->framerate = AV_RL16(&preamble[6]);
roq->frame_pts_inc = 90000 / roq->framerate;
@@ -94,7 +91,7 @@ static int roq_read_header(AVFormatContext *s,
for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
chunk_type = AV_RL16(&preamble[0]);
chunk_size = AV_RL32(&preamble[2]);
@@ -105,7 +102,7 @@ static int roq_read_header(AVFormatContext *s,
/* fetch the width and height; reuse the preamble bytes */
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
roq->width = AV_RL16(&preamble[0]);
roq->height = AV_RL16(&preamble[2]);
break;
@@ -143,7 +140,7 @@ static int roq_read_header(AVFormatContext *s,
/* initialize the decoders */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
/* set the pts reference (1 pts = 1/90000) */
av_set_pts_info(st, 33, 1, 90000);
roq->video_stream_index = st->index;
@@ -156,7 +153,7 @@ static int roq_read_header(AVFormatContext *s,
if (roq->audio_channels) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, 90000);
roq->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
@@ -177,7 +174,7 @@ static int roq_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
RoqDemuxContext *roq = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int ret = 0;
unsigned int chunk_size;
unsigned int chunk_type;
@@ -188,13 +185,13 @@ static int roq_read_packet(AVFormatContext *s,
while (!packet_read) {
- if (url_feof(&s->pb))
- return AVERROR_IO;
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
/* get the next chunk preamble */
if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
RoQ_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
chunk_type = AV_RL16(&preamble[0]);
chunk_size = AV_RL32(&preamble[2]);
@@ -215,7 +212,7 @@ static int roq_read_packet(AVFormatContext *s,
url_fseek(pb, codebook_size, SEEK_CUR);
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
codebook_size;
@@ -225,7 +222,7 @@ static int roq_read_packet(AVFormatContext *s,
/* load up the packet */
ret= av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = roq->video_stream_index;
pkt->pts = roq->video_pts;
@@ -238,7 +235,7 @@ static int roq_read_packet(AVFormatContext *s,
case RoQ_QUAD_VQ:
/* load up the packet */
if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
- return AVERROR_IO;
+ return AVERROR(EIO);
/* copy over preamble */
memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
@@ -258,7 +255,7 @@ static int roq_read_packet(AVFormatContext *s,
ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
chunk_size);
if (ret != chunk_size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
packet_read = 1;
break;
@@ -275,7 +272,7 @@ static int roq_read_packet(AVFormatContext *s,
static int roq_read_close(AVFormatContext *s)
{
-// RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
+// RoqDemuxContext *roq = s->priv_data;
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/img2.c b/contrib/ffmpeg/libavformat/img2.c
index fa67ee742..6e846df66 100644
--- a/contrib/ffmpeg/libavformat/img2.c
+++ b/contrib/ffmpeg/libavformat/img2.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
+#include "avstring.h"
typedef struct {
int img_first;
@@ -40,6 +41,7 @@ static const IdStrMap img_tags[] = {
{ CODEC_ID_MJPEG , "jpg"},
{ CODEC_ID_LJPEG , "ljpg"},
{ CODEC_ID_PNG , "png"},
+ { CODEC_ID_PNG , "mng"},
{ CODEC_ID_PPM , "ppm"},
{ CODEC_ID_PGM , "pgm"},
{ CODEC_ID_PGMYUV , "pgmyuv"},
@@ -54,6 +56,16 @@ static const IdStrMap img_tags[] = {
{ CODEC_ID_GIF , "gif"},
{ CODEC_ID_TARGA , "tga"},
{ CODEC_ID_TIFF , "tiff"},
+ { CODEC_ID_SGI , "sgi"},
+ { CODEC_ID_PTX , "ptx"},
+ { CODEC_ID_PCX , "pcx"},
+ { CODEC_ID_SUNRAST , "sun"},
+ { CODEC_ID_SUNRAST , "ras"},
+ { CODEC_ID_SUNRAST , "rs"},
+ { CODEC_ID_SUNRAST , "im1"},
+ { CODEC_ID_SUNRAST , "im8"},
+ { CODEC_ID_SUNRAST , "im24"},
+ { CODEC_ID_SUNRAST , "sunras"},
{0, NULL}
};
@@ -180,7 +192,7 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
return AVERROR(ENOMEM);
}
- pstrcpy(s->path, sizeof(s->path), s1->filename);
+ av_strlcpy(s->path, s1->filename, sizeof(s->path));
s->img_number = 0;
s->img_count = 0;
@@ -189,7 +201,7 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->is_pipe = 0;
else{
s->is_pipe = 1;
- st->need_parsing= 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
}
if (!ap->time_base.num) {
@@ -205,7 +217,7 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
if (!s->is_pipe) {
if (find_image_range(&first_index, &last_index, s->path) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
s->img_first = first_index;
s->img_last = last_index;
s->img_number = first_index;
@@ -236,7 +248,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
char filename[1024];
int i;
int size[3]={0}, ret[3]={0};
- ByteIOContext f1[3], *f[3]= {&f1[0], &f1[1], &f1[2]};
+ ByteIOContext *f[3];
AVCodecContext *codec= s1->streams[0]->codec;
if (!s->is_pipe) {
@@ -246,10 +258,10 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
}
if (av_get_frame_filename(filename, sizeof(filename),
s->path, s->img_number)<0 && s->img_number > 1)
- return AVERROR_IO;
+ return AVERROR(EIO);
for(i=0; i<3; i++){
- if (url_fopen(f[i], filename, URL_RDONLY) < 0)
- return AVERROR_IO;
+ if (url_fopen(&f[i], filename, URL_RDONLY) < 0)
+ return AVERROR(EIO);
size[i]= url_fsize(f[i]);
if(codec->codec_id != CODEC_ID_RAWVIDEO)
@@ -260,9 +272,9 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
infer_size(&codec->width, &codec->height, size[0]);
} else {
- f[0] = &s1->pb;
+ f[0] = s1->pb;
if (url_feof(f[0]))
- return AVERROR_IO;
+ return AVERROR(EIO);
size[0]= 4096;
}
@@ -283,7 +295,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
av_free_packet(pkt);
- return AVERROR_IO; /* signal EOF */
+ return AVERROR(EIO); /* signal EOF */
} else {
s->img_count++;
s->img_number++;
@@ -305,7 +317,7 @@ static int img_write_header(AVFormatContext *s)
VideoData *img = s->priv_data;
img->img_number = 1;
- pstrcpy(img->path, sizeof(img->path), s->filename);
+ av_strlcpy(img->path, s->filename, sizeof(img->path));
/* find format */
if (s->oformat->flags & AVFMT_NOFILE)
@@ -319,7 +331,7 @@ static int img_write_header(AVFormatContext *s)
static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
{
VideoData *img = s->priv_data;
- ByteIOContext pb1[3], *pb[3]= {&pb1[0], &pb1[1], &pb1[2]};
+ ByteIOContext *pb[3];
char filename[1024];
AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
int i;
@@ -327,17 +339,17 @@ static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
if (!img->is_pipe) {
if (av_get_frame_filename(filename, sizeof(filename),
img->path, img->img_number) < 0 && img->img_number>1)
- return AVERROR_IO;
+ return AVERROR(EIO);
for(i=0; i<3; i++){
- if (url_fopen(pb[i], filename, URL_WRONLY) < 0)
- return AVERROR_IO;
+ if (url_fopen(&pb[i], filename, URL_WRONLY) < 0)
+ return AVERROR(EIO);
if(codec->codec_id != CODEC_ID_RAWVIDEO)
break;
filename[ strlen(filename) - 1 ]= 'U' + i;
}
} else {
- pb[0] = &s->pb;
+ pb[0] = s->pb;
}
if(codec->codec_id == CODEC_ID_RAWVIDEO){
diff --git a/contrib/ffmpeg/libavformat/ipmovie.c b/contrib/ffmpeg/libavformat/ipmovie.c
index 975bfd36b..311f29f49 100644
--- a/contrib/ffmpeg/libavformat/ipmovie.c
+++ b/contrib/ffmpeg/libavformat/ipmovie.c
@@ -507,8 +507,6 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb,
static int ipmovie_probe(AVProbeData *p)
{
- if (p->buf_size < IPMOVIE_SIGNATURE_SIZE)
- return 0;
if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0)
return 0;
@@ -518,8 +516,8 @@ static int ipmovie_probe(AVProbeData *p)
static int ipmovie_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ IPMVEContext *ipmovie = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVPacket pkt;
AVStream *st;
unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
@@ -541,7 +539,7 @@ static int ipmovie_read_header(AVFormatContext *s,
* it; if it is the first video chunk, this is a silent file */
if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
chunk_type = AV_RL16(&chunk_preamble[2]);
url_fseek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
@@ -553,7 +551,7 @@ static int ipmovie_read_header(AVFormatContext *s,
/* initialize the stream decoders */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, 90000);
ipmovie->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
@@ -568,7 +566,7 @@ static int ipmovie_read_header(AVFormatContext *s,
if (ipmovie->audio_type) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, 90000);
ipmovie->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
@@ -590,17 +588,17 @@ static int ipmovie_read_header(AVFormatContext *s,
static int ipmovie_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ IPMVEContext *ipmovie = s->priv_data;
+ ByteIOContext *pb = s->pb;
int ret;
ret = process_ipmovie_chunk(ipmovie, pb, pkt);
if (ret == CHUNK_BAD)
ret = AVERROR_INVALIDDATA;
else if (ret == CHUNK_EOF)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
else if (ret == CHUNK_NOMEM)
- ret = AVERROR_NOMEM;
+ ret = AVERROR(ENOMEM);
else if (ret == CHUNK_VIDEO)
ret = 0;
else
@@ -611,7 +609,7 @@ static int ipmovie_read_packet(AVFormatContext *s,
static int ipmovie_read_close(AVFormatContext *s)
{
-// IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
+// IPMVEContext *ipmovie = s->priv_data;
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/isom.c b/contrib/ffmpeg/libavformat/isom.c
index f913bc0a9..f6e81cdcf 100644
--- a/contrib/ffmpeg/libavformat/isom.c
+++ b/contrib/ffmpeg/libavformat/isom.c
@@ -26,12 +26,13 @@
#include "isom.h"
/* http://www.mp4ra.org */
+/* ordered by muxing preference */
const AVCodecTag ff_mp4_obj_type[] = {
{ CODEC_ID_MPEG4 , 32 },
{ CODEC_ID_H264 , 33 },
{ CODEC_ID_AAC , 64 },
- { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
{ CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
+ { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
{ CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
{ CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
{ CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
@@ -39,22 +40,16 @@ const AVCodecTag ff_mp4_obj_type[] = {
{ CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
{ CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
{ CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
+ { CODEC_ID_MP3 , 107 }, /* 11172-3 */
{ CODEC_ID_MP3 , 105 }, /* 13818-3 */
{ CODEC_ID_MPEG1VIDEO, 106 }, /* 11172-2 */
- { CODEC_ID_MP3 , 107 }, /* 11172-3 */
{ CODEC_ID_MJPEG , 108 }, /* 10918-1 */
{ CODEC_ID_PNG , 109 },
{ CODEC_ID_JPEG2000 , 110 }, /* 15444-1 */
{ CODEC_ID_VC1 , 163 },
- { CODEC_ID_VORBIS , 221 },
- { CODEC_ID_PCM_S16LE , 224 },
+ { CODEC_ID_VORBIS , 221 }, /* non standard, gpac uses it */
+ { CODEC_ID_DVD_SUBTITLE, 224 }, /* non standard, see unsupported-embedded-subs-2.mp4 */
{ CODEC_ID_QCELP , 225 },
- { CODEC_ID_AC3 , 226 },
- { CODEC_ID_PCM_ALAW , 227 },
- { CODEC_ID_PCM_MULAW , 228 },
- { CODEC_ID_PCM_S16BE , 230 },
- { CODEC_ID_H263 , 242 },
- { CODEC_ID_H261 , 243 },
{ 0, 0 },
};
@@ -70,6 +65,7 @@ const AVCodecTag codec_movvideo_tags[] = {
{ CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
{ CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
/* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
+ { CODEC_ID_MJPEG, MKTAG('d', 'm', 'b', '1') }, /* Motion JPEG OpenDML */
{ CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
{ CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
@@ -111,8 +107,11 @@ const AVCodecTag codec_movvideo_tags[] = {
{ CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
{ CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
{ CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG2 IMX PAL 625/50 40mb/s produced by FCP */
{ CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
{ CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '2') }, /* XDCAM HD 1080i60 */
{ CODEC_ID_MPEG2VIDEO, MKTAG('A', 'V', 'm', 'p') }, /* AVID IMX PAL */
//{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
@@ -125,6 +124,7 @@ const AVCodecTag codec_movvideo_tags[] = {
{ CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */
{ CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */
+ { CODEC_ID_SGI, MKTAG('s', 'g', 'i', ' ') }, /* SGI */
{ CODEC_ID_NONE, 0 },
};
@@ -135,11 +135,11 @@ const AVCodecTag codec_movaudio_tags[] = {
{ CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
{ CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') },
{ CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
- { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, /* uncompressed */
{ CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
{ CODEC_ID_PCM_S16LE, MKTAG('l', 'p', 'c', 'm') },
{ CODEC_ID_PCM_S8, MKTAG('s', 'o', 'w', 't') },
{ CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
+ { CODEC_ID_PCM_U8, MKTAG('N', 'O', 'N', 'E') }, /* uncompressed */
{ CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
{ CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
@@ -171,6 +171,12 @@ const AVCodecTag codec_movaudio_tags[] = {
{ CODEC_ID_NONE, 0 },
};
+const AVCodecTag ff_codec_movsubtitle_tags[] = {
+ { CODEC_ID_MOV_TEXT, MKTAG('t', 'e', 'x', 't') },
+ { CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') },
+ { CODEC_ID_NONE, 0 },
+};
+
/* map numeric codes from mdhd atom to ISO 639 */
/* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
/* http://developer.apple.com/documentation/mac/Text/Text-368.html */
diff --git a/contrib/ffmpeg/libavformat/isom.h b/contrib/ffmpeg/libavformat/isom.h
index efcb1fc42..7a66ce524 100644
--- a/contrib/ffmpeg/libavformat/isom.h
+++ b/contrib/ffmpeg/libavformat/isom.h
@@ -24,17 +24,20 @@
#ifndef FFMPEG_ISOM_H
#define FFMPEG_ISOM_H
+#include "riff.h"
+
/* isom.c */
extern const AVCodecTag ff_mp4_obj_type[];
extern const AVCodecTag codec_movvideo_tags[];
extern const AVCodecTag codec_movaudio_tags[];
+extern const AVCodecTag ff_codec_movsubtitle_tags[];
int ff_mov_iso639_to_lang(const char *lang, int mp4);
int ff_mov_lang_to_iso639(int code, char *to);
-typedef struct Time2Sample{
+typedef struct {
int count;
int duration;
-}Time2Sample;
+} MOV_stts_t;
#endif /* FFMPEG_ISOM_H */
diff --git a/contrib/ffmpeg/libavformat/libnut.c b/contrib/ffmpeg/libavformat/libnut.c
index 0f7b879a9..f5423069f 100644
--- a/contrib/ffmpeg/libavformat/libnut.c
+++ b/contrib/ffmpeg/libavformat/libnut.c
@@ -54,7 +54,7 @@ static int av_write(void * h, size_t len, const uint8_t * buf) {
static int nut_write_header(AVFormatContext * avf) {
NUTContext * priv = avf->priv_data;
- ByteIOContext * bc = &avf->pb;
+ ByteIOContext * bc = avf->pb;
nut_muxer_opts_t mopts = {
.output = {
.priv = bc,
@@ -137,7 +137,7 @@ static int nut_write_packet(AVFormatContext * avf, AVPacket * pkt) {
}
static int nut_write_trailer(AVFormatContext * avf) {
- ByteIOContext * bc = &avf->pb;
+ ByteIOContext * bc = avf->pb;
NUTContext * priv = avf->priv_data;
int i;
@@ -151,7 +151,7 @@ static int nut_write_trailer(AVFormatContext * avf) {
}
AVOutputFormat libnut_muxer = {
- "nut",
+ "libnut",
"nut format",
"video/x-nut",
"nut",
@@ -166,7 +166,7 @@ AVOutputFormat libnut_muxer = {
#endif //CONFIG_MUXERS
static int nut_probe(AVProbeData *p) {
- if (p->buf_size >= ID_LENGTH && !memcmp(p->buf, ID_STRING, ID_LENGTH)) return AVPROBE_SCORE_MAX;
+ if (!memcmp(p->buf, ID_STRING, ID_LENGTH)) return AVPROBE_SCORE_MAX;
return 0;
}
@@ -187,7 +187,7 @@ static off_t av_seek(void * h, long long pos, int whence) {
static int nut_read_header(AVFormatContext * avf, AVFormatParameters * ap) {
NUTContext * priv = avf->priv_data;
- ByteIOContext * bc = &avf->pb;
+ ByteIOContext * bc = avf->pb;
nut_demuxer_opts_t dopts = {
.input = {
.priv = bc,
@@ -272,7 +272,7 @@ static int nut_read_packet(AVFormatContext * avf, AVPacket * pkt) {
if (pd.flags & NUT_FLAG_KEY) pkt->flags |= PKT_FLAG_KEY;
pkt->pts = pd.pts;
pkt->stream_index = pd.stream;
- pkt->pos = url_ftell(&avf->pb);
+ pkt->pos = url_ftell(avf->pb);
ret = nut_read_frame(priv->nut, &pd.len, pkt->data);
@@ -298,7 +298,7 @@ static int nut_read_close(AVFormatContext *s) {
}
AVInputFormat libnut_demuxer = {
- "nut",
+ "libnut",
"nut format",
sizeof(NUTContext),
nut_probe,
diff --git a/contrib/ffmpeg/libavformat/lmlm4.c b/contrib/ffmpeg/libavformat/lmlm4.c
new file mode 100644
index 000000000..6646a412b
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/lmlm4.c
@@ -0,0 +1,126 @@
+/*
+ * Linux Media Labs MPEG-4 demuxer
+ * Copyright (c) 2008 Ivo van Poorten
+ *
+ * Due to a lack of sample files, only files with one channel are supported.
+ * u-law and ADPCM audio are unsupported for the same reason.
+ *
+ * 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 "avformat.h"
+
+#define LMLM4_I_FRAME 0x00
+#define LMLM4_P_FRAME 0x01
+#define LMLM4_B_FRAME 0x02
+#define LMLM4_INVALID 0x03
+#define LMLM4_MPEG1L2 0x04
+
+#define LMLM4_MAX_PACKET_SIZE 1024 * 1024
+
+static int lmlm4_probe(AVProbeData * pd) {
+ unsigned char *buf = pd->buf;
+ unsigned int frame_type, packet_size;
+
+ frame_type = AV_RB16(buf+2);
+ packet_size = AV_RB32(buf+4);
+
+ if (!AV_RB16(buf) && frame_type <= LMLM4_MPEG1L2 && packet_size &&
+ frame_type != LMLM4_INVALID && packet_size <= LMLM4_MAX_PACKET_SIZE) {
+
+ if (frame_type == LMLM4_MPEG1L2) {
+ if ((AV_RB16(buf+8) & 0xfffe) != 0xfffc)
+ return 0;
+ /* I could calculate the audio framesize and compare with
+ * packet_size-8, but that seems overkill */
+ return AVPROBE_SCORE_MAX / 3;
+ } else if (AV_RB24(buf+8) == 0x000001) { /* PES Signal */
+ return AVPROBE_SCORE_MAX / 5;
+ }
+ }
+
+ return 0;
+}
+
+static int lmlm4_read_header(AVFormatContext *s, AVFormatParameters *ap) {
+ AVStream *st;
+
+ if (!(st = av_new_stream(s, 0)))
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MPEG4;
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ av_set_pts_info(st, 64, 1001, 30000);
+
+ if (!(st = av_new_stream(s, 1)))
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_MP2;
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
+
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+static int lmlm4_read_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = s->pb;
+ int ret;
+ unsigned int frame_type, packet_size, padding, frame_size;
+
+ get_be16(pb); /* channel number */
+ frame_type = get_be16(pb);
+ packet_size = get_be32(pb);
+ padding = -packet_size & 511;
+ frame_size = packet_size - 8;
+
+ if (frame_type > LMLM4_MPEG1L2 || frame_type == LMLM4_INVALID) {
+ av_log(s, AV_LOG_ERROR, "invalid or unsupported frame_type\n");
+ return AVERROR(EIO);
+ }
+ if (packet_size > LMLM4_MAX_PACKET_SIZE) {
+ av_log(s, AV_LOG_ERROR, "packet size exceeds maximum\n");
+ return AVERROR(EIO);
+ }
+
+ if ((ret = av_get_packet(pb, pkt, frame_size)) <= 0)
+ return AVERROR(EIO);
+
+ url_fskip(pb, padding);
+
+ switch (frame_type) {
+ case LMLM4_I_FRAME:
+ pkt->flags = PKT_FLAG_KEY;
+ case LMLM4_P_FRAME:
+ case LMLM4_B_FRAME:
+ pkt->stream_index = 0;
+ break;
+ case LMLM4_MPEG1L2:
+ pkt->stream_index = 1;
+ break;
+ }
+
+ return ret;
+}
+
+AVInputFormat lmlm4_demuxer = {
+ "lmlm4",
+ "lmlm4 raw format",
+ 0,
+ lmlm4_probe,
+ lmlm4_read_header,
+ lmlm4_read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/matroska.c b/contrib/ffmpeg/libavformat/matroska.c
index 591530490..b62511f29 100644
--- a/contrib/ffmpeg/libavformat/matroska.c
+++ b/contrib/ffmpeg/libavformat/matroska.c
@@ -1,5 +1,5 @@
/*
- * Matroska file demuxer (no muxer yet)
+ * Matroska common data
* Copyright (c) 2003-2004 The ffmpeg Project
*
* This file is part of FFmpeg.
@@ -19,190 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/**
- * @file matroska.c
- * Matroska file demuxer
- * by Ronald Bultje <rbultje@ronald.bitfreak.net>
- * with a little help from Moritz Bunkus <moritz@bunkus.org>
- * Specs available on the matroska project page:
- * http://www.matroska.org/.
- */
-
-#include "avformat.h"
-/* For codec_get_id(). */
-#include "riff.h"
-#include "intfloat_readwrite.h"
-
-/* EBML version supported */
-#define EBML_VERSION 1
-
-/* top-level master-IDs */
-#define EBML_ID_HEADER 0x1A45DFA3
-
-/* IDs in the HEADER master */
-#define EBML_ID_EBMLVERSION 0x4286
-#define EBML_ID_EBMLREADVERSION 0x42F7
-#define EBML_ID_EBMLMAXIDLENGTH 0x42F2
-#define EBML_ID_EBMLMAXSIZELENGTH 0x42F3
-#define EBML_ID_DOCTYPE 0x4282
-#define EBML_ID_DOCTYPEVERSION 0x4287
-#define EBML_ID_DOCTYPEREADVERSION 0x4285
-
-/* general EBML types */
-#define EBML_ID_VOID 0xEC
-
-/*
- * Matroska element IDs. max. 32-bit.
- */
-
-/* toplevel segment */
-#define MATROSKA_ID_SEGMENT 0x18538067
-
-/* matroska top-level master IDs */
-#define MATROSKA_ID_INFO 0x1549A966
-#define MATROSKA_ID_TRACKS 0x1654AE6B
-#define MATROSKA_ID_CUES 0x1C53BB6B
-#define MATROSKA_ID_TAGS 0x1254C367
-#define MATROSKA_ID_SEEKHEAD 0x114D9B74
-#define MATROSKA_ID_CLUSTER 0x1F43B675
-
-/* IDs in the info master */
-#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1
-#define MATROSKA_ID_DURATION 0x4489
-#define MATROSKA_ID_TITLE 0x7BA9
-#define MATROSKA_ID_WRITINGAPP 0x5741
-#define MATROSKA_ID_MUXINGAPP 0x4D80
-#define MATROSKA_ID_DATEUTC 0x4461
-
-/* ID in the tracks master */
-#define MATROSKA_ID_TRACKENTRY 0xAE
-
-/* IDs in the trackentry master */
-#define MATROSKA_ID_TRACKNUMBER 0xD7
-#define MATROSKA_ID_TRACKUID 0x73C5
-#define MATROSKA_ID_TRACKTYPE 0x83
-#define MATROSKA_ID_TRACKAUDIO 0xE1
-#define MATROSKA_ID_TRACKVIDEO 0xE0
-#define MATROSKA_ID_CODECID 0x86
-#define MATROSKA_ID_CODECPRIVATE 0x63A2
-#define MATROSKA_ID_CODECNAME 0x258688
-#define MATROSKA_ID_CODECINFOURL 0x3B4040
-#define MATROSKA_ID_CODECDOWNLOADURL 0x26B240
-#define MATROSKA_ID_TRACKNAME 0x536E
-#define MATROSKA_ID_TRACKLANGUAGE 0x22B59C
-#define MATROSKA_ID_TRACKFLAGENABLED 0xB9
-#define MATROSKA_ID_TRACKFLAGDEFAULT 0x88
-#define MATROSKA_ID_TRACKFLAGLACING 0x9C
-#define MATROSKA_ID_TRACKMINCACHE 0x6DE7
-#define MATROSKA_ID_TRACKMAXCACHE 0x6DF8
-#define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
-
-/* IDs in the trackvideo master */
-#define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
-#define MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
-#define MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
-#define MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
-#define MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
-#define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
-#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
-#define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
-#define MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
-
-/* IDs in the trackaudio master */
-#define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
-#define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5
-
-#define MATROSKA_ID_AUDIOBITDEPTH 0x6264
-#define MATROSKA_ID_AUDIOCHANNELS 0x9F
-
-/* ID in the cues master */
-#define MATROSKA_ID_POINTENTRY 0xBB
-
-/* IDs in the pointentry master */
-#define MATROSKA_ID_CUETIME 0xB3
-#define MATROSKA_ID_CUETRACKPOSITION 0xB7
-
-/* IDs in the cuetrackposition master */
-#define MATROSKA_ID_CUETRACK 0xF7
-#define MATROSKA_ID_CUECLUSTERPOSITION 0xF1
-
-/* IDs in the tags master */
-/* TODO */
-
-/* IDs in the seekhead master */
-#define MATROSKA_ID_SEEKENTRY 0x4DBB
-
-/* IDs in the seekpoint master */
-#define MATROSKA_ID_SEEKID 0x53AB
-#define MATROSKA_ID_SEEKPOSITION 0x53AC
-
-/* IDs in the cluster master */
-#define MATROSKA_ID_CLUSTERTIMECODE 0xE7
-#define MATROSKA_ID_BLOCKGROUP 0xA0
-#define MATROSKA_ID_SIMPLEBLOCK 0xA3
-
-/* IDs in the blockgroup master */
-#define MATROSKA_ID_BLOCK 0xA1
-#define MATROSKA_ID_BLOCKDURATION 0x9B
-#define MATROSKA_ID_BLOCKREFERENCE 0xFB
-
-typedef enum {
- MATROSKA_TRACK_TYPE_VIDEO = 0x1,
- MATROSKA_TRACK_TYPE_AUDIO = 0x2,
- MATROSKA_TRACK_TYPE_COMPLEX = 0x3,
- MATROSKA_TRACK_TYPE_LOGO = 0x10,
- MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
- MATROSKA_TRACK_TYPE_CONTROL = 0x20,
-} MatroskaTrackType;
-
-typedef enum {
- MATROSKA_EYE_MODE_MONO = 0x0,
- MATROSKA_EYE_MODE_RIGHT = 0x1,
- MATROSKA_EYE_MODE_LEFT = 0x2,
- MATROSKA_EYE_MODE_BOTH = 0x3,
-} MatroskaEyeMode;
-
-typedef enum {
- MATROSKA_ASPECT_RATIO_MODE_FREE = 0x0,
- MATROSKA_ASPECT_RATIO_MODE_KEEP = 0x1,
- MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2,
-} MatroskaAspectRatioMode;
-
-/*
- * These aren't in any way "matroska-form" things,
- * it's just something I use in the muxer/demuxer.
- */
-
-typedef enum {
- MATROSKA_TRACK_ENABLED = (1<<0),
- MATROSKA_TRACK_DEFAULT = (1<<1),
- MATROSKA_TRACK_LACING = (1<<2),
- MATROSKA_TRACK_REAL_V = (1<<4),
- MATROSKA_TRACK_REORDER = (1<<8),
- MATROSKA_TRACK_SHIFT = (1<<16)
-} MatroskaTrackFlags;
-
-typedef enum {
- MATROSKA_VIDEOTRACK_INTERLACED = (MATROSKA_TRACK_SHIFT<<0)
-} MatroskaVideoTrackFlags;
-
-/*
- * Matroska Codec IDs. Strings.
- */
-
-typedef struct CodecTags{
- const char *str;
- enum CodecID id;
-}CodecTags;
+#include "matroska.h"
-#define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC"
-#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
-
-static CodecTags codec_tags[]={
+const CodecTags ff_mkv_codec_tags[]={
// {"V_MS/VFW/FOURCC" , CODEC_ID_NONE},
{"V_UNCOMPRESSED" , CODEC_ID_RAWVIDEO},
- {"V_MPEG4/ISO/SP" , CODEC_ID_MPEG4},
{"V_MPEG4/ISO/ASP" , CODEC_ID_MPEG4},
+ {"V_MPEG4/ISO/SP" , CODEC_ID_MPEG4},
{"V_MPEG4/ISO/AP" , CODEC_ID_MPEG4},
{"V_MPEG4/ISO/AVC" , CODEC_ID_H264},
{"V_MPEG4/MS/V3" , CODEC_ID_MSMPEG4V3},
@@ -214,12 +37,13 @@ static CodecTags codec_tags[]={
{"V_REAL/RV30" , CODEC_ID_RV30},
{"V_REAL/RV40" , CODEC_ID_RV40},
{"V_THEORA" , CODEC_ID_THEORA},
+ {"V_SNOW" , CODEC_ID_SNOW},
/* TODO: Real/Quicktime */
// {"A_MS/ACM" , CODEC_ID_NONE},
- {"A_MPEG/L1" , CODEC_ID_MP3},
- {"A_MPEG/L2" , CODEC_ID_MP3},
{"A_MPEG/L3" , CODEC_ID_MP3},
+ {"A_MPEG/L2" , CODEC_ID_MP2},
+ {"A_MPEG/L1" , CODEC_ID_MP2},
{"A_PCM/INT/BIG" , CODEC_ID_PCM_U16BE},
{"A_PCM/INT/LIT" , CODEC_ID_PCM_U16LE},
// {"A_PCM/FLOAT/IEEE" , CODEC_ID_NONE},
@@ -230,2621 +54,32 @@ static CodecTags codec_tags[]={
{"A_FLAC" , CODEC_ID_FLAC},
{"A_WAVPACK4" , CODEC_ID_WAVPACK},
{"A_TTA1" , CODEC_ID_TTA},
- {NULL , CODEC_ID_NONE}
+ {"A_REAL/14_4" , CODEC_ID_RA_144},
+ {"A_REAL/28_8" , CODEC_ID_RA_288},
+ {"A_REAL/ATRC" , CODEC_ID_ATRAC3},
+ {"A_REAL/COOK" , CODEC_ID_COOK},
+// {"A_REAL/SIPR" , CODEC_ID_SIPRO},
+
+ {"S_TEXT/UTF8" , CODEC_ID_TEXT},
+ {"S_TEXT/ASCII" , CODEC_ID_TEXT},
+ {"S_TEXT/ASS" , CODEC_ID_SSA},
+ {"S_TEXT/SSA" , CODEC_ID_SSA},
+ {"S_ASS" , CODEC_ID_SSA},
+ {"S_SSA" , CODEC_ID_SSA},
+ {"S_VOBSUB" , CODEC_ID_DVD_SUBTITLE},
+
+ {"" , CODEC_ID_NONE}
/* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */
};
-/* max. depth in the EBML tree structure */
-#define EBML_MAX_DEPTH 16
-
-typedef struct Track {
- MatroskaTrackType type;
-
- /* Unique track number and track ID. stream_index is the index that
- * the calling app uses for this track. */
- uint32_t num,
- uid,
- stream_index;
-
- char *name,
- *language;
-
- char *codec_id,
- *codec_name;
-
- unsigned char *codec_priv;
- int codec_priv_size;
-
- uint64_t default_duration;
- MatroskaTrackFlags flags;
-} MatroskaTrack;
-
-typedef struct MatroskaVideoTrack {
- MatroskaTrack track;
-
- int pixel_width,
- pixel_height,
- display_width,
- display_height;
-
- uint32_t fourcc;
-
- MatroskaAspectRatioMode ar_mode;
- MatroskaEyeMode eye_mode;
-
- //..
-} MatroskaVideoTrack;
-
-typedef struct MatroskaAudioTrack {
- MatroskaTrack track;
-
- int channels,
- bitdepth,
- internal_samplerate,
- samplerate;
- //..
-} MatroskaAudioTrack;
-
-typedef struct MatroskaSubtitleTrack {
- MatroskaTrack track;
-
- //..
-} MatroskaSubtitleTrack;
-
-#define MAX_TRACK_SIZE (FFMAX(FFMAX(sizeof(MatroskaVideoTrack), \
- sizeof(MatroskaAudioTrack)), \
- sizeof(MatroskaSubtitleTrack)))
-
-typedef struct MatroskaLevel {
- uint64_t start, length;
-} MatroskaLevel;
-
-typedef struct MatroskaDemuxIndex {
- uint64_t pos; /* of the corresponding *cluster*! */
- uint16_t track; /* reference to 'num' */
- uint64_t time; /* in nanoseconds */
-} MatroskaDemuxIndex;
-
-typedef struct MatroskaDemuxContext {
- AVFormatContext *ctx;
-
- /* ebml stuff */
- int num_levels;
- MatroskaLevel levels[EBML_MAX_DEPTH];
- int level_up;
-
- /* matroska stuff */
- char *writing_app,
- *muxing_app;
- int64_t created;
-
- /* timescale in the file */
- int64_t time_scale;
-
- /* position (time, ns) */
- int64_t pos;
-
- /* num_streams is the number of streams that av_new_stream() was called
- * for ( = that are available to the calling program). */
- int num_tracks, num_streams;
- MatroskaTrack *tracks[MAX_STREAMS];
-
- /* cache for ID peeking */
- uint32_t peek_id;
-
- /* byte position of the segment inside the stream */
- offset_t segment_start;
-
- /* The packet queue. */
- AVPacket **packets;
- int num_packets;
- /* Second packet queue used to reorder pts of some video track. */
- AVPacket **packets_reorder;
- int num_packets_reorder;
- uint64_t reorder_max_pts;
-
- /* have we already parse metadata/cues/clusters? */
- int metadata_parsed,
- index_parsed,
- done;
-
- /* The index for seeking. */
- int num_indexes;
- MatroskaDemuxIndex *index;
-} MatroskaDemuxContext;
-
-/*
- * The first few functions handle EBML file parsing. The rest
- * is the document interpretation. Matroska really just is a
- * EBML file.
- */
-
-/*
- * Return: the amount of levels in the hierarchy that the
- * current element lies higher than the previous one.
- * The opposite isn't done - that's auto-done using master
- * element reading.
- */
-
-static int
-ebml_read_element_level_up (MatroskaDemuxContext *matroska)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- offset_t pos = url_ftell(pb);
- int num = 0;
-
- while (matroska->num_levels > 0) {
- MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
-
- if (pos >= level->start + level->length) {
- matroska->num_levels--;
- num++;
- } else {
- break;
- }
- }
-
- return num;
-}
-
-/*
- * Read: an "EBML number", which is defined as a variable-length
- * array of bytes. The first byte indicates the length by giving a
- * number of 0-bits followed by a one. The position of the first
- * "one" bit inside the first byte indicates the length of this
- * number.
- * Returns: num. of bytes read. < 0 on error.
- */
-
-static int
-ebml_read_num (MatroskaDemuxContext *matroska,
- int max_size,
- uint64_t *number)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- int len_mask = 0x80, read = 1, n = 1;
- int64_t total = 0;
-
- /* the first byte tells us the length in bytes - get_byte() can normally
- * return 0, but since that's not a valid first ebmlID byte, we can
- * use it safely here to catch EOS. */
- if (!(total = get_byte(pb))) {
- /* we might encounter EOS here */
- if (!url_feof(pb)) {
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
- pos, pos);
- }
- return AVERROR_IO; /* EOS or actual I/O error */
- }
-
- /* get the length of the EBML number */
- while (read <= max_size && !(total & len_mask)) {
- read++;
- len_mask >>= 1;
- }
- if (read > max_size) {
- offset_t pos = url_ftell(pb) - 1;
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n",
- (uint8_t) total, pos, pos);
- return AVERROR_INVALIDDATA;
- }
-
- /* read out length */
- total &= ~len_mask;
- while (n++ < read)
- total = (total << 8) | get_byte(pb);
-
- *number = total;
-
- return read;
-}
-
-/*
- * Read: the element content data ID.
- * Return: the number of bytes read or < 0 on error.
- */
-
-static int
-ebml_read_element_id (MatroskaDemuxContext *matroska,
- uint32_t *id,
- int *level_up)
-{
- int read;
- uint64_t total;
-
- /* if we re-call this, use our cached ID */
- if (matroska->peek_id != 0) {
- if (level_up)
- *level_up = 0;
- *id = matroska->peek_id;
- return 0;
- }
-
- /* read out the "EBML number", include tag in ID */
- if ((read = ebml_read_num(matroska, 4, &total)) < 0)
- return read;
- *id = matroska->peek_id = total | (1 << (read * 7));
-
- /* level tracking */
- if (level_up)
- *level_up = ebml_read_element_level_up(matroska);
-
- return read;
-}
-
-/*
- * Read: element content length.
- * Return: the number of bytes read or < 0 on error.
- */
-
-static int
-ebml_read_element_length (MatroskaDemuxContext *matroska,
- uint64_t *length)
-{
- /* clear cache since we're now beyond that data point */
- matroska->peek_id = 0;
-
- /* read out the "EBML number", include tag in ID */
- return ebml_read_num(matroska, 8, length);
-}
-
-/*
- * Return: the ID of the next element, or 0 on error.
- * Level_up contains the amount of levels that this
- * next element lies higher than the previous one.
- */
-
-static uint32_t
-ebml_peek_id (MatroskaDemuxContext *matroska,
- int *level_up)
-{
- uint32_t id;
-
- assert(level_up != NULL);
-
- if (ebml_read_element_id(matroska, &id, level_up) < 0)
- return 0;
-
- return id;
-}
-
-/*
- * Seek to a given offset.
- * 0 is success, -1 is failure.
- */
-
-static int
-ebml_read_seek (MatroskaDemuxContext *matroska,
- offset_t offset)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
-
- /* clear ID cache, if any */
- matroska->peek_id = 0;
-
- return (url_fseek(pb, offset, SEEK_SET) == offset) ? 0 : -1;
-}
-
-/*
- * Skip the next element.
- * 0 is success, -1 is failure.
- */
-
-static int
-ebml_read_skip (MatroskaDemuxContext *matroska)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- uint32_t id;
- uint64_t length;
- int res;
-
- if ((res = ebml_read_element_id(matroska, &id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &length)) < 0)
- return res;
-
- url_fskip(pb, length);
-
- return 0;
-}
-
-/*
- * Read the next element as an unsigned int.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_uint (MatroskaDemuxContext *matroska,
- uint32_t *id,
- uint64_t *num)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- int n = 0, size, res;
- uint64_t rlength;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &rlength)) < 0)
- return res;
- size = rlength;
- if (size < 1 || size > 8) {
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n",
- size, pos, pos);
- return AVERROR_INVALIDDATA;
- }
-
- /* big-endian ordening; build up number */
- *num = 0;
- while (n++ < size)
- *num = (*num << 8) | get_byte(pb);
-
- return 0;
-}
-
-/*
- * Read the next element as a signed int.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_sint (MatroskaDemuxContext *matroska,
- uint32_t *id,
- int64_t *num)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- int size, n = 1, negative = 0, res;
- uint64_t rlength;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &rlength)) < 0)
- return res;
- size = rlength;
- if (size < 1 || size > 8) {
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n",
- size, pos, pos);
- return AVERROR_INVALIDDATA;
- }
- if ((*num = get_byte(pb)) & 0x80) {
- negative = 1;
- *num &= ~0x80;
- }
- while (n++ < size)
- *num = (*num << 8) | get_byte(pb);
-
- /* make signed */
- if (negative)
- *num = *num - (1LL << ((8 * size) - 1));
-
- return 0;
-}
-
-/*
- * Read the next element as a float.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_float (MatroskaDemuxContext *matroska,
- uint32_t *id,
- double *num)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- int size, res;
- uint64_t rlength;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &rlength)) < 0)
- return res;
- size = rlength;
-
- if (size == 4) {
- *num= av_int2flt(get_be32(pb));
- } else if(size==8){
- *num= av_int2dbl(get_be64(pb));
- } else{
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n",
- size, pos, pos);
- return AVERROR_INVALIDDATA;
- }
-
- return 0;
-}
-
-/*
- * Read the next element as an ASCII string.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_ascii (MatroskaDemuxContext *matroska,
- uint32_t *id,
- char **str)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- int size, res;
- uint64_t rlength;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &rlength)) < 0)
- return res;
- size = rlength;
-
- /* ebml strings are usually not 0-terminated, so we allocate one
- * byte more, read the string and NULL-terminate it ourselves. */
- if (size < 0 || !(*str = av_malloc(size + 1))) {
- av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
- return AVERROR_NOMEM;
- }
- if (get_buffer(pb, (uint8_t *) *str, size) != size) {
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
- return AVERROR_IO;
- }
- (*str)[size] = '\0';
-
- return 0;
-}
-
-/*
- * Read the next element as a UTF-8 string.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_utf8 (MatroskaDemuxContext *matroska,
- uint32_t *id,
- char **str)
-{
- return ebml_read_ascii(matroska, id, str);
-}
-
-/*
- * Read the next element as a date (nanoseconds since 1/1/2000).
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_date (MatroskaDemuxContext *matroska,
- uint32_t *id,
- int64_t *date)
-{
- return ebml_read_sint(matroska, id, date);
-}
-
-/*
- * Read the next element, but only the header. The contents
- * are supposed to be sub-elements which can be read separately.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_master (MatroskaDemuxContext *matroska,
- uint32_t *id)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- uint64_t length;
- MatroskaLevel *level;
- int res;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &length)) < 0)
- return res;
-
- /* protect... (Heaven forbids that the '>' is true) */
- if (matroska->num_levels >= EBML_MAX_DEPTH) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH);
- return AVERROR_NOTSUPP;
- }
-
- /* remember level */
- level = &matroska->levels[matroska->num_levels++];
- level->start = url_ftell(pb);
- level->length = length;
-
- return 0;
-}
-
-/*
- * Read the next element as binary data.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_binary (MatroskaDemuxContext *matroska,
- uint32_t *id,
- uint8_t **binary,
- int *size)
-{
- ByteIOContext *pb = &matroska->ctx->pb;
- uint64_t rlength;
- int res;
-
- if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
- (res = ebml_read_element_length(matroska, &rlength)) < 0)
- return res;
- *size = rlength;
-
- if (!(*binary = av_malloc(*size))) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Memory allocation error\n");
- return AVERROR_NOMEM;
- }
-
- if (get_buffer(pb, *binary, *size) != *size) {
- offset_t pos = url_ftell(pb);
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
- return AVERROR_IO;
- }
-
- return 0;
-}
-
-/*
- * Read signed/unsigned "EBML" numbers.
- * Return: number of bytes processed, < 0 on error.
- * XXX: use ebml_read_num().
- */
-
-static int
-matroska_ebmlnum_uint (uint8_t *data,
- uint32_t size,
- uint64_t *num)
-{
- int len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
- uint64_t total;
-
- if (size <= 0)
- return AVERROR_INVALIDDATA;
-
- total = data[0];
- while (read <= 8 && !(total & len_mask)) {
- read++;
- len_mask >>= 1;
- }
- if (read > 8)
- return AVERROR_INVALIDDATA;
-
- if ((total &= (len_mask - 1)) == len_mask - 1)
- num_ffs++;
- if (size < read)
- return AVERROR_INVALIDDATA;
- while (n < read) {
- if (data[n] == 0xff)
- num_ffs++;
- total = (total << 8) | data[n];
- n++;
- }
-
- if (read == num_ffs)
- *num = (uint64_t)-1;
- else
- *num = total;
-
- return read;
-}
-
-/*
- * Same as above, but signed.
- */
-
-static int
-matroska_ebmlnum_sint (uint8_t *data,
- uint32_t size,
- int64_t *num)
-{
- uint64_t unum;
- int res;
-
- /* read as unsigned number first */
- if ((res = matroska_ebmlnum_uint(data, size, &unum)) < 0)
- return res;
-
- /* make signed (weird way) */
- if (unum == (uint64_t)-1)
- *num = INT64_MAX;
- else
- *num = unum - ((1LL << ((7 * res) - 1)) - 1);
-
- return res;
-}
-
-/*
- * Read an EBML header.
- * 0 is success, < 0 is failure.
- */
-
-static int
-ebml_read_header (MatroskaDemuxContext *matroska,
- char **doctype,
- int *version)
-{
- uint32_t id;
- int level_up, res = 0;
-
- /* default init */
- if (doctype)
- *doctype = NULL;
- if (version)
- *version = 1;
-
- if (!(id = ebml_peek_id(matroska, &level_up)) ||
- level_up != 0 || id != EBML_ID_HEADER) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "This is not an EBML file (id=0x%x/0x%x)\n", id, EBML_ID_HEADER);
- return AVERROR_INVALIDDATA;
- }
- if ((res = ebml_read_master(matroska, &id)) < 0)
- return res;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &level_up)))
- return AVERROR_IO;
-
- /* end-of-header */
- if (level_up)
- break;
-
- switch (id) {
- /* is our read version uptodate? */
- case EBML_ID_EBMLREADVERSION: {
- uint64_t num;
-
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- return res;
- if (num > EBML_VERSION) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "EBML version %"PRIu64" (> %d) is not supported\n",
- num, EBML_VERSION);
- return AVERROR_INVALIDDATA;
- }
- break;
- }
-
- /* we only handle 8 byte lengths at max */
- case EBML_ID_EBMLMAXSIZELENGTH: {
- uint64_t num;
-
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- return res;
- if (num > sizeof(uint64_t)) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Integers of size %"PRIu64" (> %zd) not supported\n",
- num, sizeof(uint64_t));
- return AVERROR_INVALIDDATA;
- }
- break;
- }
-
- /* we handle 4 byte IDs at max */
- case EBML_ID_EBMLMAXIDLENGTH: {
- uint64_t num;
-
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- return res;
- if (num > sizeof(uint32_t)) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "IDs of size %"PRIu64" (> %zu) not supported\n",
- num, sizeof(uint32_t));
- return AVERROR_INVALIDDATA;
- }
- break;
- }
-
- case EBML_ID_DOCTYPE: {
- char *text;
-
- if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
- return res;
- if (doctype) {
- if (*doctype)
- av_free(*doctype);
- *doctype = text;
- } else
- av_free(text);
- break;
- }
-
- case EBML_ID_DOCTYPEREADVERSION: {
- uint64_t num;
-
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- return res;
- if (version)
- *version = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown data type 0x%x in EBML header", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- /* we ignore these two, as they don't tell us anything we
- * care about */
- case EBML_ID_EBMLVERSION:
- case EBML_ID_DOCTYPEVERSION:
- res = ebml_read_skip (matroska);
- break;
- }
- }
-
- return 0;
-}
-
-/*
- * Put one packet in an application-supplied AVPacket struct.
- * Returns 0 on success or -1 on failure.
- */
-
-static int
-matroska_deliver_packet (MatroskaDemuxContext *matroska,
- AVPacket *pkt)
-{
- if (matroska->num_packets > 0) {
- memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
- av_free(matroska->packets[0]);
- if (matroska->num_packets > 1) {
- memmove(&matroska->packets[0], &matroska->packets[1],
- (matroska->num_packets - 1) * sizeof(AVPacket *));
- matroska->packets =
- av_realloc(matroska->packets, (matroska->num_packets - 1) *
- sizeof(AVPacket *));
- } else {
- av_freep(&matroska->packets);
- }
- matroska->num_packets--;
- return 0;
- }
-
- return -1;
-}
-
-/*
- * Put a packet into our internal queue. Will be delivered to the
- * user/application during the next get_packet() call.
- */
-
-static void
-matroska_queue_packet (MatroskaDemuxContext *matroska,
- AVPacket *pkt)
-{
- matroska->packets =
- av_realloc(matroska->packets, (matroska->num_packets + 1) *
- sizeof(AVPacket *));
- matroska->packets[matroska->num_packets] = pkt;
- matroska->num_packets++;
-}
-
-/*
- * Put a packet into our internal reordering queue. Will be moved to the
- * main packet queue when enough packets are available to reorder pts.
- */
-
-static void
-matroska_queue_packet_reordered (MatroskaDemuxContext *matroska,
- AVPacket *pkt,
- int is_bframe)
-{
- if (matroska->num_packets_reorder && !is_bframe
- && pkt->pts > matroska->reorder_max_pts) {
- /* reorder pts */
- int i, j, k = 1;
- for (j=matroska->num_packets_reorder-1; j && k; j--) {
- k = 0;
- for (i=0; i<j; i++) {
- if (matroska->packets_reorder[i]->pts > matroska->packets_reorder[i+1]->pts) {
- FFSWAP(uint64_t, matroska->packets_reorder[i]->pts, matroska->packets_reorder[i+1]->pts);
- k = 1;
- }
- }
- }
- /* then really queue the packets */
- for (i=0; i<matroska->num_packets_reorder; i++)
- matroska_queue_packet (matroska, matroska->packets_reorder[i]);
- matroska->num_packets_reorder = 0;
- }
- matroska->packets_reorder =
- av_realloc(matroska->packets_reorder,
- (matroska->num_packets_reorder + 1) * sizeof(AVPacket *));
- matroska->packets_reorder[matroska->num_packets_reorder++] = pkt;
- if (pkt->pts > matroska->reorder_max_pts)
- matroska->reorder_max_pts = pkt->pts;
-}
-
-
-/*
- * Autodetecting...
- */
-
-static int
-matroska_probe (AVProbeData *p)
-{
- uint64_t total = 0;
- int len_mask = 0x80, size = 1, n = 1;
- uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
-
- if (p->buf_size < 5)
- return 0;
-
- /* ebml header? */
- if ((p->buf[0] << 24 | p->buf[1] << 16 |
- p->buf[2] << 8 | p->buf[3]) != EBML_ID_HEADER)
- return 0;
-
- /* length of header */
- total = p->buf[4];
- while (size <= 8 && !(total & len_mask)) {
- size++;
- len_mask >>= 1;
- }
- if (size > 8)
- 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;
-
- /* the header must contain the document type 'matroska'. For now,
- * we don't parse the whole header but simply check for the
- * availability of that array of characters inside the header.
- * Not fully fool-proof, but good enough. */
- for (n = 4 + size; n <= 4 + size + total - sizeof(probe_data); n++)
- if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data)))
- return AVPROBE_SCORE_MAX;
-
- return 0;
-}
-
-/*
- * From here on, it's all XML-style DTD stuff... Needs no comments.
- */
-
-static int
-matroska_parse_info (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* cluster timecode */
- case MATROSKA_ID_TIMECODESCALE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- matroska->time_scale = num;
- break;
- }
-
- case MATROSKA_ID_DURATION: {
- double num;
- if ((res = ebml_read_float(matroska, &id, &num)) < 0)
- break;
- matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE;
- break;
- }
-
- case MATROSKA_ID_TITLE: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- strncpy(matroska->ctx->title, text,
- sizeof(matroska->ctx->title)-1);
- av_free(text);
- break;
- }
-
- case MATROSKA_ID_WRITINGAPP: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- matroska->writing_app = text;
- break;
- }
-
- case MATROSKA_ID_MUXINGAPP: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- matroska->muxing_app = text;
- break;
- }
-
- case MATROSKA_ID_DATEUTC: {
- int64_t time;
- if ((res = ebml_read_date(matroska, &id, &time)) < 0)
- break;
- matroska->created = time;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in info header\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_add_stream (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
- MatroskaTrack *track;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n");
-
- /* Allocate a generic track. As soon as we know its type we'll realloc. */
- track = av_mallocz(MAX_TRACK_SIZE);
- matroska->num_tracks++;
-
- /* start with the master */
- if ((res = ebml_read_master(matroska, &id)) < 0)
- return res;
-
- /* try reading the trackentry headers */
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* track number (unique stream ID) */
- case MATROSKA_ID_TRACKNUMBER: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->num = num;
- break;
- }
-
- /* track UID (unique identifier) */
- case MATROSKA_ID_TRACKUID: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->uid = num;
- break;
- }
-
- /* track type (video, audio, combined, subtitle, etc.) */
- case MATROSKA_ID_TRACKTYPE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (track->type && track->type != num) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "More than one tracktype in an entry - skip\n");
- break;
- }
- track->type = num;
-
- switch (track->type) {
- case MATROSKA_TRACK_TYPE_VIDEO:
- case MATROSKA_TRACK_TYPE_AUDIO:
- case MATROSKA_TRACK_TYPE_SUBTITLE:
- break;
- case MATROSKA_TRACK_TYPE_COMPLEX:
- case MATROSKA_TRACK_TYPE_LOGO:
- case MATROSKA_TRACK_TYPE_CONTROL:
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown or unsupported track type 0x%x\n",
- track->type);
- track->type = 0;
- break;
- }
- matroska->tracks[matroska->num_tracks - 1] = track;
- break;
- }
-
- /* tracktype specific stuff for video */
- case MATROSKA_ID_TRACKVIDEO: {
- MatroskaVideoTrack *videotrack;
- if (!track->type)
- track->type = MATROSKA_TRACK_TYPE_VIDEO;
- if (track->type != MATROSKA_TRACK_TYPE_VIDEO) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "video data in non-video track - ignoring\n");
- res = AVERROR_INVALIDDATA;
- break;
- } else if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- videotrack = (MatroskaVideoTrack *)track;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* fixme, this should be one-up, but I get it here */
- case MATROSKA_ID_TRACKDEFAULTDURATION: {
- uint64_t num;
- if ((res = ebml_read_uint (matroska, &id,
- &num)) < 0)
- break;
- track->default_duration = num/matroska->time_scale;
- break;
- }
-
- /* video framerate */
- case MATROSKA_ID_VIDEOFRAMERATE: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- track->default_duration = 1000000000/(matroska->time_scale*num);
- break;
- }
-
- /* width of the size to display the video at */
- case MATROSKA_ID_VIDEODISPLAYWIDTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->display_width = num;
- break;
- }
-
- /* height of the size to display the video at */
- case MATROSKA_ID_VIDEODISPLAYHEIGHT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->display_height = num;
- break;
- }
-
- /* width of the video in the file */
- case MATROSKA_ID_VIDEOPIXELWIDTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->pixel_width = num;
- break;
- }
-
- /* height of the video in the file */
- case MATROSKA_ID_VIDEOPIXELHEIGHT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->pixel_height = num;
- break;
- }
-
- /* whether the video is interlaced */
- case MATROSKA_ID_VIDEOFLAGINTERLACED: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- if (num)
- track->flags |=
- MATROSKA_VIDEOTRACK_INTERLACED;
- else
- track->flags &=
- ~MATROSKA_VIDEOTRACK_INTERLACED;
- break;
- }
-
- /* stereo mode (whether the video has two streams,
- * where one is for the left eye and the other for
- * the right eye, which creates a 3D-like
- * effect) */
- case MATROSKA_ID_VIDEOSTEREOMODE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- if (num != MATROSKA_EYE_MODE_MONO &&
- num != MATROSKA_EYE_MODE_LEFT &&
- num != MATROSKA_EYE_MODE_RIGHT &&
- num != MATROSKA_EYE_MODE_BOTH) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Ignoring unknown eye mode 0x%x\n",
- (uint32_t) num);
- break;
- }
- videotrack->eye_mode = num;
- break;
- }
-
- /* aspect ratio behaviour */
- case MATROSKA_ID_VIDEOASPECTRATIO: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- if (num != MATROSKA_ASPECT_RATIO_MODE_FREE &&
- num != MATROSKA_ASPECT_RATIO_MODE_KEEP &&
- num != MATROSKA_ASPECT_RATIO_MODE_FIXED) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Ignoring unknown aspect ratio 0x%x\n",
- (uint32_t) num);
- break;
- }
- videotrack->ar_mode = num;
- break;
- }
-
- /* colourspace (only matters for raw video)
- * fourcc */
- case MATROSKA_ID_VIDEOCOLOURSPACE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- videotrack->fourcc = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown video track header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
- break;
- }
-
- /* tracktype specific stuff for audio */
- case MATROSKA_ID_TRACKAUDIO: {
- MatroskaAudioTrack *audiotrack;
- if (!track->type)
- track->type = MATROSKA_TRACK_TYPE_AUDIO;
- if (track->type != MATROSKA_TRACK_TYPE_AUDIO) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "audio data in non-audio track - ignoring\n");
- res = AVERROR_INVALIDDATA;
- break;
- } else if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- audiotrack = (MatroskaAudioTrack *)track;
- audiotrack->channels = 1;
- audiotrack->samplerate = 8000;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up > 0) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* samplerate */
- case MATROSKA_ID_AUDIOSAMPLINGFREQ: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->internal_samplerate =
- audiotrack->samplerate = num;
- break;
- }
-
- case MATROSKA_ID_AUDIOOUTSAMPLINGFREQ: {
- double num;
- if ((res = ebml_read_float(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->samplerate = num;
- break;
- }
-
- /* bitdepth */
- case MATROSKA_ID_AUDIOBITDEPTH: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->bitdepth = num;
- break;
- }
-
- /* channels */
- case MATROSKA_ID_AUDIOCHANNELS: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id,
- &num)) < 0)
- break;
- audiotrack->channels = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown audio track header entry "
- "0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
- break;
- }
-
- /* codec identifier */
- case MATROSKA_ID_CODECID: {
- char *text;
- if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
- break;
- track->codec_id = text;
- break;
- }
-
- /* codec private data */
- case MATROSKA_ID_CODECPRIVATE: {
- uint8_t *data;
- int size;
- if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))
- break;
- track->codec_priv = data;
- track->codec_priv_size = size;
- break;
- }
-
- /* name of the codec */
- case MATROSKA_ID_CODECNAME: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- track->codec_name = text;
- break;
- }
-
- /* name of this track */
- case MATROSKA_ID_TRACKNAME: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- track->name = text;
- break;
- }
-
- /* language (matters for audio/subtitles, mostly) */
- case MATROSKA_ID_TRACKLANGUAGE: {
- char *text;
- if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
- break;
- track->language = text;
- break;
- }
-
- /* whether this is actually used */
- case MATROSKA_ID_TRACKFLAGENABLED: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (num)
- track->flags |= MATROSKA_TRACK_ENABLED;
- else
- track->flags &= ~MATROSKA_TRACK_ENABLED;
- break;
- }
-
- /* whether it's the default for this track type */
- case MATROSKA_ID_TRACKFLAGDEFAULT: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (num)
- track->flags |= MATROSKA_TRACK_DEFAULT;
- else
- track->flags &= ~MATROSKA_TRACK_DEFAULT;
- break;
- }
-
- /* lacing (like MPEG, where blocks don't end/start on frame
- * boundaries) */
- case MATROSKA_ID_TRACKFLAGLACING: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- if (num)
- track->flags |= MATROSKA_TRACK_LACING;
- else
- track->flags &= ~MATROSKA_TRACK_LACING;
- break;
- }
-
- /* default length (in time) of one data block in this track */
- case MATROSKA_ID_TRACKDEFAULTDURATION: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- track->default_duration = num / matroska->time_scale;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown track header entry 0x%x - ignoring\n", id);
- /* pass-through */
-
- case EBML_ID_VOID:
- /* we ignore these because they're nothing useful. */
- case MATROSKA_ID_CODECINFOURL:
- case MATROSKA_ID_CODECDOWNLOADURL:
- case MATROSKA_ID_TRACKMINCACHE:
- case MATROSKA_ID_TRACKMAXCACHE:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_parse_tracks (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing tracks...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* one track within the "all-tracks" header */
- case MATROSKA_ID_TRACKENTRY:
- res = matroska_add_stream(matroska);
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in track header\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_parse_index (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
- MatroskaDemuxIndex idx;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing index...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* one single index entry ('point') */
- case MATROSKA_ID_POINTENTRY:
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- /* in the end, we hope to fill one entry with a
- * timestamp, a file position and a tracknum */
- idx.pos = (uint64_t) -1;
- idx.time = (uint64_t) -1;
- idx.track = (uint16_t) -1;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* one single index entry ('point') */
- case MATROSKA_ID_CUETIME: {
- uint64_t time;
- if ((res = ebml_read_uint(matroska, &id,
- &time)) < 0)
- break;
- idx.time = time * matroska->time_scale;
- break;
- }
-
- /* position in the file + track to which it
- * belongs */
- case MATROSKA_ID_CUETRACKPOSITION:
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- while (res == 0) {
- if (!(id = ebml_peek_id (matroska,
- &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* track number */
- case MATROSKA_ID_CUETRACK: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska,
- &id, &num)) < 0)
- break;
- idx.track = num;
- break;
- }
-
- /* position in file */
- case MATROSKA_ID_CUECLUSTERPOSITION: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska,
- &id, &num)) < 0)
- break;
- idx.pos = num;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in "
- "CuesTrackPositions\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in cuespoint "
- "index\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- /* so let's see if we got what we wanted */
- if (idx.pos != (uint64_t) -1 &&
- idx.time != (uint64_t) -1 &&
- idx.track != (uint16_t) -1) {
- if (matroska->num_indexes % 32 == 0) {
- /* re-allocate bigger index */
- matroska->index =
- av_realloc(matroska->index,
- (matroska->num_indexes + 32) *
- sizeof(MatroskaDemuxIndex));
- }
- matroska->index[matroska->num_indexes] = idx;
- matroska->num_indexes++;
- }
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in cues header\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_parse_metadata (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* Hm, this is unsupported... */
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in metadata header\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_parse_seekhead (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing seekhead...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_SEEKENTRY: {
- uint32_t seek_id = 0, peek_id_cache = 0;
- uint64_t seek_pos = (uint64_t) -1, t;
-
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_SEEKID:
- res = ebml_read_uint(matroska, &id, &t);
- seek_id = t;
- break;
-
- case MATROSKA_ID_SEEKPOSITION:
- res = ebml_read_uint(matroska, &id, &seek_pos);
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown seekhead ID 0x%x\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- if (!seek_id || seek_pos == (uint64_t) -1) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Incomplete seekhead entry (0x%x/%"PRIu64")\n",
- seek_id, seek_pos);
- break;
- }
-
- switch (seek_id) {
- case MATROSKA_ID_CUES:
- case MATROSKA_ID_TAGS: {
- uint32_t level_up = matroska->level_up;
- offset_t before_pos;
- uint64_t length;
- MatroskaLevel level;
-
- /* remember the peeked ID and the current position */
- peek_id_cache = matroska->peek_id;
- before_pos = url_ftell(&matroska->ctx->pb);
-
- /* seek */
- if ((res = ebml_read_seek(matroska, seek_pos +
- matroska->segment_start)) < 0)
- return res;
-
- /* we don't want to lose our seekhead level, so we add
- * a dummy. This is a crude hack. */
- if (matroska->num_levels == EBML_MAX_DEPTH) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Max EBML element depth (%d) reached, "
- "cannot parse further.\n", EBML_MAX_DEPTH);
- return AVERROR_UNKNOWN;
- }
-
- level.start = 0;
- level.length = (uint64_t)-1;
- matroska->levels[matroska->num_levels] = level;
- matroska->num_levels++;
-
- /* check ID */
- if (!(id = ebml_peek_id (matroska,
- &matroska->level_up)))
- goto finish;
- if (id != seek_id) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "We looked for ID=0x%x but got "
- "ID=0x%x (pos=%"PRIu64")",
- seek_id, id, seek_pos +
- matroska->segment_start);
- goto finish;
- }
-
- /* read master + parse */
- if ((res = ebml_read_master(matroska, &id)) < 0)
- goto finish;
- switch (id) {
- case MATROSKA_ID_CUES:
- if (!(res = matroska_parse_index(matroska)) ||
- url_feof(&matroska->ctx->pb)) {
- matroska->index_parsed = 1;
- res = 0;
- }
- break;
- case MATROSKA_ID_TAGS:
- if (!(res = matroska_parse_metadata(matroska)) ||
- url_feof(&matroska->ctx->pb)) {
- matroska->metadata_parsed = 1;
- res = 0;
- }
- break;
- }
-
- finish:
- /* remove dummy level */
- while (matroska->num_levels) {
- matroska->num_levels--;
- length =
- matroska->levels[matroska->num_levels].length;
- if (length == (uint64_t)-1)
- break;
- }
-
- /* seek back */
- if ((res = ebml_read_seek(matroska, before_pos)) < 0)
- return res;
- matroska->peek_id = peek_id_cache;
- matroska->level_up = level_up;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Ignoring seekhead entry for ID=0x%x\n",
- seek_id);
- break;
- }
-
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown seekhead ID 0x%x\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
-
-static int
-matroska_aac_profile (char *codec_id)
-{
- static const char *aac_profiles[] = {
- "MAIN", "LC", "SSR"
- };
- int profile;
-
- for (profile=0; profile<ARRAY_SIZE(aac_profiles); profile++)
- if (strstr(codec_id, aac_profiles[profile]))
- break;
- return profile + 1;
-}
-
-static int
-matroska_aac_sri (int samplerate)
-{
- static const int aac_sample_rates[] = {
- 96000, 88200, 64000, 48000, 44100, 32000,
- 24000, 22050, 16000, 12000, 11025, 8000,
- };
- int sri;
-
- for (sri=0; sri<ARRAY_SIZE(aac_sample_rates); sri++)
- if (aac_sample_rates[sri] == samplerate)
- break;
- return sri;
-}
-
-static int
-matroska_read_header (AVFormatContext *s,
- AVFormatParameters *ap)
-{
- MatroskaDemuxContext *matroska = s->priv_data;
- char *doctype;
- int version, last_level, res = 0;
- uint32_t id;
-
- matroska->ctx = s;
-
- /* First read the EBML header. */
- doctype = NULL;
- if ((res = ebml_read_header(matroska, &doctype, &version)) < 0)
- return res;
- if ((doctype == NULL) || strcmp(doctype, "matroska")) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Wrong EBML doctype ('%s' != 'matroska').\n",
- doctype ? doctype : "(none)");
- if (doctype)
- av_free(doctype);
- return AVERROR_NOFMT;
- }
- av_free(doctype);
- if (version > 2) {
- av_log(matroska->ctx, AV_LOG_ERROR,
- "Matroska demuxer version 2 too old for file version %d\n",
- version);
- return AVERROR_NOFMT;
- }
-
- /* The next thing is a segment. */
- while (1) {
- if (!(id = ebml_peek_id(matroska, &last_level)))
- return AVERROR_IO;
- if (id == MATROSKA_ID_SEGMENT)
- break;
-
- /* oi! */
- av_log(matroska->ctx, AV_LOG_INFO,
- "Expected a Segment ID (0x%x), but received 0x%x!\n",
- MATROSKA_ID_SEGMENT, id);
- if ((res = ebml_read_skip(matroska)) < 0)
- return res;
- }
-
- /* We now have a Matroska segment.
- * Seeks are from the beginning of the segment,
- * after the segment ID/length. */
- if ((res = ebml_read_master(matroska, &id)) < 0)
- return res;
- matroska->segment_start = url_ftell(&s->pb);
-
- matroska->time_scale = 1000000;
- /* we've found our segment, start reading the different contents in here */
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* stream info */
- case MATROSKA_ID_INFO: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_info(matroska);
- break;
- }
-
- /* track info headers */
- case MATROSKA_ID_TRACKS: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_tracks(matroska);
- break;
- }
-
- /* stream index */
- case MATROSKA_ID_CUES: {
- if (!matroska->index_parsed) {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_index(matroska);
- } else
- res = ebml_read_skip(matroska);
- break;
- }
-
- /* metadata */
- case MATROSKA_ID_TAGS: {
- if (!matroska->metadata_parsed) {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_metadata(matroska);
- } else
- res = ebml_read_skip(matroska);
- break;
- }
-
- /* file index (if seekable, seek to Cues/Tags to parse it) */
- case MATROSKA_ID_SEEKHEAD: {
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_seekhead(matroska);
- break;
- }
-
- case MATROSKA_ID_CLUSTER: {
- /* Do not read the master - this will be done in the next
- * call to matroska_read_packet. */
- res = 1;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown matroska file header ID 0x%x\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- /* Have we found a cluster? */
- if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) {
- int i, j;
- MatroskaTrack *track;
- AVStream *st;
-
- for (i = 0; i < matroska->num_tracks; i++) {
- enum CodecID codec_id = CODEC_ID_NONE;
- uint8_t *extradata = NULL;
- int extradata_size = 0;
- int extradata_offset = 0;
- track = matroska->tracks[i];
-
- /* libavformat does not really support subtitles.
- * Also apply some sanity checks. */
- if ((track->type == MATROSKA_TRACK_TYPE_SUBTITLE) ||
- (track->codec_id == NULL))
- continue;
-
- for(j=0; codec_tags[j].str; j++){
- if(!strncmp(codec_tags[j].str, track->codec_id,
- strlen(codec_tags[j].str))){
- codec_id= codec_tags[j].id;
- break;
- }
- }
-
- /* Set the FourCC from the CodecID. */
- /* This is the MS compatibility mode which stores a
- * BITMAPINFOHEADER in the CodecPrivate. */
- if (!strcmp(track->codec_id,
- MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC) &&
- (track->codec_priv_size >= 40) &&
- (track->codec_priv != NULL)) {
- unsigned char *p;
-
- /* Offset of biCompression. Stored in LE. */
- p = (unsigned char *)track->codec_priv + 16;
- ((MatroskaVideoTrack *)track)->fourcc = (p[3] << 24) |
- (p[2] << 16) | (p[1] << 8) | p[0];
- codec_id = codec_get_id(codec_bmp_tags, ((MatroskaVideoTrack *)track)->fourcc);
-
- }
-
- /* This is the MS compatibility mode which stores a
- * WAVEFORMATEX in the CodecPrivate. */
- else if (!strcmp(track->codec_id,
- MATROSKA_CODEC_ID_AUDIO_ACM) &&
- (track->codec_priv_size >= 18) &&
- (track->codec_priv != NULL)) {
- unsigned char *p;
- uint16_t tag;
-
- /* Offset of wFormatTag. Stored in LE. */
- p = (unsigned char *)track->codec_priv;
- tag = (p[1] << 8) | p[0];
- codec_id = codec_get_id(codec_wav_tags, tag);
-
- }
-
- else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
- int profile = matroska_aac_profile(track->codec_id);
- int sri = matroska_aac_sri(audiotrack->internal_samplerate);
- extradata = av_malloc(5);
- if (extradata == NULL)
- return AVERROR_NOMEM;
- extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
- extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3);
- if (strstr(track->codec_id, "SBR")) {
- sri = matroska_aac_sri(audiotrack->samplerate);
- extradata[2] = 0x56;
- extradata[3] = 0xE5;
- extradata[4] = 0x80 | (sri<<3);
- extradata_size = 5;
- } else {
- extradata_size = 2;
- }
- track->default_duration = 1024*1000 / audiotrack->internal_samplerate;
- }
-
- else if (codec_id == CODEC_ID_TTA) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
- ByteIOContext b;
- extradata_size = 30;
- extradata = av_mallocz(extradata_size);
- if (extradata == NULL)
- return AVERROR_NOMEM;
- init_put_byte(&b, extradata, extradata_size, 1,
- NULL, NULL, NULL, NULL);
- put_buffer(&b, (uint8_t *) "TTA1", 4);
- put_le16(&b, 1);
- put_le16(&b, audiotrack->channels);
- put_le16(&b, audiotrack->bitdepth);
- put_le32(&b, audiotrack->samplerate);
- put_le32(&b, matroska->ctx->duration * audiotrack->samplerate);
- }
-
- else if (codec_id == CODEC_ID_RV10 || codec_id == CODEC_ID_RV20 ||
- codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
- extradata_offset = 26;
- track->codec_priv_size -= extradata_offset;
- track->flags |= MATROSKA_TRACK_REAL_V;
- }
-
- if (codec_id == CODEC_ID_NONE) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown/unsupported CodecID %s.\n",
- track->codec_id);
- }
-
- track->stream_index = matroska->num_streams;
-
- matroska->num_streams++;
- st = av_new_stream(s, track->stream_index);
- if (st == NULL)
- return AVERROR_NOMEM;
- av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
-
- st->codec->codec_id = codec_id;
-
- if (track->default_duration)
- av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
- track->default_duration, 1000, 30000);
-
- if(extradata){
- st->codec->extradata = extradata;
- st->codec->extradata_size = extradata_size;
- } else if(track->codec_priv && track->codec_priv_size > 0){
- st->codec->extradata = av_malloc(track->codec_priv_size);
- if(st->codec->extradata == NULL)
- return AVERROR_NOMEM;
- st->codec->extradata_size = track->codec_priv_size;
- memcpy(st->codec->extradata,track->codec_priv+extradata_offset,
- track->codec_priv_size);
- }
-
- if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
- MatroskaVideoTrack *videotrack = (MatroskaVideoTrack *)track;
-
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_tag = videotrack->fourcc;
- st->codec->width = videotrack->pixel_width;
- st->codec->height = videotrack->pixel_height;
- if (videotrack->display_width == 0)
- videotrack->display_width= videotrack->pixel_width;
- if (videotrack->display_height == 0)
- videotrack->display_height= videotrack->pixel_height;
- av_reduce(&st->codec->sample_aspect_ratio.num,
- &st->codec->sample_aspect_ratio.den,
- st->codec->height * videotrack->display_width,
- st->codec-> width * videotrack->display_height,
- 255);
- st->need_parsing = 2;
- } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
- MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
-
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->sample_rate = audiotrack->samplerate;
- st->codec->channels = audiotrack->channels;
- } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
- st->codec->codec_type = CODEC_TYPE_SUBTITLE;
- }
-
- /* What do we do with private data? E.g. for Vorbis. */
- }
- res = 0;
- }
-
- return res;
-}
-
-static int
-matroska_find_track_by_num (MatroskaDemuxContext *matroska,
- int num)
-{
- int i;
-
- for (i = 0; i < matroska->num_tracks; i++)
- if (matroska->tracks[i]->num == num)
- return i;
-
- return -1;
-}
-
-static inline int
-rv_offset(uint8_t *data, int slice, int slices)
-{
- return AV_RL32(data+8*slice+4) + 8*slices;
-}
-
-static int
-matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
- int64_t pos, uint64_t cluster_time, uint64_t duration,
- int is_keyframe, int is_bframe)
-{
- int res = 0;
- int track;
- AVPacket *pkt;
- uint8_t *origdata = data;
- int16_t block_time;
- uint32_t *lace_size = NULL;
- int n, flags, laces = 0;
- uint64_t num;
-
- /* first byte(s): tracknum */
- if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) {
- av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n");
- av_free(origdata);
- return res;
- }
- data += n;
- size -= n;
-
- /* fetch track from num */
- track = matroska_find_track_by_num(matroska, num);
- if (size <= 3 || track < 0 || track >= matroska->num_tracks) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "Invalid stream %d or size %u\n", track, size);
- av_free(origdata);
- return res;
- }
- if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard >= AVDISCARD_ALL){
- av_free(origdata);
- return res;
- }
- if (duration == AV_NOPTS_VALUE)
- duration = matroska->tracks[track]->default_duration;
-
- /* block_time (relative to cluster time) */
- block_time = (data[0] << 8) | data[1];
- data += 2;
- size -= 2;
- flags = *data;
- data += 1;
- size -= 1;
- if (is_keyframe == -1)
- is_keyframe = flags & 1 ? PKT_FLAG_KEY : 0;
- switch ((flags & 0x06) >> 1) {
- case 0x0: /* no lacing */
- laces = 1;
- lace_size = av_mallocz(sizeof(int));
- lace_size[0] = size;
- break;
-
- case 0x1: /* xiph lacing */
- case 0x2: /* fixed-size lacing */
- case 0x3: /* EBML lacing */
- if (size == 0) {
- res = -1;
- break;
- }
- laces = (*data) + 1;
- data += 1;
- size -= 1;
- lace_size = av_mallocz(laces * sizeof(int));
-
- switch ((flags & 0x06) >> 1) {
- case 0x1: /* xiph lacing */ {
- uint8_t temp;
- uint32_t total = 0;
- for (n = 0; res == 0 && n < laces - 1; n++) {
- while (1) {
- if (size == 0) {
- res = -1;
- break;
- }
- temp = *data;
- lace_size[n] += temp;
- data += 1;
- size -= 1;
- if (temp != 0xff)
- break;
- }
- total += lace_size[n];
- }
- lace_size[n] = size - total;
- break;
- }
-
- case 0x2: /* fixed-size lacing */
- for (n = 0; n < laces; n++)
- lace_size[n] = size / laces;
- break;
-
- case 0x3: /* EBML lacing */ {
- uint32_t total;
- n = matroska_ebmlnum_uint(data, size, &num);
- if (n < 0) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "EBML block data error\n");
- break;
- }
- data += n;
- size -= n;
- total = lace_size[0] = num;
- for (n = 1; res == 0 && n < laces - 1; n++) {
- int64_t snum;
- int r;
- r = matroska_ebmlnum_sint (data, size, &snum);
- if (r < 0) {
- av_log(matroska->ctx, AV_LOG_INFO,
- "EBML block data error\n");
- break;
- }
- data += r;
- size -= r;
- lace_size[n] = lace_size[n - 1] + snum;
- total += lace_size[n];
- }
- lace_size[n] = size - total;
- break;
- }
- }
- break;
- }
-
- if (res == 0) {
- int real_v = matroska->tracks[track]->flags & MATROSKA_TRACK_REAL_V;
- uint64_t timecode = AV_NOPTS_VALUE;
-
- if (cluster_time != (uint64_t)-1 && cluster_time + block_time >= 0)
- timecode = cluster_time + block_time;
-
- for (n = 0; n < laces; n++) {
- int slice, slices = 1;
-
- if (real_v) {
- slices = *data++ + 1;
- lace_size[n]--;
- }
-
- for (slice=0; slice<slices; slice++) {
- int slice_size, slice_offset = 0;
- if (real_v)
- slice_offset = rv_offset(data, slice, slices);
- if (slice+1 == slices)
- slice_size = lace_size[n] - slice_offset;
- else
- slice_size = rv_offset(data, slice+1, slices) - slice_offset;
- pkt = av_mallocz(sizeof(AVPacket));
- /* XXX: prevent data copy... */
- if (av_new_packet(pkt, slice_size) < 0) {
- res = AVERROR_NOMEM;
- n = laces-1;
- break;
- }
- memcpy (pkt->data, data+slice_offset, slice_size);
-
- if (n == 0)
- pkt->flags = is_keyframe;
- pkt->stream_index = matroska->tracks[track]->stream_index;
-
- pkt->pts = timecode;
- pkt->pos = pos;
- pkt->duration = duration;
-
- if (matroska->tracks[track]->flags & MATROSKA_TRACK_REORDER)
- matroska_queue_packet_reordered(matroska, pkt, is_bframe);
- else
- matroska_queue_packet(matroska, pkt);
-
- if (timecode != AV_NOPTS_VALUE)
- timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
- }
- data += lace_size[n];
- }
- }
-
- av_free(lace_size);
- av_free(origdata);
- return res;
-}
-
-static int
-matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
- uint64_t cluster_time)
-{
- int res = 0;
- uint32_t id;
- int is_bframe = 0;
- int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets;
- uint64_t duration = AV_NOPTS_VALUE;
- uint8_t *data;
- int size = 0;
- int64_t pos = 0;
-
- av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n");
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* one block inside the group. Note, block parsing is one
- * of the harder things, so this code is a bit complicated.
- * See http://www.matroska.org/ for documentation. */
- case MATROSKA_ID_BLOCK: {
- pos = url_ftell(&matroska->ctx->pb);
- res = ebml_read_binary(matroska, &id, &data, &size);
- break;
- }
-
- case MATROSKA_ID_BLOCKDURATION: {
- if ((res = ebml_read_uint(matroska, &id, &duration)) < 0)
- break;
- duration /= matroska->time_scale;
- break;
- }
-
- case MATROSKA_ID_BLOCKREFERENCE: {
- int64_t num;
- /* We've found a reference, so not even the first frame in
- * the lace is a key frame. */
- is_keyframe = 0;
- if (last_num_packets != matroska->num_packets)
- matroska->packets[last_num_packets]->flags = 0;
- if ((res = ebml_read_sint(matroska, &id, &num)) < 0)
- break;
- if (num > 0)
- is_bframe = 1;
- break;
- }
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in blockgroup data\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- if (res)
- return res;
-
- if (size > 0)
- res = matroska_parse_block(matroska, data, size, pos, cluster_time,
- duration, is_keyframe, is_bframe);
-
- return res;
-}
-
-static int
-matroska_parse_cluster (MatroskaDemuxContext *matroska)
-{
- int res = 0;
- uint32_t id;
- uint64_t cluster_time = 0;
- uint8_t *data;
- int64_t pos;
- int size;
-
- av_log(matroska->ctx, AV_LOG_DEBUG,
- "parsing cluster at %"PRId64"\n", url_ftell(&matroska->ctx->pb));
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- res = AVERROR_IO;
- break;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- /* cluster timecode */
- case MATROSKA_ID_CLUSTERTIMECODE: {
- uint64_t num;
- if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
- break;
- cluster_time = num;
- break;
- }
-
- /* a group of blocks inside a cluster */
- case MATROSKA_ID_BLOCKGROUP:
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- res = matroska_parse_blockgroup(matroska, cluster_time);
- break;
-
- case MATROSKA_ID_SIMPLEBLOCK:
- pos = url_ftell(&matroska->ctx->pb);
- res = ebml_read_binary(matroska, &id, &data, &size);
- if (res == 0)
- res = matroska_parse_block(matroska, data, size, pos,
- cluster_time, AV_NOPTS_VALUE,
- -1, 0);
- break;
-
- default:
- av_log(matroska->ctx, AV_LOG_INFO,
- "Unknown entry 0x%x in cluster data\n", id);
- /* fall-through */
-
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- return res;
-}
-
-static int
-matroska_read_packet (AVFormatContext *s,
- AVPacket *pkt)
-{
- MatroskaDemuxContext *matroska = s->priv_data;
- int res = 0;
- uint32_t id;
-
- /* Read stream until we have a packet queued. */
- while (matroska_deliver_packet(matroska, pkt)) {
-
- /* Have we already reached the end? */
- if (matroska->done)
- return AVERROR_IO;
-
- while (res == 0) {
- if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
- return AVERROR_IO;
- } else if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
-
- switch (id) {
- case MATROSKA_ID_CLUSTER:
- if ((res = ebml_read_master(matroska, &id)) < 0)
- break;
- if ((res = matroska_parse_cluster(matroska)) == 0)
- res = 1; /* Parsed one cluster, let's get out. */
- break;
-
- default:
- case EBML_ID_VOID:
- res = ebml_read_skip(matroska);
- break;
- }
-
- if (matroska->level_up) {
- matroska->level_up--;
- break;
- }
- }
-
- if (res == -1)
- matroska->done = 1;
- }
-
- return 0;
-}
-
-static int
-matroska_read_close (AVFormatContext *s)
-{
- MatroskaDemuxContext *matroska = s->priv_data;
- int n = 0;
-
- av_free(matroska->writing_app);
- av_free(matroska->muxing_app);
- av_free(matroska->index);
-
- if (matroska->packets != NULL) {
- for (n = 0; n < matroska->num_packets; n++) {
- av_free_packet(matroska->packets[n]);
- av_free(matroska->packets[n]);
- }
- av_free(matroska->packets);
- }
- if (matroska->packets_reorder) {
- for (n = 0; n < matroska->num_packets_reorder; n++) {
- av_free_packet(matroska->packets_reorder[n]);
- av_free(matroska->packets_reorder[n]);
- }
- av_free(matroska->packets_reorder);
- }
-
- for (n = 0; n < matroska->num_tracks; n++) {
- MatroskaTrack *track = matroska->tracks[n];
- av_free(track->codec_id);
- av_free(track->codec_name);
- av_free(track->codec_priv);
- av_free(track->name);
- av_free(track->language);
-
- av_free(track);
- }
-
- return 0;
-}
+const CodecMime ff_mkv_mime_tags[] = {
+ {"text/plain" , CODEC_ID_TEXT},
+ {"image/gif" , CODEC_ID_GIF},
+ {"image/jpeg" , CODEC_ID_MJPEG},
+ {"image/png" , CODEC_ID_PNG},
+ {"image/tiff" , CODEC_ID_TIFF},
+ {"application/x-truetype-font", CODEC_ID_TTF},
+ {"application/x-font" , CODEC_ID_TTF},
-AVInputFormat matroska_demuxer = {
- "matroska",
- "Matroska file format",
- sizeof(MatroskaDemuxContext),
- matroska_probe,
- matroska_read_header,
- matroska_read_packet,
- matroska_read_close,
+ {"" , CODEC_ID_NONE}
};
diff --git a/contrib/ffmpeg/libavformat/matroska.h b/contrib/ffmpeg/libavformat/matroska.h
new file mode 100644
index 000000000..370a8bfd8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/matroska.h
@@ -0,0 +1,210 @@
+/*
+ * Matroska constants
+ * Copyright (c) 2003-2004 The ffmpeg Project
+ *
+ * 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 FFMPEG_MATROSKA_H
+#define FFMPEG_MATROSKA_H
+
+#include "avcodec.h"
+
+/* EBML version supported */
+#define EBML_VERSION 1
+
+/* top-level master-IDs */
+#define EBML_ID_HEADER 0x1A45DFA3
+
+/* IDs in the HEADER master */
+#define EBML_ID_EBMLVERSION 0x4286
+#define EBML_ID_EBMLREADVERSION 0x42F7
+#define EBML_ID_EBMLMAXIDLENGTH 0x42F2
+#define EBML_ID_EBMLMAXSIZELENGTH 0x42F3
+#define EBML_ID_DOCTYPE 0x4282
+#define EBML_ID_DOCTYPEVERSION 0x4287
+#define EBML_ID_DOCTYPEREADVERSION 0x4285
+
+/* general EBML types */
+#define EBML_ID_VOID 0xEC
+
+/*
+ * Matroska element IDs. max. 32-bit.
+ */
+
+/* toplevel segment */
+#define MATROSKA_ID_SEGMENT 0x18538067
+
+/* matroska top-level master IDs */
+#define MATROSKA_ID_INFO 0x1549A966
+#define MATROSKA_ID_TRACKS 0x1654AE6B
+#define MATROSKA_ID_CUES 0x1C53BB6B
+#define MATROSKA_ID_TAGS 0x1254C367
+#define MATROSKA_ID_SEEKHEAD 0x114D9B74
+#define MATROSKA_ID_ATTACHMENTS 0x1941A469
+#define MATROSKA_ID_CLUSTER 0x1F43B675
+
+/* IDs in the info master */
+#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1
+#define MATROSKA_ID_DURATION 0x4489
+#define MATROSKA_ID_TITLE 0x7BA9
+#define MATROSKA_ID_WRITINGAPP 0x5741
+#define MATROSKA_ID_MUXINGAPP 0x4D80
+#define MATROSKA_ID_DATEUTC 0x4461
+#define MATROSKA_ID_SEGMENTUID 0x73A4
+
+/* ID in the tracks master */
+#define MATROSKA_ID_TRACKENTRY 0xAE
+
+/* IDs in the trackentry master */
+#define MATROSKA_ID_TRACKNUMBER 0xD7
+#define MATROSKA_ID_TRACKUID 0x73C5
+#define MATROSKA_ID_TRACKTYPE 0x83
+#define MATROSKA_ID_TRACKAUDIO 0xE1
+#define MATROSKA_ID_TRACKVIDEO 0xE0
+#define MATROSKA_ID_CODECID 0x86
+#define MATROSKA_ID_CODECPRIVATE 0x63A2
+#define MATROSKA_ID_CODECNAME 0x258688
+#define MATROSKA_ID_CODECINFOURL 0x3B4040
+#define MATROSKA_ID_CODECDOWNLOADURL 0x26B240
+#define MATROSKA_ID_TRACKNAME 0x536E
+#define MATROSKA_ID_TRACKLANGUAGE 0x22B59C
+#define MATROSKA_ID_TRACKFLAGENABLED 0xB9
+#define MATROSKA_ID_TRACKFLAGDEFAULT 0x88
+#define MATROSKA_ID_TRACKFLAGLACING 0x9C
+#define MATROSKA_ID_TRACKMINCACHE 0x6DE7
+#define MATROSKA_ID_TRACKMAXCACHE 0x6DF8
+#define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
+
+/* IDs in the trackvideo master */
+#define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
+#define MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
+#define MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
+#define MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
+#define MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
+#define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
+#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
+#define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
+#define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524
+
+/* IDs in the trackaudio master */
+#define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
+#define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5
+
+#define MATROSKA_ID_AUDIOBITDEPTH 0x6264
+#define MATROSKA_ID_AUDIOCHANNELS 0x9F
+
+/* ID in the cues master */
+#define MATROSKA_ID_POINTENTRY 0xBB
+
+/* IDs in the pointentry master */
+#define MATROSKA_ID_CUETIME 0xB3
+#define MATROSKA_ID_CUETRACKPOSITION 0xB7
+
+/* IDs in the cuetrackposition master */
+#define MATROSKA_ID_CUETRACK 0xF7
+#define MATROSKA_ID_CUECLUSTERPOSITION 0xF1
+
+/* IDs in the tags master */
+/* TODO */
+
+/* IDs in the seekhead master */
+#define MATROSKA_ID_SEEKENTRY 0x4DBB
+
+/* IDs in the seekpoint master */
+#define MATROSKA_ID_SEEKID 0x53AB
+#define MATROSKA_ID_SEEKPOSITION 0x53AC
+
+/* IDs in the cluster master */
+#define MATROSKA_ID_CLUSTERTIMECODE 0xE7
+#define MATROSKA_ID_BLOCKGROUP 0xA0
+#define MATROSKA_ID_SIMPLEBLOCK 0xA3
+
+/* IDs in the blockgroup master */
+#define MATROSKA_ID_BLOCK 0xA1
+#define MATROSKA_ID_BLOCKDURATION 0x9B
+#define MATROSKA_ID_BLOCKREFERENCE 0xFB
+
+/* IDs in the attachments master */
+#define MATROSKA_ID_ATTACHEDFILE 0x61A7
+#define MATROSKA_ID_FILENAME 0x466E
+#define MATROSKA_ID_FILEMIMETYPE 0x4660
+#define MATROSKA_ID_FILEDATA 0x465C
+#define MATROSKA_ID_FILEUID 0x46AE
+
+typedef enum {
+ MATROSKA_TRACK_TYPE_VIDEO = 0x1,
+ MATROSKA_TRACK_TYPE_AUDIO = 0x2,
+ MATROSKA_TRACK_TYPE_COMPLEX = 0x3,
+ MATROSKA_TRACK_TYPE_LOGO = 0x10,
+ MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
+ MATROSKA_TRACK_TYPE_CONTROL = 0x20,
+} MatroskaTrackType;
+
+typedef enum {
+ MATROSKA_EYE_MODE_MONO = 0x0,
+ MATROSKA_EYE_MODE_RIGHT = 0x1,
+ MATROSKA_EYE_MODE_LEFT = 0x2,
+ MATROSKA_EYE_MODE_BOTH = 0x3,
+} MatroskaEyeMode;
+
+typedef enum {
+ MATROSKA_ASPECT_RATIO_MODE_FREE = 0x0,
+ MATROSKA_ASPECT_RATIO_MODE_KEEP = 0x1,
+ MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2,
+} MatroskaAspectRatioMode;
+
+/*
+ * These aren't in any way "matroska-form" things,
+ * it's just something I use in the muxer/demuxer.
+ */
+
+typedef enum {
+ MATROSKA_TRACK_ENABLED = (1<<0),
+ MATROSKA_TRACK_DEFAULT = (1<<1),
+ MATROSKA_TRACK_LACING = (1<<2),
+ MATROSKA_TRACK_SHIFT = (1<<16)
+} MatroskaTrackFlags;
+
+typedef enum {
+ MATROSKA_VIDEOTRACK_INTERLACED = (MATROSKA_TRACK_SHIFT<<0)
+} MatroskaVideoTrackFlags;
+
+/*
+ * Matroska Codec IDs. Strings.
+ */
+
+typedef struct CodecTags{
+ char str[16];
+ enum CodecID id;
+}CodecTags;
+
+typedef struct CodecMime{
+ char str[32];
+ enum CodecID id;
+}CodecMime;
+
+#define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC"
+#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
+
+/* max. depth in the EBML tree structure */
+#define EBML_MAX_DEPTH 16
+
+extern const CodecTags ff_mkv_codec_tags[];
+extern const CodecMime ff_mkv_mime_tags[];
+
+#endif /* FFMPEG_MATROSKA_H */
diff --git a/contrib/ffmpeg/libavformat/matroskadec.c b/contrib/ffmpeg/libavformat/matroskadec.c
new file mode 100644
index 000000000..d9fdcec28
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/matroskadec.c
@@ -0,0 +1,2842 @@
+/*
+ * Matroska file demuxer (no muxer yet)
+ * Copyright (c) 2003-2004 The ffmpeg Project
+ *
+ * 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 matroskadec.c
+ * Matroska file demuxer
+ * by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * with a little help from Moritz Bunkus <moritz@bunkus.org>
+ * Specs available on the matroska project page:
+ * http://www.matroska.org/.
+ */
+
+#include "avformat.h"
+/* For codec_get_id(). */
+#include "riff.h"
+#include "intfloat_readwrite.h"
+#include "matroska.h"
+
+typedef struct Track {
+ MatroskaTrackType type;
+
+ /* Unique track number and track ID. stream_index is the index that
+ * the calling app uses for this track. */
+ uint32_t num;
+ uint32_t uid;
+ int stream_index;
+
+ char *name;
+ char language[4];
+
+ char *codec_id;
+ char *codec_name;
+
+ unsigned char *codec_priv;
+ int codec_priv_size;
+
+ uint64_t default_duration;
+ MatroskaTrackFlags flags;
+} MatroskaTrack;
+
+typedef struct MatroskaVideoTrack {
+ MatroskaTrack track;
+
+ int pixel_width;
+ int pixel_height;
+ int display_width;
+ int display_height;
+
+ uint32_t fourcc;
+
+ MatroskaAspectRatioMode ar_mode;
+ MatroskaEyeMode eye_mode;
+
+ //..
+} MatroskaVideoTrack;
+
+typedef struct MatroskaAudioTrack {
+ MatroskaTrack track;
+
+ int channels;
+ int bitdepth;
+ int internal_samplerate;
+ int samplerate;
+ int block_align;
+
+ /* real audio header */
+ int coded_framesize;
+ int sub_packet_h;
+ int frame_size;
+ int sub_packet_size;
+ int sub_packet_cnt;
+ int pkt_cnt;
+ uint8_t *buf;
+ //..
+} MatroskaAudioTrack;
+
+typedef struct MatroskaSubtitleTrack {
+ MatroskaTrack track;
+ //..
+} MatroskaSubtitleTrack;
+
+#define MAX_TRACK_SIZE (FFMAX(FFMAX(sizeof(MatroskaVideoTrack), \
+ sizeof(MatroskaAudioTrack)), \
+ sizeof(MatroskaSubtitleTrack)))
+
+typedef struct MatroskaLevel {
+ uint64_t start;
+ uint64_t length;
+} MatroskaLevel;
+
+typedef struct MatroskaDemuxIndex {
+ uint64_t pos; /* of the corresponding *cluster*! */
+ uint16_t track; /* reference to 'num' */
+ uint64_t time; /* in nanoseconds */
+} MatroskaDemuxIndex;
+
+typedef struct MatroskaDemuxContext {
+ AVFormatContext *ctx;
+
+ /* ebml stuff */
+ int num_levels;
+ MatroskaLevel levels[EBML_MAX_DEPTH];
+ int level_up;
+
+ /* matroska stuff */
+ char *writing_app;
+ char *muxing_app;
+ int64_t created;
+
+ /* timescale in the file */
+ int64_t time_scale;
+
+ /* num_streams is the number of streams that av_new_stream() was called
+ * for ( = that are available to the calling program). */
+ int num_tracks;
+ int num_streams;
+ MatroskaTrack *tracks[MAX_STREAMS];
+
+ /* cache for ID peeking */
+ uint32_t peek_id;
+
+ /* byte position of the segment inside the stream */
+ offset_t segment_start;
+
+ /* The packet queue. */
+ AVPacket **packets;
+ int num_packets;
+
+ /* have we already parse metadata/cues/clusters? */
+ int metadata_parsed;
+ int index_parsed;
+ int done;
+
+ /* The index for seeking. */
+ int num_indexes;
+ MatroskaDemuxIndex *index;
+
+ /* What to skip before effectively reading a packet. */
+ int skip_to_keyframe;
+ AVStream *skip_to_stream;
+} MatroskaDemuxContext;
+
+/*
+ * The first few functions handle EBML file parsing. The rest
+ * is the document interpretation. Matroska really just is a
+ * EBML file.
+ */
+
+/*
+ * Return: the amount of levels in the hierarchy that the
+ * current element lies higher than the previous one.
+ * The opposite isn't done - that's auto-done using master
+ * element reading.
+ */
+
+static int
+ebml_read_element_level_up (MatroskaDemuxContext *matroska)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ offset_t pos = url_ftell(pb);
+ int num = 0;
+
+ while (matroska->num_levels > 0) {
+ MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
+
+ if (pos >= level->start + level->length) {
+ matroska->num_levels--;
+ num++;
+ } else {
+ break;
+ }
+ }
+
+ return num;
+}
+
+/*
+ * Read: an "EBML number", which is defined as a variable-length
+ * array of bytes. The first byte indicates the length by giving a
+ * number of 0-bits followed by a one. The position of the first
+ * "one" bit inside the first byte indicates the length of this
+ * number.
+ * Returns: num. of bytes read. < 0 on error.
+ */
+
+static int
+ebml_read_num (MatroskaDemuxContext *matroska,
+ int max_size,
+ uint64_t *number)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ int len_mask = 0x80, read = 1, n = 1;
+ int64_t total = 0;
+
+ /* the first byte tells us the length in bytes - get_byte() can normally
+ * return 0, but since that's not a valid first ebmlID byte, we can
+ * use it safely here to catch EOS. */
+ if (!(total = get_byte(pb))) {
+ /* we might encounter EOS here */
+ if (!url_feof(pb)) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
+ pos, pos);
+ }
+ return AVERROR(EIO); /* EOS or actual I/O error */
+ }
+
+ /* get the length of the EBML number */
+ while (read <= max_size && !(total & len_mask)) {
+ read++;
+ len_mask >>= 1;
+ }
+ if (read > max_size) {
+ offset_t pos = url_ftell(pb) - 1;
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n",
+ (uint8_t) total, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* read out length */
+ total &= ~len_mask;
+ while (n++ < read)
+ total = (total << 8) | get_byte(pb);
+
+ *number = total;
+
+ return read;
+}
+
+/*
+ * Read: the element content data ID.
+ * Return: the number of bytes read or < 0 on error.
+ */
+
+static int
+ebml_read_element_id (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int *level_up)
+{
+ int read;
+ uint64_t total;
+
+ /* if we re-call this, use our cached ID */
+ if (matroska->peek_id != 0) {
+ if (level_up)
+ *level_up = 0;
+ *id = matroska->peek_id;
+ return 0;
+ }
+
+ /* read out the "EBML number", include tag in ID */
+ if ((read = ebml_read_num(matroska, 4, &total)) < 0)
+ return read;
+ *id = matroska->peek_id = total | (1 << (read * 7));
+
+ /* level tracking */
+ if (level_up)
+ *level_up = ebml_read_element_level_up(matroska);
+
+ return read;
+}
+
+/*
+ * Read: element content length.
+ * Return: the number of bytes read or < 0 on error.
+ */
+
+static int
+ebml_read_element_length (MatroskaDemuxContext *matroska,
+ uint64_t *length)
+{
+ /* clear cache since we're now beyond that data point */
+ matroska->peek_id = 0;
+
+ /* read out the "EBML number", include tag in ID */
+ return ebml_read_num(matroska, 8, length);
+}
+
+/*
+ * Return: the ID of the next element, or 0 on error.
+ * Level_up contains the amount of levels that this
+ * next element lies higher than the previous one.
+ */
+
+static uint32_t
+ebml_peek_id (MatroskaDemuxContext *matroska,
+ int *level_up)
+{
+ uint32_t id;
+
+ if (ebml_read_element_id(matroska, &id, level_up) < 0)
+ return 0;
+
+ return id;
+}
+
+/*
+ * Seek to a given offset.
+ * 0 is success, -1 is failure.
+ */
+
+static int
+ebml_read_seek (MatroskaDemuxContext *matroska,
+ offset_t offset)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+
+ /* clear ID cache, if any */
+ matroska->peek_id = 0;
+
+ return (url_fseek(pb, offset, SEEK_SET) == offset) ? 0 : -1;
+}
+
+/*
+ * Skip the next element.
+ * 0 is success, -1 is failure.
+ */
+
+static int
+ebml_read_skip (MatroskaDemuxContext *matroska)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ uint32_t id;
+ uint64_t length;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, &id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &length)) < 0)
+ return res;
+
+ url_fskip(pb, length);
+
+ return 0;
+}
+
+/*
+ * Read the next element as an unsigned int.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_uint (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ uint64_t *num)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ int n = 0, size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+ if (size < 1 || size > 8) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* big-endian ordening; build up number */
+ *num = 0;
+ while (n++ < size)
+ *num = (*num << 8) | get_byte(pb);
+
+ return 0;
+}
+
+/*
+ * Read the next element as a signed int.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_sint (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int64_t *num)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ int size, n = 1, negative = 0, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+ if (size < 1 || size > 8) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+ if ((*num = get_byte(pb)) & 0x80) {
+ negative = 1;
+ *num &= ~0x80;
+ }
+ while (n++ < size)
+ *num = (*num << 8) | get_byte(pb);
+
+ /* make signed */
+ if (negative)
+ *num = *num - (1LL << ((8 * size) - 1));
+
+ return 0;
+}
+
+/*
+ * Read the next element as a float.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_float (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ double *num)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ int size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+
+ if (size == 4) {
+ *num= av_int2flt(get_be32(pb));
+ } else if(size==8){
+ *num= av_int2dbl(get_be64(pb));
+ } else{
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+/*
+ * Read the next element as an ASCII string.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_ascii (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ char **str)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ int size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+
+ /* ebml strings are usually not 0-terminated, so we allocate one
+ * byte more, read the string and NULL-terminate it ourselves. */
+ if (size < 0 || !(*str = av_malloc(size + 1))) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
+ return AVERROR(ENOMEM);
+ }
+ if (get_buffer(pb, (uint8_t *) *str, size) != size) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
+ return AVERROR(EIO);
+ }
+ (*str)[size] = '\0';
+
+ return 0;
+}
+
+/*
+ * Read the next element as a UTF-8 string.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_utf8 (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ char **str)
+{
+ return ebml_read_ascii(matroska, id, str);
+}
+
+/*
+ * Read the next element as a date (nanoseconds since 1/1/2000).
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_date (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int64_t *date)
+{
+ return ebml_read_sint(matroska, id, date);
+}
+
+/*
+ * Read the next element, but only the header. The contents
+ * are supposed to be sub-elements which can be read separately.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_master (MatroskaDemuxContext *matroska,
+ uint32_t *id)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ uint64_t length;
+ MatroskaLevel *level;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &length)) < 0)
+ return res;
+
+ /* protect... (Heaven forbids that the '>' is true) */
+ if (matroska->num_levels >= EBML_MAX_DEPTH) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH);
+ return AVERROR(ENOSYS);
+ }
+
+ /* remember level */
+ level = &matroska->levels[matroska->num_levels++];
+ level->start = url_ftell(pb);
+ level->length = length;
+
+ return 0;
+}
+
+/*
+ * Read the next element as binary data.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_binary (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ uint8_t **binary,
+ int *size)
+{
+ ByteIOContext *pb = matroska->ctx->pb;
+ uint64_t rlength;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ *size = rlength;
+
+ if (!(*binary = av_malloc(*size))) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Memory allocation error\n");
+ return AVERROR(ENOMEM);
+ }
+
+ if (get_buffer(pb, *binary, *size) != *size) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
+ return AVERROR(EIO);
+ }
+
+ return 0;
+}
+
+/*
+ * Read signed/unsigned "EBML" numbers.
+ * Return: number of bytes processed, < 0 on error.
+ * XXX: use ebml_read_num().
+ */
+
+static int
+matroska_ebmlnum_uint (uint8_t *data,
+ uint32_t size,
+ uint64_t *num)
+{
+ int len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
+ uint64_t total;
+
+ if (size <= 0)
+ return AVERROR_INVALIDDATA;
+
+ total = data[0];
+ while (read <= 8 && !(total & len_mask)) {
+ read++;
+ len_mask >>= 1;
+ }
+ if (read > 8)
+ return AVERROR_INVALIDDATA;
+
+ if ((total &= (len_mask - 1)) == len_mask - 1)
+ num_ffs++;
+ if (size < read)
+ return AVERROR_INVALIDDATA;
+ while (n < read) {
+ if (data[n] == 0xff)
+ num_ffs++;
+ total = (total << 8) | data[n];
+ n++;
+ }
+
+ if (read == num_ffs)
+ *num = (uint64_t)-1;
+ else
+ *num = total;
+
+ return read;
+}
+
+/*
+ * Same as above, but signed.
+ */
+
+static int
+matroska_ebmlnum_sint (uint8_t *data,
+ uint32_t size,
+ int64_t *num)
+{
+ uint64_t unum;
+ int res;
+
+ /* read as unsigned number first */
+ if ((res = matroska_ebmlnum_uint(data, size, &unum)) < 0)
+ return res;
+
+ /* make signed (weird way) */
+ if (unum == (uint64_t)-1)
+ *num = INT64_MAX;
+ else
+ *num = unum - ((1LL << ((7 * res) - 1)) - 1);
+
+ return res;
+}
+
+/*
+ * Read an EBML header.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_header (MatroskaDemuxContext *matroska,
+ char **doctype,
+ int *version)
+{
+ uint32_t id;
+ int level_up, res = 0;
+
+ /* default init */
+ if (doctype)
+ *doctype = NULL;
+ if (version)
+ *version = 1;
+
+ if (!(id = ebml_peek_id(matroska, &level_up)) ||
+ level_up != 0 || id != EBML_ID_HEADER) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "This is not an EBML file (id=0x%x/0x%x)\n", id, EBML_ID_HEADER);
+ return AVERROR_INVALIDDATA;
+ }
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &level_up)))
+ return AVERROR(EIO);
+
+ /* end-of-header */
+ if (level_up)
+ break;
+
+ switch (id) {
+ /* is our read version uptodate? */
+ case EBML_ID_EBMLREADVERSION: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > EBML_VERSION) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "EBML version %"PRIu64" (> %d) is not supported\n",
+ num, EBML_VERSION);
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ /* we only handle 8 byte lengths at max */
+ case EBML_ID_EBMLMAXSIZELENGTH: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > sizeof(uint64_t)) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Integers of size %"PRIu64" (> %zd) not supported\n",
+ num, sizeof(uint64_t));
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ /* we handle 4 byte IDs at max */
+ case EBML_ID_EBMLMAXIDLENGTH: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > sizeof(uint32_t)) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "IDs of size %"PRIu64" (> %zu) not supported\n",
+ num, sizeof(uint32_t));
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ case EBML_ID_DOCTYPE: {
+ char *text;
+
+ if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
+ return res;
+ if (doctype) {
+ if (*doctype)
+ av_free(*doctype);
+ *doctype = text;
+ } else
+ av_free(text);
+ break;
+ }
+
+ case EBML_ID_DOCTYPEREADVERSION: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (version)
+ *version = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown data type 0x%x in EBML header", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ /* we ignore these two, as they don't tell us anything we
+ * care about */
+ case EBML_ID_EBMLVERSION:
+ case EBML_ID_DOCTYPEVERSION:
+ res = ebml_read_skip (matroska);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+matroska_find_track_by_num (MatroskaDemuxContext *matroska,
+ int num)
+{
+ int i;
+
+ for (i = 0; i < matroska->num_tracks; i++)
+ if (matroska->tracks[i]->num == num)
+ return i;
+
+ return -1;
+}
+
+
+/*
+ * Put one packet in an application-supplied AVPacket struct.
+ * Returns 0 on success or -1 on failure.
+ */
+
+static int
+matroska_deliver_packet (MatroskaDemuxContext *matroska,
+ AVPacket *pkt)
+{
+ if (matroska->num_packets > 0) {
+ memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
+ av_free(matroska->packets[0]);
+ if (matroska->num_packets > 1) {
+ memmove(&matroska->packets[0], &matroska->packets[1],
+ (matroska->num_packets - 1) * sizeof(AVPacket *));
+ matroska->packets =
+ av_realloc(matroska->packets, (matroska->num_packets - 1) *
+ sizeof(AVPacket *));
+ } else {
+ av_freep(&matroska->packets);
+ }
+ matroska->num_packets--;
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ * Put a packet into our internal queue. Will be delivered to the
+ * user/application during the next get_packet() call.
+ */
+
+static void
+matroska_queue_packet (MatroskaDemuxContext *matroska,
+ AVPacket *pkt)
+{
+ matroska->packets =
+ av_realloc(matroska->packets, (matroska->num_packets + 1) *
+ sizeof(AVPacket *));
+ matroska->packets[matroska->num_packets] = pkt;
+ matroska->num_packets++;
+}
+
+/*
+ * Free all packets in our internal queue.
+ */
+static void
+matroska_clear_queue (MatroskaDemuxContext *matroska)
+{
+ if (matroska->packets) {
+ int n;
+ for (n = 0; n < matroska->num_packets; n++) {
+ av_free_packet(matroska->packets[n]);
+ av_free(matroska->packets[n]);
+ }
+ av_free(matroska->packets);
+ matroska->packets = NULL;
+ matroska->num_packets = 0;
+ }
+}
+
+
+/*
+ * Autodetecting...
+ */
+
+static int
+matroska_probe (AVProbeData *p)
+{
+ uint64_t total = 0;
+ int len_mask = 0x80, size = 1, n = 1;
+ uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
+
+ /* ebml header? */
+ if (AV_RB32(p->buf) != EBML_ID_HEADER)
+ return 0;
+
+ /* length of header */
+ total = p->buf[4];
+ while (size <= 8 && !(total & len_mask)) {
+ size++;
+ len_mask >>= 1;
+ }
+ if (size > 8)
+ 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;
+
+ /* the header must contain the document type 'matroska'. For now,
+ * we don't parse the whole header but simply check for the
+ * availability of that array of characters inside the header.
+ * Not fully fool-proof, but good enough. */
+ for (n = 4 + size; n <= 4 + size + total - sizeof(probe_data); n++)
+ if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data)))
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+/*
+ * From here on, it's all XML-style DTD stuff... Needs no comments.
+ */
+
+static int
+matroska_parse_info (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* cluster timecode */
+ case MATROSKA_ID_TIMECODESCALE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ matroska->time_scale = num;
+ break;
+ }
+
+ case MATROSKA_ID_DURATION: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id, &num)) < 0)
+ break;
+ matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE;
+ break;
+ }
+
+ case MATROSKA_ID_TITLE: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ strncpy(matroska->ctx->title, text,
+ sizeof(matroska->ctx->title)-1);
+ av_free(text);
+ break;
+ }
+
+ case MATROSKA_ID_WRITINGAPP: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ matroska->writing_app = text;
+ break;
+ }
+
+ case MATROSKA_ID_MUXINGAPP: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ matroska->muxing_app = text;
+ break;
+ }
+
+ case MATROSKA_ID_DATEUTC: {
+ int64_t time;
+ if ((res = ebml_read_date(matroska, &id, &time)) < 0)
+ break;
+ matroska->created = time;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in info header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_add_stream (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ MatroskaTrack *track;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n");
+
+ /* Allocate a generic track. As soon as we know its type we'll realloc. */
+ track = av_mallocz(MAX_TRACK_SIZE);
+ matroska->num_tracks++;
+ strcpy(track->language, "eng");
+
+ /* start with the master */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+
+ /* try reading the trackentry headers */
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* track number (unique stream ID) */
+ case MATROSKA_ID_TRACKNUMBER: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->num = num;
+ break;
+ }
+
+ /* track UID (unique identifier) */
+ case MATROSKA_ID_TRACKUID: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->uid = num;
+ break;
+ }
+
+ /* track type (video, audio, combined, subtitle, etc.) */
+ case MATROSKA_ID_TRACKTYPE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (track->type && track->type != num) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "More than one tracktype in an entry - skip\n");
+ break;
+ }
+ track->type = num;
+
+ switch (track->type) {
+ case MATROSKA_TRACK_TYPE_VIDEO:
+ case MATROSKA_TRACK_TYPE_AUDIO:
+ case MATROSKA_TRACK_TYPE_SUBTITLE:
+ break;
+ case MATROSKA_TRACK_TYPE_COMPLEX:
+ case MATROSKA_TRACK_TYPE_LOGO:
+ case MATROSKA_TRACK_TYPE_CONTROL:
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown or unsupported track type 0x%x\n",
+ track->type);
+ track->type = 0;
+ break;
+ }
+ matroska->tracks[matroska->num_tracks - 1] = track;
+ break;
+ }
+
+ /* tracktype specific stuff for video */
+ case MATROSKA_ID_TRACKVIDEO: {
+ MatroskaVideoTrack *videotrack;
+ if (!track->type)
+ track->type = MATROSKA_TRACK_TYPE_VIDEO;
+ if (track->type != MATROSKA_TRACK_TYPE_VIDEO) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "video data in non-video track - ignoring\n");
+ res = AVERROR_INVALIDDATA;
+ break;
+ } else if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ videotrack = (MatroskaVideoTrack *)track;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* fixme, this should be one-up, but I get it here */
+ case MATROSKA_ID_TRACKDEFAULTDURATION: {
+ uint64_t num;
+ if ((res = ebml_read_uint (matroska, &id,
+ &num)) < 0)
+ break;
+ track->default_duration = num;
+ break;
+ }
+
+ /* video framerate */
+ case MATROSKA_ID_VIDEOFRAMERATE: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ if (!track->default_duration)
+ track->default_duration = 1000000000/num;
+ break;
+ }
+
+ /* width of the size to display the video at */
+ case MATROSKA_ID_VIDEODISPLAYWIDTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->display_width = num;
+ break;
+ }
+
+ /* height of the size to display the video at */
+ case MATROSKA_ID_VIDEODISPLAYHEIGHT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->display_height = num;
+ break;
+ }
+
+ /* width of the video in the file */
+ case MATROSKA_ID_VIDEOPIXELWIDTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->pixel_width = num;
+ break;
+ }
+
+ /* height of the video in the file */
+ case MATROSKA_ID_VIDEOPIXELHEIGHT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->pixel_height = num;
+ break;
+ }
+
+ /* whether the video is interlaced */
+ case MATROSKA_ID_VIDEOFLAGINTERLACED: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num)
+ track->flags |=
+ MATROSKA_VIDEOTRACK_INTERLACED;
+ else
+ track->flags &=
+ ~MATROSKA_VIDEOTRACK_INTERLACED;
+ break;
+ }
+
+ /* stereo mode (whether the video has two streams,
+ * where one is for the left eye and the other for
+ * the right eye, which creates a 3D-like
+ * effect) */
+ case MATROSKA_ID_VIDEOSTEREOMODE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num != MATROSKA_EYE_MODE_MONO &&
+ num != MATROSKA_EYE_MODE_LEFT &&
+ num != MATROSKA_EYE_MODE_RIGHT &&
+ num != MATROSKA_EYE_MODE_BOTH) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring unknown eye mode 0x%x\n",
+ (uint32_t) num);
+ break;
+ }
+ videotrack->eye_mode = num;
+ break;
+ }
+
+ /* aspect ratio behaviour */
+ case MATROSKA_ID_VIDEOASPECTRATIO: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num != MATROSKA_ASPECT_RATIO_MODE_FREE &&
+ num != MATROSKA_ASPECT_RATIO_MODE_KEEP &&
+ num != MATROSKA_ASPECT_RATIO_MODE_FIXED) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring unknown aspect ratio 0x%x\n",
+ (uint32_t) num);
+ break;
+ }
+ videotrack->ar_mode = num;
+ break;
+ }
+
+ /* colorspace (only matters for raw video)
+ * fourcc */
+ case MATROSKA_ID_VIDEOCOLORSPACE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->fourcc = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown video track header entry "
+ "0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+ }
+
+ /* tracktype specific stuff for audio */
+ case MATROSKA_ID_TRACKAUDIO: {
+ MatroskaAudioTrack *audiotrack;
+ if (!track->type)
+ track->type = MATROSKA_TRACK_TYPE_AUDIO;
+ if (track->type != MATROSKA_TRACK_TYPE_AUDIO) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "audio data in non-audio track - ignoring\n");
+ res = AVERROR_INVALIDDATA;
+ break;
+ } else if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ audiotrack = (MatroskaAudioTrack *)track;
+ audiotrack->channels = 1;
+ audiotrack->samplerate = 8000;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* samplerate */
+ case MATROSKA_ID_AUDIOSAMPLINGFREQ: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->internal_samplerate =
+ audiotrack->samplerate = num;
+ break;
+ }
+
+ case MATROSKA_ID_AUDIOOUTSAMPLINGFREQ: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->samplerate = num;
+ break;
+ }
+
+ /* bitdepth */
+ case MATROSKA_ID_AUDIOBITDEPTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->bitdepth = num;
+ break;
+ }
+
+ /* channels */
+ case MATROSKA_ID_AUDIOCHANNELS: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->channels = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown audio track header entry "
+ "0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+ }
+
+ /* codec identifier */
+ case MATROSKA_ID_CODECID: {
+ char *text;
+ if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
+ break;
+ track->codec_id = text;
+ break;
+ }
+
+ /* codec private data */
+ case MATROSKA_ID_CODECPRIVATE: {
+ uint8_t *data;
+ int size;
+ if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))
+ break;
+ track->codec_priv = data;
+ track->codec_priv_size = size;
+ break;
+ }
+
+ /* name of the codec */
+ case MATROSKA_ID_CODECNAME: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ track->codec_name = text;
+ break;
+ }
+
+ /* name of this track */
+ case MATROSKA_ID_TRACKNAME: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ track->name = text;
+ break;
+ }
+
+ /* language (matters for audio/subtitles, mostly) */
+ case MATROSKA_ID_TRACKLANGUAGE: {
+ char *text, *end;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ if ((end = strchr(text, '-')))
+ *end = '\0';
+ if (strlen(text) == 3)
+ strcpy(track->language, text);
+ av_free(text);
+ break;
+ }
+
+ /* whether this is actually used */
+ case MATROSKA_ID_TRACKFLAGENABLED: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_ENABLED;
+ else
+ track->flags &= ~MATROSKA_TRACK_ENABLED;
+ break;
+ }
+
+ /* whether it's the default for this track type */
+ case MATROSKA_ID_TRACKFLAGDEFAULT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_DEFAULT;
+ else
+ track->flags &= ~MATROSKA_TRACK_DEFAULT;
+ break;
+ }
+
+ /* lacing (like MPEG, where blocks don't end/start on frame
+ * boundaries) */
+ case MATROSKA_ID_TRACKFLAGLACING: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_LACING;
+ else
+ track->flags &= ~MATROSKA_TRACK_LACING;
+ break;
+ }
+
+ /* default length (in time) of one data block in this track */
+ case MATROSKA_ID_TRACKDEFAULTDURATION: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->default_duration = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown track header entry 0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ /* we ignore these because they're nothing useful. */
+ case MATROSKA_ID_CODECINFOURL:
+ case MATROSKA_ID_CODECDOWNLOADURL:
+ case MATROSKA_ID_TRACKMINCACHE:
+ case MATROSKA_ID_TRACKMAXCACHE:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_tracks (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing tracks...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one track within the "all-tracks" header */
+ case MATROSKA_ID_TRACKENTRY:
+ res = matroska_add_stream(matroska);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in track header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_index (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ MatroskaDemuxIndex idx;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing index...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one single index entry ('point') */
+ case MATROSKA_ID_POINTENTRY:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ /* in the end, we hope to fill one entry with a
+ * timestamp, a file position and a tracknum */
+ idx.pos = (uint64_t) -1;
+ idx.time = (uint64_t) -1;
+ idx.track = (uint16_t) -1;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one single index entry ('point') */
+ case MATROSKA_ID_CUETIME: {
+ uint64_t time;
+ if ((res = ebml_read_uint(matroska, &id,
+ &time)) < 0)
+ break;
+ idx.time = time * matroska->time_scale;
+ break;
+ }
+
+ /* position in the file + track to which it
+ * belongs */
+ case MATROSKA_ID_CUETRACKPOSITION:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id (matroska,
+ &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* track number */
+ case MATROSKA_ID_CUETRACK: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska,
+ &id, &num)) < 0)
+ break;
+ idx.track = num;
+ break;
+ }
+
+ /* position in file */
+ case MATROSKA_ID_CUECLUSTERPOSITION: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska,
+ &id, &num)) < 0)
+ break;
+ idx.pos = num+matroska->segment_start;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in "
+ "CuesTrackPositions\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cuespoint "
+ "index\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ /* so let's see if we got what we wanted */
+ if (idx.pos != (uint64_t) -1 &&
+ idx.time != (uint64_t) -1 &&
+ idx.track != (uint16_t) -1) {
+ if (matroska->num_indexes % 32 == 0) {
+ /* re-allocate bigger index */
+ matroska->index =
+ av_realloc(matroska->index,
+ (matroska->num_indexes + 32) *
+ sizeof(MatroskaDemuxIndex));
+ }
+ matroska->index[matroska->num_indexes] = idx;
+ matroska->num_indexes++;
+ }
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cues header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_metadata (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* Hm, this is unsupported... */
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in metadata header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_seekhead (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing seekhead...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_SEEKENTRY: {
+ uint32_t seek_id = 0, peek_id_cache = 0;
+ uint64_t seek_pos = (uint64_t) -1, t;
+
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_SEEKID:
+ res = ebml_read_uint(matroska, &id, &t);
+ seek_id = t;
+ break;
+
+ case MATROSKA_ID_SEEKPOSITION:
+ res = ebml_read_uint(matroska, &id, &seek_pos);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown seekhead ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (!seek_id || seek_pos == (uint64_t) -1) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Incomplete seekhead entry (0x%x/%"PRIu64")\n",
+ seek_id, seek_pos);
+ break;
+ }
+
+ switch (seek_id) {
+ case MATROSKA_ID_CUES:
+ case MATROSKA_ID_TAGS: {
+ uint32_t level_up = matroska->level_up;
+ offset_t before_pos;
+ uint64_t length;
+ MatroskaLevel level;
+
+ /* remember the peeked ID and the current position */
+ peek_id_cache = matroska->peek_id;
+ before_pos = url_ftell(matroska->ctx->pb);
+
+ /* seek */
+ if ((res = ebml_read_seek(matroska, seek_pos +
+ matroska->segment_start)) < 0)
+ return res;
+
+ /* we don't want to lose our seekhead level, so we add
+ * a dummy. This is a crude hack. */
+ if (matroska->num_levels == EBML_MAX_DEPTH) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Max EBML element depth (%d) reached, "
+ "cannot parse further.\n", EBML_MAX_DEPTH);
+ return AVERROR_UNKNOWN;
+ }
+
+ level.start = 0;
+ level.length = (uint64_t)-1;
+ matroska->levels[matroska->num_levels] = level;
+ matroska->num_levels++;
+
+ /* check ID */
+ if (!(id = ebml_peek_id (matroska,
+ &matroska->level_up)))
+ goto finish;
+ if (id != seek_id) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "We looked for ID=0x%x but got "
+ "ID=0x%x (pos=%"PRIu64")",
+ seek_id, id, seek_pos +
+ matroska->segment_start);
+ goto finish;
+ }
+
+ /* read master + parse */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ goto finish;
+ switch (id) {
+ case MATROSKA_ID_CUES:
+ if (!(res = matroska_parse_index(matroska)) ||
+ url_feof(matroska->ctx->pb)) {
+ matroska->index_parsed = 1;
+ res = 0;
+ }
+ break;
+ case MATROSKA_ID_TAGS:
+ if (!(res = matroska_parse_metadata(matroska)) ||
+ url_feof(matroska->ctx->pb)) {
+ matroska->metadata_parsed = 1;
+ res = 0;
+ }
+ break;
+ }
+
+ finish:
+ /* remove dummy level */
+ while (matroska->num_levels) {
+ matroska->num_levels--;
+ length =
+ matroska->levels[matroska->num_levels].length;
+ if (length == (uint64_t)-1)
+ break;
+ }
+
+ /* seek back */
+ if ((res = ebml_read_seek(matroska, before_pos)) < 0)
+ return res;
+ matroska->peek_id = peek_id_cache;
+ matroska->level_up = level_up;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring seekhead entry for ID=0x%x\n",
+ seek_id);
+ break;
+ }
+
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown seekhead ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_attachments(AVFormatContext *s)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_ATTACHEDFILE: {
+ char* name = NULL;
+ char* mime = NULL;
+ uint8_t* data = NULL;
+ int i, data_size = 0;
+ AVStream *st;
+
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_FILENAME:
+ res = ebml_read_utf8 (matroska, &id, &name);
+ break;
+
+ case MATROSKA_ID_FILEMIMETYPE:
+ res = ebml_read_ascii (matroska, &id, &mime);
+ break;
+
+ case MATROSKA_ID_FILEDATA:
+ res = ebml_read_binary(matroska, &id, &data, &data_size);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown attachedfile ID 0x%x\n", id);
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (!(name && mime && data && data_size > 0)) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
+ break;
+ }
+
+ st = av_new_stream(s, matroska->num_streams++);
+ if (st == NULL)
+ return AVERROR(ENOMEM);
+ st->filename = av_strdup(name);
+ st->codec->codec_id = CODEC_ID_NONE;
+ st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
+ st->codec->extradata = av_malloc(data_size);
+ if(st->codec->extradata == NULL)
+ return AVERROR(ENOMEM);
+ st->codec->extradata_size = data_size;
+ memcpy(st->codec->extradata, data, data_size);
+
+ for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
+ if (!strncmp(ff_mkv_mime_tags[i].str, mime,
+ strlen(ff_mkv_mime_tags[i].str))) {
+ st->codec->codec_id = ff_mkv_mime_tags[i].id;
+ break;
+ }
+ }
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "new attachment: %s, %s, size %d \n", name, mime, data_size);
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown attachments ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
+
+static int
+matroska_aac_profile (char *codec_id)
+{
+ static const char *aac_profiles[] = {
+ "MAIN", "LC", "SSR"
+ };
+ int profile;
+
+ for (profile=0; profile<ARRAY_SIZE(aac_profiles); profile++)
+ if (strstr(codec_id, aac_profiles[profile]))
+ break;
+ return profile + 1;
+}
+
+static int
+matroska_aac_sri (int samplerate)
+{
+ static const int aac_sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ };
+ int sri;
+
+ for (sri=0; sri<ARRAY_SIZE(aac_sample_rates); sri++)
+ if (aac_sample_rates[sri] == samplerate)
+ break;
+ return sri;
+}
+
+static int
+matroska_read_header (AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ char *doctype;
+ int version, last_level, res = 0;
+ uint32_t id;
+
+ matroska->ctx = s;
+
+ /* First read the EBML header. */
+ doctype = NULL;
+ if ((res = ebml_read_header(matroska, &doctype, &version)) < 0)
+ return res;
+ if ((doctype == NULL) || strcmp(doctype, "matroska")) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Wrong EBML doctype ('%s' != 'matroska').\n",
+ doctype ? doctype : "(none)");
+ if (doctype)
+ av_free(doctype);
+ return AVERROR_NOFMT;
+ }
+ av_free(doctype);
+ if (version > 2) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Matroska demuxer version 2 too old for file version %d\n",
+ version);
+ return AVERROR_NOFMT;
+ }
+
+ /* The next thing is a segment. */
+ while (1) {
+ if (!(id = ebml_peek_id(matroska, &last_level)))
+ return AVERROR(EIO);
+ if (id == MATROSKA_ID_SEGMENT)
+ break;
+
+ /* oi! */
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Expected a Segment ID (0x%x), but received 0x%x!\n",
+ MATROSKA_ID_SEGMENT, id);
+ if ((res = ebml_read_skip(matroska)) < 0)
+ return res;
+ }
+
+ /* We now have a Matroska segment.
+ * Seeks are from the beginning of the segment,
+ * after the segment ID/length. */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+ matroska->segment_start = url_ftell(s->pb);
+
+ matroska->time_scale = 1000000;
+ /* we've found our segment, start reading the different contents in here */
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* stream info */
+ case MATROSKA_ID_INFO: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_info(matroska);
+ break;
+ }
+
+ /* track info headers */
+ case MATROSKA_ID_TRACKS: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_tracks(matroska);
+ break;
+ }
+
+ /* stream index */
+ case MATROSKA_ID_CUES: {
+ if (!matroska->index_parsed) {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_index(matroska);
+ } else
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ /* metadata */
+ case MATROSKA_ID_TAGS: {
+ if (!matroska->metadata_parsed) {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_metadata(matroska);
+ } else
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ /* file index (if seekable, seek to Cues/Tags to parse it) */
+ case MATROSKA_ID_SEEKHEAD: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_seekhead(matroska);
+ break;
+ }
+
+ case MATROSKA_ID_ATTACHMENTS: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_attachments(s);
+ break;
+ }
+
+ case MATROSKA_ID_CLUSTER: {
+ /* Do not read the master - this will be done in the next
+ * call to matroska_read_packet. */
+ res = 1;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown matroska file header ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ /* Have we found a cluster? */
+ if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) {
+ int i, j;
+ MatroskaTrack *track;
+ AVStream *st;
+
+ for (i = 0; i < matroska->num_tracks; i++) {
+ enum CodecID codec_id = CODEC_ID_NONE;
+ uint8_t *extradata = NULL;
+ int extradata_size = 0;
+ int extradata_offset = 0;
+ track = matroska->tracks[i];
+ track->stream_index = -1;
+
+ /* Apply some sanity checks. */
+ if (track->codec_id == NULL)
+ continue;
+
+ for(j=0; ff_mkv_codec_tags[j].id != 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;
+ }
+ }
+
+ /* Set the FourCC from the CodecID. */
+ /* This is the MS compatibility mode which stores a
+ * BITMAPINFOHEADER in the CodecPrivate. */
+ if (!strcmp(track->codec_id,
+ MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC) &&
+ (track->codec_priv_size >= 40) &&
+ (track->codec_priv != NULL)) {
+ MatroskaVideoTrack *vtrack = (MatroskaVideoTrack *) track;
+
+ /* Offset of biCompression. Stored in LE. */
+ vtrack->fourcc = AV_RL32(track->codec_priv + 16);
+ codec_id = codec_get_id(codec_bmp_tags, vtrack->fourcc);
+
+ }
+
+ /* This is the MS compatibility mode which stores a
+ * WAVEFORMATEX in the CodecPrivate. */
+ else if (!strcmp(track->codec_id,
+ MATROSKA_CODEC_ID_AUDIO_ACM) &&
+ (track->codec_priv_size >= 18) &&
+ (track->codec_priv != NULL)) {
+ uint16_t tag;
+
+ /* Offset of wFormatTag. Stored in LE. */
+ tag = AV_RL16(track->codec_priv);
+ codec_id = codec_get_id(codec_wav_tags, tag);
+
+ }
+
+ else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
+ int profile = matroska_aac_profile(track->codec_id);
+ int sri = matroska_aac_sri(audiotrack->internal_samplerate);
+ extradata = av_malloc(5);
+ if (extradata == NULL)
+ return AVERROR(ENOMEM);
+ extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
+ extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3);
+ if (strstr(track->codec_id, "SBR")) {
+ sri = matroska_aac_sri(audiotrack->samplerate);
+ extradata[2] = 0x56;
+ extradata[3] = 0xE5;
+ extradata[4] = 0x80 | (sri<<3);
+ extradata_size = 5;
+ } else {
+ extradata_size = 2;
+ }
+ }
+
+ else if (codec_id == CODEC_ID_TTA) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
+ ByteIOContext b;
+ extradata_size = 30;
+ extradata = av_mallocz(extradata_size);
+ if (extradata == NULL)
+ return AVERROR(ENOMEM);
+ init_put_byte(&b, extradata, extradata_size, 1,
+ NULL, NULL, NULL, NULL);
+ put_buffer(&b, "TTA1", 4);
+ put_le16(&b, 1);
+ put_le16(&b, audiotrack->channels);
+ put_le16(&b, audiotrack->bitdepth);
+ put_le32(&b, audiotrack->samplerate);
+ put_le32(&b, matroska->ctx->duration * audiotrack->samplerate);
+ }
+
+ else if (codec_id == CODEC_ID_RV10 || codec_id == CODEC_ID_RV20 ||
+ codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
+ extradata_offset = 26;
+ track->codec_priv_size -= extradata_offset;
+ }
+
+ else if (codec_id == CODEC_ID_RA_144) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ audiotrack->samplerate = 8000;
+ audiotrack->channels = 1;
+ }
+
+ else if (codec_id == CODEC_ID_RA_288 ||
+ codec_id == CODEC_ID_COOK ||
+ codec_id == CODEC_ID_ATRAC3) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ ByteIOContext b;
+
+ init_put_byte(&b, track->codec_priv, track->codec_priv_size, 0,
+ NULL, NULL, NULL, NULL);
+ url_fskip(&b, 24);
+ audiotrack->coded_framesize = get_be32(&b);
+ url_fskip(&b, 12);
+ audiotrack->sub_packet_h = get_be16(&b);
+ audiotrack->frame_size = get_be16(&b);
+ audiotrack->sub_packet_size = get_be16(&b);
+ audiotrack->buf = av_malloc(audiotrack->frame_size * audiotrack->sub_packet_h);
+ if (codec_id == CODEC_ID_RA_288) {
+ audiotrack->block_align = audiotrack->coded_framesize;
+ track->codec_priv_size = 0;
+ } else {
+ audiotrack->block_align = audiotrack->sub_packet_size;
+ extradata_offset = 78;
+ track->codec_priv_size -= extradata_offset;
+ }
+ }
+
+ if (codec_id == CODEC_ID_NONE) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown/unsupported CodecID %s.\n",
+ track->codec_id);
+ }
+
+ track->stream_index = matroska->num_streams;
+
+ matroska->num_streams++;
+ st = av_new_stream(s, track->stream_index);
+ if (st == NULL)
+ return AVERROR(ENOMEM);
+ av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
+
+ st->codec->codec_id = codec_id;
+ st->start_time = 0;
+ if (strcmp(track->language, "und"))
+ strcpy(st->language, track->language);
+
+ if (track->default_duration)
+ av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
+ track->default_duration, 1000000000, 30000);
+
+ if(extradata){
+ st->codec->extradata = extradata;
+ st->codec->extradata_size = extradata_size;
+ } else if(track->codec_priv && track->codec_priv_size > 0){
+ st->codec->extradata = av_malloc(track->codec_priv_size);
+ if(st->codec->extradata == NULL)
+ return AVERROR(ENOMEM);
+ st->codec->extradata_size = track->codec_priv_size;
+ memcpy(st->codec->extradata,track->codec_priv+extradata_offset,
+ track->codec_priv_size);
+ }
+
+ if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
+ MatroskaVideoTrack *videotrack = (MatroskaVideoTrack *)track;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_tag = videotrack->fourcc;
+ st->codec->width = videotrack->pixel_width;
+ st->codec->height = videotrack->pixel_height;
+ if (videotrack->display_width == 0)
+ videotrack->display_width= videotrack->pixel_width;
+ if (videotrack->display_height == 0)
+ videotrack->display_height= videotrack->pixel_height;
+ av_reduce(&st->codec->sample_aspect_ratio.num,
+ &st->codec->sample_aspect_ratio.den,
+ st->codec->height * videotrack->display_width,
+ st->codec-> width * videotrack->display_height,
+ 255);
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->sample_rate = audiotrack->samplerate;
+ st->codec->channels = audiotrack->channels;
+ st->codec->block_align = audiotrack->block_align;
+ } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ }
+
+ /* What do we do with private data? E.g. for Vorbis. */
+ }
+ res = 0;
+ }
+
+ if (matroska->index_parsed) {
+ int i, track, stream;
+ for (i=0; i<matroska->num_indexes; i++) {
+ MatroskaDemuxIndex *idx = &matroska->index[i];
+ track = matroska_find_track_by_num(matroska, idx->track);
+ stream = matroska->tracks[track]->stream_index;
+ if (stream >= 0)
+ av_add_index_entry(matroska->ctx->streams[stream],
+ idx->pos, idx->time/matroska->time_scale,
+ 0, 0, AVINDEX_KEYFRAME);
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
+ int64_t pos, uint64_t cluster_time, uint64_t duration,
+ int is_keyframe, int is_bframe)
+{
+ int res = 0;
+ int track;
+ AVStream *st;
+ AVPacket *pkt;
+ uint8_t *origdata = data;
+ int16_t block_time;
+ uint32_t *lace_size = NULL;
+ int n, flags, laces = 0;
+ uint64_t num;
+
+ /* first byte(s): tracknum */
+ if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n");
+ av_free(origdata);
+ return res;
+ }
+ data += n;
+ size -= n;
+
+ /* fetch track from num */
+ track = matroska_find_track_by_num(matroska, num);
+ if (size <= 3 || track < 0 || track >= matroska->num_tracks) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Invalid stream %d or size %u\n", track, size);
+ av_free(origdata);
+ return res;
+ }
+ if (matroska->tracks[track]->stream_index < 0) {
+ av_free(origdata);
+ return res;
+ }
+ st = matroska->ctx->streams[matroska->tracks[track]->stream_index];
+ if (st->discard >= AVDISCARD_ALL) {
+ av_free(origdata);
+ return res;
+ }
+ if (duration == AV_NOPTS_VALUE)
+ duration = matroska->tracks[track]->default_duration / matroska->time_scale;
+
+ /* block_time (relative to cluster time) */
+ block_time = AV_RB16(data);
+ data += 2;
+ flags = *data++;
+ size -= 3;
+ if (is_keyframe == -1)
+ is_keyframe = flags & 0x80 ? PKT_FLAG_KEY : 0;
+
+ if (matroska->skip_to_keyframe) {
+ if (!is_keyframe || st != matroska->skip_to_stream) {
+ av_free(origdata);
+ return res;
+ }
+ matroska->skip_to_keyframe = 0;
+ }
+
+ switch ((flags & 0x06) >> 1) {
+ case 0x0: /* no lacing */
+ laces = 1;
+ lace_size = av_mallocz(sizeof(int));
+ lace_size[0] = size;
+ break;
+
+ case 0x1: /* xiph lacing */
+ case 0x2: /* fixed-size lacing */
+ case 0x3: /* EBML lacing */
+ if (size == 0) {
+ res = -1;
+ break;
+ }
+ laces = (*data) + 1;
+ data += 1;
+ size -= 1;
+ lace_size = av_mallocz(laces * sizeof(int));
+
+ switch ((flags & 0x06) >> 1) {
+ case 0x1: /* xiph lacing */ {
+ uint8_t temp;
+ uint32_t total = 0;
+ for (n = 0; res == 0 && n < laces - 1; n++) {
+ while (1) {
+ if (size == 0) {
+ res = -1;
+ break;
+ }
+ temp = *data;
+ lace_size[n] += temp;
+ data += 1;
+ size -= 1;
+ if (temp != 0xff)
+ break;
+ }
+ total += lace_size[n];
+ }
+ lace_size[n] = size - total;
+ break;
+ }
+
+ case 0x2: /* fixed-size lacing */
+ for (n = 0; n < laces; n++)
+ lace_size[n] = size / laces;
+ break;
+
+ case 0x3: /* EBML lacing */ {
+ uint32_t total;
+ n = matroska_ebmlnum_uint(data, size, &num);
+ if (n < 0) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "EBML block data error\n");
+ break;
+ }
+ data += n;
+ size -= n;
+ total = lace_size[0] = num;
+ for (n = 1; res == 0 && n < laces - 1; n++) {
+ int64_t snum;
+ int r;
+ r = matroska_ebmlnum_sint (data, size, &snum);
+ if (r < 0) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "EBML block data error\n");
+ break;
+ }
+ data += r;
+ size -= r;
+ lace_size[n] = lace_size[n - 1] + snum;
+ total += lace_size[n];
+ }
+ lace_size[n] = size - total;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (res == 0) {
+ uint64_t timecode = AV_NOPTS_VALUE;
+
+ if (cluster_time != (uint64_t)-1
+ && (block_time >= 0 || cluster_time >= -block_time))
+ timecode = cluster_time + block_time;
+
+ for (n = 0; n < laces; n++) {
+ if (st->codec->codec_id == CODEC_ID_RA_288 ||
+ st->codec->codec_id == CODEC_ID_COOK ||
+ st->codec->codec_id == CODEC_ID_ATRAC3) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)matroska->tracks[track];
+ int a = st->codec->block_align;
+ int sps = audiotrack->sub_packet_size;
+ int cfs = audiotrack->coded_framesize;
+ int h = audiotrack->sub_packet_h;
+ int y = audiotrack->sub_packet_cnt;
+ int w = audiotrack->frame_size;
+ int x;
+
+ if (!audiotrack->pkt_cnt) {
+ if (st->codec->codec_id == CODEC_ID_RA_288)
+ for (x=0; x<h/2; x++)
+ memcpy(audiotrack->buf+x*2*w+y*cfs,
+ data+x*cfs, cfs);
+ else
+ for (x=0; x<w/sps; x++)
+ memcpy(audiotrack->buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
+
+ if (++audiotrack->sub_packet_cnt >= h) {
+ audiotrack->sub_packet_cnt = 0;
+ audiotrack->pkt_cnt = h*w / a;
+ }
+ }
+ while (audiotrack->pkt_cnt) {
+ pkt = av_mallocz(sizeof(AVPacket));
+ av_new_packet(pkt, a);
+ memcpy(pkt->data, audiotrack->buf
+ + a * (h*w / a - audiotrack->pkt_cnt--), a);
+ pkt->pos = pos;
+ pkt->stream_index = matroska->tracks[track]->stream_index;
+ matroska_queue_packet(matroska, pkt);
+ }
+ } else {
+ int offset = 0;
+
+ pkt = av_mallocz(sizeof(AVPacket));
+ /* XXX: prevent data copy... */
+ if (av_new_packet(pkt, lace_size[n]-offset) < 0) {
+ res = AVERROR(ENOMEM);
+ n = laces-1;
+ break;
+ }
+ memcpy (pkt->data, data+offset, lace_size[n]-offset);
+
+ if (n == 0)
+ pkt->flags = is_keyframe;
+ pkt->stream_index = matroska->tracks[track]->stream_index;
+
+ pkt->pts = timecode;
+ pkt->pos = pos;
+ pkt->duration = duration;
+
+ matroska_queue_packet(matroska, pkt);
+ }
+
+ if (timecode != AV_NOPTS_VALUE)
+ timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
+ data += lace_size[n];
+ }
+ }
+
+ av_free(lace_size);
+ av_free(origdata);
+ return res;
+}
+
+static int
+matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
+ uint64_t cluster_time)
+{
+ int res = 0;
+ uint32_t id;
+ int is_bframe = 0;
+ int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets;
+ uint64_t duration = AV_NOPTS_VALUE;
+ uint8_t *data;
+ int size = 0;
+ int64_t pos = 0;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one block inside the group. Note, block parsing is one
+ * of the harder things, so this code is a bit complicated.
+ * See http://www.matroska.org/ for documentation. */
+ case MATROSKA_ID_BLOCK: {
+ pos = url_ftell(matroska->ctx->pb);
+ res = ebml_read_binary(matroska, &id, &data, &size);
+ break;
+ }
+
+ case MATROSKA_ID_BLOCKDURATION: {
+ if ((res = ebml_read_uint(matroska, &id, &duration)) < 0)
+ break;
+ break;
+ }
+
+ case MATROSKA_ID_BLOCKREFERENCE: {
+ int64_t num;
+ /* We've found a reference, so not even the first frame in
+ * the lace is a key frame. */
+ is_keyframe = 0;
+ if (last_num_packets != matroska->num_packets)
+ matroska->packets[last_num_packets]->flags = 0;
+ if ((res = ebml_read_sint(matroska, &id, &num)) < 0)
+ break;
+ if (num > 0)
+ is_bframe = 1;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in blockgroup data\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (res)
+ return res;
+
+ if (size > 0)
+ res = matroska_parse_block(matroska, data, size, pos, cluster_time,
+ duration, is_keyframe, is_bframe);
+
+ return res;
+}
+
+static int
+matroska_parse_cluster (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ uint64_t cluster_time = 0;
+ uint8_t *data;
+ int64_t pos;
+ int size;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG,
+ "parsing cluster at %"PRId64"\n", url_ftell(matroska->ctx->pb));
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* cluster timecode */
+ case MATROSKA_ID_CLUSTERTIMECODE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ cluster_time = num;
+ break;
+ }
+
+ /* a group of blocks inside a cluster */
+ case MATROSKA_ID_BLOCKGROUP:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_blockgroup(matroska, cluster_time);
+ break;
+
+ case MATROSKA_ID_SIMPLEBLOCK:
+ pos = url_ftell(matroska->ctx->pb);
+ res = ebml_read_binary(matroska, &id, &data, &size);
+ if (res == 0)
+ res = matroska_parse_block(matroska, data, size, pos,
+ cluster_time, AV_NOPTS_VALUE,
+ -1, 0);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cluster data\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_read_packet (AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int res;
+ uint32_t id;
+
+ /* Read stream until we have a packet queued. */
+ while (matroska_deliver_packet(matroska, pkt)) {
+
+ /* Have we already reached the end? */
+ if (matroska->done)
+ return AVERROR(EIO);
+
+ res = 0;
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ return AVERROR(EIO);
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_CLUSTER:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ if ((res = matroska_parse_cluster(matroska)) == 0)
+ res = 1; /* Parsed one cluster, let's get out. */
+ break;
+
+ default:
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (res == -1)
+ matroska->done = 1;
+ }
+
+ return 0;
+}
+
+static int
+matroska_read_seek (AVFormatContext *s, int stream_index, int64_t timestamp,
+ int flags)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ AVStream *st = s->streams[stream_index];
+ int index;
+
+ /* find index entry */
+ index = av_index_search_timestamp(st, timestamp, flags);
+ if (index < 0)
+ return 0;
+
+ matroska_clear_queue(matroska);
+
+ /* do the seek */
+ url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
+ matroska->skip_to_keyframe = !(flags & AVSEEK_FLAG_ANY);
+ matroska->skip_to_stream = st;
+ matroska->peek_id = 0;
+ return 0;
+}
+
+static int
+matroska_read_close (AVFormatContext *s)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int n = 0;
+
+ av_free(matroska->writing_app);
+ av_free(matroska->muxing_app);
+ av_free(matroska->index);
+
+ matroska_clear_queue(matroska);
+
+ for (n = 0; n < matroska->num_tracks; n++) {
+ MatroskaTrack *track = matroska->tracks[n];
+ av_free(track->codec_id);
+ av_free(track->codec_name);
+ av_free(track->codec_priv);
+ av_free(track->name);
+
+ if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ av_free(audiotrack->buf);
+ }
+
+ av_free(track);
+ }
+
+ return 0;
+}
+
+AVInputFormat matroska_demuxer = {
+ "matroska",
+ "Matroska file format",
+ sizeof(MatroskaDemuxContext),
+ matroska_probe,
+ matroska_read_header,
+ matroska_read_packet,
+ matroska_read_close,
+ matroska_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/matroskaenc.c b/contrib/ffmpeg/libavformat/matroskaenc.c
new file mode 100644
index 000000000..d096f7204
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/matroskaenc.c
@@ -0,0 +1,845 @@
+/*
+ * Matroska muxer
+ * Copyright (c) 2007 David Conrad
+ *
+ * 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 "avformat.h"
+#include "md5.h"
+#include "riff.h"
+#include "xiph.h"
+#include "matroska.h"
+#include "avc.h"
+
+typedef struct ebml_master {
+ offset_t pos; ///< absolute offset in the file where the master's elements start
+ int sizebytes; ///< how many bytes were reserved for the size
+} ebml_master;
+
+typedef struct mkv_seekhead_entry {
+ unsigned int elementid;
+ uint64_t segmentpos;
+} mkv_seekhead_entry;
+
+typedef struct mkv_seekhead {
+ offset_t filepos;
+ offset_t segment_offset; ///< the file offset to the beginning of the segment
+ int reserved_size; ///< -1 if appending to file
+ int max_entries;
+ mkv_seekhead_entry *entries;
+ int num_entries;
+} mkv_seekhead;
+
+typedef struct {
+ uint64_t pts;
+ int tracknum;
+ offset_t cluster_pos; ///< file offset of the cluster containing the block
+} mkv_cuepoint;
+
+typedef struct {
+ offset_t segment_offset;
+ mkv_cuepoint *entries;
+ int num_entries;
+} mkv_cues;
+
+typedef struct MatroskaMuxContext {
+ ebml_master segment;
+ offset_t segment_offset;
+ offset_t segment_uid;
+ ebml_master cluster;
+ offset_t cluster_pos; ///< file offset of the current cluster
+ uint64_t cluster_pts;
+ offset_t duration_offset;
+ uint64_t duration;
+ mkv_seekhead *main_seekhead;
+ mkv_seekhead *cluster_seekhead;
+ mkv_cues *cues;
+
+ struct AVMD5 *md5_ctx;
+} MatroskaMuxContext;
+
+
+/** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit
+ * offset, 4 bytes for target EBML ID */
+#define MAX_SEEKENTRY_SIZE 21
+
+/** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2
+ * 8-byte uint max */
+#define MAX_CUETRACKPOS_SIZE 22
+
+/** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */
+#define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks
+
+
+static int ebml_id_size(unsigned int id)
+{
+ return (av_log2(id+1)-1)/7+1;
+}
+
+static void put_ebml_id(ByteIOContext *pb, unsigned int id)
+{
+ int i = ebml_id_size(id);
+ while (i--)
+ put_byte(pb, id >> (i*8));
+}
+
+/**
+ * Write an EBML size meaning "unknown size".
+ *
+ * @param bytes The number of bytes the size should occupy (maximum: 8).
+ */
+static void put_ebml_size_unknown(ByteIOContext *pb, int bytes)
+{
+ assert(bytes <= 8);
+ put_byte(pb, 0x1ff >> bytes);
+ while (--bytes)
+ put_byte(pb, 0xff);
+}
+
+/**
+ * Calculate how many bytes are needed to represent a given number in EBML.
+ */
+static int ebml_num_size(uint64_t num)
+{
+ int bytes = 1;
+ while ((num+1) >> bytes*7) bytes++;
+ return bytes;
+}
+
+/**
+ * Write a number in EBML variable length format.
+ *
+ * @param bytes The number of bytes that need to be used to write the number.
+ * If zero, any number of bytes can be used.
+ */
+static void put_ebml_num(ByteIOContext *pb, uint64_t num, int bytes)
+{
+ int i, needed_bytes = ebml_num_size(num);
+
+ // sizes larger than this are currently undefined in EBML
+ assert(num < (1ULL<<56)-1);
+
+ if (bytes == 0)
+ // don't care how many bytes are used, so use the min
+ bytes = needed_bytes;
+ // the bytes needed to write the given size would exceed the bytes
+ // that we need to use, so write unknown size. This shouldn't happen.
+ assert(bytes >= needed_bytes);
+
+ num |= 1ULL << bytes*7;
+ for (i = bytes - 1; i >= 0; i--)
+ put_byte(pb, num >> i*8);
+}
+
+static void put_ebml_uint(ByteIOContext *pb, unsigned int elementid, uint64_t val)
+{
+ int i, bytes = 1;
+ uint64_t tmp = val;
+ while (tmp>>=8) bytes++;
+
+ put_ebml_id(pb, elementid);
+ put_ebml_num(pb, bytes, 0);
+ for (i = bytes - 1; i >= 0; i--)
+ put_byte(pb, val >> i*8);
+}
+
+static void put_ebml_float(ByteIOContext *pb, unsigned int elementid, double val)
+{
+ put_ebml_id(pb, elementid);
+ put_ebml_num(pb, 8, 0);
+ put_be64(pb, av_dbl2int(val));
+}
+
+static void put_ebml_binary(ByteIOContext *pb, unsigned int elementid,
+ const uint8_t *buf, int size)
+{
+ put_ebml_id(pb, elementid);
+ put_ebml_num(pb, size, 0);
+ put_buffer(pb, buf, size);
+}
+
+static void put_ebml_string(ByteIOContext *pb, unsigned int elementid, const char *str)
+{
+ put_ebml_binary(pb, elementid, str, strlen(str));
+}
+
+/**
+ * Writes a void element of a given size. Useful for reserving space in
+ * the file to be written to later.
+ *
+ * @param size The number of bytes to reserve, which must be at least 2.
+ */
+static void put_ebml_void(ByteIOContext *pb, uint64_t size)
+{
+ offset_t currentpos = url_ftell(pb);
+
+ assert(size >= 2);
+
+ put_ebml_id(pb, EBML_ID_VOID);
+ // we need to subtract the length needed to store the size from the
+ // size we need to reserve so 2 cases, we use 8 bytes to store the
+ // size if possible, 1 byte otherwise
+ if (size < 10)
+ put_ebml_num(pb, size-1, 0);
+ else
+ put_ebml_num(pb, size-9, 8);
+ while(url_ftell(pb) < currentpos + size)
+ put_byte(pb, 0);
+}
+
+static ebml_master start_ebml_master(ByteIOContext *pb, unsigned int elementid, uint64_t expectedsize)
+{
+ int bytes = expectedsize ? ebml_num_size(expectedsize) : 8;
+ put_ebml_id(pb, elementid);
+ put_ebml_size_unknown(pb, bytes);
+ return (ebml_master){ url_ftell(pb), bytes };
+}
+
+static void end_ebml_master(ByteIOContext *pb, ebml_master master)
+{
+ offset_t pos = url_ftell(pb);
+
+ // leave the unknown size for masters when streaming
+ if (url_is_streamed(pb))
+ return;
+
+ url_fseek(pb, master.pos - master.sizebytes, SEEK_SET);
+ put_ebml_num(pb, pos - master.pos, master.sizebytes);
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static void put_xiph_size(ByteIOContext *pb, int size)
+{
+ int i;
+ for (i = 0; i < size / 255; i++)
+ put_byte(pb, 255);
+ put_byte(pb, size % 255);
+}
+
+/**
+ * Initialize a mkv_seekhead element to be ready to index level 1 Matroska
+ * elements. If a maximum number of elements is specified, enough space
+ * will be reserved at the current file location to write a seek head of
+ * that size.
+ *
+ * @param segment_offset The absolute offset to the position in the file
+ * where the segment begins.
+ * @param numelements The maximum number of elements that will be indexed
+ * by this seek head, 0 if unlimited.
+ */
+static mkv_seekhead * mkv_start_seekhead(ByteIOContext *pb, offset_t segment_offset, int numelements)
+{
+ mkv_seekhead *new_seekhead = av_mallocz(sizeof(mkv_seekhead));
+ if (new_seekhead == NULL)
+ return NULL;
+
+ new_seekhead->segment_offset = segment_offset;
+
+ if (numelements > 0) {
+ new_seekhead->filepos = url_ftell(pb);
+ // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID
+ // and size, and 3 bytes to guarantee that an EBML void element
+ // will fit afterwards
+ new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 13;
+ new_seekhead->max_entries = numelements;
+ put_ebml_void(pb, new_seekhead->reserved_size);
+ }
+ return new_seekhead;
+}
+
+static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, unsigned int elementid, uint64_t filepos)
+{
+ mkv_seekhead_entry *entries = seekhead->entries;
+
+ // don't store more elements than we reserved space for
+ if (seekhead->max_entries > 0 && seekhead->max_entries <= seekhead->num_entries)
+ return -1;
+
+ entries = av_realloc(entries, (seekhead->num_entries + 1) * sizeof(mkv_seekhead_entry));
+ if (entries == NULL)
+ return AVERROR(ENOMEM);
+
+ entries[seekhead->num_entries ].elementid = elementid;
+ entries[seekhead->num_entries++].segmentpos = filepos - seekhead->segment_offset;
+
+ seekhead->entries = entries;
+ return 0;
+}
+
+/**
+ * Write the seek head to the file and free it. If a maximum number of
+ * elements was specified to mkv_start_seekhead(), the seek head will
+ * be written at the location reserved for it. Otherwise, it is written
+ * at the current location in the file.
+ *
+ * @return The file offset where the seekhead was written.
+ */
+static offset_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead)
+{
+ ebml_master metaseek, seekentry;
+ offset_t currentpos;
+ int i;
+
+ currentpos = url_ftell(pb);
+
+ if (seekhead->reserved_size > 0)
+ url_fseek(pb, seekhead->filepos, SEEK_SET);
+
+ metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_size);
+ for (i = 0; i < seekhead->num_entries; i++) {
+ mkv_seekhead_entry *entry = &seekhead->entries[i];
+
+ seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE);
+
+ put_ebml_id(pb, MATROSKA_ID_SEEKID);
+ put_ebml_num(pb, ebml_id_size(entry->elementid), 0);
+ put_ebml_id(pb, entry->elementid);
+
+ put_ebml_uint(pb, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
+ end_ebml_master(pb, seekentry);
+ }
+ end_ebml_master(pb, metaseek);
+
+ if (seekhead->reserved_size > 0) {
+ uint64_t remaining = seekhead->filepos + seekhead->reserved_size - url_ftell(pb);
+ put_ebml_void(pb, remaining);
+ url_fseek(pb, currentpos, SEEK_SET);
+
+ currentpos = seekhead->filepos;
+ }
+ av_free(seekhead->entries);
+ av_free(seekhead);
+
+ return currentpos;
+}
+
+static mkv_cues * mkv_start_cues(offset_t segment_offset)
+{
+ mkv_cues *cues = av_mallocz(sizeof(mkv_cues));
+ if (cues == NULL)
+ return NULL;
+
+ cues->segment_offset = segment_offset;
+ return cues;
+}
+
+static int mkv_add_cuepoint(mkv_cues *cues, AVPacket *pkt, offset_t cluster_pos)
+{
+ mkv_cuepoint *entries = cues->entries;
+
+ entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint));
+ if (entries == NULL)
+ return AVERROR(ENOMEM);
+
+ entries[cues->num_entries ].pts = pkt->pts;
+ entries[cues->num_entries ].tracknum = pkt->stream_index + 1;
+ entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset;
+
+ cues->entries = entries;
+ return 0;
+}
+
+static offset_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks)
+{
+ ebml_master cues_element;
+ offset_t currentpos;
+ int i, j;
+
+ currentpos = url_ftell(pb);
+ cues_element = start_ebml_master(pb, MATROSKA_ID_CUES, 0);
+
+ for (i = 0; i < cues->num_entries; i++) {
+ ebml_master cuepoint, track_positions;
+ mkv_cuepoint *entry = &cues->entries[i];
+ uint64_t pts = entry->pts;
+
+ cuepoint = start_ebml_master(pb, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_SIZE(num_tracks));
+ put_ebml_uint(pb, MATROSKA_ID_CUETIME, pts);
+
+ // put all the entries from different tracks that have the exact same
+ // timestamp into the same CuePoint
+ for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
+ track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
+ put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum );
+ put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos);
+ end_ebml_master(pb, track_positions);
+ }
+ i += j - 1;
+ end_ebml_master(pb, cuepoint);
+ }
+ end_ebml_master(pb, cues_element);
+
+ av_free(cues->entries);
+ av_free(cues);
+ return currentpos;
+}
+
+static int put_xiph_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
+{
+ uint8_t *header_start[3];
+ int header_len[3];
+ int first_header_size;
+ int j;
+
+ if (codec->codec_id == CODEC_ID_VORBIS)
+ first_header_size = 30;
+ else
+ first_header_size = 42;
+
+ if (ff_split_xiph_headers(codec->extradata, codec->extradata_size,
+ first_header_size, header_start, header_len) < 0) {
+ av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
+ return -1;
+ }
+
+ put_byte(pb, 2); // number packets - 1
+ for (j = 0; j < 2; j++) {
+ put_xiph_size(pb, header_len[j]);
+ }
+ for (j = 0; j < 3; j++)
+ put_buffer(pb, header_start[j], header_len[j]);
+
+ return 0;
+}
+
+#define FLAC_STREAMINFO_SIZE 34
+
+static int put_flac_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
+{
+ // if the extradata_size is greater than FLAC_STREAMINFO_SIZE,
+ // assume that it's in Matroska's format already
+ if (codec->extradata_size < FLAC_STREAMINFO_SIZE) {
+ av_log(s, AV_LOG_ERROR, "Invalid FLAC extradata\n");
+ return -1;
+ } else if (codec->extradata_size == FLAC_STREAMINFO_SIZE) {
+ // only the streaminfo packet
+ put_byte(pb, 0);
+ put_xiph_size(pb, codec->extradata_size);
+ av_log(s, AV_LOG_ERROR, "Only one packet\n");
+ }
+ put_buffer(pb, codec->extradata, codec->extradata_size);
+ return 0;
+}
+
+static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate)
+{
+ static const int aac_sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ };
+ int sri;
+
+ if (codec->extradata_size < 2) {
+ av_log(s, AV_LOG_WARNING, "No AAC extradata, unable to determine samplerate.\n");
+ return;
+ }
+
+ sri = ((codec->extradata[0] << 1) & 0xE) | (codec->extradata[1] >> 7);
+ if (sri > 12) {
+ av_log(s, AV_LOG_WARNING, "AAC samplerate index out of bounds\n");
+ return;
+ }
+ *sample_rate = aac_sample_rates[sri];
+
+ // if sbr, get output sample rate as well
+ if (codec->extradata_size == 5) {
+ sri = (codec->extradata[4] >> 3) & 0xF;
+ if (sri > 12) {
+ av_log(s, AV_LOG_WARNING, "AAC output samplerate index out of bounds\n");
+ return;
+ }
+ *output_sample_rate = aac_sample_rates[sri];
+ }
+}
+
+static int mkv_write_codecprivate(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec, int native_id)
+{
+ ByteIOContext *dyn_cp;
+ uint8_t *codecpriv;
+ int ret, codecpriv_size;
+
+ ret = url_open_dyn_buf(&dyn_cp);
+ if(ret < 0)
+ return ret;
+
+ if (native_id) {
+ if (codec->codec_id == CODEC_ID_VORBIS || codec->codec_id == CODEC_ID_THEORA)
+ ret = put_xiph_codecpriv(s, dyn_cp, codec);
+ else if (codec->codec_id == CODEC_ID_FLAC)
+ ret = put_flac_codecpriv(s, dyn_cp, codec);
+ else if (codec->codec_id == CODEC_ID_H264)
+ ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size);
+ else if (codec->extradata_size)
+ put_buffer(dyn_cp, codec->extradata, codec->extradata_size);
+ } else if (codec->codec_type == CODEC_TYPE_VIDEO) {
+ if (!codec->codec_tag)
+ codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id);
+ if (!codec->codec_tag) {
+ av_log(s, AV_LOG_ERROR, "No bmp codec ID found.");
+ ret = -1;
+ }
+
+ put_bmp_header(dyn_cp, codec, codec_bmp_tags, 0);
+
+ } else if (codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (!codec->codec_tag)
+ codec->codec_tag = codec_get_tag(codec_wav_tags, codec->codec_id);
+ if (!codec->codec_tag) {
+ av_log(s, AV_LOG_ERROR, "No wav codec ID found.");
+ ret = -1;
+ }
+
+ put_wav_header(dyn_cp, codec);
+ }
+
+ codecpriv_size = url_close_dyn_buf(dyn_cp, &codecpriv);
+ if (codecpriv_size)
+ put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size);
+ av_free(codecpriv);
+ return ret;
+}
+
+static int mkv_write_tracks(AVFormatContext *s)
+{
+ MatroskaMuxContext *mkv = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ ebml_master tracks;
+ int i, j, ret;
+
+ ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, url_ftell(pb));
+ if (ret < 0) return ret;
+
+ tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0);
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ AVCodecContext *codec = st->codec;
+ ebml_master subinfo, track;
+ int native_id = 0;
+ int bit_depth = av_get_bits_per_sample(codec->codec_id);
+ int sample_rate = codec->sample_rate;
+ int output_sample_rate = 0;
+
+ if (!bit_depth)
+ bit_depth = av_get_bits_per_sample_format(codec->sample_fmt);
+
+ if (codec->codec_id == CODEC_ID_AAC)
+ get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate);
+
+ track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
+ put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1);
+ put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1);
+ put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet)
+
+ if (st->language[0])
+ put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, st->language);
+ else
+ put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, "und");
+
+ // look for a codec ID string specific to mkv to use,
+ // if none are found, use AVI codes
+ for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) {
+ if (ff_mkv_codec_tags[j].id == codec->codec_id) {
+ put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
+ native_id = 1;
+ break;
+ }
+ }
+
+ switch (codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
+
+ if (!native_id)
+ // if there is no mkv-specific codec ID, use VFW mode
+ put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
+
+ subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
+ // XXX: interlace flag?
+ put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
+ put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
+ if (codec->sample_aspect_ratio.num) {
+ AVRational dar = av_mul_q(codec->sample_aspect_ratio,
+ (AVRational){codec->width, codec->height});
+ put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , dar.num);
+ put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, dar.den);
+ }
+ end_ebml_master(pb, subinfo);
+ break;
+
+ case CODEC_TYPE_AUDIO:
+ put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
+
+ if (!native_id)
+ // no mkv-specific ID, use ACM mode
+ put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_AUDIO_ACM);
+
+ subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
+ put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels);
+ put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
+ if (output_sample_rate)
+ put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
+ if (bit_depth)
+ put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
+ end_ebml_master(pb, subinfo);
+ break;
+
+ case CODEC_TYPE_SUBTITLE:
+ put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE);
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.");
+ break;
+ }
+ ret = mkv_write_codecprivate(s, pb, codec, native_id);
+ if (ret < 0) return ret;
+
+ end_ebml_master(pb, track);
+
+ // ms precision is the de-facto standard timescale for mkv files
+ av_set_pts_info(st, 64, 1, 1000);
+ }
+ end_ebml_master(pb, tracks);
+ return 0;
+}
+
+static int mkv_write_header(AVFormatContext *s)
+{
+ MatroskaMuxContext *mkv = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ ebml_master ebml_header, segment_info;
+ int ret;
+
+ mkv->md5_ctx = av_mallocz(av_md5_size);
+ av_md5_init(mkv->md5_ctx);
+
+ ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);
+ put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
+ put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
+ put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
+ put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8);
+ put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska");
+ put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2);
+ put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2);
+ end_ebml_master(pb, ebml_header);
+
+ mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);
+ mkv->segment_offset = url_ftell(pb);
+
+ // we write 2 seek heads - one at the end of the file to point to each
+ // cluster, and one at the beginning to point to all other level one
+ // elements (including the seek head at the end of the file), which
+ // isn't more than 10 elements if we only write one of each other
+ // currently defined level 1 element
+ mkv->main_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 10);
+ mkv->cluster_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 0);
+ if (mkv->main_seekhead == NULL || mkv->cluster_seekhead == NULL)
+ return AVERROR(ENOMEM);
+
+ ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, url_ftell(pb));
+ if (ret < 0) return ret;
+
+ segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0);
+ put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
+ if (strlen(s->title))
+ put_ebml_string(pb, MATROSKA_ID_TITLE, s->title);
+ if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+ put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT);
+ put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
+
+ // reserve space to write the segment UID later
+ mkv->segment_uid = url_ftell(pb);
+ put_ebml_void(pb, 19);
+ }
+
+ // reserve space for the duration
+ mkv->duration = 0;
+ mkv->duration_offset = url_ftell(pb);
+ put_ebml_void(pb, 11); // assumes double-precision float to be written
+ end_ebml_master(pb, segment_info);
+
+ ret = mkv_write_tracks(s);
+ if (ret < 0) return ret;
+
+ ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
+ if (ret < 0) return ret;
+
+ mkv->cluster_pos = url_ftell(pb);
+ mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
+ put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0);
+ mkv->cluster_pts = 0;
+
+ mkv->cues = mkv_start_cues(mkv->segment_offset);
+ if (mkv->cues == NULL)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static int mkv_block_size(AVPacket *pkt)
+{
+ int size = 4; // track num + timecode + flags
+ return size + pkt->size;
+}
+
+static int mkv_blockgroup_size(AVPacket *pkt)
+{
+ int size = mkv_block_size(pkt);
+ size += ebml_num_size(size);
+ size += 2; // EBML ID for block and block duration
+ size += 8; // max size of block duration
+ size += ebml_num_size(size);
+ size += 1; // blockgroup EBML ID
+ return size;
+}
+
+static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *pkt, int flags)
+{
+ MatroskaMuxContext *mkv = s->priv_data;
+ ByteIOContext *pb = s->pb;
+
+ av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
+ "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n",
+ url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags);
+ put_ebml_id(pb, blockid);
+ put_ebml_num(pb, mkv_block_size(pkt), 0);
+ put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126
+ put_be16(pb, pkt->pts - mkv->cluster_pts);
+ put_byte(pb, flags);
+ put_buffer(pb, pkt->data, pkt->size);
+}
+
+static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MatroskaMuxContext *mkv = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+ int keyframe = !!(pkt->flags & PKT_FLAG_KEY);
+ int ret;
+
+ // start a new cluster every 5 MB or 5 sec
+ if (url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluster_pts + 5000) {
+ av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
+ " bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts);
+ end_ebml_master(pb, mkv->cluster);
+
+ ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
+ if (ret < 0) return ret;
+
+ mkv->cluster_pos = url_ftell(pb);
+ mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
+ put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts);
+ mkv->cluster_pts = pkt->pts;
+ av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size));
+ }
+
+ if (codec->codec_id == CODEC_ID_H264 &&
+ codec->extradata_size > 0 && AV_RB32(codec->extradata) == 0x00000001) {
+ /* from x264 or from bytestream h264 */
+ /* nal reformating needed */
+ int ret = ff_avc_parse_nal_units(pkt->data, &pkt->data, &pkt->size);
+ if (ret < 0)
+ return ret;
+ assert(pkt->size);
+ }
+
+ if (codec->codec_type != CODEC_TYPE_SUBTITLE) {
+ mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
+ } else {
+ ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt));
+ mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0);
+ put_ebml_uint(pb, MATROSKA_ID_DURATION, pkt->duration);
+ end_ebml_master(pb, blockgroup);
+ }
+
+ if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) {
+ ret = mkv_add_cuepoint(mkv->cues, pkt, mkv->cluster_pos);
+ if (ret < 0) return ret;
+ }
+
+ mkv->duration = FFMAX(mkv->duration, pkt->pts + pkt->duration);
+ return 0;
+}
+
+static int mkv_write_trailer(AVFormatContext *s)
+{
+ MatroskaMuxContext *mkv = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ offset_t currentpos, second_seekhead, cuespos;
+ int ret;
+
+ end_ebml_master(pb, mkv->cluster);
+
+ if (!url_is_streamed(pb)) {
+ cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
+ second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead);
+
+ ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos);
+ if (ret < 0) return ret;
+ ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEAD, second_seekhead);
+ if (ret < 0) return ret;
+ mkv_write_seekhead(pb, mkv->main_seekhead);
+
+ // update the duration
+ av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
+ currentpos = url_ftell(pb);
+ url_fseek(pb, mkv->duration_offset, SEEK_SET);
+ put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration);
+
+ // write the md5sum of some frames as the segment UID
+ if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+ uint8_t segment_uid[16];
+ av_md5_final(mkv->md5_ctx, segment_uid);
+ url_fseek(pb, mkv->segment_uid, SEEK_SET);
+ put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);
+ }
+ url_fseek(pb, currentpos, SEEK_SET);
+ }
+
+ end_ebml_master(pb, mkv->segment);
+ av_free(mkv->md5_ctx);
+ return 0;
+}
+
+AVOutputFormat matroska_muxer = {
+ "matroska",
+ "Matroska File Format",
+ "video/x-matroska",
+ "mkv",
+ sizeof(MatroskaMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG4,
+ mkv_write_header,
+ mkv_write_packet,
+ mkv_write_trailer,
+ .codec_tag = (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
+ .subtitle_codec = CODEC_ID_TEXT,
+};
+
+AVOutputFormat matroska_audio_muxer = {
+ "matroska",
+ "Matroska File Format",
+ "audio/x-matroska",
+ "mka",
+ sizeof(MatroskaMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_NONE,
+ mkv_write_header,
+ mkv_write_packet,
+ mkv_write_trailer,
+ .codec_tag = (const AVCodecTag*[]){codec_wav_tags, 0},
+};
diff --git a/contrib/ffmpeg/libavformat/mm.c b/contrib/ffmpeg/libavformat/mm.c
index 443b70929..4e6bac027 100644
--- a/contrib/ffmpeg/libavformat/mm.c
+++ b/contrib/ffmpeg/libavformat/mm.c
@@ -16,7 +16,7 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
@@ -59,8 +59,6 @@ typedef struct {
static int mm_probe(AVProbeData *p)
{
/* the first chunk is always the header */
- if (p->buf_size < MM_PREAMBLE_SIZE)
- return 0;
if (AV_RL16(&p->buf[0]) != MM_TYPE_HEADER)
return 0;
if (AV_RL32(&p->buf[2]) != MM_HEADER_LEN_V && AV_RL32(&p->buf[2]) != MM_HEADER_LEN_AV)
@@ -73,8 +71,8 @@ static int mm_probe(AVProbeData *p)
static int mm_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- MmDemuxContext *mm = (MmDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ MmDemuxContext *mm = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVStream *st;
unsigned int type, length;
@@ -97,7 +95,7 @@ static int mm_read_header(AVFormatContext *s,
/* video stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = CODEC_ID_MMVIDEO;
st->codec->codec_tag = 0; /* no fourcc */
@@ -110,7 +108,7 @@ static int mm_read_header(AVFormatContext *s,
if (length == MM_HEADER_LEN_AV) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_tag = 0; /* no fourcc */
st->codec->codec_id = CODEC_ID_PCM_U8;
@@ -128,8 +126,8 @@ static int mm_read_header(AVFormatContext *s,
static int mm_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- MmDemuxContext *mm = (MmDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ MmDemuxContext *mm = s->priv_data;
+ ByteIOContext *pb = s->pb;
unsigned char preamble[MM_PREAMBLE_SIZE];
unsigned char pal[MM_PALETTE_SIZE];
unsigned int type, length;
@@ -138,7 +136,7 @@ static int mm_read_packet(AVFormatContext *s,
while(1) {
if (get_buffer(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
type = AV_RL16(&preamble[0]);
@@ -148,7 +146,7 @@ static int mm_read_packet(AVFormatContext *s,
case MM_TYPE_PALETTE :
url_fseek(pb, 4, SEEK_CUR); /* unknown data */
if (get_buffer(pb, pal, MM_PALETTE_SIZE) != MM_PALETTE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
url_fseek(pb, length - (4 + MM_PALETTE_SIZE), SEEK_CUR);
for (i=0; i<MM_PALETTE_COUNT; i++) {
@@ -170,18 +168,18 @@ static int mm_read_packet(AVFormatContext *s,
case MM_TYPE_INTER_HHV :
/* output preamble + data */
if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
if (get_buffer(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->size = length + MM_PREAMBLE_SIZE;
pkt->stream_index = 0;
pkt->pts = mm->video_pts++;
return 0;
case MM_TYPE_AUDIO :
- if (av_get_packet(&s->pb, pkt, length)<0)
- return AVERROR_NOMEM;
+ if (av_get_packet(s->pb, pkt, length)<0)
+ return AVERROR(ENOMEM);
pkt->size = length;
pkt->stream_index = 1;
pkt->pts = mm->audio_pts++;
diff --git a/contrib/ffmpeg/libavformat/mmf.c b/contrib/ffmpeg/libavformat/mmf.c
index 40b1a497c..84c21a01d 100644
--- a/contrib/ffmpeg/libavformat/mmf.c
+++ b/contrib/ffmpeg/libavformat/mmf.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "allformats.h"
+#include "raw.h"
#include "riff.h"
typedef struct {
@@ -60,7 +60,7 @@ static void end_tag_be(ByteIOContext *pb, offset_t start)
static int mmf_write_header(AVFormatContext *s)
{
MMFContext *mmf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t pos;
int rate;
@@ -108,7 +108,7 @@ static int mmf_write_header(AVFormatContext *s)
static int mmf_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
put_buffer(pb, pkt->data, pkt->size);
return 0;
}
@@ -127,12 +127,12 @@ static void put_varlength(ByteIOContext *pb, int val)
static int mmf_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
MMFContext *mmf = s->priv_data;
offset_t pos, size;
int gatetime;
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
/* Fill in length fields */
end_tag_be(pb, mmf->awapos);
end_tag_be(pb, mmf->atrpos);
@@ -168,8 +168,6 @@ static int mmf_write_trailer(AVFormatContext *s)
static int mmf_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size <= 32)
- return 0;
if (p->buf[0] == 'M' && p->buf[1] == 'M' &&
p->buf[2] == 'M' && p->buf[3] == 'D' &&
p->buf[8] == 'C' && p->buf[9] == 'N' &&
@@ -185,7 +183,7 @@ static int mmf_read_header(AVFormatContext *s,
{
MMFContext *mmf = s->priv_data;
unsigned int tag;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
offset_t file_size, size;
int rate, params;
@@ -244,7 +242,7 @@ static int mmf_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_ADPCM_YAMAHA;
@@ -267,8 +265,8 @@ static int mmf_read_packet(AVFormatContext *s,
AVStream *st;
int ret, size;
- if (url_feof(&s->pb))
- return AVERROR_IO;
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
st = s->streams[0];
size = MAX_SIZE;
@@ -276,13 +274,13 @@ static int mmf_read_packet(AVFormatContext *s,
size = mmf->data_size;
if(!size)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (av_new_packet(pkt, size))
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = 0;
- ret = get_buffer(&s->pb, pkt->data, pkt->size);
+ ret = get_buffer(s->pb, pkt->data, pkt->size);
if (ret < 0)
av_free_packet(pkt);
diff --git a/contrib/ffmpeg/libavformat/mov.c b/contrib/ffmpeg/libavformat/mov.c
index e9b577576..a67604b0e 100644
--- a/contrib/ffmpeg/libavformat/mov.c
+++ b/contrib/ffmpeg/libavformat/mov.c
@@ -38,16 +38,8 @@
*
* Features and limitations:
* - reads most of the QT files I have (at least the structure),
- * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
- * FIXED, Francois Revol, 07/17/2002
- * - ffmpeg has nearly none of the usual QuickTime codecs,
- * although I succesfully dumped raw and mp3 audio tracks off .mov files.
* Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
- * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
- * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
- * http://mpeg.telecomitalialab.com/faq.htm
* - the code is quite ugly... maybe I won't do it recursive next time :-)
- * - seek is not supported with files that contain edit list
*
* Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
* when coding this :) (it's a writer anyway)
@@ -71,11 +63,16 @@
* Here we just use what is needed to read the chunks
*/
-typedef struct MOV_sample_to_chunk_tbl {
- long first;
- long count;
- long id;
-} MOV_sample_to_chunk_tbl;
+typedef struct {
+ int first;
+ int count;
+ int id;
+} MOV_stsc_t;
+
+typedef struct {
+ uint32_t type;
+ char *path;
+} MOV_dref_t;
typedef struct {
uint32_t type;
@@ -83,94 +80,39 @@ typedef struct {
int64_t size; /* total size (excluding the size and type fields) */
} MOV_atom_t;
-typedef struct {
- int seed;
- int flags;
- int size;
- void* clrs;
-} MOV_ctab_t;
-
-typedef struct MOV_mdat_atom_s {
- offset_t offset;
- int64_t size;
-} MOV_mdat_atom_t;
-
-typedef struct {
- uint8_t version;
- uint32_t flags; // 24bit
-
- /* 0x03 ESDescrTag */
- uint16_t es_id;
-#define MP4ODescrTag 0x01
-#define MP4IODescrTag 0x02
-#define MP4ESDescrTag 0x03
-#define MP4DecConfigDescrTag 0x04
-#define MP4DecSpecificDescrTag 0x05
-#define MP4SLConfigDescrTag 0x06
-#define MP4ContentIdDescrTag 0x07
-#define MP4SupplContentIdDescrTag 0x08
-#define MP4IPIPtrDescrTag 0x09
-#define MP4IPMPPtrDescrTag 0x0A
-#define MP4IPMPDescrTag 0x0B
-#define MP4RegistrationDescrTag 0x0D
-#define MP4ESIDIncDescrTag 0x0E
-#define MP4ESIDRefDescrTag 0x0F
-#define MP4FileIODescrTag 0x10
-#define MP4FileODescrTag 0x11
-#define MP4ExtProfileLevelDescrTag 0x13
-#define MP4ExtDescrTagsStart 0x80
-#define MP4ExtDescrTagsEnd 0xFE
- uint8_t stream_priority;
-
- /* 0x04 DecConfigDescrTag */
- uint8_t object_type_id;
- uint8_t stream_type;
- /* XXX: really streamType is
- * only 6bit, followed by:
- * 1bit upStream
- * 1bit reserved
- */
- uint32_t buffer_size_db; // 24
- uint32_t max_bitrate;
- uint32_t avg_bitrate;
-
- /* 0x05 DecSpecificDescrTag */
- uint8_t decoder_cfg_len;
- uint8_t *decoder_cfg;
-
- /* 0x06 SLConfigDescrTag */
- uint8_t sl_config_len;
- uint8_t *sl_config;
-} MOV_esds_t;
-
struct MOVParseTableEntry;
typedef struct MOVStreamContext {
+ ByteIOContext *pb;
int ffindex; /* the ffmpeg stream id */
- long next_chunk;
+ int next_chunk;
unsigned int chunk_count;
int64_t *chunk_offsets;
unsigned int stts_count;
- Time2Sample *stts_data;
+ MOV_stts_t *stts_data;
unsigned int ctts_count;
- Time2Sample *ctts_data;
+ MOV_stts_t *ctts_data;
unsigned int edit_count; /* number of 'edit' (elst atom) */
unsigned int sample_to_chunk_sz;
- MOV_sample_to_chunk_tbl *sample_to_chunk;
+ MOV_stsc_t *sample_to_chunk;
int sample_to_ctime_index;
int sample_to_ctime_sample;
unsigned int sample_size;
unsigned int sample_count;
- long *sample_sizes;
+ int *sample_sizes;
unsigned int keyframe_count;
- long *keyframes;
+ int *keyframes;
int time_scale;
int time_rate;
- long current_sample;
- MOV_esds_t esds;
+ int current_sample;
unsigned int bytes_per_frame;
unsigned int samples_per_frame;
int dv_audio_container;
+ int pseudo_stream_id;
+ int16_t audio_cid; ///< stsd audio compression id
+ unsigned drefs_count;
+ MOV_dref_t *drefs;
+ int dref_id;
} MOVStreamContext;
typedef struct MOVContext {
@@ -179,18 +121,7 @@ typedef struct MOVContext {
int64_t duration; /* duration of the longest track */
int found_moov; /* when both 'moov' and 'mdat' sections has been found */
int found_mdat; /* we suppose we have enough data to read the file */
- int64_t mdat_offset;
- int total_streams;
- MOVStreamContext *streams[MAX_STREAMS];
-
- int ctab_size;
- MOV_ctab_t **ctab; /* color tables */
- const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
- /* NOTE: for recursion save to/ restore from local variable! */
-
AVPaletteControl palette_control;
- MOV_mdat_atom_t *mdat_list;
- int mdat_count;
DVDemuxContext *dv_demux;
AVFormatContext *dv_fctx;
int isom; /* 1 if file is ISO Media (mp4/3gp) */
@@ -205,14 +136,14 @@ typedef struct MOVContext {
0: continue to parse next atom
-1: error occured, exit
*/
-typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
-
/* links atom IDs to parse functions */
typedef struct MOVParseTableEntry {
uint32_t type;
- mov_parse_function func;
+ int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
} MOVParseTableEntry;
+static const MOVParseTableEntry mov_default_parse_table[];
+
static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
int64_t total_size = 0;
@@ -223,17 +154,18 @@ static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
a.offset = atom.offset;
if (atom.size < 0)
- atom.size = 0x7fffffffffffffffLL;
+ atom.size = INT64_MAX;
while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
a.size = atom.size;
- a.type=0L;
+ a.type=0;
if(atom.size >= 8) {
a.size = get_be32(pb);
a.type = get_le32(pb);
}
total_size += 8;
a.offset += 8;
- dprintf(c->fc, "type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
+ dprintf(c->fc, "type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n",
+ a.type, (char*)&a.type, a.size, atom.size, total_size);
if (a.size == 1) { /* 64 bit extended size */
a.size = get_be64(pb) - 8;
a.offset += 8;
@@ -245,19 +177,22 @@ static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
break;
}
a.size -= 8;
- if(a.size < 0 || a.size > atom.size - total_size)
+ if(a.size < 0)
break;
+ a.size = FFMIN(a.size, atom.size - total_size);
- for (i = 0; c->parse_table[i].type != 0L
- && c->parse_table[i].type != a.type; i++)
+ for (i = 0; mov_default_parse_table[i].type != 0
+ && mov_default_parse_table[i].type != a.type; i++)
/* empty */;
- if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
+ if (mov_default_parse_table[i].type == 0) { /* skip leaf atoms data */
url_fskip(pb, a.size);
} else {
offset_t start_pos = url_ftell(pb);
int64_t left;
- err = (c->parse_table[i].func)(c, pb, a);
+ err = mov_default_parse_table[i].parse(c, pb, a);
+ if (c->found_moov && c->found_mdat)
+ break;
left = a.size - url_ftell(pb) + start_pos;
if (left > 0) /* skip garbage at atom end */
url_fskip(pb, left);
@@ -274,27 +209,71 @@ static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
return err;
}
-static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
-#if 1
- url_fskip(pb, atom.size); // for now
-#else
- VERY VERY BROKEN, NEVER execute this, needs rewrite
- unsigned int len;
- MOV_ctab_t *t;
- c->ctab = av_realloc(c->ctab, ++c->ctab_size);
- t = c->ctab[c->ctab_size];
- t->seed = get_be32(pb);
- t->flags = get_be16(pb);
- t->size = get_be16(pb) + 1;
- len = 2 * t->size * 4;
- if (len > 0) {
- t->clrs = av_malloc(len); // 16bit A R G B
- if (t->clrs)
- get_buffer(pb, t->clrs, len);
- }
-#endif
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = st->priv_data;
+ int entries, i, j;
+ get_be32(pb); // version + flags
+ entries = get_be32(pb);
+ if (entries >= UINT_MAX / sizeof(*sc->drefs))
+ return -1;
+ sc->drefs_count = entries;
+ sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
+
+ for (i = 0; i < sc->drefs_count; i++) {
+ MOV_dref_t *dref = &sc->drefs[i];
+ uint32_t size = get_be32(pb);
+ offset_t next = url_ftell(pb) + size - 4;
+
+ dref->type = get_le32(pb);
+ get_be32(pb); // version + flags
+ dprintf(c->fc, "type %.4s size %d\n", (char*)&dref->type, size);
+
+ if (dref->type == MKTAG('a','l','i','s') && size > 150) {
+ /* macintosh alias record */
+ uint16_t volume_len, len;
+ char volume[28];
+ int16_t type;
+
+ url_fskip(pb, 10);
+
+ volume_len = get_byte(pb);
+ volume_len = FFMIN(volume_len, 27);
+ get_buffer(pb, volume, 27);
+ volume[volume_len] = 0;
+ av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len);
+
+ url_fskip(pb, 112);
+
+ for (type = 0; type != -1 && url_ftell(pb) < next; ) {
+ type = get_be16(pb);
+ len = get_be16(pb);
+ av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
+ if (len&1)
+ len += 1;
+ if (type == 2) { // absolute path
+ av_free(dref->path);
+ dref->path = av_mallocz(len+1);
+ if (!dref->path)
+ return AVERROR(ENOMEM);
+ get_buffer(pb, dref->path, len);
+ if (len > volume_len && !strncmp(dref->path, volume, volume_len)) {
+ len -= volume_len;
+ memmove(dref->path, dref->path+volume_len, len);
+ dref->path[len] = 0;
+ }
+ for (j = 0; j < len; j++)
+ if (dref->path[j] == ':')
+ dref->path[j] = '/';
+ av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
+ } else
+ url_fskip(pb, len);
+ }
+ }
+ url_fseek(pb, next, SEEK_SET);
+ }
return 0;
}
@@ -311,8 +290,10 @@ static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
ctype = get_le32(pb);
type = get_le32(pb); /* component subtype */
- dprintf(c->fc, "ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
- dprintf(c->fc, "stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
+ dprintf(c->fc, "ctype= %c%c%c%c (0x%08x)\n", *((char *)&ctype), ((char *)&ctype)[1],
+ ((char *)&ctype)[2], ((char *)&ctype)[3], (int) ctype);
+ dprintf(c->fc, "stype= %c%c%c%c\n",
+ *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
if(!ctype)
c->isom = 1;
if(type == MKTAG('v', 'i', 'd', 'e'))
@@ -323,7 +304,6 @@ static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
st->codec->codec_id = CODEC_ID_MP2;
else if(type == MKTAG('s', 'u', 'b', 'p')) {
st->codec->codec_type = CODEC_TYPE_SUBTITLE;
- st->codec->codec_id = CODEC_ID_DVD_SUBTITLE;
}
get_be32(pb); /* component manufacture */
get_be32(pb); /* component flags */
@@ -336,7 +316,7 @@ static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
return 0;
}
-static int mov_mp4_read_descr_len(ByteIOContext *pb)
+static int mp4_read_descr_len(ByteIOContext *pb)
{
int len = 0;
int count = 4;
@@ -349,51 +329,55 @@ static int mov_mp4_read_descr_len(ByteIOContext *pb)
return len;
}
-static int mov_mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag)
+static int mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag)
{
int len;
*tag = get_byte(pb);
- len = mov_mp4_read_descr_len(pb);
+ len = mp4_read_descr_len(pb);
dprintf(c->fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
return len;
}
+#define MP4ESDescrTag 0x03
+#define MP4DecConfigDescrTag 0x04
+#define MP4DecSpecificDescrTag 0x05
+
static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
int tag, len;
- /* Well, broken but suffisant for some MP4 streams */
get_be32(pb); /* version + flags */
- len = mov_mp4_read_descr(c, pb, &tag);
+ len = mp4_read_descr(c, pb, &tag);
if (tag == MP4ESDescrTag) {
get_be16(pb); /* ID */
get_byte(pb); /* priority */
} else
get_be16(pb); /* ID */
- len = mov_mp4_read_descr(c, pb, &tag);
+ len = mp4_read_descr(c, pb, &tag);
if (tag == MP4DecConfigDescrTag) {
- sc->esds.object_type_id = get_byte(pb);
- sc->esds.stream_type = get_byte(pb);
- sc->esds.buffer_size_db = get_be24(pb);
- sc->esds.max_bitrate = get_be32(pb);
- sc->esds.avg_bitrate = get_be32(pb);
-
- st->codec->codec_id= codec_get_id(ff_mp4_obj_type, sc->esds.object_type_id);
- dprintf(c->fc, "esds object type id %d\n", sc->esds.object_type_id);
- len = mov_mp4_read_descr(c, pb, &tag);
+ int object_type_id = get_byte(pb);
+ get_byte(pb); /* stream type */
+ get_be24(pb); /* buffer size db */
+ get_be32(pb); /* max bitrate */
+ get_be32(pb); /* avg bitrate */
+
+ st->codec->codec_id= codec_get_id(ff_mp4_obj_type, object_type_id);
+ dprintf(c->fc, "esds object type id %d\n", object_type_id);
+ len = mp4_read_descr(c, pb, &tag);
if (tag == MP4DecSpecificDescrTag) {
dprintf(c->fc, "Specific MPEG4 header len=%d\n", len);
+ if((uint64_t)len > (1<<30))
+ return -1;
st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
- if (st->codec->extradata) {
- get_buffer(pb, st->codec->extradata, len);
- st->codec->extradata_size = len;
- /* from mplayer */
- if ((*st->codec->extradata >> 3) == 29) {
- st->codec->codec_id = CODEC_ID_MP3ON4;
- }
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
+ get_buffer(pb, st->codec->extradata, len);
+ st->codec->extradata_size = len;
+ /* from mplayer */
+ if ((*st->codec->extradata >> 3) == 29) {
+ st->codec->codec_id = CODEC_ID_MP3ON4;
}
}
}
@@ -405,12 +389,7 @@ static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
if(atom.size == 0) /* wrong one (MP4) */
return 0;
- c->mdat_list = av_realloc(c->mdat_list, (c->mdat_count + 1) * sizeof(*c->mdat_list));
- c->mdat_list[c->mdat_count].offset = atom.offset;
- c->mdat_list[c->mdat_count].size = atom.size;
- c->mdat_count++;
c->found_mdat=1;
- c->mdat_offset = atom.offset;
if(c->found_moov)
return 1; /* found both, just go */
url_fskip(pb, atom.size);
@@ -432,9 +411,8 @@ static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
/* this atom should contain all header atoms */
static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
- int err;
-
- err = mov_read_default(c, pb, atom);
+ if (mov_read_default(c, pb, atom) < 0)
+ return -1;
/* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
/* so we don't parse the whole file if over a network */
c->found_moov=1;
@@ -447,7 +425,7 @@ static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
int version = get_byte(pb);
int lang;
@@ -488,9 +466,9 @@ static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
get_be32(pb); /* modification time */
}
c->time_scale = get_be32(pb); /* time scale */
-#ifdef DEBUG
- av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
-#endif
+
+ dprintf(c->fc, "time scale = %i\n", c->time_scale);
+
c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
get_be32(pb); /* preferred scale */
@@ -521,16 +499,13 @@ static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
// currently SVQ3 decoder expect full STSD header - so let's fake it
// this should be fixed and just SMI header should be passed
av_free(st->codec->extradata);
+ st->codec->extradata = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
st->codec->extradata_size = 0x5a + atom.size;
- st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-
- if (st->codec->extradata) {
- memcpy(st->codec->extradata, "SVQ3", 4); // fake
- get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
- dprintf(c->fc, "Reading SMI %"PRId64" %s\n", atom.size, st->codec->extradata + 0x5a);
- } else
- url_fskip(pb, atom.size);
-
+ memcpy(st->codec->extradata, "SVQ3", 4); // fake
+ get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
+ dprintf(c->fc, "Reading SMI %"PRId64" %s\n", atom.size, st->codec->extradata + 0x5a);
return 0;
}
@@ -558,16 +533,19 @@ static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- if((uint64_t)atom.size > (1<<30))
+ uint64_t size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
+ uint8_t *buf;
+ if(size > INT_MAX || (uint64_t)atom.size > INT_MAX)
return -1;
- av_free(st->codec->extradata);
- st->codec->extradata_size = atom.size + 8;
- st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (st->codec->extradata) {
- AV_WL32(st->codec->extradata + 4, atom.type);
- get_buffer(pb, st->codec->extradata + 8, atom.size);
- } else
- url_fskip(pb, atom.size);
+ buf= av_realloc(st->codec->extradata, size);
+ if(!buf)
+ return -1;
+ st->codec->extradata= buf;
+ buf+= st->codec->extradata_size;
+ st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE;
+ AV_WB32( buf , atom.size + 8);
+ AV_WL32( buf + 4, atom.type);
+ get_buffer(pb, buf + 8, atom.size);
return 0;
}
@@ -581,21 +559,24 @@ static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
if (st->codec->codec_id == CODEC_ID_QDM2) {
// pass all frma atom to codec, needed at least for QDM2
av_free(st->codec->extradata);
+ st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
st->codec->extradata_size = atom.size;
- st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-
- if (st->codec->extradata) {
- get_buffer(pb, st->codec->extradata, atom.size);
- } else
- url_fskip(pb, atom.size);
+ get_buffer(pb, st->codec->extradata, atom.size);
} else if (atom.size > 8) { /* to read frma, esds atoms */
- mov_read_default(c, pb, atom);
+ if (mov_read_default(c, pb, atom) < 0)
+ return -1;
} else
url_fskip(pb, atom.size);
return 0;
}
-static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+/**
+ * This function reads atom content and puts data in extradata without tag
+ * nor size unlike mov_read_extradata.
+ */
+static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
@@ -603,22 +584,18 @@ static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
return -1;
av_free(st->codec->extradata);
-
+ st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata)
+ return AVERROR(ENOMEM);
st->codec->extradata_size = atom.size;
- st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-
- if (st->codec->extradata) {
- get_buffer(pb, st->codec->extradata, atom.size);
- } else
- url_fskip(pb, atom.size);
-
+ get_buffer(pb, st->codec->extradata, atom.size);
return 0;
}
static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries;
get_byte(pb); /* version */
@@ -650,21 +627,21 @@ static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
int entries, frames_per_sample;
uint32_t format;
uint8_t codec_name[32];
/* for palette traversal */
- int color_depth;
- int color_start;
- int color_count;
- int color_end;
+ unsigned int color_depth;
+ unsigned int color_start;
+ unsigned int color_count;
+ unsigned int color_end;
int color_index;
int color_dec;
int color_greyscale;
- unsigned char *color_table;
- int j;
+ const uint8_t *color_table;
+ int j, pseudo_stream_id;
unsigned char r, g, b;
get_byte(pb); /* version */
@@ -672,8 +649,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
entries = get_be32(pb);
- while(entries--) { //Parsing Sample description table
+ for(pseudo_stream_id=0; pseudo_stream_id<entries; pseudo_stream_id++) { //Parsing Sample description table
enum CodecID id;
+ int dref_id;
MOV_atom_t a = { 0, 0, 0 };
offset_t start_pos = url_ftell(pb);
int size = get_be32(pb); /* size */
@@ -681,16 +659,26 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
get_be32(pb); /* reserved */
get_be16(pb); /* reserved */
- get_be16(pb); /* index */
-
- if (st->codec->codec_tag) {
- /* multiple fourcc, just skip for now */
+ dref_id = get_be16(pb);
+
+ if (st->codec->codec_tag &&
+ (c->fc->video_codec_id ? codec_get_id(codec_movvideo_tags, format) != c->fc->video_codec_id
+ : st->codec->codec_tag != MKTAG('j', 'p', 'e', 'g'))
+ ){
+ /* multiple fourcc, we skip jpeg, this isnt correct, we should export it as
+ seperate AVStream but this needs a few changes in the mov demuxer, patch
+ welcome */
url_fskip(pb, size - (url_ftell(pb) - start_pos));
continue;
}
+ sc->pseudo_stream_id= pseudo_stream_id;
+ sc->dref_id= dref_id;
st->codec->codec_tag = format;
id = codec_get_id(codec_movaudio_tags, format);
+ if (id<=0 && (format&0xFFFF) == 'm' + ('s'<<8))
+ id = codec_get_id(codec_wav_tags, bswap_32(format)&0xFFFF);
+
if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) {
st->codec->codec_type = CODEC_TYPE_AUDIO;
} else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */
@@ -700,12 +688,16 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
id = codec_get_id(codec_bmp_tags, format);
if (id > 0)
st->codec->codec_type = CODEC_TYPE_VIDEO;
+ else if(st->codec->codec_type == CODEC_TYPE_DATA){
+ id = codec_get_id(ff_codec_movsubtitle_tags, format);
+ if(id > 0)
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ }
}
- dprintf(c->fc, "size=%d 4CC= %c%c%c%c codec_type=%d\n",
- size,
- (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
- st->codec->codec_type);
+ dprintf(c->fc, "size=%d 4CC= %c%c%c%c codec_type=%d\n", size,
+ (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff,
+ (format >> 24) & 0xff, st->codec->codec_type);
if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
st->codec->codec_id = id;
@@ -713,7 +705,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
get_be16(pb); /* revision level */
get_be32(pb); /* vendor */
get_be32(pb); /* temporal quality */
- get_be32(pb); /* spacial quality */
+ get_be32(pb); /* spatial quality */
st->codec->width = get_be16(pb); /* width */
st->codec->height = get_be16(pb); /* height */
@@ -722,9 +714,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
get_be32(pb); /* vert resolution */
get_be32(pb); /* data size, always 0 */
frames_per_sample = get_be16(pb); /* frames per samples */
-#ifdef DEBUG
- av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
-#endif
+
+ dprintf(c->fc, "frames/samples = %d\n", frames_per_sample);
+
get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
if (codec_name[0] <= 31) {
memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
@@ -733,7 +725,8 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
st->codec->bits_per_sample = get_be16(pb); /* depth */
st->codec->color_table_id = get_be16(pb); /* colortable id */
-
+ dprintf(c->fc, "depth %d, ctab id %d\n",
+ st->codec->bits_per_sample, st->codec->color_table_id);
/* figure out the palette situation */
color_depth = st->codec->bits_per_sample & 0x1F;
color_greyscale = st->codec->bits_per_sample & 0x20;
@@ -741,10 +734,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
/* if the depth is 2, 4, or 8 bpp, file is palettized */
if ((color_depth == 2) || (color_depth == 4) ||
(color_depth == 8)) {
-
if (color_greyscale) {
-
/* compute the greyscale palette */
+ st->codec->bits_per_sample = color_depth;
color_count = 1 << color_depth;
color_index = 255;
color_dec = 256 / (color_count - 1);
@@ -756,9 +748,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
if (color_index < 0)
color_index = 0;
}
-
} else if (st->codec->color_table_id & 0x08) {
-
/* if flag bit 3 is set, use the default palette */
color_count = 1 << color_depth;
if (color_depth == 2)
@@ -775,30 +765,30 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
c->palette_control.palette[j] =
(r << 16) | (g << 8) | (b);
}
-
} else {
-
/* load the palette from the file */
color_start = get_be32(pb);
color_count = get_be16(pb);
color_end = get_be16(pb);
- for (j = color_start; j <= color_end; j++) {
- /* each R, G, or B component is 16 bits;
- * only use the top 8 bits; skip alpha bytes
- * up front */
- get_byte(pb);
- get_byte(pb);
- r = get_byte(pb);
- get_byte(pb);
- g = get_byte(pb);
- get_byte(pb);
- b = get_byte(pb);
- get_byte(pb);
- c->palette_control.palette[j] =
- (r << 16) | (g << 8) | (b);
+ if ((color_start <= 255) &&
+ (color_end <= 255)) {
+ for (j = color_start; j <= color_end; j++) {
+ /* each R, G, or B component is 16 bits;
+ * only use the top 8 bits; skip alpha bytes
+ * up front */
+ get_byte(pb);
+ get_byte(pb);
+ r = get_byte(pb);
+ get_byte(pb);
+ g = get_byte(pb);
+ get_byte(pb);
+ b = get_byte(pb);
+ get_byte(pb);
+ c->palette_control.palette[j] =
+ (r << 16) | (g << 8) | (b);
+ }
}
}
-
st->codec->palctrl = &c->palette_control;
st->codec->palctrl->palette_changed = 1;
} else
@@ -814,10 +804,8 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
st->codec->channels = get_be16(pb); /* channel count */
dprintf(c->fc, "audio channels %d\n", st->codec->channels);
st->codec->bits_per_sample = get_be16(pb); /* sample size */
- /* do we need to force to 16 for AMR ? */
- /* handle specific s8 codec */
- get_be16(pb); /* compression id = 0*/
+ sc->audio_cid = get_be16(pb);
get_be16(pb); /* packet size = 0 */
st->codec->sample_rate = ((get_be32(pb) >> 16));
@@ -835,11 +823,24 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
else if (st->codec->bits_per_sample == 24)
st->codec->codec_id = CODEC_ID_PCM_S24BE;
break;
+ /* set values for old format before stsd version 1 appeared */
+ case CODEC_ID_MACE3:
+ sc->samples_per_frame = 6;
+ sc->bytes_per_frame = 2*st->codec->channels;
+ break;
+ case CODEC_ID_MACE6:
+ sc->samples_per_frame = 6;
+ sc->bytes_per_frame = 1*st->codec->channels;
+ break;
+ case CODEC_ID_ADPCM_IMA_QT:
+ sc->samples_per_frame = 64;
+ sc->bytes_per_frame = 34*st->codec->channels;
+ break;
default:
break;
}
- //Read QT version 1 fields. In version 0 theese dont exist
+ //Read QT version 1 fields. In version 0 these do not exist.
dprintf(c->fc, "version =%d, isom =%d\n",version,c->isom);
if(!c->isom) {
if(version==1) {
@@ -864,45 +865,26 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
st->codec->bits_per_sample = bits_per_sample;
sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
}
+ } else if(st->codec->codec_type==CODEC_TYPE_SUBTITLE){
+ st->codec->codec_id= id;
} else {
/* other codec type, just skip (rtp, mp4s, tmcd ...) */
url_fskip(pb, size - (url_ftell(pb) - start_pos));
}
/* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
a.size = size - (url_ftell(pb) - start_pos);
- if (a.size > 8)
- mov_read_default(c, pb, a);
- else if (a.size > 0)
+ if (a.size > 8) {
+ if (mov_read_default(c, pb, a) < 0)
+ return -1;
+ } else if (a.size > 0)
url_fskip(pb, a.size);
}
- if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
+ if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1)
st->codec->sample_rate= sc->time_scale;
- }
/* special codec parameters handling */
switch (st->codec->codec_id) {
-#ifdef CONFIG_H261_DECODER
- case CODEC_ID_H261:
-#endif
-#ifdef CONFIG_H263_DECODER
- case CODEC_ID_H263:
-#endif
-#ifdef CONFIG_MPEG4_DECODER
- case CODEC_ID_MPEG4:
-#endif
- st->codec->width= 0; /* let decoder init width/height */
- st->codec->height= 0;
- break;
-#ifdef CONFIG_LIBFAAD
- case CODEC_ID_AAC:
-#endif
-#ifdef CONFIG_VORBIS_DECODER
- case CODEC_ID_VORBIS:
-#endif
- case CODEC_ID_MP3ON4:
- st->codec->sample_rate= 0; /* let decoder init parameters properly */
- break;
#ifdef CONFIG_DV_DEMUXER
case CODEC_ID_DVAUDIO:
c->dv_fctx = av_alloc_format_context();
@@ -927,7 +909,11 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
case CODEC_ID_MP2:
case CODEC_ID_MP3:
st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ break;
+ case CODEC_ID_ADPCM_MS:
+ case CODEC_ID_ADPCM_IMA_WAV:
+ st->codec->block_align = sc->bytes_per_frame;
break;
default:
break;
@@ -939,7 +925,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries;
get_byte(pb); /* version */
@@ -947,14 +933,13 @@ static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
+ if(entries >= UINT_MAX / sizeof(MOV_stsc_t))
return -1;
-#ifdef DEBUG
-av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
-#endif
+ dprintf(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
+
sc->sample_to_chunk_sz = entries;
- sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
+ sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_stsc_t));
if (!sc->sample_to_chunk)
return -1;
for(i=0; i<entries; i++) {
@@ -968,7 +953,7 @@ av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1,
static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries;
get_byte(pb); /* version */
@@ -976,21 +961,19 @@ static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(long))
+ if(entries >= UINT_MAX / sizeof(int))
return -1;
sc->keyframe_count = entries;
-#ifdef DEBUG
- av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %d\n", sc->keyframe_count);
-#endif
- sc->keyframes = av_malloc(entries * sizeof(long));
+
+ dprintf(c->fc, "keyframe_count = %d\n", sc->keyframe_count);
+
+ sc->keyframes = av_malloc(entries * sizeof(int));
if (!sc->keyframes)
return -1;
for(i=0; i<entries; i++) {
sc->keyframes[i] = get_be32(pb);
-#ifdef DEBUG
-/* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
-#endif
+ //dprintf(c->fc, "keyframes[]=%d\n", sc->keyframes[i]);
}
return 0;
}
@@ -998,7 +981,7 @@ static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries, sample_size;
get_byte(pb); /* version */
@@ -1008,24 +991,21 @@ static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
if (!sc->sample_size) /* do not overwrite value computed in stsd */
sc->sample_size = sample_size;
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(long))
+ if(entries >= UINT_MAX / sizeof(int))
return -1;
sc->sample_count = entries;
if (sample_size)
return 0;
-#ifdef DEBUG
- av_log(NULL, AV_LOG_DEBUG, "sample_size = %d sample_count = %d\n", sc->sample_size, sc->sample_count);
-#endif
- sc->sample_sizes = av_malloc(entries * sizeof(long));
+ dprintf(c->fc, "sample_size = %d sample_count = %d\n", sc->sample_size, sc->sample_count);
+
+ sc->sample_sizes = av_malloc(entries * sizeof(int));
if (!sc->sample_sizes)
return -1;
for(i=0; i<entries; i++) {
sc->sample_sizes[i] = get_be32(pb);
-#ifdef DEBUG
- av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
-#endif
+ dprintf(c->fc, "sample_sizes[]=%d\n", sc->sample_sizes[i]);
}
return 0;
}
@@ -1033,7 +1013,7 @@ static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries;
int64_t duration=0;
int64_t total_sample_count=0;
@@ -1041,15 +1021,14 @@ static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
get_byte(pb); /* version */
get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(Time2Sample))
+ if(entries >= UINT_MAX / sizeof(MOV_stts_t))
return -1;
sc->stts_count = entries;
- sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
-
-#ifdef DEBUG
-av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
-#endif
+ sc->stts_data = av_malloc(entries * sizeof(MOV_stts_t));
+ if (!sc->stts_data)
+ return -1;
+ dprintf(c->fc, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
sc->time_rate=0;
@@ -1079,18 +1058,19 @@ av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1,
static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ MOVStreamContext *sc = st->priv_data;
unsigned int i, entries;
get_byte(pb); /* version */
get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(Time2Sample))
+ if(entries >= UINT_MAX / sizeof(MOV_stts_t))
return -1;
sc->ctts_count = entries;
- sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
-
+ sc->ctts_data = av_malloc(entries * sizeof(MOV_stts_t));
+ if (!sc->ctts_data)
+ return -1;
dprintf(c->fc, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
for(i=0; i<entries; i++) {
@@ -1127,11 +1107,53 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
st->priv_data = sc;
st->codec->codec_type = CODEC_TYPE_DATA;
st->start_time = 0; /* XXX: check */
- c->streams[c->fc->nb_streams-1] = sc;
return mov_read_default(c, pb, atom);
}
+static void mov_parse_udta_string(ByteIOContext *pb, char *str, int size)
+{
+ uint16_t str_size = get_be16(pb); /* string length */;
+
+ get_be16(pb); /* skip language */
+ get_buffer(pb, str, FFMIN(size, str_size));
+}
+
+static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ uint64_t end = url_ftell(pb) + atom.size;
+
+ while (url_ftell(pb) + 8 < end) {
+ uint32_t tag_size = get_be32(pb);
+ uint32_t tag = get_le32(pb);
+ uint64_t next = url_ftell(pb) + tag_size - 8;
+
+ if (next > end) // stop if tag_size is wrong
+ break;
+
+ switch (tag) {
+ case MKTAG(0xa9,'n','a','m'):
+ mov_parse_udta_string(pb, c->fc->title, sizeof(c->fc->title));
+ break;
+ case MKTAG(0xa9,'w','r','t'):
+ mov_parse_udta_string(pb, c->fc->author, sizeof(c->fc->author));
+ break;
+ case MKTAG(0xa9,'c','p','y'):
+ mov_parse_udta_string(pb, c->fc->copyright, sizeof(c->fc->copyright));
+ break;
+ case MKTAG(0xa9,'i','n','f'):
+ mov_parse_udta_string(pb, c->fc->comment, sizeof(c->fc->comment));
+ break;
+ default:
+ break;
+ }
+
+ url_fseek(pb, next, SEEK_SET);
+ }
+
+ return 0;
+}
+
static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
@@ -1252,18 +1274,23 @@ static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
/* edit list atom */
static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
{
+ MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
int i, edit_count;
get_byte(pb); /* version */
get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
- edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
+ edit_count= sc->edit_count = get_be32(pb); /* entries */
for(i=0; i<edit_count; i++){
+ int time;
get_be32(pb); /* Track duration */
- get_be32(pb); /* Media time */
+ time = get_be32(pb); /* Media time */
get_be32(pb); /* Media rate */
+ if (time != 0)
+ av_log(c->fc, AV_LOG_WARNING, "edit list not starting at 0, "
+ "a/v desync might occur, patch welcome\n");
}
- dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
+ dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count);
return 0;
}
@@ -1271,11 +1298,14 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
/* mp4 atoms */
{ MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
{ MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
+{ MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default },
+{ MKTAG( 'd', 'r', 'e', 'f' ), mov_read_dref },
{ MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
{ MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
{ MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
{ MKTAG( 'f', 'i', 'e', 'l' ), mov_read_extradata },
{ MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
+{ MKTAG( 'g', 'l', 'b', 'l' ), mov_read_glbl },
{ MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
{ MKTAG( 'j', 'p', '2', 'h' ), mov_read_extradata },
{ MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
@@ -1286,7 +1316,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
{ MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
{ MKTAG( 'a', 'l', 'a', 'c' ), mov_read_extradata }, /* alac specific atom */
-{ MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
+{ MKTAG( 'a', 'v', 'c', 'C' ), mov_read_glbl },
{ MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
{ MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
{ MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
@@ -1296,22 +1326,14 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG( 's', 't', 't', 's' ), mov_read_stts },
{ MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
{ MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
+{ MKTAG( 'u', 'd', 't', 'a' ), mov_read_udta },
{ MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
-{ MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
{ MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
{ MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
{ MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
-{ 0L, NULL }
+{ 0, NULL }
};
-static void mov_free_stream_context(MOVStreamContext *sc)
-{
- if(sc) {
- av_freep(&sc->ctts_data);
- av_freep(&sc);
- }
-}
-
/* XXX: is it sufficient ? */
static int mov_probe(AVProbeData *p)
{
@@ -1320,8 +1342,6 @@ static int mov_probe(AVProbeData *p)
int score = 0;
/* check file header */
- if (p->buf_size <= 12)
- return 0;
offset = 0;
for(;;) {
/* ignore invalid offset */
@@ -1337,11 +1357,13 @@ static int mov_probe(AVProbeData *p)
case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
return AVPROBE_SCORE_MAX;
/* those are more common words, so rate then a bit less */
+ case MKTAG( 'e', 'd', 'i', 'w' ): /* xdcam files have reverted first tags */
case MKTAG( 'w', 'i', 'd', 'e' ):
case MKTAG( 'f', 'r', 'e', 'e' ):
case MKTAG( 'j', 'u', 'n', 'k' ):
case MKTAG( 'p', 'i', 'c', 't' ):
return AVPROBE_SCORE_MAX - 5;
+ case MKTAG(0x82,0x82,0x7f,0x7d ):
case MKTAG( 'f', 't', 'y', 'p' ):
case MKTAG( 's', 'k', 'i', 'p' ):
case MKTAG( 'u', 'u', 'i', 'd' ):
@@ -1365,34 +1387,40 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
unsigned int stts_index = 0;
unsigned int stsc_index = 0;
unsigned int stss_index = 0;
- unsigned int i, j, k;
+ unsigned int i, j;
- if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO || sc->dv_audio_container) {
+ if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO ||
+ sc->audio_cid == -2) {
unsigned int current_sample = 0;
unsigned int stts_sample = 0;
unsigned int keyframe, sample_size;
unsigned int distance = 0;
+ int key_off = sc->keyframes && sc->keyframes[0] == 1;
st->nb_frames = sc->sample_count;
for (i = 0; i < sc->chunk_count; i++) {
current_offset = sc->chunk_offsets[i];
- if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
+ if (stsc_index + 1 < sc->sample_to_chunk_sz &&
+ i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
stsc_index++;
for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) {
if (current_sample >= sc->sample_count) {
av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
goto out;
}
- keyframe = !sc->keyframe_count || current_sample + 1 == sc->keyframes[stss_index];
+ keyframe = !sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index];
if (keyframe) {
distance = 0;
if (stss_index + 1 < sc->keyframe_count)
stss_index++;
}
sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
- dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", size %d, distance %d, keyframe %d\n",
- st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe);
- av_add_index_entry(st, current_offset, current_dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0);
+ dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
+ "size %d, distance %d, keyframe %d\n", st->index, current_sample,
+ current_offset, current_dts, sample_size, distance, keyframe);
+ if(sc->sample_to_chunk[stsc_index].id - 1 == sc->pseudo_stream_id)
+ av_add_index_entry(st, current_offset, current_dts, sample_size, distance,
+ keyframe ? AVINDEX_KEYFRAME : 0);
current_offset += sample_size;
assert(sc->stts_data[stts_index].duration % sc->time_rate == 0);
current_dts += sc->stts_data[stts_index].duration / sc->time_rate;
@@ -1407,63 +1435,51 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
}
} else { /* read whole chunk */
unsigned int chunk_samples, chunk_size, chunk_duration;
-
+ unsigned int frames = 1;
for (i = 0; i < sc->chunk_count; i++) {
current_offset = sc->chunk_offsets[i];
- if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
+ if (stsc_index + 1 < sc->sample_to_chunk_sz &&
+ i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
stsc_index++;
chunk_samples = sc->sample_to_chunk[stsc_index].count;
- /* get chunk size */
- if (sc->sample_size > 1 || st->codec->codec_id == CODEC_ID_PCM_U8 || st->codec->codec_id == CODEC_ID_PCM_S8)
- chunk_size = chunk_samples * sc->sample_size;
- else if (sc->samples_per_frame > 0 && (chunk_samples * sc->bytes_per_frame % sc->samples_per_frame == 0))
- chunk_size = chunk_samples * sc->bytes_per_frame / sc->samples_per_frame;
- else { /* workaround to find nearest next chunk offset */
- chunk_size = INT_MAX;
- for (j = 0; j < mov->total_streams; j++) {
- MOVStreamContext *msc = mov->streams[j];
-
- for (k = msc->next_chunk; k < msc->chunk_count; k++) {
- if (msc->chunk_offsets[k] > current_offset && msc->chunk_offsets[k] - current_offset < chunk_size) {
- chunk_size = msc->chunk_offsets[k] - current_offset;
- msc->next_chunk = k;
- break;
- }
- }
- }
- /* check for last chunk */
- if (chunk_size == INT_MAX)
- for (j = 0; j < mov->mdat_count; j++) {
- dprintf(mov->fc, "mdat %d, offset %"PRIx64", size %"PRId64", current offset %"PRIx64"\n",
- j, mov->mdat_list[j].offset, mov->mdat_list[j].size, current_offset);
- if (mov->mdat_list[j].offset <= current_offset && mov->mdat_list[j].offset + mov->mdat_list[j].size > current_offset)
- chunk_size = mov->mdat_list[j].offset + mov->mdat_list[j].size - current_offset;
- }
- assert(chunk_size != INT_MAX);
- for (j = 0; j < mov->total_streams; j++) {
- mov->streams[j]->next_chunk = 0;
+ /* get chunk size, beware of alaw/ulaw/mace */
+ if (sc->samples_per_frame > 0 &&
+ (chunk_samples * sc->bytes_per_frame % sc->samples_per_frame == 0)) {
+ if (sc->samples_per_frame < 1024)
+ chunk_size = chunk_samples * sc->bytes_per_frame / sc->samples_per_frame;
+ else {
+ chunk_size = sc->bytes_per_frame;
+ frames = chunk_samples / sc->samples_per_frame;
+ chunk_samples = sc->samples_per_frame;
}
+ } else if (sc->sample_size > 1 || st->codec->bits_per_sample == 8) {
+ chunk_size = chunk_samples * sc->sample_size;
+ } else {
+ av_log(mov->fc, AV_LOG_ERROR, "could not determine chunk size, report problem\n");
+ goto out;
}
- av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
- /* get chunk duration */
- chunk_duration = 0;
- while (chunk_samples > 0) {
- if (chunk_samples < sc->stts_data[stts_index].count) {
- chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
- sc->stts_data[stts_index].count -= chunk_samples;
- break;
- } else {
- chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
- chunk_samples -= sc->stts_data[stts_index].count;
- if (stts_index + 1 < sc->stts_count) {
- stts_index++;
+ for (j = 0; j < frames; j++) {
+ av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
+ /* get chunk duration */
+ chunk_duration = 0;
+ while (chunk_samples > 0) {
+ if (chunk_samples < sc->stts_data[stts_index].count) {
+ chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
+ sc->stts_data[stts_index].count -= chunk_samples;
+ break;
+ } else {
+ chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
+ chunk_samples -= sc->stts_data[stts_index].count;
+ if (stts_index + 1 < sc->stts_count)
+ stts_index++;
}
}
+ current_offset += sc->bytes_per_frame;
+ dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", size %d, "
+ "duration %d\n", st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
+ assert(chunk_duration % sc->time_rate == 0);
+ current_dts += chunk_duration / sc->time_rate;
}
- dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", size %d, duration %d\n",
- st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
- assert(chunk_duration % sc->time_rate == 0);
- current_dts += chunk_duration / sc->time_rate;
}
}
out:
@@ -1473,18 +1489,17 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
- MOVContext *mov = (MOVContext *) s->priv_data;
- ByteIOContext *pb = &s->pb;
+ MOVContext *mov = s->priv_data;
+ ByteIOContext *pb = s->pb;
int i, err;
MOV_atom_t atom = { 0, 0, 0 };
mov->fc = s;
- mov->parse_table = mov_default_parse_table;
if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
atom.size = url_fsize(pb);
else
- atom.size = 0x7FFFFFFFFFFFFFFFLL;
+ atom.size = INT64_MAX;
/* check MOV header */
err = mov_read_default(mov, pb, atom);
@@ -1495,15 +1510,9 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
dprintf(mov->fc, "on_parse_exit_offset=%d\n", (int) url_ftell(pb));
- /* some cleanup : make sure we are on the mdat atom */
- if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
- url_fseek(pb, mov->mdat_offset, SEEK_SET);
-
- mov->total_streams = s->nb_streams;
-
- for(i=0; i<mov->total_streams; i++) {
- MOVStreamContext *sc = mov->streams[i];
+ for(i=0; i<s->nb_streams; i++) {
AVStream *st = s->streams[i];
+ MOVStreamContext *sc = st->priv_data;
/* sanity checks */
if(!sc->stts_count || !sc->chunk_count || !sc->sample_to_chunk_sz ||
(!sc->sample_size && !sc->sample_count)){
@@ -1518,7 +1527,7 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_set_pts_info(st, 64, sc->time_rate, sc->time_scale);
if (st->codec->codec_type == CODEC_TYPE_AUDIO && sc->stts_count == 1)
- st->codec->frame_size = sc->stts_data[0].duration;
+ st->codec->frame_size = av_rescale(sc->time_rate, st->codec->sample_rate, sc->time_scale);
if(st->duration != AV_NOPTS_VALUE){
assert(st->duration % sc->time_rate == 0);
@@ -1526,17 +1535,48 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
sc->ffindex = i;
mov_build_index(mov, st);
+
+ if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
+ if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0)
+ av_log(s, AV_LOG_ERROR, "stream %d, error opening external essence: %s\n",
+ st->index, strerror(errno));
+ } else
+ sc->pb = s->pb;
+
+ switch (st->codec->codec_id) {
+#ifdef CONFIG_H261_DECODER
+ case CODEC_ID_H261:
+#endif
+#ifdef CONFIG_H263_DECODER
+ case CODEC_ID_H263:
+#endif
+#ifdef CONFIG_MPEG4_DECODER
+ case CODEC_ID_MPEG4:
+#endif
+ st->codec->width= 0; /* let decoder init width/height */
+ st->codec->height= 0;
+ break;
+#ifdef CONFIG_LIBFAAD
+ case CODEC_ID_AAC:
+#endif
+#ifdef CONFIG_VORBIS_DECODER
+ case CODEC_ID_VORBIS:
+#endif
+ case CODEC_ID_MP3ON4:
+ st->codec->sample_rate= 0; /* let decoder init parameters properly */
+ break;
+ }
}
- for(i=0; i<mov->total_streams; i++) {
- /* dont need those anymore */
- av_freep(&mov->streams[i]->chunk_offsets);
- av_freep(&mov->streams[i]->sample_to_chunk);
- av_freep(&mov->streams[i]->sample_sizes);
- av_freep(&mov->streams[i]->keyframes);
- av_freep(&mov->streams[i]->stts_data);
+ for(i=0; i<s->nb_streams; i++) {
+ MOVStreamContext *sc = s->streams[i]->priv_data;
+ /* Do not need those anymore. */
+ av_freep(&sc->chunk_offsets);
+ av_freep(&sc->sample_to_chunk);
+ av_freep(&sc->sample_sizes);
+ av_freep(&sc->keyframes);
+ av_freep(&sc->stts_data);
}
- av_freep(&mov->mdat_list);
return 0;
}
@@ -1548,15 +1588,19 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
int64_t best_dts = INT64_MAX;
int i;
- for (i = 0; i < mov->total_streams; i++) {
- MOVStreamContext *msc = mov->streams[i];
-
- if (s->streams[i]->discard != AVDISCARD_ALL && msc->current_sample < msc->sample_count) {
- AVIndexEntry *current_sample = &s->streams[i]->index_entries[msc->current_sample];
- int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale);
-
- dprintf(s, "stream %d, sample %ld, dts %"PRId64"\n", i, msc->current_sample, dts);
- if (dts < best_dts) {
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ MOVStreamContext *msc = st->priv_data;
+ if (st->discard != AVDISCARD_ALL && msc->pb && msc->current_sample < msc->sample_count) {
+ AVIndexEntry *current_sample = &st->index_entries[msc->current_sample];
+ int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate,
+ AV_TIME_BASE, msc->time_scale);
+ dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
+ if (!sample || (url_is_streamed(s->pb) && current_sample->pos < sample->pos) ||
+ (!url_is_streamed(s->pb) &&
+ ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb &&
+ ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
+ (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
sample = current_sample;
best_dts = dts;
sc = msc;
@@ -1567,24 +1611,19 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
return -1;
/* must be done just before reading, to avoid infinite loop on sample */
sc->current_sample++;
- if (sample->pos >= url_fsize(&s->pb)) {
- av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", sc->ffindex, sample->pos);
+ if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
+ av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
+ sc->ffindex, sample->pos);
return -1;
}
+ av_get_packet(sc->pb, pkt, sample->size);
#ifdef CONFIG_DV_DEMUXER
- if (sc->dv_audio_container) {
- dv_get_packet(mov->dv_demux, pkt);
- dprintf(s, "dv audio pkt size %d\n", pkt->size);
- } else {
-#endif
- url_fseek(&s->pb, sample->pos, SEEK_SET);
- av_get_packet(&s->pb, pkt, sample->size);
-#ifdef CONFIG_DV_DEMUXER
- if (mov->dv_demux) {
- void *pkt_destruct_func = pkt->destruct;
- dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
- pkt->destruct = pkt_destruct_func;
- }
+ if (mov->dv_demux && sc->dv_audio_container) {
+ dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
+ av_free(pkt->data);
+ pkt->size = 0;
+ if (dv_get_packet(mov->dv_demux, pkt) < 0)
+ return -1;
}
#endif
pkt->stream_index = sc->ffindex;
@@ -1594,7 +1633,8 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate;
/* update ctts context */
sc->sample_to_ctime_sample++;
- if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
+ if (sc->sample_to_ctime_index < sc->ctts_count &&
+ sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
sc->sample_to_ctime_index++;
sc->sample_to_ctime_sample = 0;
}
@@ -1603,7 +1643,8 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
}
pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
pkt->pos = sample->pos;
- dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
+ dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n",
+ pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
return 0;
}
@@ -1618,17 +1659,18 @@ static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
if (sample < 0) /* not sure what to do */
return -1;
sc->current_sample = sample;
- dprintf(st->codec, "stream %d, found sample %ld\n", st->index, sc->current_sample);
+ dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample);
/* adjust ctts index */
if (sc->ctts_data) {
time_sample = 0;
for (i = 0; i < sc->ctts_count; i++) {
- time_sample += sc->ctts_data[i].count;
- if (time_sample >= sc->current_sample) {
+ int next = time_sample + sc->ctts_data[i].count;
+ if (next > sc->current_sample) {
sc->sample_to_ctime_index = i;
- sc->sample_to_ctime_sample = time_sample - sc->current_sample;
+ sc->sample_to_ctime_sample = sc->current_sample - time_sample;
break;
}
+ time_sample = next;
}
}
return sample;
@@ -1665,13 +1707,17 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
static int mov_read_close(AVFormatContext *s)
{
- int i;
- MOVContext *mov = (MOVContext *) s->priv_data;
- for(i=0; i<mov->total_streams; i++)
- mov_free_stream_context(mov->streams[i]);
- /* free color tabs */
- for(i=0; i<mov->ctab_size; i++)
- av_freep(&mov->ctab[i]);
+ int i, j;
+ MOVContext *mov = s->priv_data;
+ for(i=0; i<s->nb_streams; i++) {
+ MOVStreamContext *sc = s->streams[i]->priv_data;
+ av_freep(&sc->ctts_data);
+ for (j=0; j<sc->drefs_count; j++)
+ av_freep(&sc->drefs[j].path);
+ av_freep(&sc->drefs);
+ if (sc->pb && sc->pb != s->pb)
+ url_fclose(sc->pb);
+ }
if(mov->dv_demux){
for(i=0; i<mov->dv_fctx->nb_streams; i++){
av_freep(&mov->dv_fctx->streams[i]->codec);
@@ -1680,7 +1726,6 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&mov->dv_fctx);
av_freep(&mov->dv_demux);
}
- av_freep(&mov->ctab);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/movenc.c b/contrib/ffmpeg/libavformat/movenc.c
index e93416914..501c44ebd 100644
--- a/contrib/ffmpeg/libavformat/movenc.c
+++ b/contrib/ffmpeg/libavformat/movenc.c
@@ -23,6 +23,7 @@
#include "riff.h"
#include "avio.h"
#include "isom.h"
+#include "avc.h"
#undef NDEBUG
#include <assert.h>
@@ -59,7 +60,7 @@ typedef struct MOVIndex {
int hasBframes;
int language;
int trackID;
- int tag;
+ int tag; ///< stsd fourcc
AVCodecContext *enc;
int vosLen;
@@ -78,7 +79,7 @@ typedef struct MOVContext {
MOVTrack tracks[MAX_STREAMS];
} MOVContext;
-//FIXME supprt 64bit varaint with wide placeholders
+//FIXME support 64 bit variant with wide placeholders
static offset_t updateSize (ByteIOContext *pb, offset_t pos)
{
offset_t curpos = url_ftell(pb);
@@ -140,7 +141,7 @@ static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
put_be32(pb, 0); // sample size
put_be32(pb, entries); // sample count
for (i=0; i<track->entry; i++) {
- for ( j=0; j<track->cluster[i].entries; j++) {
+ for (j=0; j<track->cluster[i].entries; j++) {
put_be32(pb, track->cluster[i].size /
track->cluster[i].entries);
}
@@ -322,6 +323,14 @@ static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
return updateSize (pb, pos);
}
+static int mov_write_glbl_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ put_be32(pb, track->vosLen+8);
+ put_tag(pb, "glbl");
+ put_buffer(pb, track->vosData, track->vosLen);
+ return 8+track->vosLen;
+}
+
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
{
offset_t pos = url_ftell(pb);
@@ -372,10 +381,12 @@ static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
track->enc->codec_id == CODEC_ID_PCM_S24LE ||
track->enc->codec_id == CODEC_ID_PCM_S32LE))
mov_write_wave_tag(pb, track);
- else if(track->enc->codec_id == CODEC_ID_AAC)
+ else if(track->tag == MKTAG('m','p','4','a'))
mov_write_esds_tag(pb, track);
else if(track->enc->codec_id == CODEC_ID_AMR_NB)
mov_write_amr_tag(pb, track);
+ else if(track->vosLen > 0)
+ mov_write_glbl_tag(pb, track);
return updateSize (pb, pos);
}
@@ -405,170 +416,128 @@ static int mov_write_svq3_tag(ByteIOContext *pb)
return 0x15;
}
-static uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end )
-{
- uint8_t *a = p + 4 - ((int)p & 3);
-
- for( end -= 3; p < a && p < end; p++ ) {
- if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
- return p;
- }
-
- for( end -= 3; p < end; p += 4 ) {
- uint32_t x = *(uint32_t*)p;
-// if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian
-// if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian
- if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic
- if( p[1] == 0 ) {
- if( p[0] == 0 && p[2] == 1 )
- return p-1;
- if( p[2] == 0 && p[3] == 1 )
- return p;
- }
- if( p[3] == 0 ) {
- if( p[2] == 0 && p[4] == 1 )
- return p+1;
- if( p[4] == 0 && p[5] == 1 )
- return p+2;
- }
- }
- }
-
- for( end += 3; p < end; p++ ) {
- if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
- return p;
- }
-
- return end + 3;
-}
-
-static void avc_parse_nal_units(uint8_t **buf, int *size)
-{
- ByteIOContext pb;
- uint8_t *p = *buf;
- uint8_t *end = p + *size;
- uint8_t *nal_start, *nal_end;
-
- url_open_dyn_buf(&pb);
- nal_start = avc_find_startcode(p, end);
- while (nal_start < end) {
- while(!*(nal_start++));
- nal_end = avc_find_startcode(nal_start, end);
- put_be32(&pb, nal_end - nal_start);
- put_buffer(&pb, nal_start, nal_end - nal_start);
- nal_start = nal_end;
- }
- av_freep(buf);
- *size = url_close_dyn_buf(&pb, buf);
-}
-
static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
{
offset_t pos = url_ftell(pb);
put_be32(pb, 0);
put_tag(pb, "avcC");
- if (track->vosLen > 6) {
- /* check for h264 start code */
- if (AV_RB32(track->vosData) == 0x00000001) {
- uint8_t *buf, *end;
- uint32_t sps_size=0, pps_size=0;
- uint8_t *sps=0, *pps=0;
-
- avc_parse_nal_units(&track->vosData, &track->vosLen);
- buf = track->vosData;
- end = track->vosData + track->vosLen;
-
- /* look for sps and pps */
- while (buf < end) {
- unsigned int size;
- uint8_t nal_type;
- size = AV_RB32(buf);
- nal_type = buf[4] & 0x1f;
- if (nal_type == 7) { /* SPS */
- sps = buf + 4;
- sps_size = size;
- } else if (nal_type == 8) { /* PPS */
- pps = buf + 4;
- pps_size = size;
- }
- buf += size + 4;
- }
- assert(sps);
- assert(pps);
-
- put_byte(pb, 1); /* version */
- put_byte(pb, sps[1]); /* profile */
- put_byte(pb, sps[2]); /* profile compat */
- put_byte(pb, sps[3]); /* level */
- put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
- put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
-
- put_be16(pb, sps_size);
- put_buffer(pb, sps, sps_size);
- put_byte(pb, 1); /* number of pps */
- put_be16(pb, pps_size);
- put_buffer(pb, pps, pps_size);
- } else {
- put_buffer(pb, track->vosData, track->vosLen);
- }
- }
+ ff_isom_write_avcc(pb, track->vosData, track->vosLen);
return updateSize(pb, pos);
}
-static int mov_find_video_codec_tag(AVFormatContext *s, MOVTrack *track)
+/* also used by all avid codecs (dv, imx, meridien) and their variants */
+static int mov_write_avid_tag(ByteIOContext *pb, MOVTrack *track)
{
- int tag = track->enc->codec_tag;
- if (!tag) {
- if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
- if (track->enc->height == 480) { /* NTSC */
- if (track->enc->pix_fmt == PIX_FMT_YUV422P)
- tag = MKTAG('d', 'v', '5', 'n');
- else
- tag = MKTAG('d', 'v', 'c', ' ');
- } else { /* assume PAL */
- if (track->enc->pix_fmt == PIX_FMT_YUV422P)
- tag = MKTAG('d', 'v', '5', 'p');
- else if (track->enc->pix_fmt == PIX_FMT_YUV420P)
- tag = MKTAG('d', 'v', 'c', 'p');
- else
- tag = MKTAG('d', 'v', 'p', 'p');
- }
- } else if (track->enc->codec_id == CODEC_ID_H263) {
- if (track->mode == MODE_MOV)
- tag = MKTAG('h', '2', '6', '3');
- else
- tag = MKTAG('s', '2', '6', '3');
- } else {
- tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
- }
- }
- // if no mac fcc found, try with Microsoft tags
- if (!tag) {
- tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
- if (tag) {
- av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
- }
+ int i;
+ put_be32(pb, 24); /* size */
+ put_tag(pb, "ACLR");
+ put_tag(pb, "ACLR");
+ put_tag(pb, "0001");
+ put_be32(pb, 1); /* yuv 1 / rgb 2 ? */
+ put_be32(pb, 0); /* unknown */
+
+ put_be32(pb, 24); /* size */
+ put_tag(pb, "APRG");
+ put_tag(pb, "APRG");
+ put_tag(pb, "0001");
+ put_be32(pb, 1); /* unknown */
+ put_be32(pb, 0); /* unknown */
+
+ put_be32(pb, 120); /* size */
+ put_tag(pb, "ARES");
+ put_tag(pb, "ARES");
+ put_tag(pb, "0001");
+ put_be32(pb, AV_RB32(track->vosData + 0x28)); /* dnxhd cid, some id ? */
+ put_be32(pb, track->enc->width);
+ /* values below are based on samples created with quicktime and avid codecs */
+ if (track->vosData[5] & 2) { // interlaced
+ put_be32(pb, track->enc->height/2);
+ put_be32(pb, 2); /* unknown */
+ put_be32(pb, 0); /* unknown */
+ put_be32(pb, 4); /* unknown */
+ } else {
+ put_be32(pb, track->enc->height);
+ put_be32(pb, 1); /* unknown */
+ put_be32(pb, 0); /* unknown */
+ if (track->enc->height == 1080)
+ put_be32(pb, 5); /* unknown */
+ else
+ put_be32(pb, 6); /* unknown */
}
- assert(tag);
- return tag;
+ /* padding */
+ for (i = 0; i < 10; i++)
+ put_be64(pb, 0);
+
+ /* extra padding for stsd needed */
+ put_be32(pb, 0);
+ return 0;
}
-static int mov_find_audio_codec_tag(AVFormatContext *s, MOVTrack *track)
+static const AVCodecTag codec_3gp_tags[] = {
+ { CODEC_ID_H263, MKTAG('s','2','6','3') },
+ { CODEC_ID_H264, MKTAG('a','v','c','1') },
+ { CODEC_ID_MPEG4, MKTAG('m','p','4','v') },
+ { CODEC_ID_AAC, MKTAG('m','p','4','a') },
+ { CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
+ { CODEC_ID_AMR_WB, MKTAG('s','a','w','b') },
+};
+
+static const AVCodecTag mov_pix_fmt_tags[] = {
+ { PIX_FMT_YUYV422, MKTAG('y','u','v','s') },
+ { PIX_FMT_UYVY422, MKTAG('2','v','u','y') },
+ { PIX_FMT_BGR555, MKTAG('r','a','w',' ') },
+ { PIX_FMT_RGB24, MKTAG('r','a','w',' ') },
+ { PIX_FMT_BGR32_1, MKTAG('r','a','w',' ') },
+};
+
+static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
{
int tag = track->enc->codec_tag;
- if (!tag) {
- tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
- }
- // if no mac fcc found, try with Microsoft tags
- if (!tag) {
- int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
- if (ms_tag) {
- tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
- av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
+ if (track->mode == MODE_MP4 || track->mode == MODE_PSP) {
+ if (!codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
+ return 0;
+ if (track->enc->codec_id == CODEC_ID_H264) tag = MKTAG('a','v','c','1');
+ else if (track->enc->codec_type == CODEC_TYPE_VIDEO) tag = MKTAG('m','p','4','v');
+ else if (track->enc->codec_type == CODEC_TYPE_AUDIO) tag = MKTAG('m','p','4','a');
+ } else if (track->mode == MODE_3GP || track->mode == MODE_3G2) {
+ tag = codec_get_tag(codec_3gp_tags, track->enc->codec_id);
+ } else if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
+ (tag == MKTAG('d','v','c','p') ||
+ track->enc->codec_id == CODEC_ID_RAWVIDEO))) {
+ if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
+ if (track->enc->height == 480) /* NTSC */
+ if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
+ else tag = MKTAG('d','v','c',' ');
+ else if (track->enc->pix_fmt == PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
+ else if (track->enc->pix_fmt == PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
+ else tag = MKTAG('d','v','p','p');
+ } else if (track->enc->codec_id == CODEC_ID_RAWVIDEO) {
+ tag = codec_get_tag(mov_pix_fmt_tags, track->enc->pix_fmt);
+ if (!tag) // restore tag
+ tag = track->enc->codec_tag;
+ } else {
+ if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
+ tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
+ if (!tag) { // if no mac fcc found, try with Microsoft tags
+ tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
+ if (tag)
+ av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, "
+ "the file may be unplayable!\n");
+ }
+ } else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
+ tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
+ if (!tag) { // if no mac fcc found, try with Microsoft tags
+ int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
+ if (ms_tag) {
+ tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
+ av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
+ "the file may be unplayable!\n");
+ }
+ }
+ }
}
}
- assert(tag);
return tag;
}
@@ -613,9 +582,12 @@ static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
put_byte(pb, strlen(compressor_name));
put_buffer(pb, compressor_name, 31);
- put_be16(pb, 0x18); /* Reserved */
+ if (track->mode == MODE_MOV && track->enc->bits_per_sample)
+ put_be16(pb, track->enc->bits_per_sample);
+ else
+ put_be16(pb, 0x18); /* Reserved */
put_be16(pb, 0xffff); /* Reserved */
- if(track->enc->codec_id == CODEC_ID_MPEG4)
+ if(track->tag == MKTAG('m','p','4','v'))
mov_write_esds_tag(pb, track);
else if(track->enc->codec_id == CODEC_ID_H263)
mov_write_d263_tag(pb);
@@ -623,6 +595,10 @@ static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
mov_write_svq3_tag(pb);
else if(track->enc->codec_id == CODEC_ID_H264)
mov_write_avcc_tag(pb, track);
+ else if(track->enc->codec_id == CODEC_ID_DNXHD)
+ mov_write_avid_tag(pb, track);
+ else if(track->vosLen > 0)
+ mov_write_glbl_tag(pb, track);
return updateSize (pb, pos);
}
@@ -643,7 +619,7 @@ static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track)
{
- Time2Sample *ctts_entries;
+ MOV_stts_t *ctts_entries;
uint32_t entries = 0;
uint32_t atom_size;
int i;
@@ -677,7 +653,7 @@ static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track)
/* Time to sample atom */
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
{
- Time2Sample *stts_entries;
+ MOV_stts_t *stts_entries;
uint32_t entries = -1;
uint32_t atom_size;
int i;
@@ -845,6 +821,14 @@ static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
(version == 1) ? put_be64(pb, track->trackDuration) : put_be32(pb, track->trackDuration); /* duration */
put_be16(pb, track->language); /* language */
put_be16(pb, 0); /* reserved (quality) */
+
+ if(version!=0 && track->mode == MODE_MOV){
+ av_log(NULL, AV_LOG_ERROR,
+ "FATAL error, file duration too long for timebase, this file will not be\n"
+ "playable with quicktime. Choose a different timebase or a different\n"
+ "container format\n");
+ }
+
return 32;
}
@@ -903,7 +887,7 @@ static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
/* Track width and height, for visual only */
if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
- if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
+ if(!sample_aspect_ratio) sample_aspect_ratio = 1;
put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
put_be32(pb, track->enc->height*0x10000);
}
@@ -1075,7 +1059,7 @@ static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int lo
static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int long_style){
int size = 0;
- if ( value && value[0] ) {
+ if (value && value[0]) {
offset_t pos = url_ftell(pb);
put_be32(pb, 0); /* size */
put_tag(pb, name);
@@ -1101,7 +1085,7 @@ static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov,
AVFormatContext *s)
{
int size = 0;
- if ( s->track ) {
+ if (s->track) {
offset_t pos = url_ftell(pb);
put_be32(pb, 0); /* size */
put_tag(pb, "trkn");
@@ -1149,8 +1133,8 @@ static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
int size = 0;
// only save meta tag if required
- if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
- s->comment[0] || s->genre[0] || s->track ) {
+ if (s->title[0] || s->author[0] || s->album[0] || s->year ||
+ s->comment[0] || s->genre[0] || s->track) {
offset_t pos = url_ftell(pb);
put_be32(pb, 0); /* size */
put_tag(pb, "meta");
@@ -1165,40 +1149,52 @@ static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
AVFormatContext *s)
{
- offset_t pos = url_ftell(pb);
- int i;
-
- put_be32(pb, 0); /* size */
- put_tag(pb, "udta");
-
- /* iTunes meta data */
- mov_write_meta_tag(pb, mov, s);
+ int i, req = 0;
- if(mov->mode == MODE_MOV){ // the title field breaks gtkpod with mp4 and my suspicion is that stuff isnt valid in mp4
/* Requirements */
for (i=0; i<mov->nb_streams; i++) {
if(mov->tracks[i].entry <= 0) continue;
if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
- mov_write_string_tag(pb, "\251req", "QuickTime 6.0 or greater", 0);
+ req = 1;
break;
}
}
- mov_write_string_tag(pb, "\251nam", s->title , 0);
- mov_write_string_tag(pb, "\251aut", s->author , 0);
- mov_write_string_tag(pb, "\251alb", s->album , 0);
- mov_write_day_tag(pb, s->year, 0);
- if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
- mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0);
- mov_write_string_tag(pb, "\251des", s->comment , 0);
- mov_write_string_tag(pb, "\251gen", s->genre , 0);
- }
+ if (s->title[0] || s->author[0] || s->album[0] || s->year ||
+ s->comment[0] || s->genre[0] || s->track ||
+ (mov->mode == MODE_MOV &&
+ ((mov->tracks[0].enc && !mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT) || req))) {
+ offset_t pos = url_ftell(pb);
- return updateSize(pb, pos);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "udta");
+
+ /* iTunes meta data */
+ mov_write_meta_tag(pb, mov, s);
+
+ if(mov->mode == MODE_MOV){ // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
+ /* Requirements */
+ if (req)
+ mov_write_string_tag(pb, "\251req", "QuickTime 6.0 or greater", 0);
+
+ mov_write_string_tag(pb, "\251nam", s->title , 0);
+ mov_write_string_tag(pb, "\251aut", s->author , 0);
+ mov_write_string_tag(pb, "\251alb", s->album , 0);
+ mov_write_day_tag(pb, s->year, 0);
+ if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
+ mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0);
+ mov_write_string_tag(pb, "\251des", s->comment , 0);
+ mov_write_string_tag(pb, "\251gen", s->genre , 0);
+ }
+
+ return updateSize(pb, pos);
+ }
+
+ return 0;
}
-static int utf8len(uint8_t *b){
+static int utf8len(const uint8_t *b){
int len=0;
int val;
while(*b){
@@ -1208,7 +1204,7 @@ static int utf8len(uint8_t *b){
return len;
}
-static int ascii_to_wc (ByteIOContext *pb, uint8_t *b)
+static int ascii_to_wc (ByteIOContext *pb, const uint8_t *b)
{
int val;
while(*b){
@@ -1235,9 +1231,9 @@ static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
put_be32(pb, 0); /* size placeholder*/
put_tag(pb, "uuid");
put_tag(pb, "USMT");
- put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
- put_be32(pb, 0xbb88695c );
- put_be32(pb, 0xfac9c740 );
+ put_be32(pb, 0x21d24fce); /* 96 bit UUID */
+ put_be32(pb, 0xbb88695c);
+ put_be32(pb, 0xfac9c740);
size += 24;
put_be32(pb, 0); /* size placeholder*/
@@ -1328,7 +1324,7 @@ static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
if (mov->mode == MODE_PSP)
mov_write_uuidusmt_tag(pb, s);
- else
+ else if (mov->mode != MODE_3GP && mov->mode != MODE_3G2)
mov_write_udta_tag(pb, mov, s);
return updateSize(pb, pos);
@@ -1350,29 +1346,29 @@ static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
{
MOVContext *mov = s->priv_data;
- put_be32(pb, 0x14 ); /* size */
+ put_be32(pb, 0x14); /* size */
put_tag(pb, "ftyp");
- if ( mov->mode == MODE_3GP )
+ if (mov->mode == MODE_3GP)
put_tag(pb, "3gp4");
- else if ( mov->mode == MODE_3G2 )
+ else if (mov->mode == MODE_3G2)
put_tag(pb, "3g2a");
- else if ( mov->mode == MODE_PSP )
+ else if (mov->mode == MODE_PSP)
put_tag(pb, "MSNV");
- else if ( mov->mode == MODE_MP4 )
+ else if (mov->mode == MODE_MP4)
put_tag(pb, "isom");
else
put_tag(pb, "qt ");
- put_be32(pb, 0x200 );
+ put_be32(pb, 0x200);
- if ( mov->mode == MODE_3GP )
+ if (mov->mode == MODE_3GP)
put_tag(pb, "3gp4");
- else if ( mov->mode == MODE_3G2 )
+ else if (mov->mode == MODE_3G2)
put_tag(pb, "3g2a");
- else if ( mov->mode == MODE_PSP )
+ else if (mov->mode == MODE_PSP)
put_tag(pb, "MSNV");
- else if ( mov->mode == MODE_MP4 )
+ else if (mov->mode == MODE_MP4)
put_tag(pb, "mp41");
else
put_tag(pb, "qt ");
@@ -1387,49 +1383,49 @@ static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
int audio_kbitrate= AudioCodec->bit_rate / 1000;
int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
- put_be32(pb, 0x94 ); /* size */
+ put_be32(pb, 0x94); /* size */
put_tag(pb, "uuid");
put_tag(pb, "PROF");
- put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
- put_be32(pb, 0xbb88695c );
- put_be32(pb, 0xfac9c740 );
+ put_be32(pb, 0x21d24fce); /* 96 bit UUID */
+ put_be32(pb, 0xbb88695c);
+ put_be32(pb, 0xfac9c740);
- put_be32(pb, 0x0 ); /* ? */
- put_be32(pb, 0x3 ); /* 3 sections ? */
+ put_be32(pb, 0x0); /* ? */
+ put_be32(pb, 0x3); /* 3 sections ? */
- put_be32(pb, 0x14 ); /* size */
+ put_be32(pb, 0x14); /* size */
put_tag(pb, "FPRF");
- put_be32(pb, 0x0 ); /* ? */
- put_be32(pb, 0x0 ); /* ? */
- put_be32(pb, 0x0 ); /* ? */
+ put_be32(pb, 0x0); /* ? */
+ put_be32(pb, 0x0); /* ? */
+ put_be32(pb, 0x0); /* ? */
- put_be32(pb, 0x2c ); /* size */
+ put_be32(pb, 0x2c); /* size */
put_tag(pb, "APRF"); /* audio */
- put_be32(pb, 0x0 );
- put_be32(pb, 0x2 ); /* TrackID */
+ put_be32(pb, 0x0);
+ put_be32(pb, 0x2); /* TrackID */
put_tag(pb, "mp4a");
- put_be32(pb, 0x20f );
- put_be32(pb, 0x0 );
+ put_be32(pb, 0x20f);
+ put_be32(pb, 0x0);
put_be32(pb, audio_kbitrate);
put_be32(pb, audio_kbitrate);
- put_be32(pb, AudioRate );
- put_be32(pb, AudioCodec->channels );
+ put_be32(pb, AudioRate);
+ put_be32(pb, AudioCodec->channels);
- put_be32(pb, 0x34 ); /* size */
+ put_be32(pb, 0x34); /* size */
put_tag(pb, "VPRF"); /* video */
- put_be32(pb, 0x0 );
- put_be32(pb, 0x1 ); /* TrackID */
+ put_be32(pb, 0x0);
+ put_be32(pb, 0x1); /* TrackID */
if (VideoCodec->codec_id == CODEC_ID_H264) {
put_tag(pb, "avc1");
- put_be16(pb, 0x014D );
- put_be16(pb, 0x0015 );
+ put_be16(pb, 0x014D);
+ put_be16(pb, 0x0015);
} else {
put_tag(pb, "mp4v");
- put_be16(pb, 0x0000 );
- put_be16(pb, 0x0103 );
+ put_be16(pb, 0x0000);
+ put_be16(pb, 0x0103);
}
- put_be32(pb, 0x0 );
+ put_be32(pb, 0x0);
put_be32(pb, video_kbitrate);
put_be32(pb, video_kbitrate);
put_be32(pb, FrameRate);
@@ -1441,10 +1437,15 @@ static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
static int mov_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
MOVContext *mov = s->priv_data;
int i;
+ if (url_is_streamed(s->pb)) {
+ av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
+ return -1;
+ }
+
/* Default mode == MP4 */
mov->mode = MODE_MP4;
@@ -1455,8 +1456,8 @@ static int mov_write_header(AVFormatContext *s)
else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
mov_write_ftyp_tag(pb,s);
- if ( mov->mode == MODE_PSP ) {
- if ( s->nb_streams != 2 ) {
+ if (mov->mode == MODE_PSP) {
+ if (s->nb_streams != 2) {
av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
return -1;
}
@@ -1471,12 +1472,20 @@ static int mov_write_header(AVFormatContext *s)
track->enc = st->codec;
track->language = ff_mov_iso639_to_lang(st->language, mov->mode != MODE_MOV);
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 for codec\n", i);
+ return -1;
+ }
if(st->codec->codec_type == CODEC_TYPE_VIDEO){
- track->tag = mov_find_video_codec_tag(s, track);
track->timescale = st->codec->time_base.den;
av_set_pts_info(st, 64, 1, st->codec->time_base.den);
+ if (track->mode == MODE_MOV && track->timescale > 100000)
+ av_log(s, AV_LOG_WARNING,
+ "WARNING codec timebase is very high. If duration is too long,\n"
+ "file may not be playable by quicktime. Specify a shorter timebase\n"
+ "or choose different container.\n");
}else if(st->codec->codec_type == CODEC_TYPE_AUDIO){
- track->tag = mov_find_audio_codec_tag(s, track);
track->timescale = st->codec->sample_rate;
av_set_pts_info(st, 64, 1, st->codec->sample_rate);
if(!st->codec->frame_size){
@@ -1502,13 +1511,13 @@ static int mov_write_header(AVFormatContext *s)
static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
{
MOVContext *mov = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
MOVTrack *trk = &mov->tracks[pkt->stream_index];
AVCodecContext *enc = trk->enc;
unsigned int samplesInChunk = 0;
int size= pkt->size;
- if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
+ if (url_is_streamed(s->pb)) return 0; /* Can't handle that */
if (!size) return 0; /* Discard 0 sized packets */
if (enc->codec_id == CODEC_ID_AMR_NB) {
@@ -1522,7 +1531,7 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
samplesInChunk++;
}
if(samplesInChunk > 1){
- av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, inplement a AVParser for it\n");
+ av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
return -1;
}
} else if (trk->sampleSize)
@@ -1540,9 +1549,18 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
/* from x264 or from bytestream h264 */
/* nal reformating needed */
- avc_parse_nal_units(&pkt->data, &pkt->size);
+ int ret = ff_avc_parse_nal_units(pkt->data, &pkt->data, &pkt->size);
+ if (ret < 0)
+ return ret;
assert(pkt->size);
size = pkt->size;
+ } else if (enc->codec_id == CODEC_ID_DNXHD && !trk->vosLen) {
+ /* copy frame header to create needed atoms */
+ if (size < 640)
+ return -1;
+ trk->vosLen = 640;
+ trk->vosData = av_malloc(trk->vosLen);
+ memcpy(trk->vosData, pkt->data, 640);
}
if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
@@ -1579,7 +1597,7 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
static int mov_write_trailer(AVFormatContext *s)
{
MOVContext *mov = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int res = 0;
int i;
@@ -1603,7 +1621,7 @@ static int mov_write_trailer(AVFormatContext *s)
for (i=0; i<mov->nb_streams; i++) {
av_freep(&mov->tracks[i].cluster);
- if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
+ if(mov->tracks[i].vosLen) av_free(mov->tracks[i].vosData);
}
@@ -1625,6 +1643,7 @@ AVOutputFormat mov_muxer = {
mov_write_packet,
mov_write_trailer,
.flags = AVFMT_GLOBALHEADER,
+ .codec_tag = (const AVCodecTag*[]){codec_movvideo_tags, codec_movaudio_tags, 0},
};
#endif
#ifdef CONFIG_TGP_MUXER
@@ -1640,6 +1659,7 @@ AVOutputFormat tgp_muxer = {
mov_write_packet,
mov_write_trailer,
.flags = AVFMT_GLOBALHEADER,
+ .codec_tag = (const AVCodecTag*[]){codec_3gp_tags, 0},
};
#endif
#ifdef CONFIG_MP4_MUXER
@@ -1655,6 +1675,7 @@ AVOutputFormat mp4_muxer = {
mov_write_packet,
mov_write_trailer,
.flags = AVFMT_GLOBALHEADER,
+ .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0},
};
#endif
#ifdef CONFIG_PSP_MUXER
@@ -1670,6 +1691,7 @@ AVOutputFormat psp_muxer = {
mov_write_packet,
mov_write_trailer,
.flags = AVFMT_GLOBALHEADER,
+ .codec_tag = (const AVCodecTag*[]){ff_mp4_obj_type, 0},
};
#endif
#ifdef CONFIG_TG2_MUXER
@@ -1685,5 +1707,6 @@ AVOutputFormat tg2_muxer = {
mov_write_packet,
mov_write_trailer,
.flags = AVFMT_GLOBALHEADER,
+ .codec_tag = (const AVCodecTag*[]){codec_3gp_tags, 0},
};
#endif
diff --git a/contrib/ffmpeg/libavformat/mp3.c b/contrib/ffmpeg/libavformat/mp3.c
index e86ea14c8..64e0ce285 100644
--- a/contrib/ffmpeg/libavformat/mp3.c
+++ b/contrib/ffmpeg/libavformat/mp3.c
@@ -20,13 +20,15 @@
*/
#include "avformat.h"
#include "mpegaudio.h"
+#include "avstring.h"
+#include "mpegaudiodecheader.h"
-#define ID3_HEADER_SIZE 10
-#define ID3_TAG_SIZE 128
+#define ID3v2_HEADER_SIZE 10
+#define ID3v1_TAG_SIZE 128
-#define ID3_GENRE_MAX 125
+#define ID3v1_GENRE_MAX 125
-static const char *id3_genre_str[ID3_GENRE_MAX + 1] = {
+static const char *id3v1_genre_str[ID3v1_GENRE_MAX + 1] = {
[0] = "Blues",
[1] = "Classic Rock",
[2] = "Country",
@@ -155,8 +157,8 @@ static const char *id3_genre_str[ID3_GENRE_MAX + 1] = {
[125] = "Dance Hall",
};
-/* buf must be ID3_HEADER_SIZE byte long */
-static int id3_match(const uint8_t *buf)
+/* buf must be ID3v2_HEADER_SIZE byte long */
+static int id3v2_match(const uint8_t *buf)
{
return (buf[0] == 'I' &&
buf[1] == 'D' &&
@@ -169,8 +171,152 @@ static int id3_match(const uint8_t *buf)
(buf[9] & 0x80) == 0);
}
-static void id3_get_string(char *str, int str_size,
- const uint8_t *buf, int buf_size)
+static unsigned int id3v2_get_size(ByteIOContext *s, int len)
+{
+ int v=0;
+ while(len--)
+ v= (v<<7) + (get_byte(s)&0x7F);
+ return v;
+}
+
+static void id3v2_read_ttag(AVFormatContext *s, int taglen, char *dst, int dstlen)
+{
+ char *q;
+ int len;
+
+ if(taglen < 1)
+ return;
+
+ taglen--; /* account for encoding type byte */
+ dstlen--; /* Leave space for zero terminator */
+
+ switch(get_byte(s->pb)) { /* encoding type */
+
+ case 0: /* ISO-8859-1 (0 - 255 maps directly into unicode) */
+ q = dst;
+ while(taglen--) {
+ uint8_t tmp;
+ PUT_UTF8(get_byte(s->pb), tmp, if (q - dst < dstlen - 1) *q++ = tmp;)
+ }
+ *q = '\0';
+ break;
+
+ case 3: /* UTF-8 */
+ len = FFMIN(taglen, dstlen);
+ get_buffer(s->pb, dst, len);
+ dst[len] = 0;
+ break;
+ }
+}
+
+/**
+ * ID3v2 parser
+ *
+ * Handles ID3v2.2, 2.3 and 2.4.
+ *
+ */
+
+static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
+{
+ int isv34, tlen;
+ uint32_t tag;
+ offset_t next;
+ char tmp[16];
+ int taghdrlen;
+ const char *reason;
+
+ switch(version) {
+ case 2:
+ if(flags & 0x40) {
+ reason = "compression";
+ goto error;
+ }
+ isv34 = 0;
+ taghdrlen = 6;
+ break;
+
+ case 3:
+ case 4:
+ isv34 = 1;
+ taghdrlen = 10;
+ break;
+
+ default:
+ reason = "version";
+ goto error;
+ }
+
+ if(flags & 0x80) {
+ reason = "unsynchronization";
+ goto error;
+ }
+
+ if(isv34 && flags & 0x40) /* Extended header present, just skip over it */
+ url_fskip(s->pb, id3v2_get_size(s->pb, 4));
+
+ while(len >= taghdrlen) {
+ if(isv34) {
+ tag = get_be32(s->pb);
+ tlen = id3v2_get_size(s->pb, 4);
+ get_be16(s->pb); /* flags */
+ } else {
+ tag = get_be24(s->pb);
+ tlen = id3v2_get_size(s->pb, 3);
+ }
+ len -= taghdrlen + tlen;
+
+ if(len < 0)
+ break;
+
+ next = url_ftell(s->pb) + tlen;
+
+ switch(tag) {
+ case MKBETAG('T', 'I', 'T', '2'):
+ case MKBETAG(0, 'T', 'T', '2'):
+ id3v2_read_ttag(s, tlen, s->title, sizeof(s->title));
+ break;
+ case MKBETAG('T', 'P', 'E', '1'):
+ case MKBETAG(0, 'T', 'P', '1'):
+ id3v2_read_ttag(s, tlen, s->author, sizeof(s->author));
+ break;
+ case MKBETAG('T', 'A', 'L', 'B'):
+ case MKBETAG(0, 'T', 'A', 'L'):
+ id3v2_read_ttag(s, tlen, s->album, sizeof(s->album));
+ break;
+ case MKBETAG('T', 'C', 'O', 'N'):
+ case MKBETAG(0, 'T', 'C', 'O'):
+ id3v2_read_ttag(s, tlen, s->genre, sizeof(s->genre));
+ break;
+ case MKBETAG('T', 'C', 'O', 'P'):
+ case MKBETAG(0, 'T', 'C', 'R'):
+ id3v2_read_ttag(s, tlen, s->copyright, sizeof(s->copyright));
+ break;
+ case MKBETAG('T', 'R', 'C', 'K'):
+ case MKBETAG(0, 'T', 'R', 'K'):
+ id3v2_read_ttag(s, tlen, tmp, sizeof(tmp));
+ s->track = atoi(tmp);
+ break;
+ case 0:
+ /* padding, skip to end */
+ url_fskip(s->pb, len);
+ len = 0;
+ continue;
+ }
+ /* Skip to end of tag */
+ url_fseek(s->pb, next, SEEK_SET);
+ }
+
+ if(version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
+ url_fskip(s->pb, 10);
+ return;
+
+ error:
+ av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
+ url_fskip(s->pb, len);
+}
+
+static void id3v1_get_string(char *str, int str_size,
+ const uint8_t *buf, int buf_size)
{
int i, c;
char *q;
@@ -187,8 +333,8 @@ static void id3_get_string(char *str, int str_size,
*q = '\0';
}
-/* 'buf' must be ID3_TAG_SIZE byte long */
-static int id3_parse_tag(AVFormatContext *s, const uint8_t *buf)
+/* 'buf' must be ID3v1_TAG_SIZE byte long */
+static int id3v1_parse_tag(AVFormatContext *s, const uint8_t *buf)
{
char str[5];
int genre;
@@ -197,25 +343,25 @@ static int id3_parse_tag(AVFormatContext *s, const uint8_t *buf)
buf[1] == 'A' &&
buf[2] == 'G'))
return -1;
- id3_get_string(s->title, sizeof(s->title), buf + 3, 30);
- id3_get_string(s->author, sizeof(s->author), buf + 33, 30);
- id3_get_string(s->album, sizeof(s->album), buf + 63, 30);
- id3_get_string(str, sizeof(str), buf + 93, 4);
+ id3v1_get_string(s->title, sizeof(s->title), buf + 3, 30);
+ id3v1_get_string(s->author, sizeof(s->author), buf + 33, 30);
+ id3v1_get_string(s->album, sizeof(s->album), buf + 63, 30);
+ id3v1_get_string(str, sizeof(str), buf + 93, 4);
s->year = atoi(str);
- id3_get_string(s->comment, sizeof(s->comment), buf + 97, 30);
+ id3v1_get_string(s->comment, sizeof(s->comment), buf + 97, 30);
if (buf[125] == 0 && buf[126] != 0)
s->track = buf[126];
genre = buf[127];
- if (genre <= ID3_GENRE_MAX)
- pstrcpy(s->genre, sizeof(s->genre), id3_genre_str[genre]);
+ if (genre <= ID3v1_GENRE_MAX)
+ av_strlcpy(s->genre, id3v1_genre_str[genre], sizeof(s->genre));
return 0;
}
-static void id3_create_tag(AVFormatContext *s, uint8_t *buf)
+static void id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
{
int v, i;
- memset(buf, 0, ID3_TAG_SIZE); /* fail safe */
+ memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
buf[0] = 'T';
buf[1] = 'A';
buf[2] = 'G';
@@ -234,8 +380,8 @@ static void id3_create_tag(AVFormatContext *s, uint8_t *buf)
buf[125] = 0;
buf[126] = s->track;
}
- for(i = 0; i <= ID3_GENRE_MAX; i++) {
- if (!strcasecmp(s->genre, id3_genre_str[i])) {
+ for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
+ if (!strcasecmp(s->genre, id3v1_genre_str[i])) {
buf[127] = i;
break;
}
@@ -246,28 +392,25 @@ static void id3_create_tag(AVFormatContext *s, uint8_t *buf)
static int mp3_read_probe(AVProbeData *p)
{
- int max_frames, first_frames;
+ int max_frames, first_frames = 0;
int fsize, frames, sample_rate;
uint32_t header;
uint8_t *buf, *buf2, *end;
AVCodecContext avctx;
- if(p->buf_size < ID3_HEADER_SIZE)
- return 0;
-
- if(id3_match(p->buf))
- return AVPROBE_SCORE_MAX/2+1; // this must be less then mpeg-ps because some retards put id3 tage before mpeg-ps files
+ if(id3v2_match(p->buf))
+ return AVPROBE_SCORE_MAX/2+1; // this must be less than mpeg-ps because some retards put id3v2 tags before mpeg-ps files
max_frames = 0;
buf = p->buf;
- end = buf + FFMIN(4096, p->buf_size - sizeof(uint32_t));
+ end = buf + p->buf_size - sizeof(uint32_t);
- for(; buf < end; buf++) {
+ for(; buf < end; buf= buf2+1) {
buf2 = buf;
for(frames = 0; buf2 < end; frames++) {
- header = (buf2[0] << 24) | (buf2[1] << 16) | (buf2[2] << 8) | buf2[3];
- fsize = mpa_decode_header(&avctx, header, &sample_rate);
+ header = AV_RB32(buf2);
+ fsize = ff_mpa_decode_header(&avctx, header, &sample_rate);
if(fsize < 0)
break;
buf2 += fsize;
@@ -277,55 +420,109 @@ static int mp3_read_probe(AVProbeData *p)
first_frames= frames;
}
if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1;
+ else if(max_frames>500)return AVPROBE_SCORE_MAX/2;
else if(max_frames>=3) return AVPROBE_SCORE_MAX/4;
else if(max_frames>=1) return 1;
else return 0;
}
+/**
+ * Try to find Xing/Info/VBRI tags and compute duration from info therein
+ */
+static void mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, offset_t base)
+{
+ uint32_t v, spf;
+ int frames = -1; /* Total number of frames in file */
+ const offset_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
+ MPADecodeContext c;
+
+ v = get_be32(s->pb);
+ if(ff_mpa_check_header(v) < 0)
+ return;
+
+ ff_mpegaudio_decode_header(&c, v);
+ if(c.layer != 3)
+ return;
+
+ /* Check for Xing / Info tag */
+ url_fseek(s->pb, xing_offtbl[c.lsf == 1][c.nb_channels == 1], SEEK_CUR);
+ v = get_be32(s->pb);
+ if(v == MKBETAG('X', 'i', 'n', 'g') || v == MKBETAG('I', 'n', 'f', 'o')) {
+ v = get_be32(s->pb);
+ if(v & 0x1)
+ frames = get_be32(s->pb);
+ }
+
+ /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
+ url_fseek(s->pb, base + 4 + 32, SEEK_SET);
+ v = get_be32(s->pb);
+ if(v == MKBETAG('V', 'B', 'R', 'I')) {
+ /* Check tag version */
+ if(get_be16(s->pb) == 1) {
+ /* skip delay, quality and total bytes */
+ url_fseek(s->pb, 8, SEEK_CUR);
+ frames = get_be32(s->pb);
+ }
+ }
+
+ if(frames < 0)
+ return;
+
+ spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */
+ st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},
+ st->time_base);
+}
+
static int mp3_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
- uint8_t buf[ID3_TAG_SIZE];
+ uint8_t buf[ID3v1_TAG_SIZE];
int len, ret, filesize;
+ offset_t off;
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_MP3;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ st->start_time = 0;
/* try to get the TAG */
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
/* XXX: change that */
- filesize = url_fsize(&s->pb);
+ filesize = url_fsize(s->pb);
if (filesize > 128) {
- url_fseek(&s->pb, filesize - 128, SEEK_SET);
- ret = get_buffer(&s->pb, buf, ID3_TAG_SIZE);
- if (ret == ID3_TAG_SIZE) {
- id3_parse_tag(s, buf);
+ url_fseek(s->pb, filesize - 128, SEEK_SET);
+ ret = get_buffer(s->pb, buf, ID3v1_TAG_SIZE);
+ if (ret == ID3v1_TAG_SIZE) {
+ id3v1_parse_tag(s, buf);
}
- url_fseek(&s->pb, 0, SEEK_SET);
+ url_fseek(s->pb, 0, SEEK_SET);
}
}
- /* if ID3 header found, skip it */
- ret = get_buffer(&s->pb, buf, ID3_HEADER_SIZE);
- if (ret != ID3_HEADER_SIZE)
+ /* if ID3v2 header found, skip it */
+ ret = get_buffer(s->pb, buf, ID3v2_HEADER_SIZE);
+ if (ret != ID3v2_HEADER_SIZE)
return -1;
- if (id3_match(buf)) {
- /* skip ID3 header */
+ if (id3v2_match(buf)) {
+ /* parse ID3v2 header */
len = ((buf[6] & 0x7f) << 21) |
((buf[7] & 0x7f) << 14) |
((buf[8] & 0x7f) << 7) |
(buf[9] & 0x7f);
- url_fskip(&s->pb, len);
+ id3v2_parse(s, len, buf[3], buf[5]);
} else {
- url_fseek(&s->pb, 0, SEEK_SET);
+ url_fseek(s->pb, 0, SEEK_SET);
}
+ off = url_ftell(s->pb);
+ mp3_parse_vbr_tags(s, st, off);
+ url_fseek(s->pb, off, SEEK_SET);
+
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -339,11 +536,11 @@ static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt)
size= MP3_PACKET_SIZE;
- ret= av_get_packet(&s->pb, pkt, size);
+ ret= av_get_packet(s->pb, pkt, size);
pkt->stream_index = 0;
if (ret <= 0) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
/* note: we need to modify the packet size here to handle the last
packet */
@@ -358,27 +555,88 @@ static int mp3_read_close(AVFormatContext *s)
#ifdef CONFIG_MUXERS
/* simple formats */
+
+static void id3v2_put_size(AVFormatContext *s, int size)
+{
+ put_byte(s->pb, size >> 21 & 0x7f);
+ put_byte(s->pb, size >> 14 & 0x7f);
+ put_byte(s->pb, size >> 7 & 0x7f);
+ put_byte(s->pb, size & 0x7f);
+}
+
+static void id3v2_put_ttag(AVFormatContext *s, const char *string, uint32_t tag)
+{
+ int len = strlen(string);
+ put_be32(s->pb, tag);
+ id3v2_put_size(s, len + 1);
+ put_be16(s->pb, 0);
+ put_byte(s->pb, 3); /* UTF-8 */
+ put_buffer(s->pb, string, len);
+}
+
+
+/**
+ * Write an ID3v2.4 header at beginning of stream
+ */
+
static int mp3_write_header(struct AVFormatContext *s)
{
+ int totlen = 0;
+ char tracktxt[10];
+ char yeartxt[10];
+
+ if(s->track)
+ snprintf(tracktxt, sizeof(tracktxt), "%d", s->track);
+ if(s->year)
+ snprintf( yeartxt, sizeof(yeartxt) , "%d", s->year );
+
+ if(s->title[0]) totlen += 11 + strlen(s->title);
+ if(s->author[0]) totlen += 11 + strlen(s->author);
+ if(s->album[0]) totlen += 11 + strlen(s->album);
+ if(s->genre[0]) totlen += 11 + strlen(s->genre);
+ if(s->copyright[0]) totlen += 11 + strlen(s->copyright);
+ if(s->track) totlen += 11 + strlen(tracktxt);
+ if(s->year) totlen += 11 + strlen(yeartxt);
+ if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
+ totlen += strlen(LIBAVFORMAT_IDENT) + 11;
+
+ if(totlen == 0)
+ return 0;
+
+ put_be32(s->pb, MKBETAG('I', 'D', '3', 0x04)); /* ID3v2.4 */
+ put_byte(s->pb, 0);
+ put_byte(s->pb, 0); /* flags */
+
+ id3v2_put_size(s, totlen);
+
+ if(s->title[0]) id3v2_put_ttag(s, s->title, MKBETAG('T', 'I', 'T', '2'));
+ if(s->author[0]) id3v2_put_ttag(s, s->author, MKBETAG('T', 'P', 'E', '1'));
+ if(s->album[0]) id3v2_put_ttag(s, s->album, MKBETAG('T', 'A', 'L', 'B'));
+ if(s->genre[0]) id3v2_put_ttag(s, s->genre, MKBETAG('T', 'C', 'O', 'N'));
+ if(s->copyright[0]) id3v2_put_ttag(s, s->copyright, MKBETAG('T', 'C', 'O', 'P'));
+ if(s->track) id3v2_put_ttag(s, tracktxt, MKBETAG('T', 'R', 'C', 'K'));
+ if(s->year) id3v2_put_ttag(s, yeartxt, MKBETAG('T', 'Y', 'E', 'R'));
+ if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
+ id3v2_put_ttag(s, LIBAVFORMAT_IDENT, MKBETAG('T', 'E', 'N', 'C'));
return 0;
}
static int mp3_write_packet(struct AVFormatContext *s, AVPacket *pkt)
{
- put_buffer(&s->pb, pkt->data, pkt->size);
- put_flush_packet(&s->pb);
+ put_buffer(s->pb, pkt->data, pkt->size);
+ put_flush_packet(s->pb);
return 0;
}
static int mp3_write_trailer(struct AVFormatContext *s)
{
- uint8_t buf[ID3_TAG_SIZE];
+ uint8_t buf[ID3v1_TAG_SIZE];
- /* write the id3 header */
+ /* write the id3v1 tag */
if (s->title[0] != '\0') {
- id3_create_tag(s, buf);
- put_buffer(&s->pb, buf, ID3_TAG_SIZE);
- put_flush_packet(&s->pb);
+ id3v1_create_tag(s, buf);
+ put_buffer(s->pb, buf, ID3v1_TAG_SIZE);
+ put_flush_packet(s->pb);
}
return 0;
}
@@ -410,7 +668,7 @@ AVOutputFormat mp2_muxer = {
0,
CODEC_ID_MP2,
0,
- mp3_write_header,
+ NULL,
mp3_write_packet,
mp3_write_trailer,
};
diff --git a/contrib/ffmpeg/libavformat/mpc.c b/contrib/ffmpeg/libavformat/mpc.c
index a28efb16d..8e6c573df 100644
--- a/contrib/ffmpeg/libavformat/mpc.c
+++ b/contrib/ffmpeg/libavformat/mpc.c
@@ -16,7 +16,7 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "bitstream.h"
@@ -42,8 +42,6 @@ typedef struct {
static int mpc_probe(AVProbeData *p)
{
const uint8_t *d = p->buf;
- if (p->buf_size < 32)
- return 0;
if (d[0] == 'M' && d[1] == 'P' && d[2] == '+' && (d[3] == 0x17 || d[3] == 0x7))
return AVPROBE_SCORE_MAX;
if (d[0] == 'I' && d[1] == 'D' && d[2] == '3')
@@ -57,31 +55,31 @@ static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap)
AVStream *st;
int t;
- t = get_le24(&s->pb);
+ t = get_le24(s->pb);
if(t != MKTAG('M', 'P', '+', 0)){
if(t != MKTAG('I', 'D', '3', 0)){
av_log(s, AV_LOG_ERROR, "Not a Musepack file\n");
return -1;
}
/* skip ID3 tags and try again */
- url_fskip(&s->pb, 3);
- t = get_byte(&s->pb) << 21;
- t |= get_byte(&s->pb) << 14;
- t |= get_byte(&s->pb) << 7;
- t |= get_byte(&s->pb);
+ url_fskip(s->pb, 3);
+ t = get_byte(s->pb) << 21;
+ t |= get_byte(s->pb) << 14;
+ t |= get_byte(s->pb) << 7;
+ t |= get_byte(s->pb);
av_log(s, AV_LOG_DEBUG, "Skipping %d(%X) bytes of ID3 data\n", t, t);
- url_fskip(&s->pb, t);
- if(get_le24(&s->pb) != MKTAG('M', 'P', '+', 0)){
+ url_fskip(s->pb, t);
+ if(get_le24(s->pb) != MKTAG('M', 'P', '+', 0)){
av_log(s, AV_LOG_ERROR, "Not a Musepack file\n");
return -1;
}
}
- c->ver = get_byte(&s->pb);
+ c->ver = get_byte(s->pb);
if(c->ver != 0x07 && c->ver != 0x17){
av_log(s, AV_LOG_ERROR, "Can demux Musepack SV7, got version %02X\n", c->ver);
return -1;
}
- c->fcount = get_le32(&s->pb);
+ c->fcount = get_le32(s->pb);
if((int64_t)c->fcount * sizeof(MPCFrame) >= UINT_MAX){
av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n");
return -1;
@@ -94,7 +92,7 @@ static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap)
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_MUSEPACK7;
st->codec->channels = 2;
@@ -102,7 +100,7 @@ static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->extradata_size = 16;
st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE);
- get_buffer(&s->pb, st->codec->extradata, 16);
+ get_buffer(s->pb, st->codec->extradata, 16);
st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3];
av_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate);
/* scan for seekpoints */
@@ -122,22 +120,22 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt)
return -1;
if(c->curframe != c->lastframe + 1){
- url_fseek(&s->pb, c->frames[c->curframe].pos, SEEK_SET);
+ url_fseek(s->pb, c->frames[c->curframe].pos, SEEK_SET);
c->curbits = c->frames[c->curframe].skip;
}
c->lastframe = c->curframe;
c->curframe++;
curbits = c->curbits;
- pos = url_ftell(&s->pb);
- tmp = get_le32(&s->pb);
+ pos = url_ftell(s->pb);
+ tmp = get_le32(s->pb);
if(curbits <= 12){
size2 = (tmp >> (12 - curbits)) & 0xFFFFF;
}else{
- tmp = (tmp << 32) | get_le32(&s->pb);
+ tmp = (tmp << 32) | get_le32(s->pb);
size2 = (tmp >> (44 - curbits)) & 0xFFFFF;
}
curbits += 20;
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
size = ((size2 + curbits + 31) & ~31) >> 3;
if(cur == c->frames_noted){
@@ -150,19 +148,19 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt)
c->curbits = (curbits + size2) & 0x1F;
if (av_new_packet(pkt, size) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->data[0] = curbits;
pkt->data[1] = (c->curframe > c->fcount);
pkt->stream_index = 0;
pkt->pts = cur;
- ret = get_buffer(&s->pb, pkt->data + 4, size);
+ ret = get_buffer(s->pb, pkt->data + 4, size);
if(c->curbits)
- url_fseek(&s->pb, -4, SEEK_CUR);
+ url_fseek(s->pb, -4, SEEK_CUR);
if(ret < size){
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->size = ret + 4;
diff --git a/contrib/ffmpeg/libavformat/mpc8.c b/contrib/ffmpeg/libavformat/mpc8.c
new file mode 100644
index 000000000..879c7d236
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpc8.c
@@ -0,0 +1,244 @@
+/*
+ * Musepack SV8 demuxer
+ * Copyright (c) 2007 Konstantin Shishkov
+ *
+ * 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 "avformat.h"
+#include "bitstream.h"
+#include "unary.h"
+
+/// Two-byte MPC tag
+#define MKMPCTAG(a, b) (a | (b << 8))
+
+#define TAG_MPCK MKTAG('M','P','C','K')
+
+/// Reserved MPC tags
+enum MPCPacketTags{
+ TAG_STREAMHDR = MKMPCTAG('S','H'),
+ TAG_STREAMEND = MKMPCTAG('S','E'),
+
+ TAG_AUDIOPACKET = MKMPCTAG('A','P'),
+
+ TAG_SEEKTBLOFF = MKMPCTAG('S','O'),
+ TAG_SEEKTABLE = MKMPCTAG('S','T'),
+
+ TAG_REPLAYGAIN = MKMPCTAG('R','G'),
+ TAG_ENCINFO = MKMPCTAG('E','I'),
+};
+
+static const int mpc8_rate[8] = { 44100, 48000, 37800, 32000, -1, -1, -1, -1 };
+
+typedef struct {
+ int ver;
+ int frame;
+ int64_t header_pos;
+ int64_t samples;
+} MPCContext;
+
+static int mpc8_probe(AVProbeData *p)
+{
+ if (AV_RL32(p->buf) == TAG_MPCK)
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+static inline int64_t gb_get_v(GetBitContext *gb)
+{
+ int64_t v = 0;
+ int bits = 0;
+ while(get_bits1(gb) && bits < 64-7){
+ v <<= 7;
+ v |= get_bits(gb, 7);
+ bits += 7;
+ }
+ v <<= 7;
+ v |= get_bits(gb, 7);
+
+ return v;
+}
+
+static void mpc8_get_chunk_header(ByteIOContext *pb, int *tag, int64_t *size)
+{
+ int64_t pos;
+ pos = url_ftell(pb);
+ *tag = get_le16(pb);
+ *size = ff_get_v(pb);
+ *size -= url_ftell(pb) - pos;
+}
+
+static void mpc8_parse_seektable(AVFormatContext *s, int64_t off)
+{
+ MPCContext *c = s->priv_data;
+ int tag;
+ int64_t size, pos, ppos[2];
+ uint8_t *buf;
+ int i, t, seekd;
+ GetBitContext gb;
+
+ url_fseek(s->pb, off, SEEK_SET);
+ mpc8_get_chunk_header(s->pb, &tag, &size);
+ if(tag != TAG_SEEKTABLE){
+ av_log(s, AV_LOG_ERROR, "No seek table at given position\n");
+ return;
+ }
+ if(!(buf = av_malloc(size)))
+ return;
+ get_buffer(s->pb, buf, size);
+ init_get_bits(&gb, buf, size * 8);
+ size = gb_get_v(&gb);
+ if(size > UINT_MAX/4 || size > c->samples/1152){
+ av_log(s, AV_LOG_ERROR, "Seek table is too big\n");
+ return;
+ }
+ seekd = get_bits(&gb, 4);
+ for(i = 0; i < 2; i++){
+ pos = gb_get_v(&gb) + c->header_pos;
+ ppos[1 - i] = pos;
+ av_add_index_entry(s->streams[0], pos, i, 0, 0, AVINDEX_KEYFRAME);
+ }
+ for(; i < size; i++){
+ t = get_unary(&gb, 1, 33) << 12;
+ t += get_bits(&gb, 12);
+ if(t & 1)
+ t = -(t & ~1);
+ pos = (t >> 1) + ppos[0]*2 - ppos[1];
+ av_add_index_entry(s->streams[0], pos, i << seekd, 0, 0, AVINDEX_KEYFRAME);
+ ppos[1] = ppos[0];
+ ppos[0] = pos;
+ }
+ av_free(buf);
+}
+
+static void mpc8_handle_chunk(AVFormatContext *s, int tag, int64_t chunk_pos, int64_t size)
+{
+ ByteIOContext *pb = s->pb;
+ int64_t pos, off;
+
+ switch(tag){
+ case TAG_SEEKTBLOFF:
+ pos = url_ftell(pb) + size;
+ off = ff_get_v(pb);
+ mpc8_parse_seektable(s, chunk_pos + off);
+ url_fseek(pb, pos, SEEK_SET);
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+}
+
+static int mpc8_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ MPCContext *c = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVStream *st;
+ int tag = 0;
+ int64_t size, pos;
+
+ c->header_pos = url_ftell(pb);
+ if(get_le32(pb) != TAG_MPCK){
+ av_log(s, AV_LOG_ERROR, "Not a Musepack8 file\n");
+ return -1;
+ }
+
+ while(!url_feof(pb)){
+ pos = url_ftell(pb);
+ mpc8_get_chunk_header(pb, &tag, &size);
+ if(tag == TAG_STREAMHDR)
+ break;
+ mpc8_handle_chunk(s, tag, pos, size);
+ }
+ if(tag != TAG_STREAMHDR){
+ av_log(s, AV_LOG_ERROR, "Stream header not found\n");
+ return -1;
+ }
+ pos = url_ftell(pb);
+ url_fskip(pb, 4); //CRC
+ c->ver = get_byte(pb);
+ if(c->ver != 8){
+ av_log(s, AV_LOG_ERROR, "Unknown stream version %d\n", c->ver);
+ return -1;
+ }
+ c->samples = ff_get_v(pb);
+ ff_get_v(pb); //silence samples at the beginning
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_MUSEPACK8;
+ st->codec->bits_per_sample = 16;
+
+ st->codec->extradata_size = 2;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(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];
+ av_set_pts_info(st, 32, 1152 << (st->codec->extradata[1]&3)*2, st->codec->sample_rate);
+ st->duration = c->samples / (1152 << (st->codec->extradata[1]&3)*2);
+ size -= url_ftell(pb) - pos;
+
+ return 0;
+}
+
+static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MPCContext *c = s->priv_data;
+ int tag;
+ int64_t pos, size;
+
+ while(!url_feof(s->pb)){
+ pos = url_ftell(s->pb);
+ mpc8_get_chunk_header(s->pb, &tag, &size);
+ if(tag == TAG_AUDIOPACKET){
+ if(av_get_packet(s->pb, pkt, size) < 0)
+ return AVERROR(ENOMEM);
+ pkt->stream_index = 0;
+ pkt->pts = c->frame;
+ return 0;
+ }
+ if(tag == TAG_STREAMEND)
+ return AVERROR(EIO);
+ mpc8_handle_chunk(s, tag, pos, size);
+ }
+ return 0;
+}
+
+static int mpc8_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+ AVStream *st = s->streams[stream_index];
+ MPCContext *c = s->priv_data;
+ int index = av_index_search_timestamp(st, timestamp, flags);
+
+ if(index < 0) return -1;
+ url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
+ c->frame = st->index_entries[index].timestamp;
+ return 0;
+}
+
+
+AVInputFormat mpc8_demuxer = {
+ "mpc8",
+ "musepack8",
+ sizeof(MPCContext),
+ mpc8_probe,
+ mpc8_read_header,
+ mpc8_read_packet,
+ NULL,
+ mpc8_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/mpeg.c b/contrib/ffmpeg/libavformat/mpeg.c
index ae47fa60a..97b2a637a 100644
--- a/contrib/ffmpeg/libavformat/mpeg.c
+++ b/contrib/ffmpeg/libavformat/mpeg.c
@@ -1,5 +1,5 @@
/*
- * MPEG1/2 muxer and demuxer
+ * MPEG1/2 demuxer
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
*
* This file is part of FFmpeg.
@@ -18,1290 +18,72 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
#include "avformat.h"
-#include "bitstream.h"
-#include "fifo.h"
+#include "mpeg.h"
-#define MAX_PAYLOAD_SIZE 4096
//#define DEBUG_SEEK
#undef NDEBUG
#include <assert.h>
-typedef struct PacketDesc {
- int64_t pts;
- int64_t dts;
- int size;
- int unwritten_size;
- int flags;
- struct PacketDesc *next;
-} PacketDesc;
-
-typedef struct {
- AVFifoBuffer fifo;
- uint8_t id;
- int max_buffer_size; /* in bytes */
- int buffer_index;
- PacketDesc *predecode_packet;
- PacketDesc *premux_packet;
- PacketDesc **next_packet;
- int packet_number;
- uint8_t lpcm_header[3];
- int lpcm_align;
- int bytes_to_iframe;
- int align_iframe;
- int64_t vobu_start_pts;
-} StreamInfo;
-
-typedef struct {
- int packet_size; /* required packet size */
- int packet_number;
- int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */
- int system_header_freq;
- int system_header_size;
- int mux_rate; /* bitrate in units of 50 bytes/s */
- /* stream info */
- int audio_bound;
- int video_bound;
- int is_mpeg2;
- int is_vcd;
- int is_svcd;
- int is_dvd;
- int64_t last_scr; /* current system clock */
-
- double vcd_padding_bitrate; //FIXME floats
- int64_t vcd_padding_bytes_written;
-
-} MpegMuxContext;
-
-#define PACK_START_CODE ((unsigned int)0x000001ba)
-#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
-#define SEQUENCE_END_CODE ((unsigned int)0x000001b7)
-#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
-#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
-#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
-
-/* mpeg2 */
-#define PROGRAM_STREAM_MAP 0x1bc
-#define PRIVATE_STREAM_1 0x1bd
-#define PADDING_STREAM 0x1be
-#define PRIVATE_STREAM_2 0x1bf
-
-
-#define AUDIO_ID 0xc0
-#define VIDEO_ID 0xe0
-#define AC3_ID 0x80
-#define DTS_ID 0x8a
-#define LPCM_ID 0xa0
-#define SUB_ID 0x20
-
-#define STREAM_TYPE_VIDEO_MPEG1 0x01
-#define STREAM_TYPE_VIDEO_MPEG2 0x02
-#define STREAM_TYPE_AUDIO_MPEG1 0x03
-#define STREAM_TYPE_AUDIO_MPEG2 0x04
-#define STREAM_TYPE_PRIVATE_SECTION 0x05
-#define STREAM_TYPE_PRIVATE_DATA 0x06
-#define STREAM_TYPE_AUDIO_AAC 0x0f
-#define STREAM_TYPE_VIDEO_MPEG4 0x10
-#define STREAM_TYPE_VIDEO_H264 0x1b
-
-#define STREAM_TYPE_AUDIO_AC3 0x81
-#define STREAM_TYPE_AUDIO_DTS 0x8a
-
-static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };
-
-#ifdef CONFIG_MUXERS
-AVOutputFormat mpeg1system_muxer;
-AVOutputFormat mpeg1vcd_muxer;
-AVOutputFormat mpeg2vob_muxer;
-AVOutputFormat mpeg2svcd_muxer;
-AVOutputFormat mpeg2dvd_muxer;
-
-static int put_pack_header(AVFormatContext *ctx,
- uint8_t *buf, int64_t timestamp)
-{
- MpegMuxContext *s = ctx->priv_data;
- PutBitContext pb;
-
- init_put_bits(&pb, buf, 128);
-
- put_bits(&pb, 32, PACK_START_CODE);
- if (s->is_mpeg2) {
- put_bits(&pb, 2, 0x1);
- } else {
- put_bits(&pb, 4, 0x2);
- }
- put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07));
- put_bits(&pb, 1, 1);
- put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff));
- put_bits(&pb, 1, 1);
- put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff));
- put_bits(&pb, 1, 1);
- if (s->is_mpeg2) {
- /* clock extension */
- put_bits(&pb, 9, 0);
- }
- put_bits(&pb, 1, 1);
- put_bits(&pb, 22, s->mux_rate);
- put_bits(&pb, 1, 1);
- if (s->is_mpeg2) {
- put_bits(&pb, 1, 1);
- put_bits(&pb, 5, 0x1f); /* reserved */
- put_bits(&pb, 3, 0); /* stuffing length */
- }
- flush_put_bits(&pb);
- return pbBufPtr(&pb) - pb.buf;
-}
-
-static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_stream_id)
-{
- MpegMuxContext *s = ctx->priv_data;
- int size, i, private_stream_coded, id;
- PutBitContext pb;
-
- init_put_bits(&pb, buf, 128);
-
- put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
- put_bits(&pb, 16, 0);
- put_bits(&pb, 1, 1);
-
- put_bits(&pb, 22, s->mux_rate); /* maximum bit rate of the multiplexed stream */
- put_bits(&pb, 1, 1); /* marker */
- if (s->is_vcd && only_for_stream_id==VIDEO_ID) {
- /* This header applies only to the video stream (see VCD standard p. IV-7)*/
- put_bits(&pb, 6, 0);
- } else
- put_bits(&pb, 6, s->audio_bound);
-
- if (s->is_vcd) {
- /* see VCD standard, p. IV-7*/
- put_bits(&pb, 1, 0);
- put_bits(&pb, 1, 1);
- } else {
- put_bits(&pb, 1, 0); /* variable bitrate*/
- put_bits(&pb, 1, 0); /* non constrainted bit stream */
- }
-
- if (s->is_vcd || s->is_dvd) {
- /* see VCD standard p IV-7 */
- put_bits(&pb, 1, 1); /* audio locked */
- put_bits(&pb, 1, 1); /* video locked */
- } else {
- put_bits(&pb, 1, 0); /* audio locked */
- put_bits(&pb, 1, 0); /* video locked */
- }
-
- put_bits(&pb, 1, 1); /* marker */
-
- if (s->is_vcd && only_for_stream_id==AUDIO_ID) {
- /* This header applies only to the audio stream (see VCD standard p. IV-7)*/
- put_bits(&pb, 5, 0);
- } else
- put_bits(&pb, 5, s->video_bound);
-
- if (s->is_dvd) {
- put_bits(&pb, 1, 0); /* packet_rate_restriction_flag */
- put_bits(&pb, 7, 0x7f); /* reserved byte */
- } else
- put_bits(&pb, 8, 0xff); /* reserved byte */
-
- /* DVD-Video Stream_bound entries
- id (0xB9) video, maximum P-STD for stream 0xE0. (P-STD_buffer_bound_scale = 1)
- id (0xB8) audio, maximum P-STD for any MPEG audio (0xC0 to 0xC7) streams. If there are none set to 4096 (32x128). (P-STD_buffer_bound_scale = 0)
- id (0xBD) private stream 1 (audio other than MPEG and subpictures). (P-STD_buffer_bound_scale = 1)
- id (0xBF) private stream 2, NAV packs, set to 2x1024. */
- if (s->is_dvd) {
-
- int P_STD_max_video = 0;
- int P_STD_max_mpeg_audio = 0;
- int P_STD_max_mpeg_PS1 = 0;
-
- for(i=0;i<ctx->nb_streams;i++) {
- StreamInfo *stream = ctx->streams[i]->priv_data;
-
- id = stream->id;
- if (id == 0xbd && stream->max_buffer_size > P_STD_max_mpeg_PS1) {
- P_STD_max_mpeg_PS1 = stream->max_buffer_size;
- } else if (id >= 0xc0 && id <= 0xc7 && stream->max_buffer_size > P_STD_max_mpeg_audio) {
- P_STD_max_mpeg_audio = stream->max_buffer_size;
- } else if (id == 0xe0 && stream->max_buffer_size > P_STD_max_video) {
- P_STD_max_video = stream->max_buffer_size;
- }
- }
-
- /* video */
- put_bits(&pb, 8, 0xb9); /* stream ID */
- put_bits(&pb, 2, 3);
- put_bits(&pb, 1, 1);
- put_bits(&pb, 13, P_STD_max_video / 1024);
-
- /* audio */
- if (P_STD_max_mpeg_audio == 0)
- P_STD_max_mpeg_audio = 4096;
- put_bits(&pb, 8, 0xb8); /* stream ID */
- put_bits(&pb, 2, 3);
- put_bits(&pb, 1, 0);
- put_bits(&pb, 13, P_STD_max_mpeg_audio / 128);
-
- /* private stream 1 */
- put_bits(&pb, 8, 0xbd); /* stream ID */
- put_bits(&pb, 2, 3);
- put_bits(&pb, 1, 0);
- put_bits(&pb, 13, P_STD_max_mpeg_PS1 / 128);
-
- /* private stream 2 */
- put_bits(&pb, 8, 0xbf); /* stream ID */
- put_bits(&pb, 2, 3);
- put_bits(&pb, 1, 1);
- put_bits(&pb, 13, 2);
- }
- else {
- /* audio stream info */
- private_stream_coded = 0;
- for(i=0;i<ctx->nb_streams;i++) {
- StreamInfo *stream = ctx->streams[i]->priv_data;
-
-
- /* For VCDs, only include the stream info for the stream
- that the pack which contains this system belongs to.
- (see VCD standard p. IV-7) */
- if ( !s->is_vcd || stream->id==only_for_stream_id
- || only_for_stream_id==0) {
-
- id = stream->id;
- if (id < 0xc0) {
- /* special case for private streams (AC3 use that) */
- if (private_stream_coded)
- continue;
- private_stream_coded = 1;
- id = 0xbd;
- }
- put_bits(&pb, 8, id); /* stream ID */
- put_bits(&pb, 2, 3);
- if (id < 0xe0) {
- /* audio */
- put_bits(&pb, 1, 0);
- put_bits(&pb, 13, stream->max_buffer_size / 128);
- } else {
- /* video */
- put_bits(&pb, 1, 1);
- put_bits(&pb, 13, stream->max_buffer_size / 1024);
- }
- }
- }
- }
-
- flush_put_bits(&pb);
- size = pbBufPtr(&pb) - pb.buf;
- /* patch packet size */
- buf[4] = (size - 6) >> 8;
- buf[5] = (size - 6) & 0xff;
-
- return size;
-}
-
-static int get_system_header_size(AVFormatContext *ctx)
-{
- int buf_index, i, private_stream_coded;
- StreamInfo *stream;
- MpegMuxContext *s = ctx->priv_data;
-
- if (s->is_dvd)
- return 18; // DVD-Video system headers are 18 bytes fixed length.
-
- buf_index = 12;
- private_stream_coded = 0;
- for(i=0;i<ctx->nb_streams;i++) {
- stream = ctx->streams[i]->priv_data;
- if (stream->id < 0xc0) {
- if (private_stream_coded)
- continue;
- private_stream_coded = 1;
- }
- buf_index += 3;
- }
- return buf_index;
-}
-
-static int mpeg_mux_init(AVFormatContext *ctx)
-{
- MpegMuxContext *s = ctx->priv_data;
- int bitrate, i, mpa_id, mpv_id, mps_id, ac3_id, dts_id, lpcm_id, j;
- AVStream *st;
- StreamInfo *stream;
- int audio_bitrate;
- int video_bitrate;
-
- s->packet_number = 0;
- s->is_vcd = (ctx->oformat == &mpeg1vcd_muxer);
- s->is_svcd = (ctx->oformat == &mpeg2svcd_muxer);
- s->is_mpeg2 = (ctx->oformat == &mpeg2vob_muxer || ctx->oformat == &mpeg2svcd_muxer || ctx->oformat == &mpeg2dvd_muxer);
- s->is_dvd = (ctx->oformat == &mpeg2dvd_muxer);
-
- if(ctx->packet_size)
- s->packet_size = ctx->packet_size;
- else
- s->packet_size = 2048;
-
- s->vcd_padding_bytes_written = 0;
- s->vcd_padding_bitrate=0;
-
- s->audio_bound = 0;
- s->video_bound = 0;
- mpa_id = AUDIO_ID;
- ac3_id = AC3_ID;
- dts_id = DTS_ID;
- mpv_id = VIDEO_ID;
- mps_id = SUB_ID;
- lpcm_id = LPCM_ID;
- for(i=0;i<ctx->nb_streams;i++) {
- st = ctx->streams[i];
- stream = av_mallocz(sizeof(StreamInfo));
- if (!stream)
- goto fail;
- st->priv_data = stream;
-
- av_set_pts_info(st, 64, 1, 90000);
-
- switch(st->codec->codec_type) {
- case CODEC_TYPE_AUDIO:
- if (st->codec->codec_id == CODEC_ID_AC3) {
- stream->id = ac3_id++;
- } else if (st->codec->codec_id == CODEC_ID_DTS) {
- stream->id = dts_id++;
- } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) {
- stream->id = lpcm_id++;
- for(j = 0; j < 4; j++) {
- if (lpcm_freq_tab[j] == st->codec->sample_rate)
- break;
- }
- if (j == 4)
- goto fail;
- if (st->codec->channels > 8)
- return -1;
- stream->lpcm_header[0] = 0x0c;
- stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
- stream->lpcm_header[2] = 0x80;
- stream->lpcm_align = st->codec->channels * 2;
- } else {
- stream->id = mpa_id++;
- }
-
- /* This value HAS to be used for VCD (see VCD standard, p. IV-7).
- Right now it is also used for everything else.*/
- stream->max_buffer_size = 4 * 1024;
- s->audio_bound++;
- break;
- case CODEC_TYPE_VIDEO:
- stream->id = mpv_id++;
- if (st->codec->rc_buffer_size)
- stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8;
- else
- stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default
-#if 0
- /* see VCD standard, p. IV-7*/
- stream->max_buffer_size = 46 * 1024;
- else
- /* This value HAS to be used for SVCD (see SVCD standard, p. 26 V.2.3.2).
- Right now it is also used for everything else.*/
- stream->max_buffer_size = 230 * 1024;
-#endif
- s->video_bound++;
- break;
- case CODEC_TYPE_SUBTITLE:
- stream->id = mps_id++;
- stream->max_buffer_size = 16 * 1024;
- break;
- default:
- return -1;
- }
- av_fifo_init(&stream->fifo, 16);
- }
- bitrate = 0;
- audio_bitrate = 0;
- video_bitrate = 0;
- for(i=0;i<ctx->nb_streams;i++) {
- int codec_rate;
- st = ctx->streams[i];
- stream = (StreamInfo*) st->priv_data;
-
- if(st->codec->rc_max_rate || stream->id==VIDEO_ID)
- codec_rate= st->codec->rc_max_rate;
- else
- codec_rate= st->codec->bit_rate;
-
- if(!codec_rate)
- codec_rate= (1<<21)*8*50/ctx->nb_streams;
-
- bitrate += codec_rate;
-
- if (stream->id==AUDIO_ID)
- audio_bitrate += codec_rate;
- else if (stream->id==VIDEO_ID)
- video_bitrate += codec_rate;
- }
-
- if(ctx->mux_rate){
- s->mux_rate= (ctx->mux_rate + (8 * 50) - 1) / (8 * 50);
- } else {
- /* we increase slightly the bitrate to take into account the
- headers. XXX: compute it exactly */
- bitrate += bitrate*5/100;
- bitrate += 10000;
- s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
- }
-
- if (s->is_vcd) {
- double overhead_rate;
-
- /* The VCD standard mandates that the mux_rate field is 3528
- (see standard p. IV-6).
- The value is actually "wrong", i.e. if you calculate
- it using the normal formula and the 75 sectors per second transfer
- rate you get a different value because the real pack size is 2324,
- not 2352. But the standard explicitly specifies that the mux_rate
- field in the header must have this value.*/
-// s->mux_rate=2352 * 75 / 50; /* = 3528*/
-
- /* The VCD standard states that the muxed stream must be
- exactly 75 packs / second (the data rate of a single speed cdrom).
- Since the video bitrate (probably 1150000 bits/sec) will be below
- the theoretical maximum we have to add some padding packets
- to make up for the lower data rate.
- (cf. VCD standard p. IV-6 )*/
-
- /* Add the header overhead to the data rate.
- 2279 data bytes per audio pack, 2294 data bytes per video pack*/
- overhead_rate = ((audio_bitrate / 8.0) / 2279) * (2324 - 2279);
- overhead_rate += ((video_bitrate / 8.0) / 2294) * (2324 - 2294);
- overhead_rate *= 8;
-
- /* Add padding so that the full bitrate is 2324*75 bytes/sec */
- s->vcd_padding_bitrate = 2324 * 75 * 8 - (bitrate + overhead_rate);
- }
-
- if (s->is_vcd || s->is_mpeg2)
- /* every packet */
- s->pack_header_freq = 1;
- else
- /* every 2 seconds */
- s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
-
- /* the above seems to make pack_header_freq zero sometimes */
- if (s->pack_header_freq == 0)
- s->pack_header_freq = 1;
-
- if (s->is_mpeg2)
- /* every 200 packets. Need to look at the spec. */
- s->system_header_freq = s->pack_header_freq * 40;
- else if (s->is_vcd)
- /* the standard mandates that there are only two system headers
- in the whole file: one in the first packet of each stream.
- (see standard p. IV-7 and IV-8) */
- s->system_header_freq = 0x7fffffff;
- else
- s->system_header_freq = s->pack_header_freq * 5;
-
- for(i=0;i<ctx->nb_streams;i++) {
- stream = ctx->streams[i]->priv_data;
- stream->packet_number = 0;
- }
- s->system_header_size = get_system_header_size(ctx);
- s->last_scr = 0;
- return 0;
- fail:
- for(i=0;i<ctx->nb_streams;i++) {
- av_free(ctx->streams[i]->priv_data);
- }
- return AVERROR(ENOMEM);
-}
-
-static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp)
-{
- put_byte(pb,
- (id << 4) |
- (((timestamp >> 30) & 0x07) << 1) |
- 1);
- put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1));
- put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));
-}
-
-
-/* return the number of padding bytes that should be inserted into
- the multiplexed stream.*/
-static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts)
-{
- MpegMuxContext *s = ctx->priv_data;
- int pad_bytes = 0;
-
- if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE)
- {
- int64_t full_pad_bytes;
-
- full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); //FIXME this is wrong
- pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written);
-
- if (pad_bytes<0)
- /* might happen if we have already padded to a later timestamp. This
- can occur if another stream has already advanced further.*/
- pad_bytes=0;
- }
-
- return pad_bytes;
-}
-
-
-#if 0 /* unused, remove? */
-/* return the exact available payload size for the next packet for
- stream 'stream_index'. 'pts' and 'dts' are only used to know if
- timestamps are needed in the packet header. */
-static int get_packet_payload_size(AVFormatContext *ctx, int stream_index,
- int64_t pts, int64_t dts)
-{
- MpegMuxContext *s = ctx->priv_data;
- int buf_index;
- StreamInfo *stream;
-
- stream = ctx->streams[stream_index]->priv_data;
-
- buf_index = 0;
- if (((s->packet_number % s->pack_header_freq) == 0)) {
- /* pack header size */
- if (s->is_mpeg2)
- buf_index += 14;
- else
- buf_index += 12;
-
- if (s->is_vcd) {
- /* there is exactly one system header for each stream in a VCD MPEG,
- One in the very first video packet and one in the very first
- audio packet (see VCD standard p. IV-7 and IV-8).*/
-
- if (stream->packet_number==0)
- /* The system headers refer only to the stream they occur in,
- so they have a constant size.*/
- buf_index += 15;
-
- } else {
- if ((s->packet_number % s->system_header_freq) == 0)
- buf_index += s->system_header_size;
- }
- }
-
- if ((s->is_vcd && stream->packet_number==0)
- || (s->is_svcd && s->packet_number==0))
- /* the first pack of each stream contains only the pack header,
- the system header and some padding (see VCD standard p. IV-6)
- Add the padding size, so that the actual payload becomes 0.*/
- buf_index += s->packet_size - buf_index;
- else {
- /* packet header size */
- buf_index += 6;
- if (s->is_mpeg2) {
- buf_index += 3;
- if (stream->packet_number==0)
- buf_index += 3; /* PES extension */
- buf_index += 1; /* obligatory stuffing byte */
- }
- if (pts != AV_NOPTS_VALUE) {
- if (dts != pts)
- buf_index += 5 + 5;
- else
- buf_index += 5;
-
- } else {
- if (!s->is_mpeg2)
- buf_index++;
- }
-
- if (stream->id < 0xc0) {
- /* AC3/LPCM private data header */
- buf_index += 4;
- if (stream->id >= 0xa0) {
- int n;
- buf_index += 3;
- /* NOTE: we round the payload size to an integer number of
- LPCM samples */
- n = (s->packet_size - buf_index) % stream->lpcm_align;
- if (n)
- buf_index += (stream->lpcm_align - n);
- }
- }
-
- if (s->is_vcd && stream->id == AUDIO_ID)
- /* The VCD standard demands that 20 zero bytes follow
- each audio packet (see standard p. IV-8).*/
- buf_index+=20;
- }
- return s->packet_size - buf_index;
-}
-#endif
-
-/* Write an MPEG padding packet header. */
-static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes)
-{
- MpegMuxContext *s = ctx->priv_data;
- int i;
-
- put_be32(pb, PADDING_STREAM);
- put_be16(pb, packet_bytes - 6);
- if (!s->is_mpeg2) {
- put_byte(pb, 0x0f);
- packet_bytes -= 7;
- } else
- packet_bytes -= 6;
-
- for(i=0;i<packet_bytes;i++)
- put_byte(pb, 0xff);
-}
-
-static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len){
- int nb_frames=0;
- PacketDesc *pkt_desc= stream->premux_packet;
-
- while(len>0){
- if(pkt_desc->size == pkt_desc->unwritten_size)
- nb_frames++;
- len -= pkt_desc->unwritten_size;
- pkt_desc= pkt_desc->next;
- }
-
- return nb_frames;
-}
-
-/* flush the packet on stream stream_index */
-static int flush_packet(AVFormatContext *ctx, int stream_index,
- int64_t pts, int64_t dts, int64_t scr, int trailer_size)
-{
- MpegMuxContext *s = ctx->priv_data;
- StreamInfo *stream = ctx->streams[stream_index]->priv_data;
- uint8_t *buf_ptr;
- int size, payload_size, startcode, id, stuffing_size, i, header_len;
- int packet_size;
- uint8_t buffer[128];
- int zero_trail_bytes = 0;
- int pad_packet_bytes = 0;
- int pes_flags;
- int general_pack = 0; /*"general" pack without data specific to one stream?*/
- int nb_frames;
-
- id = stream->id;
-
-#if 0
- printf("packet ID=%2x PTS=%0.3f\n",
- id, pts / 90000.0);
-#endif
-
- buf_ptr = buffer;
-
- if ((s->packet_number % s->pack_header_freq) == 0 || s->last_scr != scr) {
- /* output pack and systems header if needed */
- size = put_pack_header(ctx, buf_ptr, scr);
- buf_ptr += size;
- s->last_scr= scr;
-
- if (s->is_vcd) {
- /* there is exactly one system header for each stream in a VCD MPEG,
- One in the very first video packet and one in the very first
- audio packet (see VCD standard p. IV-7 and IV-8).*/
-
- if (stream->packet_number==0) {
- size = put_system_header(ctx, buf_ptr, id);
- buf_ptr += size;
- }
- } else if (s->is_dvd) {
- if (stream->align_iframe || s->packet_number == 0){
- int PES_bytes_to_fill = s->packet_size - size - 10;
-
- if (pts != AV_NOPTS_VALUE) {
- if (dts != pts)
- PES_bytes_to_fill -= 5 + 5;
- else
- PES_bytes_to_fill -= 5;
- }
-
- if (stream->bytes_to_iframe == 0 || s->packet_number == 0) {
- size = put_system_header(ctx, buf_ptr, 0);
- buf_ptr += size;
- size = buf_ptr - buffer;
- put_buffer(&ctx->pb, buffer, size);
-
- put_be32(&ctx->pb, PRIVATE_STREAM_2);
- put_be16(&ctx->pb, 0x03d4); // length
- put_byte(&ctx->pb, 0x00); // substream ID, 00=PCI
- for (i = 0; i < 979; i++)
- put_byte(&ctx->pb, 0x00);
-
- put_be32(&ctx->pb, PRIVATE_STREAM_2);
- put_be16(&ctx->pb, 0x03fa); // length
- put_byte(&ctx->pb, 0x01); // substream ID, 01=DSI
- for (i = 0; i < 1017; i++)
- put_byte(&ctx->pb, 0x00);
-
- memset(buffer, 0, 128);
- buf_ptr = buffer;
- s->packet_number++;
- stream->align_iframe = 0;
- scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
- size = put_pack_header(ctx, buf_ptr, scr);
- s->last_scr= scr;
- buf_ptr += size;
- /* GOP Start */
- } else if (stream->bytes_to_iframe < PES_bytes_to_fill) {
- pad_packet_bytes = PES_bytes_to_fill - stream->bytes_to_iframe;
- }
- }
- } else {
- if ((s->packet_number % s->system_header_freq) == 0) {
- size = put_system_header(ctx, buf_ptr, 0);
- buf_ptr += size;
- }
- }
- }
- size = buf_ptr - buffer;
- put_buffer(&ctx->pb, buffer, size);
-
- packet_size = s->packet_size - size;
-
- if (s->is_vcd && id == AUDIO_ID)
- /* The VCD standard demands that 20 zero bytes follow
- each audio pack (see standard p. IV-8).*/
- zero_trail_bytes += 20;
-
- if ((s->is_vcd && stream->packet_number==0)
- || (s->is_svcd && s->packet_number==0)) {
- /* for VCD the first pack of each stream contains only the pack header,
- the system header and lots of padding (see VCD standard p. IV-6).
- In the case of an audio pack, 20 zero bytes are also added at
- the end.*/
- /* For SVCD we fill the very first pack to increase compatibility with
- some DVD players. Not mandated by the standard.*/
- if (s->is_svcd)
- general_pack = 1; /* the system header refers to both streams and no stream data*/
- pad_packet_bytes = packet_size - zero_trail_bytes;
- }
-
- packet_size -= pad_packet_bytes + zero_trail_bytes;
-
- if (packet_size > 0) {
-
- /* packet header size */
- packet_size -= 6;
-
- /* packet header */
- if (s->is_mpeg2) {
- header_len = 3;
- if (stream->packet_number==0)
- header_len += 3; /* PES extension */
- header_len += 1; /* obligatory stuffing byte */
- } else {
- header_len = 0;
- }
- if (pts != AV_NOPTS_VALUE) {
- if (dts != pts)
- header_len += 5 + 5;
- else
- header_len += 5;
- } else {
- if (!s->is_mpeg2)
- header_len++;
- }
-
- payload_size = packet_size - header_len;
- if (id < 0xc0) {
- startcode = PRIVATE_STREAM_1;
- payload_size -= 1;
- if (id >= 0x40) {
- payload_size -= 3;
- if (id >= 0xa0)
- payload_size -= 3;
- }
- } else {
- startcode = 0x100 + id;
- }
-
- stuffing_size = payload_size - av_fifo_size(&stream->fifo);
-
- // first byte doesnt fit -> reset pts/dts + stuffing
- if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){
- int timestamp_len=0;
- if(dts != pts)
- timestamp_len += 5;
- if(pts != AV_NOPTS_VALUE)
- timestamp_len += s->is_mpeg2 ? 5 : 4;
- pts=dts= AV_NOPTS_VALUE;
- header_len -= timestamp_len;
- if (s->is_dvd && stream->align_iframe) {
- pad_packet_bytes += timestamp_len;
- packet_size -= timestamp_len;
- } else {
- payload_size += timestamp_len;
- }
- stuffing_size += timestamp_len;
- if(payload_size > trailer_size)
- stuffing_size += payload_size - trailer_size;
- }
-
- if (pad_packet_bytes > 0 && pad_packet_bytes <= 7) { // can't use padding, so use stuffing
- packet_size += pad_packet_bytes;
- payload_size += pad_packet_bytes; // undo the previous adjustment
- if (stuffing_size < 0) {
- stuffing_size = pad_packet_bytes;
- } else {
- stuffing_size += pad_packet_bytes;
- }
- pad_packet_bytes = 0;
- }
-
- if (stuffing_size < 0)
- stuffing_size = 0;
- if (stuffing_size > 16) { /*<=16 for MPEG-1, <=32 for MPEG-2*/
- pad_packet_bytes += stuffing_size;
- packet_size -= stuffing_size;
- payload_size -= stuffing_size;
- stuffing_size = 0;
- }
-
- nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);
-
- put_be32(&ctx->pb, startcode);
-
- put_be16(&ctx->pb, packet_size);
-
- if (!s->is_mpeg2)
- for(i=0;i<stuffing_size;i++)
- put_byte(&ctx->pb, 0xff);
-
- if (s->is_mpeg2) {
- put_byte(&ctx->pb, 0x80); /* mpeg2 id */
-
- pes_flags=0;
-
- if (pts != AV_NOPTS_VALUE) {
- pes_flags |= 0x80;
- if (dts != pts)
- pes_flags |= 0x40;
- }
-
- /* Both the MPEG-2 and the SVCD standards demand that the
- P-STD_buffer_size field be included in the first packet of
- every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2
- and MPEG-2 standard 2.7.7) */
- if (stream->packet_number == 0)
- pes_flags |= 0x01;
-
- put_byte(&ctx->pb, pes_flags); /* flags */
- put_byte(&ctx->pb, header_len - 3 + stuffing_size);
-
- if (pes_flags & 0x80) /*write pts*/
- put_timestamp(&ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
- if (pes_flags & 0x40) /*write dts*/
- put_timestamp(&ctx->pb, 0x01, dts);
-
- if (pes_flags & 0x01) { /*write pes extension*/
- put_byte(&ctx->pb, 0x10); /* flags */
-
- /* P-STD buffer info */
- if (id == AUDIO_ID)
- put_be16(&ctx->pb, 0x4000 | stream->max_buffer_size/128);
- else
- put_be16(&ctx->pb, 0x6000 | stream->max_buffer_size/1024);
- }
-
- } else {
- if (pts != AV_NOPTS_VALUE) {
- if (dts != pts) {
- put_timestamp(&ctx->pb, 0x03, pts);
- put_timestamp(&ctx->pb, 0x01, dts);
- } else {
- put_timestamp(&ctx->pb, 0x02, pts);
- }
- } else {
- put_byte(&ctx->pb, 0x0f);
- }
- }
-
- if (s->is_mpeg2) {
- /* special stuffing byte that is always written
- to prevent accidental generation of start codes. */
- put_byte(&ctx->pb, 0xff);
-
- for(i=0;i<stuffing_size;i++)
- put_byte(&ctx->pb, 0xff);
- }
-
- if (startcode == PRIVATE_STREAM_1) {
- put_byte(&ctx->pb, id);
- if (id >= 0xa0) {
- /* LPCM (XXX: check nb_frames) */
- put_byte(&ctx->pb, 7);
- put_be16(&ctx->pb, 4); /* skip 3 header bytes */
- put_byte(&ctx->pb, stream->lpcm_header[0]);
- put_byte(&ctx->pb, stream->lpcm_header[1]);
- put_byte(&ctx->pb, stream->lpcm_header[2]);
- } else if (id >= 0x40) {
- /* AC3 */
- put_byte(&ctx->pb, nb_frames);
- put_be16(&ctx->pb, trailer_size+1);
- }
- }
-
- /* output data */
- if(av_fifo_generic_read(&stream->fifo, payload_size - stuffing_size, &put_buffer, &ctx->pb) < 0)
- return -1;
- stream->bytes_to_iframe -= payload_size - stuffing_size;
- }else{
- payload_size=
- stuffing_size= 0;
- }
-
- if (pad_packet_bytes > 0)
- put_padding_packet(ctx,&ctx->pb, pad_packet_bytes);
-
- for(i=0;i<zero_trail_bytes;i++)
- put_byte(&ctx->pb, 0x00);
-
- put_flush_packet(&ctx->pb);
-
- s->packet_number++;
-
- /* only increase the stream packet number if this pack actually contains
- something that is specific to this stream! I.e. a dedicated header
- or some data.*/
- if (!general_pack)
- stream->packet_number++;
-
- return payload_size - stuffing_size;
-}
-
-static void put_vcd_padding_sector(AVFormatContext *ctx)
-{
- /* There are two ways to do this padding: writing a sector/pack
- of 0 values, or writing an MPEG padding pack. Both seem to
- work with most decoders, BUT the VCD standard only allows a 0-sector
- (see standard p. IV-4, IV-5).
- So a 0-sector it is...*/
-
- MpegMuxContext *s = ctx->priv_data;
- int i;
-
- for(i=0;i<s->packet_size;i++)
- put_byte(&ctx->pb, 0);
-
- s->vcd_padding_bytes_written += s->packet_size;
-
- put_flush_packet(&ctx->pb);
-
- /* increasing the packet number is correct. The SCR of the following packs
- is calculated from the packet_number and it has to include the padding
- sector (it represents the sector index, not the MPEG pack index)
- (see VCD standard p. IV-6)*/
- s->packet_number++;
-}
-
-#if 0 /* unused, remove? */
-static int64_t get_vcd_scr(AVFormatContext *ctx,int stream_index,int64_t pts)
-{
- MpegMuxContext *s = ctx->priv_data;
- int64_t scr;
-
- /* Since the data delivery rate is constant, SCR is computed
- using the formula C + i * 1200 where C is the start constant
- and i is the pack index.
- It is recommended that SCR 0 is at the beginning of the VCD front
- margin (a sequence of empty Form 2 sectors on the CD).
- It is recommended that the front margin is 30 sectors long, so
- we use C = 30*1200 = 36000
- (Note that even if the front margin is not 30 sectors the file
- will still be correct according to the standard. It just won't have
- the "recommended" value).*/
- scr = 36000 + s->packet_number * 1200;
-
- return scr;
-}
-#endif
-
-static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr){
-// MpegMuxContext *s = ctx->priv_data;
- int i;
-
- for(i=0; i<ctx->nb_streams; i++){
- AVStream *st = ctx->streams[i];
- StreamInfo *stream = st->priv_data;
- PacketDesc *pkt_desc= stream->predecode_packet;
-
- while(pkt_desc && scr > pkt_desc->dts){ //FIXME > vs >=
- if(stream->buffer_index < pkt_desc->size ||
- stream->predecode_packet == stream->premux_packet){
- av_log(ctx, AV_LOG_ERROR, "buffer underflow\n");
- break;
- }
- stream->buffer_index -= pkt_desc->size;
-
- stream->predecode_packet= pkt_desc->next;
- av_freep(&pkt_desc);
- }
- }
-
- return 0;
-}
-
-static int output_packet(AVFormatContext *ctx, int flush){
- MpegMuxContext *s = ctx->priv_data;
- AVStream *st;
- StreamInfo *stream;
- int i, avail_space, es_size, trailer_size;
- int best_i= -1;
- int best_score= INT_MIN;
- int ignore_constraints=0;
- int64_t scr= s->last_scr;
- PacketDesc *timestamp_packet;
- const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE);
-
-retry:
- for(i=0; i<ctx->nb_streams; i++){
- AVStream *st = ctx->streams[i];
- StreamInfo *stream = st->priv_data;
- const int avail_data= av_fifo_size(&stream->fifo);
- const int space= stream->max_buffer_size - stream->buffer_index;
- int rel_space= 1024*space / stream->max_buffer_size;
- PacketDesc *next_pkt= stream->premux_packet;
-
- /* for subtitle, a single PES packet must be generated,
- so we flush after every single subtitle packet */
- if(s->packet_size > avail_data && !flush
- && st->codec->codec_type != CODEC_TYPE_SUBTITLE)
- return 0;
- if(avail_data==0)
- continue;
- assert(avail_data>0);
-
- if(space < s->packet_size && !ignore_constraints)
- continue;
-
- if(next_pkt && next_pkt->dts - scr > max_delay)
- continue;
-
- if(rel_space > best_score){
- best_score= rel_space;
- best_i = i;
- avail_space= space;
- }
- }
-
- if(best_i < 0){
- int64_t best_dts= INT64_MAX;
-
- for(i=0; i<ctx->nb_streams; i++){
- AVStream *st = ctx->streams[i];
- StreamInfo *stream = st->priv_data;
- PacketDesc *pkt_desc= stream->predecode_packet;
- if(pkt_desc && pkt_desc->dts < best_dts)
- best_dts= pkt_desc->dts;
- }
-
-#if 0
- av_log(ctx, AV_LOG_DEBUG, "bumping scr, scr:%f, dts:%f\n",
- scr/90000.0, best_dts/90000.0);
-#endif
- if(best_dts == INT64_MAX)
- return 0;
-
- if(scr >= best_dts+1 && !ignore_constraints){
- av_log(ctx, AV_LOG_ERROR, "packet too large, ignoring buffer limits to mux it\n");
- ignore_constraints= 1;
- }
- scr= FFMAX(best_dts+1, scr);
- if(remove_decoded_packets(ctx, scr) < 0)
- return -1;
- goto retry;
- }
-
- assert(best_i >= 0);
-
- st = ctx->streams[best_i];
- stream = st->priv_data;
-
- assert(av_fifo_size(&stream->fifo) > 0);
-
- assert(avail_space >= s->packet_size || ignore_constraints);
-
- timestamp_packet= stream->premux_packet;
- if(timestamp_packet->unwritten_size == timestamp_packet->size){
- trailer_size= 0;
- }else{
- trailer_size= timestamp_packet->unwritten_size;
- timestamp_packet= timestamp_packet->next;
- }
-
- if(timestamp_packet){
-//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, scr/90000.0, best_i);
- es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size);
- }else{
- assert(av_fifo_size(&stream->fifo) == trailer_size);
- es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size);
- }
-
- if (s->is_vcd) {
- /* Write one or more padding sectors, if necessary, to reach
- the constant overall bitrate.*/
- int vcd_pad_bytes;
-
- while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->premux_packet->pts) ) >= s->packet_size){ //FIXME pts cannot be correct here
- put_vcd_padding_sector(ctx);
- s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
- }
- }
-
- stream->buffer_index += es_size;
- s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
-
- while(stream->premux_packet && stream->premux_packet->unwritten_size <= es_size){
- es_size -= stream->premux_packet->unwritten_size;
- stream->premux_packet= stream->premux_packet->next;
- }
- if(es_size)
- stream->premux_packet->unwritten_size -= es_size;
-
- if(remove_decoded_packets(ctx, s->last_scr) < 0)
- return -1;
-
- return 1;
-}
-
-static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
-{
- MpegMuxContext *s = ctx->priv_data;
- int stream_index= pkt->stream_index;
- int size= pkt->size;
- uint8_t *buf= pkt->data;
- AVStream *st = ctx->streams[stream_index];
- StreamInfo *stream = st->priv_data;
- int64_t pts, dts;
- PacketDesc *pkt_desc;
- const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
- const int is_iframe = st->codec->codec_type == CODEC_TYPE_VIDEO && (pkt->flags & PKT_FLAG_KEY);
-
- pts= pkt->pts;
- dts= pkt->dts;
-
- if(pts != AV_NOPTS_VALUE) pts += preload;
- if(dts != AV_NOPTS_VALUE) dts += preload;
-
-//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
- if (!stream->premux_packet)
- stream->next_packet = &stream->premux_packet;
- *stream->next_packet=
- pkt_desc= av_mallocz(sizeof(PacketDesc));
- pkt_desc->pts= pts;
- pkt_desc->dts= dts;
- pkt_desc->unwritten_size=
- pkt_desc->size= size;
- if(!stream->predecode_packet)
- stream->predecode_packet= pkt_desc;
- stream->next_packet= &pkt_desc->next;
-
- av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size + 1);
-
- if (s->is_dvd){
- if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
- stream->bytes_to_iframe = av_fifo_size(&stream->fifo);
- stream->align_iframe = 1;
- stream->vobu_start_pts = pts;
- } else {
- stream->align_iframe = 0;
- }
- }
-
- av_fifo_write(&stream->fifo, buf, size);
-
- for(;;){
- int ret= output_packet(ctx, 0);
- if(ret<=0)
- return ret;
- }
-}
-
-static int mpeg_mux_end(AVFormatContext *ctx)
-{
-// MpegMuxContext *s = ctx->priv_data;
- StreamInfo *stream;
- int i;
-
- for(;;){
- int ret= output_packet(ctx, 1);
- if(ret<0)
- return ret;
- else if(ret==0)
- break;
- }
-
- /* End header according to MPEG1 systems standard. We do not write
- it as it is usually not needed by decoders and because it
- complicates MPEG stream concatenation. */
- //put_be32(&ctx->pb, ISO_11172_END_CODE);
- //put_flush_packet(&ctx->pb);
-
- for(i=0;i<ctx->nb_streams;i++) {
- stream = ctx->streams[i]->priv_data;
-
- assert(av_fifo_size(&stream->fifo) == 0);
- av_fifo_free(&stream->fifo);
- }
- return 0;
-}
-#endif //CONFIG_MUXERS
-
/*********************************************/
/* demux code */
#define MAX_SYNC_SIZE 100000
-static int cdxa_probe(AVProbeData *p)
-{
- /* check file header */
- if (p->buf_size <= 32)
- return 0;
- if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
- p->buf[2] == 'F' && p->buf[3] == 'F' &&
- p->buf[8] == 'C' && p->buf[9] == 'D' &&
- p->buf[10] == 'X' && p->buf[11] == 'A')
- return AVPROBE_SCORE_MAX;
- else
- return 0;
+static int check_pes(uint8_t *p, 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;
+ p+=5;
+ }else if((*p&0xF0) == 0x30){
+ pes1= p[0]&p[2]&p[4]&p[5]&p[7]&p[9]&1;
+ p+=10;
+ }else
+ pes1 = *p == 0x0F;
+
+ return pes1||pes2;
}
static int mpegps_probe(AVProbeData *p)
{
uint32_t code= -1;
- int sys=0, pspack=0, priv1=0, vid=0, audio=0;
+ int sys=0, pspack=0, priv1=0, vid=0, audio=0, invalid=0;
int i;
int score=0;
- score = cdxa_probe(p);
- if (score > 0) return score;
-
- /* Search for MPEG stream */
for(i=0; i<p->buf_size; i++){
code = (code<<8) + p->buf[i];
if ((code & 0xffffff00) == 0x100) {
+ int pes= check_pes(p->buf+i, p->buf+p->buf_size);
+
if(code == SYSTEM_HEADER_START_CODE) sys++;
else if(code == PRIVATE_STREAM_1) priv1++;
else if(code == PACK_START_CODE) pspack++;
- else if((code & 0xf0) == VIDEO_ID) vid++;
- else if((code & 0xe0) == AUDIO_ID) audio++;
+ else if((code & 0xf0) == VIDEO_ID && pes) vid++;
+ else if((code & 0xe0) == AUDIO_ID && pes) audio++;
+
+ else if((code & 0xf0) == VIDEO_ID && !pes) invalid++;
+ else if((code & 0xe0) == AUDIO_ID && !pes) invalid++;
}
}
- if(vid || audio) /* invalid VDR files nd short PES streams */
+ if(vid+audio > invalid) /* invalid VDR files nd short PES streams */
score= AVPROBE_SCORE_MAX/4;
-//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d\n", sys, priv1, pspack,vid, audio);
- if(sys && sys*9 <= pspack*10)
+//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d len:%d\n", sys, priv1, pspack,vid, audio, p->buf_size);
+ if(sys>invalid && sys*9 <= pspack*10)
return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
- if((priv1 || vid || audio) && (priv1+vid+audio)*9 <= pspack*10)
+ if(priv1 + vid + audio > invalid && (priv1+vid+audio)*9 <= pspack*10)
return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
- if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack) /* PES stream */
+ if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack && p->buf_size>2048) /* PES stream */
return AVPROBE_SCORE_MAX/2+2;
//02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
@@ -1312,32 +94,38 @@ static int mpegps_probe(AVProbeData *p)
typedef struct MpegDemuxContext {
int32_t header_state;
unsigned char psm_es_type[256];
+ int sofdec;
} MpegDemuxContext;
static int mpegps_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
MpegDemuxContext *m = s->priv_data;
+ const char *sofdec = "Sofdec";
+ int v, i = 0;
+
m->header_state = 0xff;
s->ctx_flags |= AVFMTCTX_NOHEADER;
+ m->sofdec = -1;
+ do {
+ v = get_byte(s->pb);
+ m->header_state = m->header_state << 8 | v;
+ m->sofdec++;
+ } while (v == sofdec[i] && i++ < 6);
+
/* no need to do more */
return 0;
}
static int64_t get_pts(ByteIOContext *pb, int c)
{
- int64_t pts;
- int val;
+ uint8_t buf[5];
+
+ buf[0] = c<0 ? get_byte(pb) : c;
+ get_buffer(pb, buf+1, 4);
- if (c < 0)
- c = get_byte(pb);
- pts = (int64_t)((c >> 1) & 0x07) << 30;
- val = get_be16(pb);
- pts |= (int64_t)(val >> 1) << 15;
- val = get_be16(pb);
- pts |= (int64_t)(val >> 1);
- return pts;
+ return ff_parse_pes_pts(buf);
}
static int find_next_start_code(ByteIOContext *pb, int *size_ptr,
@@ -1447,32 +235,46 @@ 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= url_ftell(&s->pb);
+ int64_t last_sync= url_ftell(s->pb);
error_redo:
- url_fseek(&s->pb, last_sync, SEEK_SET);
+ url_fseek(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 = url_ftell(&s->pb);
- //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(&s->pb));
+ startcode = find_next_start_code(s->pb, &size, &m->header_state);
+ last_sync = url_ftell(s->pb);
+ //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(s->pb));
if (startcode < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (startcode == PACK_START_CODE)
goto redo;
if (startcode == SYSTEM_HEADER_START_CODE)
goto redo;
- if (startcode == PADDING_STREAM ||
- startcode == PRIVATE_STREAM_2) {
- /* skip them */
- len = get_be16(&s->pb);
- url_fskip(&s->pb, len);
+ if (startcode == PADDING_STREAM) {
+ url_fskip(s->pb, get_be16(s->pb));
+ goto redo;
+ }
+ if (startcode == PRIVATE_STREAM_2) {
+ len = get_be16(s->pb);
+ if (!m->sofdec) {
+ while (len-- >= 6) {
+ if (get_byte(s->pb) == 'S') {
+ uint8_t buf[5];
+ get_buffer(s->pb, buf, sizeof(buf));
+ m->sofdec = !memcmp(buf, "ofdec", 5);
+ len -= sizeof(buf);
+ break;
+ }
+ }
+ m->sofdec -= !m->sofdec;
+ }
+ url_fskip(s->pb, len);
goto redo;
}
if (startcode == PROGRAM_STREAM_MAP) {
- mpegps_psm_parse(m, &s->pb);
+ mpegps_psm_parse(m, s->pb);
goto redo;
}
@@ -1482,16 +284,16 @@ static int mpegps_read_pes_header(AVFormatContext *s,
(startcode == 0x1bd) || (startcode == 0x1fd)))
goto redo;
if (ppos) {
- *ppos = url_ftell(&s->pb) - 4;
+ *ppos = url_ftell(s->pb) - 4;
}
- len = get_be16(&s->pb);
+ len = get_be16(s->pb);
pts =
dts = AV_NOPTS_VALUE;
/* stuffing */
for(;;) {
if (len < 1)
goto error_redo;
- c = get_byte(&s->pb);
+ c = get_byte(s->pb);
len--;
/* XXX: for mpeg1, should test only bit 7 */
if (c != 0xff)
@@ -1499,15 +301,15 @@ static int mpegps_read_pes_header(AVFormatContext *s,
}
if ((c & 0xc0) == 0x40) {
/* buffer scale & size */
- get_byte(&s->pb);
- c = get_byte(&s->pb);
+ get_byte(s->pb);
+ c = get_byte(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);
+ dts = get_pts(s->pb, -1);
len -= 5;
}
} else if ((c & 0xc0) == 0x80) {
@@ -1518,22 +320,22 @@ static int mpegps_read_pes_header(AVFormatContext *s,
goto redo;
}
#endif
- flags = get_byte(&s->pb);
- header_len = get_byte(&s->pb);
+ flags = get_byte(s->pb);
+ header_len = get_byte(s->pb);
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 & 0x01) { /* PES extension */
- pes_ext = get_byte(&s->pb);
+ pes_ext = get_byte(s->pb);
header_len--;
if (pes_ext & 0x40) { /* pack header - should be zero in PS */
goto error_redo;
@@ -1541,14 +343,14 @@ static int mpegps_read_pes_header(AVFormatContext *s,
/* Skip PES private data, program packet sequence counter and P-STD buffer */
skip = (pes_ext >> 4) & 0xb;
skip += skip & 0x9;
- url_fskip(&s->pb, skip);
+ url_fskip(s->pb, skip);
header_len -= skip;
if (pes_ext & 0x01) { /* PES extension 2 */
- ext2_len = get_byte(&s->pb);
+ ext2_len = get_byte(s->pb);
header_len--;
if ((ext2_len & 0x7f) > 0) {
- id_ext = get_byte(&s->pb);
+ id_ext = get_byte(s->pb);
if ((id_ext & 0x80) == 0)
startcode = ((startcode & 0xff) << 8) | id_ext;
header_len--;
@@ -1557,23 +359,23 @@ static int mpegps_read_pes_header(AVFormatContext *s,
}
if(header_len < 0)
goto error_redo;
- url_fskip(&s->pb, header_len);
+ url_fskip(s->pb, header_len);
}
else if( c!= 0xf )
goto redo;
if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) {
- startcode = get_byte(&s->pb);
+ startcode = get_byte(s->pb);
len--;
if (startcode >= 0x80 && startcode <= 0xcf) {
/* audio: skip header */
- get_byte(&s->pb);
- get_byte(&s->pb);
- get_byte(&s->pb);
+ get_byte(s->pb);
+ get_byte(s->pb);
+ get_byte(s->pb);
len -= 3;
if (startcode >= 0xb0 && startcode <= 0xbf) {
/* MLP/TrueHD audio has a 4-byte header */
- get_byte(&s->pb);
+ get_byte(s->pb);
len--;
}
}
@@ -1583,7 +385,9 @@ static int mpegps_read_pes_header(AVFormatContext *s,
if(dts != AV_NOPTS_VALUE && ppos){
int i;
for(i=0; i<s->nb_streams; i++){
- if(startcode == s->streams[i]->id) {
+ if(startcode == s->streams[i]->id &&
+ !url_is_streamed(s->pb) /* 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? */);
}
}
@@ -1645,8 +449,8 @@ static int mpegps_read_packet(AVFormatContext *s,
} else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 };
unsigned char buf[8];
- get_buffer(&s->pb, buf, 8);
- url_fseek(&s->pb, -8, SEEK_CUR);
+ get_buffer(s->pb, buf, 8);
+ url_fseek(s->pb, -8, SEEK_CUR);
if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
codec_id = CODEC_ID_CAVS;
else
@@ -1654,7 +458,7 @@ static int mpegps_read_packet(AVFormatContext *s,
type = CODEC_TYPE_VIDEO;
} else if (startcode >= 0x1c0 && startcode <= 0x1df) {
type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_MP2;
+ codec_id = m->sofdec > 0 ? CODEC_ID_ADPCM_ADX : CODEC_ID_MP2;
} else if (startcode >= 0x80 && startcode <= 0x87) {
type = CODEC_TYPE_AUDIO;
codec_id = CODEC_ID_AC3;
@@ -1682,7 +486,7 @@ static int mpegps_read_packet(AVFormatContext *s,
} else {
skip:
/* skip packet */
- url_fskip(&s->pb, len);
+ url_fskip(s->pb, len);
goto redo;
}
/* no stream found: add a new stream */
@@ -1692,7 +496,7 @@ static int mpegps_read_packet(AVFormatContext *s,
st->codec->codec_type = type;
st->codec->codec_id = codec_id;
if (codec_id != CODEC_ID_PCM_S16BE)
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
found:
if(st->discard >= AVDISCARD_ALL)
goto skip;
@@ -1703,9 +507,9 @@ static int mpegps_read_packet(AVFormatContext *s,
audio data */
if (len <= 3)
goto skip;
- get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */
- b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */
- get_byte(&s->pb); /* dynamic range control (0x80 = off) */
+ get_byte(s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */
+ b1 = get_byte(s->pb); /* quant (2), freq(2), reserved(1), channels(3) */
+ get_byte(s->pb); /* dynamic range control (0x80 = off) */
len -= 3;
freq = (b1 >> 4) & 3;
st->codec->sample_rate = lpcm_freq_tab[freq];
@@ -1713,7 +517,7 @@ static int mpegps_read_packet(AVFormatContext *s,
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2;
}
av_new_packet(pkt, len);
- get_buffer(&s->pb, pkt->data, pkt->size);
+ get_buffer(s->pb, pkt->data, pkt->size);
pkt->pts = pts;
pkt->dts = dts;
pkt->stream_index = st->index;
@@ -1740,7 +544,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
#ifdef DEBUG_SEEK
printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next);
#endif
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
for(;;) {
len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts);
if (len < 0) {
@@ -1753,7 +557,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
dts != AV_NOPTS_VALUE) {
break;
}
- url_fskip(&s->pb, len);
+ url_fskip(s->pb, len);
}
#ifdef DEBUG_SEEK
printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0);
@@ -1762,82 +566,6 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
return dts;
}
-#ifdef CONFIG_MPEG1SYSTEM_MUXER
-AVOutputFormat mpeg1system_muxer = {
- "mpeg",
- "MPEG1 System format",
- "video/mpeg",
- "mpg,mpeg",
- sizeof(MpegMuxContext),
- CODEC_ID_MP2,
- CODEC_ID_MPEG1VIDEO,
- mpeg_mux_init,
- mpeg_mux_write_packet,
- mpeg_mux_end,
-};
-#endif
-#ifdef CONFIG_MPEG1VCD_MUXER
-AVOutputFormat mpeg1vcd_muxer = {
- "vcd",
- "MPEG1 System format (VCD)",
- "video/mpeg",
- NULL,
- sizeof(MpegMuxContext),
- CODEC_ID_MP2,
- CODEC_ID_MPEG1VIDEO,
- mpeg_mux_init,
- mpeg_mux_write_packet,
- mpeg_mux_end,
-};
-#endif
-#ifdef CONFIG_MPEG2VOB_MUXER
-AVOutputFormat mpeg2vob_muxer = {
- "vob",
- "MPEG2 PS format (VOB)",
- "video/mpeg",
- "vob",
- sizeof(MpegMuxContext),
- CODEC_ID_MP2,
- CODEC_ID_MPEG2VIDEO,
- mpeg_mux_init,
- mpeg_mux_write_packet,
- mpeg_mux_end,
-};
-#endif
-
-/* Same as mpeg2vob_mux except that the pack size is 2324 */
-#ifdef CONFIG_MPEG2SVCD_MUXER
-AVOutputFormat mpeg2svcd_muxer = {
- "svcd",
- "MPEG2 PS format (VOB)",
- "video/mpeg",
- "vob",
- sizeof(MpegMuxContext),
- CODEC_ID_MP2,
- CODEC_ID_MPEG2VIDEO,
- mpeg_mux_init,
- mpeg_mux_write_packet,
- mpeg_mux_end,
-};
-#endif
-
-/* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */
-#ifdef CONFIG_MPEG2DVD_MUXER
-AVOutputFormat mpeg2dvd_muxer = {
- "dvd",
- "MPEG2 PS format (DVD VOB)",
- "video/mpeg",
- "dvd",
- sizeof(MpegMuxContext),
- CODEC_ID_MP2,
- CODEC_ID_MPEG2VIDEO,
- mpeg_mux_init,
- mpeg_mux_write_packet,
- mpeg_mux_end,
-};
-#endif
-
-#ifdef CONFIG_MPEGPS_DEMUXER
AVInputFormat mpegps_demuxer = {
"mpeg",
"MPEG PS format",
@@ -1850,4 +578,3 @@ AVInputFormat mpegps_demuxer = {
mpegps_read_dts,
.flags = AVFMT_SHOW_IDS,
};
-#endif
diff --git a/contrib/ffmpeg/libavformat/mpeg.h b/contrib/ffmpeg/libavformat/mpeg.h
new file mode 100644
index 000000000..9283101d1
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpeg.h
@@ -0,0 +1,69 @@
+/*
+ * MPEG1/2 muxer and demuxer common defines
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
+ *
+ * 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 FFMPEG_MPEG_H
+#define FFMPEG_MPEG_H
+
+#define PACK_START_CODE ((unsigned int)0x000001ba)
+#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
+#define SEQUENCE_END_CODE ((unsigned int)0x000001b7)
+#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
+#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
+#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
+
+/* mpeg2 */
+#define PROGRAM_STREAM_MAP 0x1bc
+#define PRIVATE_STREAM_1 0x1bd
+#define PADDING_STREAM 0x1be
+#define PRIVATE_STREAM_2 0x1bf
+
+#define AUDIO_ID 0xc0
+#define VIDEO_ID 0xe0
+#define AC3_ID 0x80
+#define DTS_ID 0x8a
+#define LPCM_ID 0xa0
+#define SUB_ID 0x20
+
+#define STREAM_TYPE_VIDEO_MPEG1 0x01
+#define STREAM_TYPE_VIDEO_MPEG2 0x02
+#define STREAM_TYPE_AUDIO_MPEG1 0x03
+#define STREAM_TYPE_AUDIO_MPEG2 0x04
+#define STREAM_TYPE_PRIVATE_SECTION 0x05
+#define STREAM_TYPE_PRIVATE_DATA 0x06
+#define STREAM_TYPE_AUDIO_AAC 0x0f
+#define STREAM_TYPE_VIDEO_MPEG4 0x10
+#define STREAM_TYPE_VIDEO_H264 0x1b
+
+#define STREAM_TYPE_AUDIO_AC3 0x81
+#define STREAM_TYPE_AUDIO_DTS 0x8a
+
+static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };
+
+/**
+ * Parse MPEG-PES five-byte timestamp
+ */
+static inline int64_t ff_parse_pes_pts(uint8_t *buf) {
+ return (int64_t)(*buf & 0x0e) << 29 |
+ (AV_RB16(buf+1) >> 1) << 15 |
+ AV_RB16(buf+3) >> 1;
+}
+
+#endif /* FFMPEG_MPEG_H */
diff --git a/contrib/ffmpeg/libavformat/mpegenc.c b/contrib/ffmpeg/libavformat/mpegenc.c
new file mode 100644
index 000000000..0558226b8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpegenc.c
@@ -0,0 +1,1294 @@
+/*
+ * MPEG1/2 muxer
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "bitstream.h"
+#include "fifo.h"
+#include "mpeg.h"
+
+#define MAX_PAYLOAD_SIZE 4096
+//#define DEBUG_SEEK
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct PacketDesc {
+ int64_t pts;
+ int64_t dts;
+ int size;
+ int unwritten_size;
+ int flags;
+ struct PacketDesc *next;
+} PacketDesc;
+
+typedef struct {
+ AVFifoBuffer fifo;
+ uint8_t id;
+ int max_buffer_size; /* in bytes */
+ int buffer_index;
+ PacketDesc *predecode_packet;
+ PacketDesc *premux_packet;
+ PacketDesc **next_packet;
+ int packet_number;
+ uint8_t lpcm_header[3];
+ int lpcm_align;
+ int bytes_to_iframe;
+ int align_iframe;
+ int64_t vobu_start_pts;
+} StreamInfo;
+
+typedef struct {
+ int packet_size; /* required packet size */
+ int packet_number;
+ int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */
+ int system_header_freq;
+ int system_header_size;
+ int mux_rate; /* bitrate in units of 50 bytes/s */
+ /* stream info */
+ int audio_bound;
+ int video_bound;
+ int is_mpeg2;
+ int is_vcd;
+ int is_svcd;
+ int is_dvd;
+ int64_t last_scr; /* current system clock */
+
+ double vcd_padding_bitrate; //FIXME floats
+ int64_t vcd_padding_bytes_written;
+
+} MpegMuxContext;
+
+extern AVOutputFormat mpeg1vcd_muxer;
+extern AVOutputFormat mpeg2dvd_muxer;
+extern AVOutputFormat mpeg2svcd_muxer;
+extern AVOutputFormat mpeg2vob_muxer;
+
+static int put_pack_header(AVFormatContext *ctx,
+ uint8_t *buf, int64_t timestamp)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128);
+
+ put_bits(&pb, 32, PACK_START_CODE);
+ if (s->is_mpeg2) {
+ put_bits(&pb, 2, 0x1);
+ } else {
+ put_bits(&pb, 4, 0x2);
+ }
+ put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07));
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff));
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff));
+ put_bits(&pb, 1, 1);
+ if (s->is_mpeg2) {
+ /* clock extension */
+ put_bits(&pb, 9, 0);
+ }
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 22, s->mux_rate);
+ put_bits(&pb, 1, 1);
+ if (s->is_mpeg2) {
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 5, 0x1f); /* reserved */
+ put_bits(&pb, 3, 0); /* stuffing length */
+ }
+ flush_put_bits(&pb);
+ return pbBufPtr(&pb) - pb.buf;
+}
+
+static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_stream_id)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int size, i, private_stream_coded, id;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128);
+
+ put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
+ put_bits(&pb, 16, 0);
+ put_bits(&pb, 1, 1);
+
+ put_bits(&pb, 22, s->mux_rate); /* maximum bit rate of the multiplexed stream */
+ put_bits(&pb, 1, 1); /* marker */
+ if (s->is_vcd && only_for_stream_id==VIDEO_ID) {
+ /* This header applies only to the video stream (see VCD standard p. IV-7)*/
+ put_bits(&pb, 6, 0);
+ } else
+ put_bits(&pb, 6, s->audio_bound);
+
+ if (s->is_vcd) {
+ /* see VCD standard, p. IV-7*/
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 1, 1);
+ } else {
+ put_bits(&pb, 1, 0); /* variable bitrate*/
+ put_bits(&pb, 1, 0); /* non constrainted bit stream */
+ }
+
+ if (s->is_vcd || s->is_dvd) {
+ /* see VCD standard p IV-7 */
+ put_bits(&pb, 1, 1); /* audio locked */
+ put_bits(&pb, 1, 1); /* video locked */
+ } else {
+ put_bits(&pb, 1, 0); /* audio locked */
+ put_bits(&pb, 1, 0); /* video locked */
+ }
+
+ put_bits(&pb, 1, 1); /* marker */
+
+ if (s->is_vcd && only_for_stream_id==AUDIO_ID) {
+ /* This header applies only to the audio stream (see VCD standard p. IV-7)*/
+ put_bits(&pb, 5, 0);
+ } else
+ put_bits(&pb, 5, s->video_bound);
+
+ if (s->is_dvd) {
+ put_bits(&pb, 1, 0); /* packet_rate_restriction_flag */
+ put_bits(&pb, 7, 0x7f); /* reserved byte */
+ } else
+ put_bits(&pb, 8, 0xff); /* reserved byte */
+
+ /* DVD-Video Stream_bound entries
+ id (0xB9) video, maximum P-STD for stream 0xE0. (P-STD_buffer_bound_scale = 1)
+ id (0xB8) audio, maximum P-STD for any MPEG audio (0xC0 to 0xC7) streams. If there are none set to 4096 (32x128). (P-STD_buffer_bound_scale = 0)
+ id (0xBD) private stream 1 (audio other than MPEG and subpictures). (P-STD_buffer_bound_scale = 1)
+ id (0xBF) private stream 2, NAV packs, set to 2x1024. */
+ if (s->is_dvd) {
+
+ int P_STD_max_video = 0;
+ int P_STD_max_mpeg_audio = 0;
+ int P_STD_max_mpeg_PS1 = 0;
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+
+ id = stream->id;
+ if (id == 0xbd && stream->max_buffer_size > P_STD_max_mpeg_PS1) {
+ P_STD_max_mpeg_PS1 = stream->max_buffer_size;
+ } else if (id >= 0xc0 && id <= 0xc7 && stream->max_buffer_size > P_STD_max_mpeg_audio) {
+ P_STD_max_mpeg_audio = stream->max_buffer_size;
+ } else if (id == 0xe0 && stream->max_buffer_size > P_STD_max_video) {
+ P_STD_max_video = stream->max_buffer_size;
+ }
+ }
+
+ /* video */
+ put_bits(&pb, 8, 0xb9); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, P_STD_max_video / 1024);
+
+ /* audio */
+ if (P_STD_max_mpeg_audio == 0)
+ P_STD_max_mpeg_audio = 4096;
+ put_bits(&pb, 8, 0xb8); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, P_STD_max_mpeg_audio / 128);
+
+ /* private stream 1 */
+ put_bits(&pb, 8, 0xbd); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, P_STD_max_mpeg_PS1 / 128);
+
+ /* private stream 2 */
+ put_bits(&pb, 8, 0xbf); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, 2);
+ }
+ else {
+ /* audio stream info */
+ private_stream_coded = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+
+
+ /* For VCDs, only include the stream info for the stream
+ that the pack which contains this system belongs to.
+ (see VCD standard p. IV-7) */
+ if ( !s->is_vcd || stream->id==only_for_stream_id
+ || only_for_stream_id==0) {
+
+ id = stream->id;
+ if (id < 0xc0) {
+ /* special case for private streams (AC3 use that) */
+ if (private_stream_coded)
+ continue;
+ private_stream_coded = 1;
+ id = 0xbd;
+ }
+ put_bits(&pb, 8, id); /* stream ID */
+ put_bits(&pb, 2, 3);
+ if (id < 0xe0) {
+ /* audio */
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, stream->max_buffer_size / 128);
+ } else {
+ /* video */
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, stream->max_buffer_size / 1024);
+ }
+ }
+ }
+ }
+
+ flush_put_bits(&pb);
+ size = pbBufPtr(&pb) - pb.buf;
+ /* patch packet size */
+ buf[4] = (size - 6) >> 8;
+ buf[5] = (size - 6) & 0xff;
+
+ return size;
+}
+
+static int get_system_header_size(AVFormatContext *ctx)
+{
+ int buf_index, i, private_stream_coded;
+ StreamInfo *stream;
+ MpegMuxContext *s = ctx->priv_data;
+
+ if (s->is_dvd)
+ return 18; // DVD-Video system headers are 18 bytes fixed length.
+
+ buf_index = 12;
+ private_stream_coded = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ if (stream->id < 0xc0) {
+ if (private_stream_coded)
+ continue;
+ private_stream_coded = 1;
+ }
+ buf_index += 3;
+ }
+ return buf_index;
+}
+
+static int mpeg_mux_init(AVFormatContext *ctx)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int bitrate, i, mpa_id, mpv_id, mps_id, ac3_id, dts_id, lpcm_id, j;
+ AVStream *st;
+ StreamInfo *stream;
+ int audio_bitrate;
+ int video_bitrate;
+
+ s->packet_number = 0;
+ s->is_vcd = (ENABLE_MPEG1VCD_MUXER && ctx->oformat == &mpeg1vcd_muxer);
+ s->is_svcd = (ENABLE_MPEG2SVCD_MUXER && ctx->oformat == &mpeg2svcd_muxer);
+ s->is_mpeg2 = ((ENABLE_MPEG2VOB_MUXER && ctx->oformat == &mpeg2vob_muxer) ||
+ (ENABLE_MPEG2DVD_MUXER && ctx->oformat == &mpeg2dvd_muxer) ||
+ (ENABLE_MPEG2SVCD_MUXER && ctx->oformat == &mpeg2svcd_muxer));
+ s->is_dvd = (ENABLE_MPEG2DVD_MUXER && ctx->oformat == &mpeg2dvd_muxer);
+
+ if(ctx->packet_size)
+ s->packet_size = ctx->packet_size;
+ else
+ s->packet_size = 2048;
+
+ s->vcd_padding_bytes_written = 0;
+ s->vcd_padding_bitrate=0;
+
+ s->audio_bound = 0;
+ s->video_bound = 0;
+ mpa_id = AUDIO_ID;
+ ac3_id = AC3_ID;
+ dts_id = DTS_ID;
+ mpv_id = VIDEO_ID;
+ mps_id = SUB_ID;
+ lpcm_id = LPCM_ID;
+ for(i=0;i<ctx->nb_streams;i++) {
+ st = ctx->streams[i];
+ stream = av_mallocz(sizeof(StreamInfo));
+ if (!stream)
+ goto fail;
+ st->priv_data = stream;
+
+ av_set_pts_info(st, 64, 1, 90000);
+
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (st->codec->codec_id == CODEC_ID_AC3) {
+ stream->id = ac3_id++;
+ } else if (st->codec->codec_id == CODEC_ID_DTS) {
+ stream->id = dts_id++;
+ } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) {
+ stream->id = lpcm_id++;
+ for(j = 0; j < 4; j++) {
+ if (lpcm_freq_tab[j] == st->codec->sample_rate)
+ break;
+ }
+ if (j == 4)
+ goto fail;
+ if (st->codec->channels > 8)
+ return -1;
+ stream->lpcm_header[0] = 0x0c;
+ stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
+ stream->lpcm_header[2] = 0x80;
+ stream->lpcm_align = st->codec->channels * 2;
+ } else {
+ stream->id = mpa_id++;
+ }
+
+ /* This value HAS to be used for VCD (see VCD standard, p. IV-7).
+ Right now it is also used for everything else.*/
+ stream->max_buffer_size = 4 * 1024;
+ s->audio_bound++;
+ break;
+ case CODEC_TYPE_VIDEO:
+ stream->id = mpv_id++;
+ if (st->codec->rc_buffer_size)
+ stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8;
+ else
+ stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default
+#if 0
+ /* see VCD standard, p. IV-7*/
+ stream->max_buffer_size = 46 * 1024;
+ else
+ /* This value HAS to be used for SVCD (see SVCD standard, p. 26 V.2.3.2).
+ Right now it is also used for everything else.*/
+ stream->max_buffer_size = 230 * 1024;
+#endif
+ s->video_bound++;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ stream->id = mps_id++;
+ stream->max_buffer_size = 16 * 1024;
+ break;
+ default:
+ return -1;
+ }
+ av_fifo_init(&stream->fifo, 16);
+ }
+ bitrate = 0;
+ audio_bitrate = 0;
+ video_bitrate = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ int codec_rate;
+ st = ctx->streams[i];
+ stream = (StreamInfo*) st->priv_data;
+
+ if(st->codec->rc_max_rate || stream->id==VIDEO_ID)
+ codec_rate= st->codec->rc_max_rate;
+ else
+ codec_rate= st->codec->bit_rate;
+
+ if(!codec_rate)
+ codec_rate= (1<<21)*8*50/ctx->nb_streams;
+
+ bitrate += codec_rate;
+
+ if (stream->id==AUDIO_ID)
+ audio_bitrate += codec_rate;
+ else if (stream->id==VIDEO_ID)
+ video_bitrate += codec_rate;
+ }
+
+ if(ctx->mux_rate){
+ s->mux_rate= (ctx->mux_rate + (8 * 50) - 1) / (8 * 50);
+ } else {
+ /* we increase slightly the bitrate to take into account the
+ headers. XXX: compute it exactly */
+ bitrate += bitrate*5/100;
+ bitrate += 10000;
+ s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
+ }
+
+ if (s->is_vcd) {
+ double overhead_rate;
+
+ /* The VCD standard mandates that the mux_rate field is 3528
+ (see standard p. IV-6).
+ The value is actually "wrong", i.e. if you calculate
+ it using the normal formula and the 75 sectors per second transfer
+ rate you get a different value because the real pack size is 2324,
+ not 2352. But the standard explicitly specifies that the mux_rate
+ field in the header must have this value.*/
+// s->mux_rate=2352 * 75 / 50; /* = 3528*/
+
+ /* The VCD standard states that the muxed stream must be
+ exactly 75 packs / second (the data rate of a single speed cdrom).
+ Since the video bitrate (probably 1150000 bits/sec) will be below
+ the theoretical maximum we have to add some padding packets
+ to make up for the lower data rate.
+ (cf. VCD standard p. IV-6 )*/
+
+ /* Add the header overhead to the data rate.
+ 2279 data bytes per audio pack, 2294 data bytes per video pack*/
+ overhead_rate = ((audio_bitrate / 8.0) / 2279) * (2324 - 2279);
+ overhead_rate += ((video_bitrate / 8.0) / 2294) * (2324 - 2294);
+ overhead_rate *= 8;
+
+ /* Add padding so that the full bitrate is 2324*75 bytes/sec */
+ s->vcd_padding_bitrate = 2324 * 75 * 8 - (bitrate + overhead_rate);
+ }
+
+ if (s->is_vcd || s->is_mpeg2)
+ /* every packet */
+ s->pack_header_freq = 1;
+ else
+ /* every 2 seconds */
+ s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
+
+ /* the above seems to make pack_header_freq zero sometimes */
+ if (s->pack_header_freq == 0)
+ s->pack_header_freq = 1;
+
+ if (s->is_mpeg2)
+ /* every 200 packets. Need to look at the spec. */
+ s->system_header_freq = s->pack_header_freq * 40;
+ else if (s->is_vcd)
+ /* the standard mandates that there are only two system headers
+ in the whole file: one in the first packet of each stream.
+ (see standard p. IV-7 and IV-8) */
+ s->system_header_freq = 0x7fffffff;
+ else
+ s->system_header_freq = s->pack_header_freq * 5;
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ stream->packet_number = 0;
+ }
+ s->system_header_size = get_system_header_size(ctx);
+ s->last_scr = 0;
+ return 0;
+ fail:
+ for(i=0;i<ctx->nb_streams;i++) {
+ av_free(ctx->streams[i]->priv_data);
+ }
+ return AVERROR(ENOMEM);
+}
+
+static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp)
+{
+ put_byte(pb,
+ (id << 4) |
+ (((timestamp >> 30) & 0x07) << 1) |
+ 1);
+ put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1));
+ put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));
+}
+
+
+/* return the number of padding bytes that should be inserted into
+ the multiplexed stream.*/
+static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int pad_bytes = 0;
+
+ if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE)
+ {
+ int64_t full_pad_bytes;
+
+ full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); //FIXME this is wrong
+ pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written);
+
+ if (pad_bytes<0)
+ /* might happen if we have already padded to a later timestamp. This
+ can occur if another stream has already advanced further.*/
+ pad_bytes=0;
+ }
+
+ return pad_bytes;
+}
+
+
+#if 0 /* unused, remove? */
+/* return the exact available payload size for the next packet for
+ stream 'stream_index'. 'pts' and 'dts' are only used to know if
+ timestamps are needed in the packet header. */
+static int get_packet_payload_size(AVFormatContext *ctx, int stream_index,
+ int64_t pts, int64_t dts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int buf_index;
+ StreamInfo *stream;
+
+ stream = ctx->streams[stream_index]->priv_data;
+
+ buf_index = 0;
+ if (((s->packet_number % s->pack_header_freq) == 0)) {
+ /* pack header size */
+ if (s->is_mpeg2)
+ buf_index += 14;
+ else
+ buf_index += 12;
+
+ if (s->is_vcd) {
+ /* there is exactly one system header for each stream in a VCD MPEG,
+ One in the very first video packet and one in the very first
+ audio packet (see VCD standard p. IV-7 and IV-8).*/
+
+ if (stream->packet_number==0)
+ /* The system headers refer only to the stream they occur in,
+ so they have a constant size.*/
+ buf_index += 15;
+
+ } else {
+ if ((s->packet_number % s->system_header_freq) == 0)
+ buf_index += s->system_header_size;
+ }
+ }
+
+ if ((s->is_vcd && stream->packet_number==0)
+ || (s->is_svcd && s->packet_number==0))
+ /* the first pack of each stream contains only the pack header,
+ the system header and some padding (see VCD standard p. IV-6)
+ Add the padding size, so that the actual payload becomes 0.*/
+ buf_index += s->packet_size - buf_index;
+ else {
+ /* packet header size */
+ buf_index += 6;
+ if (s->is_mpeg2) {
+ buf_index += 3;
+ if (stream->packet_number==0)
+ buf_index += 3; /* PES extension */
+ buf_index += 1; /* obligatory stuffing byte */
+ }
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ buf_index += 5 + 5;
+ else
+ buf_index += 5;
+
+ } else {
+ if (!s->is_mpeg2)
+ buf_index++;
+ }
+
+ if (stream->id < 0xc0) {
+ /* AC3/LPCM private data header */
+ buf_index += 4;
+ if (stream->id >= 0xa0) {
+ int n;
+ buf_index += 3;
+ /* NOTE: we round the payload size to an integer number of
+ LPCM samples */
+ n = (s->packet_size - buf_index) % stream->lpcm_align;
+ if (n)
+ buf_index += (stream->lpcm_align - n);
+ }
+ }
+
+ if (s->is_vcd && stream->id == AUDIO_ID)
+ /* The VCD standard demands that 20 zero bytes follow
+ each audio packet (see standard p. IV-8).*/
+ buf_index+=20;
+ }
+ return s->packet_size - buf_index;
+}
+#endif
+
+/* Write an MPEG padding packet header. */
+static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ put_be32(pb, PADDING_STREAM);
+ put_be16(pb, packet_bytes - 6);
+ if (!s->is_mpeg2) {
+ put_byte(pb, 0x0f);
+ packet_bytes -= 7;
+ } else
+ packet_bytes -= 6;
+
+ for(i=0;i<packet_bytes;i++)
+ put_byte(pb, 0xff);
+}
+
+static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len){
+ int nb_frames=0;
+ PacketDesc *pkt_desc= stream->premux_packet;
+
+ while(len>0){
+ if(pkt_desc->size == pkt_desc->unwritten_size)
+ nb_frames++;
+ len -= pkt_desc->unwritten_size;
+ pkt_desc= pkt_desc->next;
+ }
+
+ return nb_frames;
+}
+
+/* flush the packet on stream stream_index */
+static int flush_packet(AVFormatContext *ctx, int stream_index,
+ int64_t pts, int64_t dts, int64_t scr, int trailer_size)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ StreamInfo *stream = ctx->streams[stream_index]->priv_data;
+ uint8_t *buf_ptr;
+ int size, payload_size, startcode, id, stuffing_size, i, header_len;
+ int packet_size;
+ uint8_t buffer[128];
+ int zero_trail_bytes = 0;
+ int pad_packet_bytes = 0;
+ int pes_flags;
+ int general_pack = 0; /*"general" pack without data specific to one stream?*/
+ int nb_frames;
+
+ id = stream->id;
+
+#if 0
+ printf("packet ID=%2x PTS=%0.3f\n",
+ id, pts / 90000.0);
+#endif
+
+ buf_ptr = buffer;
+
+ if ((s->packet_number % s->pack_header_freq) == 0 || s->last_scr != scr) {
+ /* output pack and systems header if needed */
+ size = put_pack_header(ctx, buf_ptr, scr);
+ buf_ptr += size;
+ s->last_scr= scr;
+
+ if (s->is_vcd) {
+ /* there is exactly one system header for each stream in a VCD MPEG,
+ One in the very first video packet and one in the very first
+ audio packet (see VCD standard p. IV-7 and IV-8).*/
+
+ if (stream->packet_number==0) {
+ size = put_system_header(ctx, buf_ptr, id);
+ buf_ptr += size;
+ }
+ } else if (s->is_dvd) {
+ if (stream->align_iframe || s->packet_number == 0){
+ int PES_bytes_to_fill = s->packet_size - size - 10;
+
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ PES_bytes_to_fill -= 5 + 5;
+ else
+ PES_bytes_to_fill -= 5;
+ }
+
+ if (stream->bytes_to_iframe == 0 || s->packet_number == 0) {
+ size = put_system_header(ctx, buf_ptr, 0);
+ buf_ptr += size;
+ size = buf_ptr - buffer;
+ put_buffer(ctx->pb, buffer, size);
+
+ put_be32(ctx->pb, PRIVATE_STREAM_2);
+ put_be16(ctx->pb, 0x03d4); // length
+ put_byte(ctx->pb, 0x00); // substream ID, 00=PCI
+ for (i = 0; i < 979; i++)
+ put_byte(ctx->pb, 0x00);
+
+ put_be32(ctx->pb, PRIVATE_STREAM_2);
+ put_be16(ctx->pb, 0x03fa); // length
+ put_byte(ctx->pb, 0x01); // substream ID, 01=DSI
+ for (i = 0; i < 1017; i++)
+ put_byte(ctx->pb, 0x00);
+
+ memset(buffer, 0, 128);
+ buf_ptr = buffer;
+ s->packet_number++;
+ stream->align_iframe = 0;
+ scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+ size = put_pack_header(ctx, buf_ptr, scr);
+ s->last_scr= scr;
+ buf_ptr += size;
+ /* GOP Start */
+ } else if (stream->bytes_to_iframe < PES_bytes_to_fill) {
+ pad_packet_bytes = PES_bytes_to_fill - stream->bytes_to_iframe;
+ }
+ }
+ } else {
+ if ((s->packet_number % s->system_header_freq) == 0) {
+ size = put_system_header(ctx, buf_ptr, 0);
+ buf_ptr += size;
+ }
+ }
+ }
+ size = buf_ptr - buffer;
+ put_buffer(ctx->pb, buffer, size);
+
+ packet_size = s->packet_size - size;
+
+ if (s->is_vcd && id == AUDIO_ID)
+ /* The VCD standard demands that 20 zero bytes follow
+ each audio pack (see standard p. IV-8).*/
+ zero_trail_bytes += 20;
+
+ if ((s->is_vcd && stream->packet_number==0)
+ || (s->is_svcd && s->packet_number==0)) {
+ /* for VCD the first pack of each stream contains only the pack header,
+ the system header and lots of padding (see VCD standard p. IV-6).
+ In the case of an audio pack, 20 zero bytes are also added at
+ the end.*/
+ /* For SVCD we fill the very first pack to increase compatibility with
+ some DVD players. Not mandated by the standard.*/
+ if (s->is_svcd)
+ general_pack = 1; /* the system header refers to both streams and no stream data*/
+ pad_packet_bytes = packet_size - zero_trail_bytes;
+ }
+
+ packet_size -= pad_packet_bytes + zero_trail_bytes;
+
+ if (packet_size > 0) {
+
+ /* packet header size */
+ packet_size -= 6;
+
+ /* packet header */
+ if (s->is_mpeg2) {
+ header_len = 3;
+ if (stream->packet_number==0)
+ header_len += 3; /* PES extension */
+ header_len += 1; /* obligatory stuffing byte */
+ } else {
+ header_len = 0;
+ }
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ header_len += 5 + 5;
+ else
+ header_len += 5;
+ } else {
+ if (!s->is_mpeg2)
+ header_len++;
+ }
+
+ payload_size = packet_size - header_len;
+ if (id < 0xc0) {
+ startcode = PRIVATE_STREAM_1;
+ payload_size -= 1;
+ if (id >= 0x40) {
+ payload_size -= 3;
+ if (id >= 0xa0)
+ payload_size -= 3;
+ }
+ } else {
+ startcode = 0x100 + id;
+ }
+
+ stuffing_size = payload_size - av_fifo_size(&stream->fifo);
+
+ // first byte does not fit -> reset pts/dts + stuffing
+ if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){
+ int timestamp_len=0;
+ if(dts != pts)
+ timestamp_len += 5;
+ if(pts != AV_NOPTS_VALUE)
+ timestamp_len += s->is_mpeg2 ? 5 : 4;
+ pts=dts= AV_NOPTS_VALUE;
+ header_len -= timestamp_len;
+ if (s->is_dvd && stream->align_iframe) {
+ pad_packet_bytes += timestamp_len;
+ packet_size -= timestamp_len;
+ } else {
+ payload_size += timestamp_len;
+ }
+ stuffing_size += timestamp_len;
+ if(payload_size > trailer_size)
+ stuffing_size += payload_size - trailer_size;
+ }
+
+ if (pad_packet_bytes > 0 && pad_packet_bytes <= 7) { // can't use padding, so use stuffing
+ packet_size += pad_packet_bytes;
+ payload_size += pad_packet_bytes; // undo the previous adjustment
+ if (stuffing_size < 0) {
+ stuffing_size = pad_packet_bytes;
+ } else {
+ stuffing_size += pad_packet_bytes;
+ }
+ pad_packet_bytes = 0;
+ }
+
+ if (stuffing_size < 0)
+ stuffing_size = 0;
+ if (stuffing_size > 16) { /*<=16 for MPEG-1, <=32 for MPEG-2*/
+ pad_packet_bytes += stuffing_size;
+ packet_size -= stuffing_size;
+ payload_size -= stuffing_size;
+ stuffing_size = 0;
+ }
+
+ nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);
+
+ put_be32(ctx->pb, startcode);
+
+ put_be16(ctx->pb, packet_size);
+
+ if (!s->is_mpeg2)
+ for(i=0;i<stuffing_size;i++)
+ put_byte(ctx->pb, 0xff);
+
+ if (s->is_mpeg2) {
+ put_byte(ctx->pb, 0x80); /* mpeg2 id */
+
+ pes_flags=0;
+
+ if (pts != AV_NOPTS_VALUE) {
+ pes_flags |= 0x80;
+ if (dts != pts)
+ pes_flags |= 0x40;
+ }
+
+ /* Both the MPEG-2 and the SVCD standards demand that the
+ P-STD_buffer_size field be included in the first packet of
+ every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2
+ and MPEG-2 standard 2.7.7) */
+ if (stream->packet_number == 0)
+ pes_flags |= 0x01;
+
+ put_byte(ctx->pb, pes_flags); /* flags */
+ put_byte(ctx->pb, header_len - 3 + stuffing_size);
+
+ if (pes_flags & 0x80) /*write pts*/
+ put_timestamp(ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
+ if (pes_flags & 0x40) /*write dts*/
+ put_timestamp(ctx->pb, 0x01, dts);
+
+ if (pes_flags & 0x01) { /*write pes extension*/
+ put_byte(ctx->pb, 0x10); /* flags */
+
+ /* P-STD buffer info */
+ if (id == AUDIO_ID)
+ put_be16(ctx->pb, 0x4000 | stream->max_buffer_size/128);
+ else
+ put_be16(ctx->pb, 0x6000 | stream->max_buffer_size/1024);
+ }
+
+ } else {
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts) {
+ put_timestamp(ctx->pb, 0x03, pts);
+ put_timestamp(ctx->pb, 0x01, dts);
+ } else {
+ put_timestamp(ctx->pb, 0x02, pts);
+ }
+ } else {
+ put_byte(ctx->pb, 0x0f);
+ }
+ }
+
+ if (s->is_mpeg2) {
+ /* special stuffing byte that is always written
+ to prevent accidental generation of start codes. */
+ put_byte(ctx->pb, 0xff);
+
+ for(i=0;i<stuffing_size;i++)
+ put_byte(ctx->pb, 0xff);
+ }
+
+ if (startcode == PRIVATE_STREAM_1) {
+ put_byte(ctx->pb, id);
+ if (id >= 0xa0) {
+ /* LPCM (XXX: check nb_frames) */
+ put_byte(ctx->pb, 7);
+ put_be16(ctx->pb, 4); /* skip 3 header bytes */
+ put_byte(ctx->pb, stream->lpcm_header[0]);
+ put_byte(ctx->pb, stream->lpcm_header[1]);
+ put_byte(ctx->pb, stream->lpcm_header[2]);
+ } else if (id >= 0x40) {
+ /* AC3 */
+ put_byte(ctx->pb, nb_frames);
+ put_be16(ctx->pb, trailer_size+1);
+ }
+ }
+
+ /* output data */
+ if(av_fifo_generic_read(&stream->fifo, payload_size - stuffing_size, &put_buffer, ctx->pb) < 0)
+ return -1;
+ stream->bytes_to_iframe -= payload_size - stuffing_size;
+ }else{
+ payload_size=
+ stuffing_size= 0;
+ }
+
+ if (pad_packet_bytes > 0)
+ put_padding_packet(ctx,ctx->pb, pad_packet_bytes);
+
+ for(i=0;i<zero_trail_bytes;i++)
+ put_byte(ctx->pb, 0x00);
+
+ put_flush_packet(ctx->pb);
+
+ s->packet_number++;
+
+ /* only increase the stream packet number if this pack actually contains
+ something that is specific to this stream! I.e. a dedicated header
+ or some data.*/
+ if (!general_pack)
+ stream->packet_number++;
+
+ return payload_size - stuffing_size;
+}
+
+static void put_vcd_padding_sector(AVFormatContext *ctx)
+{
+ /* There are two ways to do this padding: writing a sector/pack
+ of 0 values, or writing an MPEG padding pack. Both seem to
+ work with most decoders, BUT the VCD standard only allows a 0-sector
+ (see standard p. IV-4, IV-5).
+ So a 0-sector it is...*/
+
+ MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ for(i=0;i<s->packet_size;i++)
+ put_byte(ctx->pb, 0);
+
+ s->vcd_padding_bytes_written += s->packet_size;
+
+ put_flush_packet(ctx->pb);
+
+ /* increasing the packet number is correct. The SCR of the following packs
+ is calculated from the packet_number and it has to include the padding
+ sector (it represents the sector index, not the MPEG pack index)
+ (see VCD standard p. IV-6)*/
+ s->packet_number++;
+}
+
+#if 0 /* unused, remove? */
+static int64_t get_vcd_scr(AVFormatContext *ctx,int stream_index,int64_t pts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int64_t scr;
+
+ /* Since the data delivery rate is constant, SCR is computed
+ using the formula C + i * 1200 where C is the start constant
+ and i is the pack index.
+ It is recommended that SCR 0 is at the beginning of the VCD front
+ margin (a sequence of empty Form 2 sectors on the CD).
+ It is recommended that the front margin is 30 sectors long, so
+ we use C = 30*1200 = 36000
+ (Note that even if the front margin is not 30 sectors the file
+ will still be correct according to the standard. It just won't have
+ the "recommended" value).*/
+ scr = 36000 + s->packet_number * 1200;
+
+ return scr;
+}
+#endif
+
+static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr){
+// MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ PacketDesc *pkt_desc;
+
+ while((pkt_desc= stream->predecode_packet)
+ && scr > pkt_desc->dts){ //FIXME > vs >=
+ if(stream->buffer_index < pkt_desc->size ||
+ stream->predecode_packet == stream->premux_packet){
+ av_log(ctx, AV_LOG_ERROR,
+ "buffer underflow i=%d bufi=%d size=%d\n",
+ i, stream->buffer_index, pkt_desc->size);
+ break;
+ }
+ stream->buffer_index -= pkt_desc->size;
+
+ stream->predecode_packet= pkt_desc->next;
+ av_freep(&pkt_desc);
+ }
+ }
+
+ return 0;
+}
+
+static int output_packet(AVFormatContext *ctx, int flush){
+ MpegMuxContext *s = ctx->priv_data;
+ AVStream *st;
+ StreamInfo *stream;
+ int i, avail_space=0, es_size, trailer_size;
+ int best_i= -1;
+ int best_score= INT_MIN;
+ int ignore_constraints=0;
+ int64_t scr= s->last_scr;
+ PacketDesc *timestamp_packet;
+ const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE);
+
+retry:
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ const int avail_data= av_fifo_size(&stream->fifo);
+ const int space= stream->max_buffer_size - stream->buffer_index;
+ int rel_space= 1024*space / stream->max_buffer_size;
+ PacketDesc *next_pkt= stream->premux_packet;
+
+ /* for subtitle, a single PES packet must be generated,
+ so we flush after every single subtitle packet */
+ if(s->packet_size > avail_data && !flush
+ && st->codec->codec_type != CODEC_TYPE_SUBTITLE)
+ return 0;
+ if(avail_data==0)
+ continue;
+ assert(avail_data>0);
+
+ if(space < s->packet_size && !ignore_constraints)
+ continue;
+
+ if(next_pkt && next_pkt->dts - scr > max_delay)
+ continue;
+
+ if(rel_space > best_score){
+ best_score= rel_space;
+ best_i = i;
+ avail_space= space;
+ }
+ }
+
+ if(best_i < 0){
+ int64_t best_dts= INT64_MAX;
+
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ PacketDesc *pkt_desc= stream->predecode_packet;
+ if(pkt_desc && pkt_desc->dts < best_dts)
+ best_dts= pkt_desc->dts;
+ }
+
+#if 0
+ av_log(ctx, AV_LOG_DEBUG, "bumping scr, scr:%f, dts:%f\n",
+ scr/90000.0, best_dts/90000.0);
+#endif
+ if(best_dts == INT64_MAX)
+ return 0;
+
+ if(scr >= best_dts+1 && !ignore_constraints){
+ av_log(ctx, AV_LOG_ERROR, "packet too large, ignoring buffer limits to mux it\n");
+ ignore_constraints= 1;
+ }
+ scr= FFMAX(best_dts+1, scr);
+ if(remove_decoded_packets(ctx, scr) < 0)
+ return -1;
+ goto retry;
+ }
+
+ assert(best_i >= 0);
+
+ st = ctx->streams[best_i];
+ stream = st->priv_data;
+
+ assert(av_fifo_size(&stream->fifo) > 0);
+
+ assert(avail_space >= s->packet_size || ignore_constraints);
+
+ timestamp_packet= stream->premux_packet;
+ if(timestamp_packet->unwritten_size == timestamp_packet->size){
+ trailer_size= 0;
+ }else{
+ trailer_size= timestamp_packet->unwritten_size;
+ timestamp_packet= timestamp_packet->next;
+ }
+
+ if(timestamp_packet){
+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, scr/90000.0, best_i);
+ es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size);
+ }else{
+ assert(av_fifo_size(&stream->fifo) == trailer_size);
+ es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size);
+ }
+
+ if (s->is_vcd) {
+ /* Write one or more padding sectors, if necessary, to reach
+ the constant overall bitrate.*/
+ int vcd_pad_bytes;
+
+ while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->premux_packet->pts) ) >= s->packet_size){ //FIXME pts cannot be correct here
+ put_vcd_padding_sector(ctx);
+ s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+ }
+ }
+
+ stream->buffer_index += es_size;
+ s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+
+ while(stream->premux_packet && stream->premux_packet->unwritten_size <= es_size){
+ es_size -= stream->premux_packet->unwritten_size;
+ stream->premux_packet= stream->premux_packet->next;
+ }
+ if(es_size)
+ stream->premux_packet->unwritten_size -= es_size;
+
+ if(remove_decoded_packets(ctx, s->last_scr) < 0)
+ return -1;
+
+ return 1;
+}
+
+static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int stream_index= pkt->stream_index;
+ int size= pkt->size;
+ uint8_t *buf= pkt->data;
+ AVStream *st = ctx->streams[stream_index];
+ StreamInfo *stream = st->priv_data;
+ int64_t pts, dts;
+ PacketDesc *pkt_desc;
+ const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
+ const int is_iframe = st->codec->codec_type == CODEC_TYPE_VIDEO && (pkt->flags & PKT_FLAG_KEY);
+
+ pts= pkt->pts;
+ dts= pkt->dts;
+
+ if(pts != AV_NOPTS_VALUE) pts += preload;
+ if(dts != AV_NOPTS_VALUE) dts += preload;
+
+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
+ if (!stream->premux_packet)
+ stream->next_packet = &stream->premux_packet;
+ *stream->next_packet=
+ pkt_desc= av_mallocz(sizeof(PacketDesc));
+ pkt_desc->pts= pts;
+ pkt_desc->dts= dts;
+ pkt_desc->unwritten_size=
+ pkt_desc->size= size;
+ if(!stream->predecode_packet)
+ stream->predecode_packet= pkt_desc;
+ stream->next_packet= &pkt_desc->next;
+
+ av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size + 1);
+
+ if (s->is_dvd){
+ if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
+ stream->bytes_to_iframe = av_fifo_size(&stream->fifo);
+ stream->align_iframe = 1;
+ stream->vobu_start_pts = pts;
+ }
+ }
+
+ av_fifo_write(&stream->fifo, buf, size);
+
+ for(;;){
+ int ret= output_packet(ctx, 0);
+ if(ret<=0)
+ return ret;
+ }
+}
+
+static int mpeg_mux_end(AVFormatContext *ctx)
+{
+// MpegMuxContext *s = ctx->priv_data;
+ StreamInfo *stream;
+ int i;
+
+ for(;;){
+ int ret= output_packet(ctx, 1);
+ if(ret<0)
+ return ret;
+ else if(ret==0)
+ break;
+ }
+
+ /* End header according to MPEG1 systems standard. We do not write
+ it as it is usually not needed by decoders and because it
+ complicates MPEG stream concatenation. */
+ //put_be32(ctx->pb, ISO_11172_END_CODE);
+ //put_flush_packet(ctx->pb);
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+
+ assert(av_fifo_size(&stream->fifo) == 0);
+ av_fifo_free(&stream->fifo);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_MPEG1SYSTEM_MUXER
+AVOutputFormat mpeg1system_muxer = {
+ "mpeg",
+ "MPEG1 System format",
+ "video/mpeg",
+ "mpg,mpeg",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+#ifdef CONFIG_MPEG1VCD_MUXER
+AVOutputFormat mpeg1vcd_muxer = {
+ "vcd",
+ "MPEG1 System format (VCD)",
+ "video/mpeg",
+ NULL,
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+#ifdef CONFIG_MPEG2VOB_MUXER
+AVOutputFormat mpeg2vob_muxer = {
+ "vob",
+ "MPEG2 PS format (VOB)",
+ "video/mpeg",
+ "vob",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+
+/* Same as mpeg2vob_mux except that the pack size is 2324 */
+#ifdef CONFIG_MPEG2SVCD_MUXER
+AVOutputFormat mpeg2svcd_muxer = {
+ "svcd",
+ "MPEG2 PS format (VOB)",
+ "video/mpeg",
+ "vob",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+
+/* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */
+#ifdef CONFIG_MPEG2DVD_MUXER
+AVOutputFormat mpeg2dvd_muxer = {
+ "dvd",
+ "MPEG2 PS format (DVD VOB)",
+ "video/mpeg",
+ "dvd",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/mpegts.c b/contrib/ffmpeg/libavformat/mpegts.c
index c466710ee..ab046199a 100644
--- a/contrib/ffmpeg/libavformat/mpegts.c
+++ b/contrib/ffmpeg/libavformat/mpegts.c
@@ -31,25 +31,30 @@
/* maximum size in which we look for synchronisation if
synchronisation is lost */
#define MAX_RESYNC_SIZE 4096
+#define REGISTRATION_DESCRIPTOR 5
typedef struct PESContext PESContext;
-static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int stream_type);
+static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid, int stream_type);
static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code);
+extern void av_set_program_name(AVProgram *program, char *provider_name, char *name);
+extern void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);
enum MpegTSFilterType {
MPEGTS_PES,
MPEGTS_SECTION,
};
-typedef void PESCallback(void *opaque, const uint8_t *buf, int len, int is_start);
+typedef struct MpegTSFilter MpegTSFilter;
+
+typedef void PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start);
typedef struct MpegTSPESFilter {
PESCallback *pes_cb;
void *opaque;
} MpegTSPESFilter;
-typedef void SectionCallback(void *opaque, const uint8_t *buf, int len);
+typedef void SectionCallback(MpegTSFilter *f, const uint8_t *buf, int len);
typedef void SetServiceCallback(void *opaque, int ret);
@@ -63,7 +68,7 @@ typedef struct MpegTSSectionFilter {
void *opaque;
} MpegTSSectionFilter;
-typedef struct MpegTSFilter {
+struct MpegTSFilter {
int pid;
int last_cc; /* last cc code (-1 if first packet) */
enum MpegTSFilterType type;
@@ -71,14 +76,14 @@ typedef struct MpegTSFilter {
MpegTSPESFilter pes_filter;
MpegTSSectionFilter section_filter;
} u;
-} MpegTSFilter;
+};
-typedef struct MpegTSService {
- int running:1;
- int sid; /**< MPEG Program Number of stream */
- char *provider_name; /**< DVB Network name, "" if not DVB stream */
- char *name; /**< DVB Service name, "MPEG Program [sid]" if not DVB stream*/
-} MpegTSService;
+#define MAX_PIDS_PER_PROGRAM 64
+typedef struct {
+ unsigned int id; //program id/service id
+ unsigned int nb_pids;
+ unsigned int pids[MAX_PIDS_PER_PROGRAM];
+} Program_t;
struct MpegTSContext {
/* user data */
@@ -87,16 +92,12 @@ struct MpegTSContext {
int raw_packet_size;
/** if true, all pids are analyzed to find streams */
int auto_guess;
- int set_service_ret;
- /** force raw MPEG2 transport stream output, if possible */
- int mpeg2ts_raw;
/** compute exact PCR for each transport stream packet */
int mpeg2ts_compute_pcr;
int64_t cur_pcr; /**< used to estimate the exact PCR */
int pcr_incr; /**< used to estimate the exact PCR */
- int pcr_pid; /**< used to estimate the exact PCR */
/* data needed to handle file based ts */
/** stop parsing loop */
@@ -107,26 +108,125 @@ struct MpegTSContext {
/******************************************/
/* private mpegts data */
/* scan context */
- MpegTSFilter *sdt_filter;
- /** number of PMTs in the last PAT seen */
- int nb_services;
- /** list of PMTs in the last PAT seen */
- MpegTSService **services;
-
- /* set service context (XXX: allocated it ?) */
- SetServiceCallback *set_service_cb;
- void *set_service_opaque;
- /** filter for the PAT */
- MpegTSFilter *pat_filter;
- /** filter for the PMT for the MPEG program number specified by req_sid */
- MpegTSFilter *pmt_filter;
- /** MPEG program number of stream we want to decode */
- int req_sid;
+ /** structure to keep track of Program->pids mapping */
+ unsigned int nb_prg;
+ Program_t *prg;
+
/** filters for various streams specified by PMT + for the PAT and PMT */
MpegTSFilter *pids[NB_PID_MAX];
};
+/* TS stream handling */
+
+enum MpegTSState {
+ MPEGTS_HEADER = 0,
+ MPEGTS_PESHEADER_FILL,
+ MPEGTS_PAYLOAD,
+ MPEGTS_SKIP,
+};
+
+/* enough for PES header + length */
+#define PES_START_SIZE 9
+#define MAX_PES_HEADER_SIZE (9 + 255)
+
+struct PESContext {
+ int pid;
+ int pcr_pid; /**< if -1 then all packets containing PCR are considered */
+ int stream_type;
+ MpegTSContext *ts;
+ AVFormatContext *stream;
+ AVStream *st;
+ enum MpegTSState state;
+ /* used to get the format */
+ int data_index;
+ int total_size;
+ int pes_header_size;
+ int64_t pts, dts;
+ uint8_t header[MAX_PES_HEADER_SIZE];
+};
+
+extern AVInputFormat mpegts_demuxer;
+
+static void clear_program(MpegTSContext *ts, unsigned int programid)
+{
+ int i;
+
+ for(i=0; i<ts->nb_prg; i++)
+ if(ts->prg[i].id == programid)
+ ts->prg[i].nb_pids = 0;
+}
+
+static void clear_programs(MpegTSContext *ts)
+{
+ av_freep(&ts->prg);
+ ts->nb_prg=0;
+}
+
+static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
+{
+ Program_t *p;
+ void *tmp = av_realloc(ts->prg, (ts->nb_prg+1)*sizeof(Program_t));
+ if(!tmp)
+ return;
+ ts->prg = tmp;
+ p = &ts->prg[ts->nb_prg];
+ p->id = programid;
+ p->nb_pids = 0;
+ ts->nb_prg++;
+}
+
+static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned int pid)
+{
+ int i;
+ Program_t *p = NULL;
+ for(i=0; i<ts->nb_prg; i++) {
+ if(ts->prg[i].id == programid) {
+ p = &ts->prg[i];
+ break;
+ }
+ }
+ if(!p)
+ return;
+
+ if(p->nb_pids >= MAX_PIDS_PER_PROGRAM)
+ return;
+ p->pids[p->nb_pids++] = pid;
+}
+
+/**
+ * \brief discard_pid() decides if the pid is to be discarded according
+ * to caller's programs selection
+ * \param ts : - TS context
+ * \param pid : - pid
+ * \return 1 if the pid is only comprised in programs that have .discard=AVDISCARD_ALL
+ * 0 otherwise
+ */
+static int discard_pid(MpegTSContext *ts, unsigned int pid)
+{
+ int i, j, k;
+ int used = 0, discarded = 0;
+ Program_t *p;
+ 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)
+ 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)
+ discarded++;
+ else
+ used++;
+ }
+ }
+ }
+ }
+
+ return (!used && discarded);
+}
+
/**
* Assembles PES packets out of TS packets, and then calls the "section_cb"
* function when they are complete.
@@ -154,7 +254,7 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
/* compute section length if possible */
if (tss->section_h_size == -1 && tss->section_index >= 3) {
- len = (((tss->section_buf[1] & 0xf) << 8) | tss->section_buf[2]) + 3;
+ len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;
if (len > 4096)
return;
tss->section_h_size = len;
@@ -163,8 +263,9 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {
tss->end_of_section_reached = 1;
if (!tss->check_crc ||
- av_crc(av_crc04C11DB7, -1, tss->section_buf, tss->section_h_size) == 0)
- tss->section_cb(tss->opaque, tss->section_buf, tss->section_h_size);
+ av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1,
+ tss->section_buf, tss->section_h_size) == 0)
+ tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
}
}
@@ -308,7 +409,7 @@ static inline int get16(const uint8_t **pp, const uint8_t *p_end)
p = *pp;
if ((p + 1) >= p_end)
return -1;
- c = (p[0] << 8) | p[1];
+ c = AV_RB16(p);
p += 2;
*pp = p;
return c;
@@ -366,30 +467,10 @@ static int parse_section_header(SectionHeader *h,
return 0;
}
-static MpegTSService *new_service(MpegTSContext *ts, int sid,
- char *provider_name, char *name)
-{
- MpegTSService *service;
-
-#ifdef DEBUG_SI
- av_log(ts->stream, AV_LOG_DEBUG, "new_service: "
- "sid=0x%04x provider='%s' name='%s'\n",
- sid, provider_name, name);
-#endif
-
- service = av_mallocz(sizeof(MpegTSService));
- if (!service)
- return NULL;
- service->sid = sid;
- service->provider_name = provider_name;
- service->name = name;
- dynarray_add(&ts->services, &ts->nb_services, service);
- return service;
-}
-static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
+static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{
- MpegTSContext *ts = opaque;
+ MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h1, *h = &h1;
PESContext *pes;
AVStream *st;
@@ -397,7 +478,8 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
int program_info_length, pcr_pid, pid, stream_type;
int desc_list_len, desc_len, desc_tag;
int comp_page = 0, anc_page = 0; /* initialize to kill warnings */
- char language[4];
+ char language[4] = {0}; /* initialize to kill warnings */
+ int has_hdmv_descr = 0;
#ifdef DEBUG_SI
av_log(ts->stream, AV_LOG_DEBUG, "PMT: len %i\n", section_len);
@@ -411,19 +493,41 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x sec_num=%d/%d\n",
h->id, h->sec_num, h->last_sec_num);
#endif
- if (h->tid != PMT_TID || (ts->req_sid >= 0 && h->id != ts->req_sid) )
+ if (h->tid != PMT_TID)
return;
+ clear_program(ts, h->id);
pcr_pid = get16(&p, p_end) & 0x1fff;
if (pcr_pid < 0)
return;
- ts->pcr_pid = pcr_pid;
+ add_pid_to_pmt(ts, h->id, pcr_pid);
#ifdef DEBUG_SI
av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid);
#endif
program_info_length = get16(&p, p_end) & 0xfff;
if (program_info_length < 0)
return;
+ while(program_info_length >= 2) {
+ uint8_t tag, len;
+ tag = get8(&p, p_end);
+ len = get8(&p, p_end);
+ if(len > program_info_length - 2)
+ //something else is broken, exit the program_descriptors_loop
+ break;
+ program_info_length -= len + 2;
+ if(tag == REGISTRATION_DESCRIPTOR && len >= 4) {
+ uint8_t bytes[4];
+ bytes[0] = get8(&p, p_end);
+ bytes[1] = get8(&p, p_end);
+ bytes[2] = get8(&p, p_end);
+ bytes[3] = get8(&p, p_end);
+ len -= 4;
+ if(bytes[0] == 'H' && bytes[1] == 'D' &&
+ bytes[2] == 'M' && bytes[3] == 'V')
+ has_hdmv_descr = 1;
+ }
+ p += len;
+ }
p += program_info_length;
if (p >= p_end)
return;
@@ -507,10 +611,22 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
case STREAM_TYPE_AUDIO_AAC:
case STREAM_TYPE_AUDIO_AC3:
case STREAM_TYPE_AUDIO_DTS:
+ case STREAM_TYPE_AUDIO_HDMV_DTS:
case STREAM_TYPE_SUBTITLE_DVB:
- pes = add_pes_stream(ts, pid, stream_type);
- if (pes)
- st = new_pes_av_stream(pes, 0);
+ if(stream_type == STREAM_TYPE_AUDIO_HDMV_DTS && !has_hdmv_descr)
+ break;
+ if(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES){
+ pes= ts->pids[pid]->u.pes_filter.opaque;
+ st= pes->st;
+ }else{
+ if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); //wrongly added sdt filter probably
+ pes = add_pes_stream(ts, pid, pcr_pid, stream_type);
+ if (pes)
+ st = new_pes_av_stream(pes, 0);
+ }
+ add_pid_to_pmt(ts, h->id, pid);
+ if(st)
+ av_program_add_stream_index(ts->stream, h->id, st->index);
break;
default:
/* we ignore the other streams */
@@ -519,10 +635,7 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
if (st) {
if (language[0] != 0) {
- st->language[0] = language[0];
- st->language[1] = language[1];
- st->language[2] = language[2];
- st->language[3] = language[3];
+ memcpy(st->language, language, 4);
}
if (stream_type == STREAM_TYPE_SUBTITLE_DVB) {
@@ -531,14 +644,13 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
}
}
/* all parameters are there */
- ts->set_service_cb(ts->set_service_opaque, 0);
- mpegts_close_filter(ts, ts->pmt_filter);
- ts->pmt_filter = NULL;
+ ts->stop_parse++;
+ mpegts_close_filter(ts, filter);
}
-static void pat_cb(void *opaque, const uint8_t *section, int section_len)
+static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{
- MpegTSContext *ts = opaque;
+ MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
int sid, pmt_pid;
@@ -554,6 +666,7 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len)
if (h->tid != PAT_TID)
return;
+ clear_programs(ts);
for(;;) {
sid = get16(&p, p_end);
if (sid < 0)
@@ -567,87 +680,29 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len)
if (sid == 0x0000) {
/* NIT info */
} else {
- if (ts->req_sid == sid) {
- ts->pmt_filter = mpegts_open_section_filter(ts, pmt_pid,
- pmt_cb, ts, 1);
- goto found;
- }
+ av_new_program(ts->stream, sid);
+ ts->stop_parse--;
+ 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, pmt_pid);
}
}
/* not found */
- ts->set_service_cb(ts->set_service_opaque, -1);
+ ts->stop_parse++;
- found:
- mpegts_close_filter(ts, ts->pat_filter);
- ts->pat_filter = NULL;
+ mpegts_close_filter(ts, filter);
}
-/* add all services found in the PAT */
-static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len)
+static void mpegts_set_service(MpegTSContext *ts)
{
- MpegTSContext *ts = opaque;
- SectionHeader h1, *h = &h1;
- const uint8_t *p, *p_end;
- int sid, pmt_pid;
- char *provider_name, *name;
- char buf[256];
-
-#ifdef DEBUG_SI
- av_log(ts->stream, AV_LOG_DEBUG, "PAT:\n");
- av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
-#endif
- p_end = section + section_len - 4;
- p = section;
- if (parse_section_header(h, &p, p_end) < 0)
- return;
- if (h->tid != PAT_TID)
- return;
-
- for(;;) {
- sid = get16(&p, p_end);
- if (sid < 0)
- break;
- pmt_pid = get16(&p, p_end) & 0x1fff;
- if (pmt_pid < 0)
- break;
-#ifdef DEBUG_SI
- av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid);
-#endif
- if (sid == 0x0000) {
- /* NIT info */
- } else {
- /* add the service with a dummy name */
- snprintf(buf, sizeof(buf), "Service %x\n", sid);
- name = av_strdup(buf);
- provider_name = av_strdup("");
- if (name && provider_name) {
- new_service(ts, sid, provider_name, name);
- } else {
- av_freep(&name);
- av_freep(&provider_name);
- }
- }
- }
- ts->stop_parse = 1;
-
- /* remove filter */
- mpegts_close_filter(ts, ts->pat_filter);
- ts->pat_filter = NULL;
-}
-
-static void mpegts_set_service(MpegTSContext *ts, int sid,
- SetServiceCallback *set_service_cb, void *opaque)
-{
- ts->set_service_cb = set_service_cb;
- ts->set_service_opaque = opaque;
- ts->req_sid = sid;
- ts->pat_filter = mpegts_open_section_filter(ts, PAT_PID,
+ mpegts_open_section_filter(ts, PAT_PID,
pat_cb, ts, 1);
}
-static void sdt_cb(void *opaque, const uint8_t *section, int section_len)
+static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{
- MpegTSContext *ts = opaque;
+ MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end, *desc_list_end, *desc_end;
int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
@@ -704,9 +759,11 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len)
if (!provider_name)
break;
name = getstr8(&p, p_end);
- if (!name)
- break;
- new_service(ts, sid, provider_name, name);
+ if (name) {
+ AVProgram *program = av_new_program(ts->stream, sid);
+ if(program)
+ av_set_program_name(program, provider_name, name);
+ }
break;
default:
break;
@@ -715,78 +772,35 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len)
}
p = desc_list_end;
}
- ts->stop_parse = 1;
-
- /* remove filter */
- mpegts_close_filter(ts, ts->sdt_filter);
- ts->sdt_filter = NULL;
}
/* scan services in a transport stream by looking at the SDT */
static void mpegts_scan_sdt(MpegTSContext *ts)
{
- ts->sdt_filter = mpegts_open_section_filter(ts, SDT_PID,
+ mpegts_open_section_filter(ts, SDT_PID,
sdt_cb, ts, 1);
}
-/* scan services in a transport stream by looking at the PAT (better
- than nothing !) */
-static void mpegts_scan_pat(MpegTSContext *ts)
-{
- ts->pat_filter = mpegts_open_section_filter(ts, PAT_PID,
- pat_scan_cb, ts, 1);
-}
-
-/* TS stream handling */
-
-enum MpegTSState {
- MPEGTS_HEADER = 0,
- MPEGTS_PESHEADER_FILL,
- MPEGTS_PAYLOAD,
- MPEGTS_SKIP,
-};
-
-/* enough for PES header + length */
-#define PES_START_SIZE 9
-#define MAX_PES_HEADER_SIZE (9 + 255)
-
-struct PESContext {
- int pid;
- int stream_type;
- MpegTSContext *ts;
- AVFormatContext *stream;
- AVStream *st;
- enum MpegTSState state;
- /* used to get the format */
- int data_index;
- int total_size;
- int pes_header_size;
- int64_t pts, dts;
- uint8_t header[MAX_PES_HEADER_SIZE];
-};
-
static int64_t get_pts(const uint8_t *p)
{
- int64_t pts;
- int val;
-
- pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
- val = (p[1] << 8) | p[2];
- pts |= (int64_t)(val >> 1) << 15;
- val = (p[3] << 8) | p[4];
- pts |= (int64_t)(val >> 1);
+ int64_t pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
+ pts |= (AV_RB16(p + 1) >> 1) << 15;
+ pts |= AV_RB16(p + 3) >> 1;
return pts;
}
/* return non zero if a packet could be constructed */
-static void mpegts_push_data(void *opaque,
+static void mpegts_push_data(MpegTSFilter *filter,
const uint8_t *buf, int buf_size, int is_start)
{
- PESContext *pes = opaque;
+ PESContext *pes = filter->u.pes_filter.opaque;
MpegTSContext *ts = pes->ts;
const uint8_t *p;
int len, code;
+ if(!ts->pkt)
+ return;
+
if (is_start) {
pes->state = MPEGTS_HEADER;
pes->data_index = 0;
@@ -821,7 +835,7 @@ static void mpegts_push_data(void *opaque,
new_pes_av_stream(pes, code);
}
pes->state = MPEGTS_PESHEADER_FILL;
- pes->total_size = (pes->header[4] << 8) | pes->header[5];
+ pes->total_size = AV_RB16(pes->header + 4);
/* NOTE: a zero total size means the PES size is
unbounded */
if (pes->total_size)
@@ -935,6 +949,7 @@ static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code)
codec_id = CODEC_ID_AC3;
break;
case STREAM_TYPE_AUDIO_DTS:
+ case STREAM_TYPE_AUDIO_HDMV_DTS:
codec_type = CODEC_TYPE_AUDIO;
codec_id = CODEC_ID_DTS;
break;
@@ -961,14 +976,14 @@ static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code)
st->priv_data = pes;
st->codec->codec_type = codec_type;
st->codec->codec_id = codec_id;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
pes->st = st;
}
return st;
}
-static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int stream_type)
+static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid, int stream_type)
{
MpegTSFilter *tss;
PESContext *pes;
@@ -980,6 +995,7 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int stream_type)
pes->ts = ts;
pes->stream = ts->stream;
pes->pid = pid;
+ pes->pcr_pid = pcr_pid;
pes->stream_type = stream_type;
tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
if (!tss) {
@@ -997,11 +1013,13 @@ static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
int len, pid, cc, cc_ok, afc, is_start;
const uint8_t *p, *p_end;
- pid = ((packet[1] & 0x1f) << 8) | packet[2];
+ pid = AV_RB16(packet + 1) & 0x1fff;
+ if(pid && discard_pid(ts, pid))
+ return;
is_start = packet[1] & 0x40;
tss = ts->pids[pid];
if (ts->auto_guess && tss == NULL && is_start) {
- add_pes_stream(ts, pid, 0);
+ add_pes_stream(ts, pid, -1, 0);
tss = ts->pids[pid];
}
if (!tss)
@@ -1054,7 +1072,7 @@ static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
}
}
} else {
- tss->u.pes_filter.pes_cb(tss->u.pes_filter.opaque,
+ tss->u.pes_filter.pes_cb(tss,
p, p_end - p, is_start);
}
}
@@ -1086,7 +1104,7 @@ static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size)
for(;;) {
len = get_buffer(pb, buf, TS_PACKET_SIZE);
if (len != TS_PACKET_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* check paquet sync byte */
if (buf[0] != 0x47) {
/* find a new packet start */
@@ -1108,14 +1126,14 @@ static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size)
static int handle_packets(MpegTSContext *ts, int nb_packets)
{
AVFormatContext *s = ts->stream;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint8_t packet[TS_PACKET_SIZE];
int packet_num, ret;
ts->stop_parse = 0;
packet_num = 0;
for(;;) {
- if (ts->stop_parse)
+ if (ts->stop_parse>0)
break;
packet_num++;
if (nb_packets != 0 && packet_num >= nb_packets)
@@ -1157,13 +1175,6 @@ static int mpegts_probe(AVProbeData *p)
#endif
}
-static void set_service_cb(void *opaque, int ret)
-{
- MpegTSContext *ts = opaque;
- ts->set_service_ret = ret;
- ts->stop_parse = 1;
-}
-
/* return the 90 kHz PCR and the extension for the 27 MHz PCR. return
(-1) if not available */
static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
@@ -1187,7 +1198,7 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
return -1;
if (len < 6)
return -1;
- v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ v = AV_RB32(p);
*ppcr_high = ((int64_t)v << 1) | (p[4] >> 7);
*ppcr_low = ((p[4] & 1) << 8) | p[5];
return 0;
@@ -1197,15 +1208,17 @@ static int mpegts_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
MpegTSContext *ts = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint8_t buf[1024];
- int len, sid, i;
+ int len;
int64_t pos;
- MpegTSService *service;
if (ap) {
- ts->mpeg2ts_raw = ap->mpeg2ts_raw;
ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
+ if(ap->mpeg2ts_raw){
+ av_log(s, AV_LOG_ERROR, "use mpegtsraw_demuxer!\n");
+ return -1;
+ }
}
/* read the first 1024 bytes to get packet size */
@@ -1219,73 +1232,23 @@ static int mpegts_read_header(AVFormatContext *s,
ts->stream = s;
ts->auto_guess = 0;
-goto_auto_guess:
- if (!ts->mpeg2ts_raw) {
+ if (s->iformat == &mpegts_demuxer) {
/* normal demux */
- if (!ts->auto_guess) {
- ts->set_service_ret = -1;
-
- /* first do a scaning to get all the services */
- url_fseek(pb, pos, SEEK_SET);
- mpegts_scan_sdt(ts);
+ /* first do a scaning to get all the services */
+ url_fseek(pb, pos, SEEK_SET);
+ mpegts_scan_sdt(ts);
- handle_packets(ts, s->probesize);
+ mpegts_set_service(ts);
- if (ts->nb_services <= 0) {
- /* no SDT found, we try to look at the PAT */
+ handle_packets(ts, s->probesize);
+ /* if could not find service, enable auto_guess */
- /* First remove the SDT filters from each PID */
- int i;
- for (i=0; i < NB_PID_MAX; i++) {
- if (ts->pids[i])
- mpegts_close_filter(ts, ts->pids[i]);
- }
- url_fseek(pb, pos, SEEK_SET);
- mpegts_scan_pat(ts);
-
- handle_packets(ts, s->probesize);
- }
+ ts->auto_guess = 1;
- if (ts->nb_services <= 0) {
- /* raw transport stream */
- ts->auto_guess = 1;
- s->ctx_flags |= AVFMTCTX_NOHEADER;
- goto do_pcr;
- }
-
- /* tune to first service found */
- for(i=0; i<ts->nb_services && ts->set_service_ret; i++){
- service = ts->services[i];
- sid = service->sid;
#ifdef DEBUG_SI
- av_log(ts->stream, AV_LOG_DEBUG, "tuning to '%s'\n", service->name);
+ av_log(ts->stream, AV_LOG_DEBUG, "tuning done\n");
#endif
-
- /* now find the info for the first service if we found any,
- otherwise try to filter all PATs */
-
- url_fseek(pb, pos, SEEK_SET);
- mpegts_set_service(ts, sid, set_service_cb, ts);
-
- handle_packets(ts, s->probesize);
- }
- /* if could not find service, exit */
-
- if (ts->set_service_ret != 0) {
- if(ts->auto_guess)
- return -1;
- else {
- //let's retry with auto_guess set
- ts->auto_guess = 1;
- goto goto_auto_guess;
- }
- }
-
-#ifdef DEBUG_SI
- av_log(ts->stream, AV_LOG_DEBUG, "tuning done\n");
-#endif
- }
s->ctx_flags |= AVFMTCTX_NOHEADER;
} else {
AVStream *st;
@@ -1296,7 +1259,6 @@ goto_auto_guess:
/* only read packets */
- do_pcr:
st = av_new_stream(s, 0);
if (!st)
goto fail;
@@ -1309,10 +1271,10 @@ goto_auto_guess:
nb_pcrs = 0;
nb_packets = 0;
for(;;) {
- ret = read_packet(&s->pb, packet, ts->raw_packet_size);
+ ret = read_packet(s->pb, packet, ts->raw_packet_size);
if (ret < 0)
return -1;
- pid = ((packet[1] & 0x1f) << 8) | packet[2];
+ pid = AV_RB16(packet + 1) & 0x1fff;
if ((pcr_pid == -1 || pcr_pid == pid) &&
parse_pcr(&pcr_h, &pcr_l, packet) == 0) {
pcr_pid = pid;
@@ -1324,7 +1286,6 @@ goto_auto_guess:
}
nb_packets++;
}
- ts->pcr_pid = pcr_pid;
/* NOTE1: the bitrate is computed without the FEC */
/* NOTE2: it is only the bitrate of the start of the stream */
@@ -1358,8 +1319,8 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
return AVERROR(ENOMEM);
- pkt->pos= url_ftell(&s->pb);
- ret = read_packet(&s->pb, pkt->data, ts->raw_packet_size);
+ pkt->pos= url_ftell(s->pb);
+ ret = read_packet(s->pb, pkt->data, ts->raw_packet_size);
if (ret < 0) {
av_free_packet(pkt);
return ret;
@@ -1368,10 +1329,10 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
/* compute exact PCR for each packet */
if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
/* we read the next PCR (XXX: optimize it by using a bigger buffer */
- pos = url_ftell(&s->pb);
+ pos = url_ftell(s->pb);
for(i = 0; i < MAX_PACKET_READAHEAD; i++) {
- url_fseek(&s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
- get_buffer(&s->pb, pcr_buf, 12);
+ url_fseek(s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
+ get_buffer(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)) /
@@ -1379,7 +1340,7 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
break;
}
}
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
/* no next PCR found: we use previous increment */
ts->cur_pcr = pcr_h * 300 + pcr_l;
}
@@ -1396,12 +1357,8 @@ static int mpegts_read_packet(AVFormatContext *s,
{
MpegTSContext *ts = s->priv_data;
- if (!ts->mpeg2ts_raw) {
- ts->pkt = pkt;
- return handle_packets(ts, 0);
- } else {
- return mpegts_raw_read_packet(s, pkt);
- }
+ ts->pkt = pkt;
+ return handle_packets(ts, 0);
}
static int mpegts_read_close(AVFormatContext *s)
@@ -1411,13 +1368,6 @@ static int mpegts_read_close(AVFormatContext *s)
for(i=0;i<NB_PID_MAX;i++)
if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]);
- for(i = 0; i < ts->nb_services; i++){
- av_free(ts->services[i]->provider_name);
- av_free(ts->services[i]->name);
- av_free(ts->services[i]);
- }
- av_freep(&ts->services);
-
return 0;
}
@@ -1427,16 +1377,15 @@ static 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, pid;
+ int pcr_l, pcr_pid = ((PESContext*)s->streams[stream_index]->priv_data)->pcr_pid;
const int find_next= 1;
pos = ((*ppos + ts->raw_packet_size - 1) / ts->raw_packet_size) * ts->raw_packet_size;
if (find_next) {
for(;;) {
- url_fseek(&s->pb, pos, SEEK_SET);
- if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ url_fseek(s->pb, pos, SEEK_SET);
+ if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
return AV_NOPTS_VALUE;
- pid = ((buf[1] & 0x1f) << 8) | buf[2];
- if (pid == ts->pcr_pid &&
+ if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
parse_pcr(&timestamp, &pcr_l, buf) == 0) {
break;
}
@@ -1447,11 +1396,10 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
pos -= ts->raw_packet_size;
if (pos < 0)
return AV_NOPTS_VALUE;
- url_fseek(&s->pb, pos, SEEK_SET);
- if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ url_fseek(s->pb, pos, SEEK_SET);
+ if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
return AV_NOPTS_VALUE;
- pid = ((buf[1] & 0x1f) << 8) | buf[2];
- if (pid == ts->pcr_pid &&
+ if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
parse_pcr(&timestamp, &pcr_l, buf) == 0) {
break;
}
@@ -1470,17 +1418,17 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, in
if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
return -1;
- pos= url_ftell(&s->pb);
+ pos= url_ftell(s->pb);
for(;;) {
- url_fseek(&s->pb, pos, SEEK_SET);
- if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ url_fseek(s->pb, pos, SEEK_SET);
+ if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
return -1;
-// pid = ((buf[1] & 0x1f) << 8) | buf[2];
+// pid = AV_RB16(buf + 1) & 0x1fff;
if(buf[1] & 0x40) break;
pos += ts->raw_packet_size;
}
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
return 0;
}
@@ -1513,7 +1461,7 @@ int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
ts->pkt = pkt;
ts->stop_parse = 0;
for(;;) {
- if (ts->stop_parse)
+ if (ts->stop_parse>0)
break;
if (len < TS_PACKET_SIZE)
return -1;
@@ -1550,3 +1498,16 @@ AVInputFormat mpegts_demuxer = {
mpegts_get_pcr,
.flags = AVFMT_SHOW_IDS,
};
+
+AVInputFormat mpegtsraw_demuxer = {
+ "mpegtsraw",
+ "MPEG2 raw transport stream format",
+ sizeof(MpegTSContext),
+ mpegts_probe,
+ mpegts_read_header,
+ mpegts_raw_read_packet,
+ mpegts_read_close,
+ read_seek,
+ mpegts_get_pcr,
+ .flags = AVFMT_SHOW_IDS,
+};
diff --git a/contrib/ffmpeg/libavformat/mpegts.h b/contrib/ffmpeg/libavformat/mpegts.h
index 771becbd4..bdfc760b3 100644
--- a/contrib/ffmpeg/libavformat/mpegts.h
+++ b/contrib/ffmpeg/libavformat/mpegts.h
@@ -19,6 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef FFMPEG_MPEGTS_H
+#define FFMPEG_MPEGTS_H
+
+#include "avformat.h"
+
#define TS_FEC_PACKET_SIZE 204
#define TS_DVHS_PACKET_SIZE 192
#define TS_PACKET_SIZE 188
@@ -50,14 +55,15 @@
#define STREAM_TYPE_AUDIO_AC3 0x81
#define STREAM_TYPE_AUDIO_DTS 0x8a
+#define STREAM_TYPE_AUDIO_HDMV_DTS 0x82
#define STREAM_TYPE_SUBTITLE_DVB 0x100
-extern AVOutputFormat mpegts_muxer;
-
typedef struct MpegTSContext MpegTSContext;
MpegTSContext *mpegts_parse_open(AVFormatContext *s);
int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
const uint8_t *buf, int len);
void mpegts_parse_close(MpegTSContext *ts);
+
+#endif /* FFMPEG_MPEGTS_H */
diff --git a/contrib/ffmpeg/libavformat/mpegtsenc.c b/contrib/ffmpeg/libavformat/mpegtsenc.c
index c521b68b8..49d29aa2b 100644
--- a/contrib/ffmpeg/libavformat/mpegtsenc.c
+++ b/contrib/ffmpeg/libavformat/mpegtsenc.c
@@ -43,7 +43,7 @@ static void mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len)
unsigned char *q;
int first, b, len1, left;
- crc = bswap_32(av_crc(av_crc04C11DB7, -1, buf, len - 4));
+ crc = bswap_32(av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, buf, len - 4));
buf[len - 4] = (crc >> 24) & 0xff;
buf[len - 3] = (crc >> 16) & 0xff;
buf[len - 2] = (crc >> 8) & 0xff;
@@ -353,7 +353,7 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts,
static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
{
AVFormatContext *ctx = s->opaque;
- put_buffer(&ctx->pb, packet, TS_PACKET_SIZE);
+ put_buffer(ctx->pb, packet, TS_PACKET_SIZE);
}
static int mpegts_write_header(AVFormatContext *s)
@@ -431,7 +431,7 @@ static int mpegts_write_header(AVFormatContext *s)
for(i = 0; i < ts->nb_services; i++) {
mpegts_write_pmt(s, ts->services[i]);
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
@@ -608,9 +608,9 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
memcpy(buf + TS_PACKET_SIZE - len, payload, len);
payload += len;
payload_size -= len;
- put_buffer(&s->pb, buf, TS_PACKET_SIZE);
+ put_buffer(s->pb, buf, TS_PACKET_SIZE);
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
}
static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
@@ -668,7 +668,7 @@ static int mpegts_write_end(AVFormatContext *s)
ts_st->payload_pts, ts_st->payload_dts);
}
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
for(i = 0; i < ts->nb_services; i++) {
service = ts->services[i];
diff --git a/contrib/ffmpeg/libavformat/mpjpeg.c b/contrib/ffmpeg/libavformat/mpjpeg.c
index 937917313..2e745721b 100644
--- a/contrib/ffmpeg/libavformat/mpjpeg.c
+++ b/contrib/ffmpeg/libavformat/mpjpeg.c
@@ -29,8 +29,8 @@ static int mpjpeg_write_header(AVFormatContext *s)
uint8_t buf1[256];
snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
- put_buffer(&s->pb, buf1, strlen(buf1));
- put_flush_packet(&s->pb);
+ put_buffer(s->pb, buf1, strlen(buf1));
+ put_flush_packet(s->pb);
return 0;
}
@@ -39,12 +39,12 @@ static int mpjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
uint8_t buf1[256];
snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
- put_buffer(&s->pb, buf1, strlen(buf1));
- put_buffer(&s->pb, pkt->data, pkt->size);
+ put_buffer(s->pb, buf1, strlen(buf1));
+ put_buffer(s->pb, pkt->data, pkt->size);
snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
- put_buffer(&s->pb, buf1, strlen(buf1));
- put_flush_packet(&s->pb);
+ put_buffer(s->pb, buf1, strlen(buf1));
+ put_flush_packet(s->pb);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/mtv.c b/contrib/ffmpeg/libavformat/mtv.c
index 7a68ea97f..32057e623 100644
--- a/contrib/ffmpeg/libavformat/mtv.c
+++ b/contrib/ffmpeg/libavformat/mtv.c
@@ -54,9 +54,6 @@ typedef struct MTVDemuxContext {
static int mtv_probe(AVProbeData *p)
{
- if(p->buf_size < 3)
- return 0;
-
/* Magic is 'AMV' */
if(*(p->buf) != 'A' || *(p->buf+1) != 'M' || *(p->buf+2) != 'V')
@@ -68,7 +65,7 @@ static int mtv_probe(AVProbeData *p)
static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
MTVDemuxContext *mtv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
@@ -89,7 +86,7 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* FIXME Add sanity check here */
- /* first packet is allways audio*/
+ /* first packet is always audio*/
mtv->audio_packet_count = 1;
@@ -99,7 +96,7 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
st = av_new_stream(s, VIDEO_SID);
if(!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 64, 1, mtv->video_fps);
st->codec->codec_type = CODEC_TYPE_VIDEO;
@@ -114,18 +111,18 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
st = av_new_stream(s, AUDIO_SID);
if(!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_MP3;
st->codec->bit_rate = mtv->audio_br;
- st->need_parsing=1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* Jump over header */
if(url_fseek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
return(0);
@@ -134,7 +131,7 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MTVDemuxContext *mtv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int ret;
#ifndef WORDS_BIGENDIAN
int i;
@@ -148,7 +145,7 @@ static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);
if(ret != MTV_ASUBCHUNK_DATA_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
mtv->audio_packet_count++;
pkt->stream_index = AUDIO_SID;
@@ -157,7 +154,7 @@ static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ret = av_get_packet(pb, pkt, mtv->img_segment_size);
if(ret != mtv->img_segment_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
#ifndef WORDS_BIGENDIAN
diff --git a/contrib/ffmpeg/libavformat/mxf.c b/contrib/ffmpeg/libavformat/mxf.c
index 677e023f0..0c69cd2e1 100644
--- a/contrib/ffmpeg/libavformat/mxf.c
+++ b/contrib/ffmpeg/libavformat/mxf.c
@@ -47,6 +47,7 @@
#include "avformat.h"
#include "aes.h"
+#include "bytestream.h"
typedef uint8_t UID[16];
@@ -60,18 +61,16 @@ enum MXFMetadataSetType {
MultipleDescriptor,
Descriptor,
Track,
- EssenceContainerData,
CryptoContext,
};
-typedef struct MXFCryptoContext {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
- UID context_uid;
UID source_container_ul;
} MXFCryptoContext;
-typedef struct MXFStructuralComponent {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
UID source_package_uid;
@@ -81,7 +80,7 @@ typedef struct MXFStructuralComponent {
int source_track_id;
} MXFStructuralComponent;
-typedef struct MXFSequence {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
UID data_definition_ul;
@@ -90,7 +89,7 @@ typedef struct MXFSequence {
int64_t duration;
} MXFSequence;
-typedef struct MXFTrack {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
MXFSequence *sequence; /* mandatory, and only one */
@@ -100,7 +99,7 @@ typedef struct MXFTrack {
AVRational edit_rate;
} MXFTrack;
-typedef struct MXFDescriptor {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
UID essence_container_ul;
@@ -118,7 +117,7 @@ typedef struct MXFDescriptor {
int extradata_size;
} MXFDescriptor;
-typedef struct MXFPackage {
+typedef struct {
UID uid;
enum MXFMetadataSetType type;
UID package_uid;
@@ -128,28 +127,23 @@ typedef struct MXFPackage {
UID descriptor_ref;
} MXFPackage;
-typedef struct MXFEssenceContainerData {
- UID uid;
- enum MXFMetadataSetType type;
- UID linked_package_uid;
-} MXFEssenceContainerData;
-
typedef struct {
UID uid;
enum MXFMetadataSetType type;
} MXFMetadataSet;
-typedef struct MXFContext {
+typedef struct {
UID *packages_refs;
int packages_count;
MXFMetadataSet **metadata_sets;
int metadata_sets_count;
- const uint8_t *sync_key;
AVFormatContext *fc;
struct AVAES *aesc;
+ uint8_t *local_tags;
+ int local_tags_count;
} MXFContext;
-typedef struct KLVPacket {
+typedef struct {
UID key;
offset_t offset;
uint64_t length;
@@ -160,18 +154,18 @@ enum MXFWrappingScheme {
Clip,
};
-typedef struct MXFCodecUL {
+typedef struct {
UID uid;
+ unsigned matching_len;
enum CodecID id;
- enum MXFWrappingScheme wrapping;
} MXFCodecUL;
-typedef struct MXFDataDefinitionUL {
+typedef struct {
UID uid;
enum CodecType type;
} MXFDataDefinitionUL;
-typedef struct MXFMetadataReadTableEntry {
+typedef struct {
const UID key;
int (*read)();
int ctx_size;
@@ -181,9 +175,12 @@ typedef struct MXFMetadataReadTableEntry {
/* partial keys to match */
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_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_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)))
@@ -205,10 +202,26 @@ static int64_t klv_decode_ber_length(ByteIOContext *pb)
return size;
}
+static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size)
+{
+ int i, b;
+ for (i = 0; i < size && !url_feof(pb); i++) {
+ b = get_byte(pb);
+ if (b == key[0])
+ i = 0;
+ else if (b != key[i])
+ i = -1;
+ }
+ return i == size;
+}
+
static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb)
{
- klv->offset = url_ftell(pb);
- get_buffer(pb, klv->key, 16);
+ if (!mxf_read_sync(pb, mxf_klv_key, 4))
+ return -1;
+ klv->offset = url_ftell(pb) - 4;
+ memcpy(klv->key, mxf_klv_key, 4);
+ get_buffer(pb, klv->key + 4, 12);
klv->length = klv_decode_ber_length(pb);
return klv->length == -1 ? -1 : 0;
}
@@ -231,7 +244,9 @@ static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv)
static int mxf_get_d10_aes3_packet(ByteIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length)
{
uint8_t buffer[61444];
- uint8_t *buf_ptr, *end_ptr, *data_ptr;
+ const uint8_t *buf_ptr, *end_ptr;
+ uint8_t *data_ptr;
+ int i;
if (length > 61444) /* worst case PAL 1920 samples 8 channels */
return -1;
@@ -240,17 +255,15 @@ static int mxf_get_d10_aes3_packet(ByteIOContext *pb, AVStream *st, AVPacket *pk
data_ptr = pkt->data;
end_ptr = buffer + length;
buf_ptr = buffer + 4; /* skip SMPTE 331M header */
- for (; buf_ptr < end_ptr; buf_ptr += 4) {
- if (st->codec->bits_per_sample == 24) {
- data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
- data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
- data_ptr[2] = (buf_ptr[0] >> 4) | ((buf_ptr[1] & 0x0f) << 4);
- data_ptr += 3;
- } else {
- data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
- data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
- data_ptr += 2;
+ for (; buf_ptr < end_ptr; ) {
+ for (i = 0; i < st->codec->channels; i++) {
+ uint32_t sample = bytestream_get_le32(&buf_ptr);
+ if (st->codec->bits_per_sample == 24)
+ bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff);
+ else
+ bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff);
}
+ buf_ptr += 32 - st->codec->channels*4; // always 8 channels stored SMPTE 331M
}
pkt->size = data_ptr - pkt->data;
return 0;
@@ -260,7 +273,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv
{
static const uint8_t checkv[16] = {0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b};
MXFContext *mxf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t end = url_ftell(pb) + klv->length;
uint64_t size;
uint64_t orig_size;
@@ -271,6 +284,8 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv
if (!mxf->aesc && s->key && s->keylen == 16) {
mxf->aesc = av_malloc(av_aes_size);
+ if (!mxf->aesc)
+ return -1;
av_aes_init(mxf->aesc, s->key, 128, 1);
}
// crypto context
@@ -281,16 +296,20 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv
// source klv key
klv_decode_ber_length(pb);
get_buffer(pb, klv->key, 16);
- if (!IS_KLV_KEY(klv, mxf_essence_element_key)) goto err_out;
+ if (!IS_KLV_KEY(klv, mxf_essence_element_key))
+ return -1;
index = mxf_get_stream_index(s, klv);
- if (index < 0) goto err_out;
+ if (index < 0)
+ return -1;
// source size
klv_decode_ber_length(pb);
orig_size = get_be64(pb);
- if (orig_size < plaintext_size) goto err_out;
+ if (orig_size < plaintext_size)
+ return -1;
// enc. code
size = klv_decode_ber_length(pb);
- if (size < 32 || size - 32 < orig_size) goto err_out;
+ if (size < 32 || size - 32 < orig_size)
+ return -1;
get_buffer(pb, ivec, 16);
get_buffer(pb, tmpbuf, 16);
if (mxf->aesc)
@@ -307,28 +326,20 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv
pkt->stream_index = index;
url_fskip(pb, end - url_ftell(pb));
return 0;
-
-err_out:
- url_fskip(pb, end - url_ftell(pb));
- return -1;
}
static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- MXFContext *mxf = s->priv_data;
KLVPacket klv;
- while (!url_feof(&s->pb)) {
- if (klv_read_packet(&klv, &s->pb) < 0) {
- av_log(s, AV_LOG_ERROR, "error reading KLV packet\n");
+ while (!url_feof(s->pb)) {
+ if (klv_read_packet(&klv, s->pb) < 0)
return -1;
- }
#ifdef DEBUG
PRINT_KEY(s, "read packet", klv.key);
#endif
if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {
int res = mxf_decrypt_triplet(s, pkt, &klv);
- mxf->sync_key = mxf_encrypted_triplet_key;
if (res < 0) {
av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");
return -1;
@@ -339,47 +350,66 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
int index = mxf_get_stream_index(s, &klv);
if (index < 0) {
av_log(s, AV_LOG_ERROR, "error getting stream index\n");
- url_fskip(&s->pb, klv.length);
+ url_fskip(s->pb, klv.length);
return -1;
}
/* 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) {
+ if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) {
av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
return -1;
}
} else
- av_get_packet(&s->pb, pkt, klv.length);
+ av_get_packet(s->pb, pkt, klv.length);
pkt->stream_index = index;
+ pkt->pos = klv.offset;
return 0;
} else
- url_fskip(&s->pb, klv.length);
+ url_fskip(s->pb, klv.length);
+ }
+ return AVERROR(EIO);
+}
+
+static int mxf_read_primer_pack(MXFContext *mxf)
+{
+ ByteIOContext *pb = mxf->fc->pb;
+ int item_num = get_be32(pb);
+ int item_len = get_be32(pb);
+
+ if (item_len != 18) {
+ av_log(mxf->fc, AV_LOG_ERROR, "unsupported primer pack item length\n");
+ return -1;
}
- return AVERROR_IO;
+ if (item_num > UINT_MAX / item_len)
+ return -1;
+ mxf->local_tags_count = item_num;
+ mxf->local_tags = av_malloc(item_num*item_len);
+ if (!mxf->local_tags)
+ return -1;
+ get_buffer(pb, mxf->local_tags, item_num*item_len);
+ return 0;
}
static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set)
{
mxf->metadata_sets = av_realloc(mxf->metadata_sets, (mxf->metadata_sets_count + 1) * sizeof(*mxf->metadata_sets));
+ if (!mxf->metadata_sets)
+ return -1;
mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set;
mxf->metadata_sets_count++;
return 0;
}
-static int mxf_read_metadata_cryptographic_context(MXFCryptoContext *cryptocontext, ByteIOContext *pb, int tag)
+static int mxf_read_cryptographic_context(MXFCryptoContext *cryptocontext, ByteIOContext *pb, int tag, int size, UID uid)
{
- switch(tag) {
- case 0xFFFE:
- get_buffer(pb, cryptocontext->context_uid, 16);
- break;
- case 0xFFFD:
+ if (size != 16)
+ return -1;
+ if (IS_KLV_KEY(uid, mxf_crypto_source_container_ul))
get_buffer(pb, cryptocontext->source_container_ul, 16);
- break;
- }
return 0;
}
-static int mxf_read_metadata_content_storage(MXFContext *mxf, ByteIOContext *pb, int tag)
+static int mxf_read_content_storage(MXFContext *mxf, ByteIOContext *pb, int tag)
{
switch (tag) {
case 0x1901:
@@ -387,6 +417,8 @@ static int mxf_read_metadata_content_storage(MXFContext *mxf, ByteIOContext *pb,
if (mxf->packages_count >= UINT_MAX / sizeof(UID))
return -1;
mxf->packages_refs = av_malloc(mxf->packages_count * sizeof(UID));
+ if (!mxf->packages_refs)
+ return -1;
url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
get_buffer(pb, (uint8_t *)mxf->packages_refs, mxf->packages_count * sizeof(UID));
break;
@@ -394,7 +426,7 @@ static int mxf_read_metadata_content_storage(MXFContext *mxf, ByteIOContext *pb,
return 0;
}
-static int mxf_read_metadata_source_clip(MXFStructuralComponent *source_clip, ByteIOContext *pb, int tag)
+static int mxf_read_source_clip(MXFStructuralComponent *source_clip, ByteIOContext *pb, int tag)
{
switch(tag) {
case 0x0202:
@@ -415,7 +447,7 @@ static int mxf_read_metadata_source_clip(MXFStructuralComponent *source_clip, By
return 0;
}
-static int mxf_read_metadata_material_package(MXFPackage *package, ByteIOContext *pb, int tag)
+static int mxf_read_material_package(MXFPackage *package, ByteIOContext *pb, int tag)
{
switch(tag) {
case 0x4403:
@@ -423,6 +455,8 @@ static int mxf_read_metadata_material_package(MXFPackage *package, ByteIOContext
if (package->tracks_count >= UINT_MAX / sizeof(UID))
return -1;
package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
+ if (!package->tracks_refs)
+ return -1;
url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
get_buffer(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
break;
@@ -430,7 +464,7 @@ static int mxf_read_metadata_material_package(MXFPackage *package, ByteIOContext
return 0;
}
-static int mxf_read_metadata_track(MXFTrack *track, ByteIOContext *pb, int tag)
+static int mxf_read_track(MXFTrack *track, ByteIOContext *pb, int tag)
{
switch(tag) {
case 0x4801:
@@ -450,7 +484,7 @@ static int mxf_read_metadata_track(MXFTrack *track, ByteIOContext *pb, int tag)
return 0;
}
-static int mxf_read_metadata_sequence(MXFSequence *sequence, ByteIOContext *pb, int tag)
+static int mxf_read_sequence(MXFSequence *sequence, ByteIOContext *pb, int tag)
{
switch(tag) {
case 0x0202:
@@ -464,6 +498,8 @@ static int mxf_read_metadata_sequence(MXFSequence *sequence, ByteIOContext *pb,
if (sequence->structural_components_count >= UINT_MAX / sizeof(UID))
return -1;
sequence->structural_components_refs = av_malloc(sequence->structural_components_count * sizeof(UID));
+ if (!sequence->structural_components_refs)
+ return -1;
url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
get_buffer(pb, (uint8_t *)sequence->structural_components_refs, sequence->structural_components_count * sizeof(UID));
break;
@@ -471,7 +507,7 @@ static int mxf_read_metadata_sequence(MXFSequence *sequence, ByteIOContext *pb,
return 0;
}
-static int mxf_read_metadata_source_package(MXFPackage *package, ByteIOContext *pb, int tag)
+static int mxf_read_source_package(MXFPackage *package, ByteIOContext *pb, int tag)
{
switch(tag) {
case 0x4403:
@@ -479,6 +515,8 @@ static int mxf_read_metadata_source_package(MXFPackage *package, ByteIOContext *
if (package->tracks_count >= UINT_MAX / sizeof(UID))
return -1;
package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
+ if (!package->tracks_refs)
+ return -1;
url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
get_buffer(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
break;
@@ -494,7 +532,7 @@ static int mxf_read_metadata_source_package(MXFPackage *package, ByteIOContext *
return 0;
}
-static void mxf_read_metadata_pixel_layout(ByteIOContext *pb, MXFDescriptor *descriptor)
+static void mxf_read_pixel_layout(ByteIOContext *pb, MXFDescriptor *descriptor)
{
int code;
@@ -517,7 +555,7 @@ static void mxf_read_metadata_pixel_layout(ByteIOContext *pb, MXFDescriptor *des
} while (code != 0); /* SMPTE 377M E.2.46 */
}
-static int mxf_read_metadata_generic_descriptor(MXFDescriptor *descriptor, ByteIOContext *pb, int tag, int size)
+static int mxf_read_generic_descriptor(MXFDescriptor *descriptor, ByteIOContext *pb, int tag, int size, UID uid)
{
switch(tag) {
case 0x3F01:
@@ -525,6 +563,8 @@ static int mxf_read_metadata_generic_descriptor(MXFDescriptor *descriptor, ByteI
if (descriptor->sub_descriptors_count >= UINT_MAX / sizeof(UID))
return -1;
descriptor->sub_descriptors_refs = av_malloc(descriptor->sub_descriptors_count * sizeof(UID));
+ if (!descriptor->sub_descriptors_refs)
+ return -1;
url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
get_buffer(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID));
break;
@@ -561,12 +601,17 @@ static int mxf_read_metadata_generic_descriptor(MXFDescriptor *descriptor, ByteI
descriptor->bits_per_sample = get_be32(pb);
break;
case 0x3401:
- mxf_read_metadata_pixel_layout(pb, descriptor);
+ mxf_read_pixel_layout(pb, descriptor);
break;
- case 0x8201: /* Private tag used by SONY C0023S01.mxf */
- descriptor->extradata = av_malloc(size);
- descriptor->extradata_size = size;
- get_buffer(pb, descriptor->extradata, size);
+ default:
+ /* Private uid used by SONY C0023S01.mxf */
+ if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) {
+ descriptor->extradata = av_malloc(size);
+ if (!descriptor->extradata)
+ return -1;
+ descriptor->extradata_size = size;
+ get_buffer(pb, descriptor->extradata, size);
+ }
break;
}
return 0;
@@ -582,55 +627,56 @@ static const MXFDataDefinitionUL mxf_data_definition_uls[] = {
static const MXFCodecUL mxf_codec_uls[] = {
/* PictureEssenceCoding */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML I-Frame */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL I-Frame */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL Long GoP */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@ML Long GoP */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML Long GoP */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@HL Long GoP */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, CODEC_ID_MPEG4, Frame }, /* XDCAM proxy_pal030926.mxf */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x04 }, CODEC_ID_MPEG4, Frame }, /* XDCAM Proxy C0023S01.mxf */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 30Mbps PAL */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 50Mbps PAL */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO50 PAL */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO25 PAL */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DV25 IEC PAL */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_JPEG2000, Frame }, /* JPEG2000 Codestream */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_RAWVIDEO, Frame }, /* Uncompressed */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* MP@ML Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* D-10 50Mbps PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* MP@HL Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* 422P@HL I-Frame */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, 14, CODEC_ID_MPEG4 }, /* XDCAM proxy_pal030926.mxf */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13, CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, CODEC_ID_RAWVIDEO }, /* Uncompressed */
/* SoundEssenceCompression */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* Uncompressed */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame },
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, CODEC_ID_PCM_S16BE, Frame }, /* From Omneon MXF file */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame },
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame }, /* XDCAM Proxy C0023S01.mxf */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, CODEC_ID_AC3, Frame },
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, CODEC_ID_MP2, Frame }, /* MP2 or MP3 */
- //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, CODEC_ID_DOLBY_E, Frame }, /* Dolby-E */
- { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, CODEC_ID_PCM_S16LE }, /* Uncompressed */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, CODEC_ID_PCM_S16LE },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13, CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15, CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15, CODEC_ID_AC3 },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15, CODEC_ID_MP2 }, /* MP2 or MP3 */
+ //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15, CODEC_ID_DOLBY_E }, /* Dolby-E */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE },
};
static const MXFCodecUL mxf_picture_essence_container_uls[] = {
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MPEG-ES Frame wrapped */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xe0,0x02 }, CODEC_ID_MPEG2VIDEO, Clip }, /* MPEG-ES Clip wrapped, 0xe0 MPV stream id */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x04,0x61,0x07 }, CODEC_ID_MPEG2VIDEO, Clip }, /* MPEG-ES Custom wrapped, 0x61 ??? stream id */
- { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE },
};
static const MXFCodecUL mxf_sound_essence_container_uls[] = {
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* BWF Frame wrapped */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x03,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* AES Frame wrapped */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x01 }, CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0xc0 MPA stream id */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x02 }, CODEC_ID_MP2, Clip }, /* MPEG-ES Clip wrapped, 0xc0 MPA stream id */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 30Mbps PAL Extended Template */
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 50Mbps PAL Extended Template */
- { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, 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, CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE },
};
+/*
+ * Match an uid independently of the version byte and up to len common bytes
+ * Returns: boolean
+ */
+static int mxf_match_uid(const UID key, const UID uid, int len)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ if (i != 7 && key[i] != uid[i])
+ return 0;
+ }
+ return 1;
+}
+
static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid)
{
while (uls->id != CODEC_ID_NONE) {
- if(!memcmp(uls->uid, *uid, 16))
+ if(mxf_match_uid(uls->uid, *uid, uls->matching_len))
break;
uls++;
}
@@ -640,7 +686,7 @@ static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid)
static enum CodecType mxf_get_codec_type(const MXFDataDefinitionUL *uls, UID *uid)
{
while (uls->type != CODEC_TYPE_DATA) {
- if(!memcmp(uls->uid, *uid, 16))
+ if(mxf_match_uid(uls->uid, *uid, 16))
break;
uls++;
}
@@ -740,6 +786,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
continue;
st = av_new_stream(mxf->fc, source_track->track_id);
+ if (!st) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not allocate stream\n");
+ return -1;
+ }
st->priv_data = source_track;
st->duration = component->duration;
if (st->duration == -1)
@@ -810,7 +860,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
st->codec->width = descriptor->width;
st->codec->height = descriptor->height;
st->codec->bits_per_sample = descriptor->bits_per_sample; /* Uncompressed */
- st->need_parsing = 2; /* only parse headers */
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
} else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
if (st->codec->codec_id == CODEC_ID_NONE)
@@ -829,71 +879,73 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
st->codec->codec_id = CODEC_ID_PCM_S24BE;
else if (descriptor->bits_per_sample == 32)
st->codec->codec_id = CODEC_ID_PCM_S32BE;
- if (descriptor->essence_container_ul[13] == 0x01) /* D-10 Mapping */
- st->codec->channels = 8; /* force channels to 8 */
} else if (st->codec->codec_id == CODEC_ID_MP2) {
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
}
}
- if (container_ul && container_ul->wrapping == Clip) {
- dprintf(mxf->fc, "stream %d: clip wrapped essence\n", st->index);
- st->need_parsing = 1;
+ if (st->codec->codec_type != CODEC_TYPE_DATA && (*essence_container_ul)[15] > 0x01) {
+ av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are correctly supported\n");
+ st->need_parsing = AVSTREAM_PARSE_FULL;
}
}
return 0;
}
static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_metadata_content_storage, 0, AnyType },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_metadata_source_package, sizeof(MXFPackage), SourcePackage },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_metadata_material_package, sizeof(MXFPackage), MaterialPackage },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_metadata_sequence, sizeof(MXFSequence), Sequence },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_metadata_source_clip, sizeof(MXFStructuralComponent), SourceClip },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_metadata_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_metadata_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_metadata_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_metadata_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_metadata_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_metadata_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_metadata_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_metadata_track, sizeof(MXFTrack), Track }, /* Static Track */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_metadata_track, sizeof(MXFTrack), Track }, /* Generic Track */
- { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_metadata_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
+ { { 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,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,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },
};
-static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size)
-{
- int i, b;
- for (i = 0; i < size && !url_feof(pb); i++) {
- b = get_byte(pb);
- if (b == key[0])
- i = 0;
- else if (b != key[i])
- i = -1;
- }
- return i == size;
-}
-
static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, int (*read_child)(), int ctx_size, enum MXFMetadataSetType type)
{
- ByteIOContext *pb = &mxf->fc->pb;
+ ByteIOContext *pb = mxf->fc->pb;
MXFMetadataSet *ctx = ctx_size ? av_mallocz(ctx_size) : mxf;
- uint64_t klv_end= url_ftell(pb) + klv->length;
+ uint64_t klv_end = url_ftell(pb) + klv->length;
+ if (!ctx)
+ return -1;
while (url_ftell(pb) + 4 < klv_end) {
int tag = get_be16(pb);
int size = get_be16(pb); /* KLV specified by 0x53 */
- uint64_t next= url_ftell(pb) + size;
+ uint64_t next = url_ftell(pb) + size;
+ UID uid = {0};
if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */
av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag);
continue;
}
- if(ctx_size && tag == 0x3C0A)
+ if (tag > 0x7FFF) { /* dynamic tag */
+ int i;
+ for (i = 0; i < mxf->local_tags_count; i++) {
+ int local_tag = AV_RB16(mxf->local_tags+i*18);
+ if (local_tag == tag) {
+ memcpy(uid, mxf->local_tags+i*18+2, 16);
+ dprintf(mxf->fc, "local tag 0x%04X\n", local_tag);
+#ifdef DEBUG
+ PRINT_KEY(mxf->fc, "uid", uid);
+#endif
+ }
+ }
+ }
+ if (ctx_size && tag == 0x3C0A)
get_buffer(pb, ctx->uid, 16);
- else
- read_child(ctx, pb, tag, size);
+ else if (read_child(ctx, pb, tag, size, uid) < 0)
+ return -1;
url_fseek(pb, next, SEEK_SET);
}
@@ -906,33 +958,31 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
MXFContext *mxf = s->priv_data;
KLVPacket klv;
- mxf->sync_key = mxf_essence_element_key;
- if (!mxf_read_sync(&s->pb, mxf_header_partition_pack_key, 14)) {
+ if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) {
av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
return -1;
}
- url_fseek(&s->pb, -14, SEEK_CUR);
+ url_fseek(s->pb, -14, SEEK_CUR);
mxf->fc = s;
- while (!url_feof(&s->pb)) {
+ while (!url_feof(s->pb)) {
const MXFMetadataReadTableEntry *metadata;
- if (klv_read_packet(&klv, &s->pb) < 0) {
- av_log(s, AV_LOG_ERROR, "error reading KLV packet\n");
+ if (klv_read_packet(&klv, s->pb) < 0)
return -1;
- }
#ifdef DEBUG
PRINT_KEY(s, "read header", klv.key);
#endif
if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) ||
IS_KLV_KEY(klv.key, mxf_essence_element_key)) {
/* FIXME avoid seek */
- url_fseek(&s->pb, klv.offset, SEEK_SET);
+ url_fseek(s->pb, klv.offset, SEEK_SET);
break;
}
for (metadata = mxf_metadata_read_table; metadata->read; metadata++) {
if (IS_KLV_KEY(klv.key, metadata->key)) {
- if (mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type) < 0) {
+ int (*read)() = klv.key[5] == 0x53 ? mxf_read_local_tags : metadata->read;
+ if (read(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type) < 0) {
av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
return -1;
}
@@ -940,7 +990,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
}
if (!metadata->read)
- url_fskip(&s->pb, klv.length);
+ url_fskip(s->pb, klv.length);
}
return mxf_parse_structural_metadata(mxf);
}
@@ -970,6 +1020,7 @@ static int mxf_read_close(AVFormatContext *s)
}
av_freep(&mxf->metadata_sets);
av_freep(&mxf->aesc);
+ av_freep(&mxf->local_tags);
return 0;
}
@@ -989,11 +1040,10 @@ static int mxf_probe(AVProbeData *p) {
return 0;
}
-/* rudimentary binary seek */
+/* rudimentary byte seek */
/* XXX: use MXF Index */
static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
{
- MXFContext *mxf = s->priv_data;
AVStream *st = s->streams[stream_index];
int64_t seconds;
@@ -1002,12 +1052,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
if (sample_time < 0)
sample_time = 0;
seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den);
- url_fseek(&s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
- if (!mxf_read_sync(&s->pb, mxf->sync_key, 12))
- return -1;
-
- /* found KLV key */
- url_fseek(&s->pb, -12, SEEK_CUR);
+ url_fseek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
av_update_cur_dts(s, st, sample_time);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/network.h b/contrib/ffmpeg/libavformat/network.h
index 3aa8ba836..d897722c9 100644
--- a/contrib/ffmpeg/libavformat/network.h
+++ b/contrib/ffmpeg/libavformat/network.h
@@ -18,20 +18,52 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef NETWORK_H
-#define NETWORK_H
+#ifndef FFMPEG_NETWORK_H
+#define FFMPEG_NETWORK_H
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#define ff_neterrno() WSAGetLastError()
+#define FF_NETERROR(err) WSA##err
+#define WSAEAGAIN WSAEWOULDBLOCK
+#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netdb.h>
+
+#define ff_neterrno() errno
+#define FF_NETERROR(err) err
+#endif
+
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#include <netdb.h>
+
+int ff_socket_nonblock(int socket, int enable);
+
+static inline int ff_network_init(void)
+{
+#ifdef HAVE_WINSOCK2_H
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(1,1), &wsaData))
+ return 0;
+#endif
+ return 1;
+}
+
+static inline void ff_network_close(void)
+{
+#ifdef HAVE_WINSOCK2_H
+ WSACleanup();
+#endif
+}
#if !defined(HAVE_INET_ATON)
/* in os_support.c */
int inet_aton (const char * str, struct in_addr * add);
#endif
-#endif
+#endif /* FFMPEG_NETWORK_H */
diff --git a/contrib/ffmpeg/libavformat/nsvdec.c b/contrib/ffmpeg/libavformat/nsvdec.c
index 2753edbd9..a115fe571 100644
--- a/contrib/ffmpeg/libavformat/nsvdec.c
+++ b/contrib/ffmpeg/libavformat/nsvdec.c
@@ -91,7 +91,7 @@
struct NSVf_header {
uint32_t chunk_tag; /* 'NSVf' */
uint32_t chunk_size;
- uint32_t file_size; /* max 4GB ??? noone learns anything it seems :^) */
+ uint32_t file_size; /* max 4GB ??? no one learns anything it seems :^) */
uint32_t file_length; //unknown1; /* what about MSB of file_size ? */
uint32_t info_strings_size; /* size of the info strings */ //unknown2;
uint32_t table_entries;
@@ -197,7 +197,7 @@ static const AVCodecTag nsv_codec_video_tags[] = {
{ CODEC_ID_VP4, MKTAG('V', 'P', '4', ' ') },
{ CODEC_ID_VP4, MKTAG('V', 'P', '4', '0') },
*/
- { CODEC_ID_XVID, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
+ { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
{ CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
{ 0, 0 },
};
@@ -228,7 +228,7 @@ static void print_tag(const char *str, unsigned int tag, int size)
static int nsv_resync(AVFormatContext *s)
{
NSVContext *nsv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t v = 0;
int i;
@@ -275,7 +275,7 @@ static int nsv_resync(AVFormatContext *s)
static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
{
NSVContext *nsv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned int file_size, size;
int64_t duration;
int strings_size;
@@ -394,7 +394,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
{
NSVContext *nsv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t vtag, atag;
uint16_t vwidth, vheight;
AVRational framerate;
@@ -474,7 +474,7 @@ static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_tag = atag;
st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag);
- st->need_parsing = 1; /* for PCM we will read a chunk later and put correct info */
+ st->need_parsing = AVSTREAM_PARSE_FULL; /* for PCM we will read a chunk later and put correct info */
/* set timebase to common denominator of ms and framerate */
av_set_pts_info(st, 64, 1, framerate.num*1000);
@@ -533,7 +533,7 @@ static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int nsv_read_chunk(AVFormatContext *s, int fill_header)
{
NSVContext *nsv = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st[2] = {NULL, NULL};
NSVStream *nst;
AVPacket *pkt;
@@ -609,7 +609,8 @@ null_chunk_retry:
PRINT(("NSV video: [%d] = %02x\n", i, pkt->data[i]));
*/
}
- ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
+ if(st[NSV_ST_VIDEO])
+ ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
if (asize/*st[NSV_ST_AUDIO]*/) {
nst = st[NSV_ST_AUDIO]->priv_data;
@@ -626,7 +627,7 @@ null_chunk_retry:
asize-=4;
PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
if (fill_header) {
- st[NSV_ST_AUDIO]->need_parsing = 0; /* we know everything */
+ st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE; /* we know everything */
if (bps != 16) {
PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps));
}
@@ -728,14 +729,9 @@ static int nsv_probe(AVProbeData *p)
int i;
// PRINT(("nsv_probe(), buf_size %d\n", p->buf_size));
/* check file header */
- if (p->buf_size <= 32)
- return 0;
- if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
- p->buf[2] == 'V' && p->buf[3] == 'f')
- return AVPROBE_SCORE_MAX;
/* streamed files might not have any header */
if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
- p->buf[2] == 'V' && p->buf[3] == 's')
+ p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
return AVPROBE_SCORE_MAX;
/* XXX: do streamed files always start at chunk boundary ?? */
/* or do we need to search NSVs in the byte stream ? */
@@ -748,7 +744,7 @@ static int nsv_probe(AVProbeData *p)
}
/* so we'll have more luck on extension... */
if (match_ext(p->filename, "nsv"))
- return AVPROBE_SCORE_MAX-20;
+ return AVPROBE_SCORE_MAX/2;
/* FIXME: add mime-type check */
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/nut.c b/contrib/ffmpeg/libavformat/nut.c
index 995149951..fdcaac6a3 100644
--- a/contrib/ffmpeg/libavformat/nut.c
+++ b/contrib/ffmpeg/libavformat/nut.c
@@ -1,7 +1,6 @@
/*
- * "NUT" Container Format muxer and demuxer (DRAFT-200403??)
- * Copyright (c) 2003 Alex Beregszaszi
- * Copyright (c) 2004 Michael Niedermayer
+ * nut
+ * Copyright (c) 2004-2007 Michael Niedermayer
*
* This file is part of FFmpeg.
*
@@ -18,1440 +17,46 @@
* 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
- *
- *
- * Visit the official site at http://www.nut.hu/
- *
*/
-/*
- * TODO:
- * - index writing
- * - index packet reading support
-*/
-
-//#define DEBUG 1
-
-#include <limits.h>
-#include "avformat.h"
-#include "mpegaudio.h"
-#include "riff.h"
-#include "adler32.h"
-
-#undef NDEBUG
-#include <assert.h>
-
-//#define TRACE
-
-//from /dev/random
-
-#define MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48))
-#define STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48))
-#define KEYFRAME_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48))
-#define INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48))
-#define INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48))
-
-#define ID_STRING "nut/multimedia container\0"
-
-#define MAX_DISTANCE (1024*16-1)
-#define MAX_SHORT_DISTANCE (1024*4-1)
-
-#define FLAG_DATA_SIZE 1
-#define FLAG_KEY_FRAME 2
-#define FLAG_INVALID 4
-
-typedef struct {
- uint8_t flags;
- uint8_t stream_id_plus1;
- uint16_t size_mul;
- uint16_t size_lsb;
- int16_t timestamp_delta;
- uint8_t reserved_count;
-} FrameCode;
-
-typedef struct {
- int last_key_frame;
- int msb_timestamp_shift;
- int rate_num;
- int rate_den;
- int64_t last_pts;
- int64_t last_sync_pos; ///<pos of last 1/2 type frame
- int decode_delay;
-} StreamContext;
-
-typedef struct {
- AVFormatContext *avf;
- int written_packet_size;
- int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
- FrameCode frame_code[256];
- unsigned int stream_count;
- uint64_t next_startcode; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
- StreamContext *stream;
- int max_distance;
- int max_short_distance;
- int rate_num;
- int rate_den;
- int short_startcode;
-} NUTContext;
-
-static char *info_table[][2]={
- {NULL , NULL }, // end
- {NULL , NULL },
- {NULL , "UTF8"},
- {NULL , "v"},
- {NULL , "s"},
- {"StreamId" , "v"},
- {"SegmentId" , "v"},
- {"StartTimestamp" , "v"},
- {"EndTimestamp" , "v"},
- {"Author" , "UTF8"},
- {"Title" , "UTF8"},
- {"Description" , "UTF8"},
- {"Copyright" , "UTF8"},
- {"Encoder" , "UTF8"},
- {"Keyword" , "UTF8"},
- {"Cover" , "JPEG"},
- {"Cover" , "PNG"},
-};
-
-static void update(NUTContext *nut, int stream_index, int64_t frame_start, int frame_type, int frame_code, int key_frame, int size, int64_t pts){
- StreamContext *stream= &nut->stream[stream_index];
-
- stream->last_key_frame= key_frame;
- nut->packet_start[ frame_type ]= frame_start;
- stream->last_pts= pts;
-}
+#include "nut.h"
+#include "tree.h"
-static void reset(AVFormatContext *s, int64_t global_ts){
- NUTContext *nut = s->priv_data;
+void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val){
int i;
-
- for(i=0; i<s->nb_streams; i++){
- StreamContext *stream= &nut->stream[i];
-
- stream->last_key_frame= 1;
-
- stream->last_pts= av_rescale(global_ts, stream->rate_num*(int64_t)nut->rate_den, stream->rate_den*(int64_t)nut->rate_num);
- }
-}
-
-static void build_frame_code(AVFormatContext *s){
- NUTContext *nut = s->priv_data;
- int key_frame, index, pred, stream_id;
- int start=0;
- int end= 255;
- int keyframe_0_esc= s->nb_streams > 2;
- int pred_table[10];
-
- if(keyframe_0_esc){
- /* keyframe = 0 escape */
- FrameCode *ft= &nut->frame_code[start];
- ft->flags= FLAG_DATA_SIZE;
- ft->stream_id_plus1= 0;
- ft->size_mul=1;
- ft->timestamp_delta=0;
- start++;
- }
-
- for(stream_id= 0; stream_id<s->nb_streams; stream_id++){
- int start2= start + (end-start)*stream_id / s->nb_streams;
- int end2 = start + (end-start)*(stream_id+1) / s->nb_streams;
- AVCodecContext *codec = s->streams[stream_id]->codec;
- int is_audio= codec->codec_type == CODEC_TYPE_AUDIO;
- int intra_only= /*codec->intra_only || */is_audio;
- int pred_count;
-
- for(key_frame=0; key_frame<2; key_frame++){
- if(intra_only && keyframe_0_esc && key_frame==0)
- continue;
-
- {
- FrameCode *ft= &nut->frame_code[start2];
- ft->flags= FLAG_KEY_FRAME*key_frame;
- ft->flags|= FLAG_DATA_SIZE;
- ft->stream_id_plus1= stream_id + 1;
- ft->size_mul=1;
- ft->timestamp_delta=0;
- start2++;
- }
- }
-
- key_frame= intra_only;
-#if 1
- if(is_audio){
- int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);
- int pts;
- for(pts=0; pts<2; pts++){
- for(pred=0; pred<2; pred++){
- FrameCode *ft= &nut->frame_code[start2];
- ft->flags= FLAG_KEY_FRAME*key_frame;
- ft->stream_id_plus1= stream_id + 1;
- ft->size_mul=frame_bytes + 2;
- ft->size_lsb=frame_bytes + pred;
- ft->timestamp_delta=pts;
- start2++;
- }
- }
- }else{
- FrameCode *ft= &nut->frame_code[start2];
- ft->flags= FLAG_KEY_FRAME | FLAG_DATA_SIZE;
- ft->stream_id_plus1= stream_id + 1;
- ft->size_mul=1;
- ft->timestamp_delta=1;
- start2++;
- }
-#endif
-
- if(codec->has_b_frames){
- pred_count=5;
- pred_table[0]=-2;
- pred_table[1]=-1;
- pred_table[2]=1;
- pred_table[3]=3;
- pred_table[4]=4;
- }else if(codec->codec_id == CODEC_ID_VORBIS){
- pred_count=3;
- pred_table[0]=2;
- pred_table[1]=9;
- pred_table[2]=16;
- }else{
- pred_count=1;
- pred_table[0]=1;
- }
-
- for(pred=0; pred<pred_count; pred++){
- int start3= start2 + (end2-start2)*pred / pred_count;
- int end3 = start2 + (end2-start2)*(pred+1) / pred_count;
-
- for(index=start3; index<end3; index++){
- FrameCode *ft= &nut->frame_code[index];
- ft->flags= FLAG_KEY_FRAME*key_frame;
- ft->flags|= FLAG_DATA_SIZE;
- ft->stream_id_plus1= stream_id + 1;
-//FIXME use single byte size and pred from last
- ft->size_mul= end3-start3;
- ft->size_lsb= index - start3;
- ft->timestamp_delta= pred_table[pred];
- }
- }
- }
- memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));
- nut->frame_code['N'].flags= FLAG_INVALID;
-}
-
-static uint64_t get_v(ByteIOContext *bc)
-{
- uint64_t val = 0;
-
- for(;;)
- {
- int tmp = get_byte(bc);
-
- if (tmp&0x80)
- val= (val<<7) + tmp - 0x80;
- else{
-//av_log(NULL, AV_LOG_DEBUG, "get_v()= %"PRId64"\n", (val<<7) + tmp);
- return (val<<7) + tmp;
- }
+ for(i=0; i<nut->avf->nb_streams; i++){
+ nut->stream[i].last_pts= av_rescale_rnd(
+ val,
+ time_base.num * (int64_t)nut->stream[i].time_base->den,
+ time_base.den * (int64_t)nut->stream[i].time_base->num,
+ AV_ROUND_DOWN);
}
- return -1;
-}
-
-static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
- unsigned int len= get_v(bc);
-
- if(len && maxlen)
- get_buffer(bc, string, FFMIN(len, maxlen));
- while(len > maxlen){
- get_byte(bc);
- len--;
- }
-
- if(maxlen)
- string[FFMIN(len, maxlen-1)]= 0;
-
- if(maxlen == len)
- return -1;
- else
- return 0;
-}
-
-static int64_t get_s(ByteIOContext *bc){
- int64_t v = get_v(bc) + 1;
-
- if (v&1) return -(v>>1);
- else return (v>>1);
-}
-
-static uint64_t get_vb(ByteIOContext *bc){
- uint64_t val=0;
- unsigned int i= get_v(bc);
-
- if(i>8)
- return UINT64_MAX;
-
- while(i--)
- val = (val<<8) + get_byte(bc);
-
-//av_log(NULL, AV_LOG_DEBUG, "get_vb()= %"PRId64"\n", val);
- return val;
-}
-
-#ifdef TRACE
-static inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){
- uint64_t v= get_v(bc);
-
- printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
- return v;
-}
-
-static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){
- int64_t v= get_s(bc);
-
- printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
- return v;
-}
-
-static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){
- uint64_t v= get_vb(bc);
-
- printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
- return v;
-}
-#define get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#endif
-
-
-static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
-{
- int64_t start, size;
- start= url_ftell(bc) - 8;
-
- size= get_v(bc);
-
- init_checksum(bc, calculate_checksum ? av_adler32_update : NULL, 1);
-
- nut->packet_start[2] = start;
- nut->written_packet_size= size;
-
- return size;
-}
-
-static int check_checksum(ByteIOContext *bc){
- unsigned long checksum= get_checksum(bc);
- return checksum != get_be32(bc);
-}
-
-/**
- *
- */
-static int get_length(uint64_t val){
- int i;
-
- for (i=7; val>>i; i+=7);
-
- return i;
}
-static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
- uint64_t state=0;
-
- if(pos >= 0)
- url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
-
- while(!url_feof(bc)){
- state= (state<<8) | get_byte(bc);
- if((state>>56) != 'N')
- continue;
- switch(state){
- case MAIN_STARTCODE:
- case STREAM_STARTCODE:
- case KEYFRAME_STARTCODE:
- case INFO_STARTCODE:
- case INDEX_STARTCODE:
- return state;
- }
- }
-
- return 0;
-}
-
-/**
- * find the given startcode.
- * @param code the startcode
- * @param pos the start position of the search, or -1 if the current position
- * @returns the position of the startcode or -1 if not found
- */
-static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
- for(;;){
- uint64_t startcode= find_any_startcode(bc, pos);
- if(startcode == code)
- return url_ftell(bc) - 8;
- else if(startcode == 0)
- return -1;
- pos=-1;
- }
-}
-
-static int64_t lsb2full(StreamContext *stream, int64_t lsb){
- int64_t mask = (1<<stream->msb_timestamp_shift)-1;
+int64_t ff_lsb2full(StreamContext *stream, int64_t lsb){
+ int64_t mask = (1<<stream->msb_pts_shift)-1;
int64_t delta= stream->last_pts - mask/2;
return ((lsb - delta)&mask) + delta;
}
-#ifdef CONFIG_MUXERS
-
-static void put_v(ByteIOContext *bc, uint64_t val)
-{
- int i;
-
-//av_log(NULL, AV_LOG_DEBUG, "put_v()= %"PRId64"\n", val);
- val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
- i= get_length(val);
-
- for (i-=7; i>0; i-=7){
- put_byte(bc, 0x80 | (val>>i));
- }
-
- put_byte(bc, val&0x7f);
-}
-
-/**
- * stores a string as vb.
- */
-static void put_str(ByteIOContext *bc, const char *string){
- int len= strlen(string);
-
- put_v(bc, len);
- put_buffer(bc, string, len);
-}
-
-static void put_s(ByteIOContext *bc, int64_t val){
- if (val<=0) put_v(bc, -2*val );
- else put_v(bc, 2*val-1);
-}
-
-static void put_vb(ByteIOContext *bc, uint64_t val){
- int i;
-
- for (i=8; val>>i; i+=8);
-
- put_v(bc, i>>3);
- for(i-=8; i>=0; i-=8)
- put_byte(bc, (val>>i)&0xFF);
-}
-
-#ifdef TRACE
-static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
- printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
- put_v(bc, v);
-}
-
-static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){
- printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
- put_s(bc, v);
-}
-
-static inline void put_vb_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
- printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
- put_vb(bc, v);
-}
-#define put_v(bc, v) put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_vb(bc, v) put_vb_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#endif
-
-static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
-{
- put_flush_packet(bc);
- nut->packet_start[2]= url_ftell(bc) - 8;
- nut->written_packet_size = max_size;
-
- /* packet header */
- put_v(bc, nut->written_packet_size); /* forward ptr */
-
- if(calculate_checksum)
- init_checksum(bc, av_adler32_update, 1);
-
- return 0;
-}
-
-/**
- *
- * must not be called more then once per packet
- */
-static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
- int64_t start= nut->packet_start[2];
- int64_t cur= url_ftell(bc);
- int size= cur - start - get_length(nut->written_packet_size)/7 - 8;
-
- if(calculate_checksum)
- size += 4;
-
- if(size != nut->written_packet_size){
- int i;
-
- assert( size <= nut->written_packet_size );
-
- url_fseek(bc, start + 8, SEEK_SET);
- for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)
- put_byte(bc, 0x80);
- put_v(bc, size);
-
- url_fseek(bc, cur, SEEK_SET);
- nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ
-
- if(calculate_checksum)
- put_be32(bc, get_checksum(bc));
- }
-
- return 0;
-}
-
-static int nut_write_header(AVFormatContext *s)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
- AVCodecContext *codec;
- int i, j, tmp_time, tmp_flags,tmp_stream, tmp_mul, tmp_size, tmp_fields;
-
- if (strcmp(s->filename, "./data/b-libav.nut")) {
- av_log(s, AV_LOG_ERROR, " libavformat NUT is non-compliant and disabled\n");
- return -1;
- }
-
- nut->avf= s;
-
- nut->stream =
- av_mallocz(sizeof(StreamContext)*s->nb_streams);
-
-
- put_buffer(bc, ID_STRING, strlen(ID_STRING));
- put_byte(bc, 0);
- nut->packet_start[2]= url_ftell(bc);
-
- /* main header */
- put_be64(bc, MAIN_STARTCODE);
- put_packetheader(nut, bc, 120+5*256, 1);
- put_v(bc, 2); /* version */
- put_v(bc, s->nb_streams);
- put_v(bc, MAX_DISTANCE);
- put_v(bc, MAX_SHORT_DISTANCE);
-
- put_v(bc, nut->rate_num=1);
- put_v(bc, nut->rate_den=2);
- put_v(bc, nut->short_startcode=0x4EFE79);
-
- build_frame_code(s);
- assert(nut->frame_code['N'].flags == FLAG_INVALID);
-
- tmp_time= tmp_flags= tmp_stream= tmp_mul= tmp_size= /*tmp_res=*/ INT_MAX;
- for(i=0; i<256;){
- tmp_fields=0;
- tmp_size= 0;
- if(tmp_time != nut->frame_code[i].timestamp_delta) tmp_fields=1;
- if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2;
- if(tmp_stream != nut->frame_code[i].stream_id_plus1) tmp_fields=3;
- if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4;
-// if(tmp_res != nut->frame_code[i].res ) tmp_fields=5;
-
- tmp_time = nut->frame_code[i].timestamp_delta;
- tmp_flags = nut->frame_code[i].flags;
- tmp_stream= nut->frame_code[i].stream_id_plus1;
- tmp_mul = nut->frame_code[i].size_mul;
- tmp_size = nut->frame_code[i].size_lsb;
-// tmp_res = nut->frame_code[i].res;
-
- for(j=0; i<256; j++,i++){
- if(nut->frame_code[i].timestamp_delta != tmp_time ) break;
- if(nut->frame_code[i].flags != tmp_flags ) break;
- if(nut->frame_code[i].stream_id_plus1 != tmp_stream) break;
- if(nut->frame_code[i].size_mul != tmp_mul ) break;
- if(nut->frame_code[i].size_lsb != tmp_size+j) break;
-// if(nut->frame_code[i].res != tmp_res ) break;
- }
- if(j != tmp_mul - tmp_size) tmp_fields=6;
-
- put_v(bc, tmp_flags);
- put_v(bc, tmp_fields);
- if(tmp_fields>0) put_s(bc, tmp_time);
- if(tmp_fields>1) put_v(bc, tmp_mul);
- if(tmp_fields>2) put_v(bc, tmp_stream);
- if(tmp_fields>3) put_v(bc, tmp_size);
- if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/);
- if(tmp_fields>5) put_v(bc, j);
- }
-
- update_packetheader(nut, bc, 0, 1);
-
- /* stream headers */
- for (i = 0; i < s->nb_streams; i++)
- {
- int nom, denom, ssize;
-
- codec = s->streams[i]->codec;
-
- put_be64(bc, STREAM_STARTCODE);
- put_packetheader(nut, bc, 120 + codec->extradata_size, 1);
- put_v(bc, i /*s->streams[i]->index*/);
- switch(codec->codec_type){
- case CODEC_TYPE_VIDEO: put_v(bc, 0); break;
- case CODEC_TYPE_AUDIO: put_v(bc, 1); break;
-// case CODEC_TYPE_TEXT : put_v(bc, 2); break;
- case CODEC_TYPE_DATA : put_v(bc, 3); break;
- default: return -1;
- }
- if (codec->codec_tag)
- put_vb(bc, codec->codec_tag);
- else if (codec->codec_type == CODEC_TYPE_VIDEO)
- {
- put_vb(bc, codec_get_bmp_tag(codec->codec_id));
- }
- else if (codec->codec_type == CODEC_TYPE_AUDIO)
- {
- put_vb(bc, codec_get_wav_tag(codec->codec_id));
- }
- else
- put_vb(bc, 0);
-
- ff_parse_specific_params(codec, &nom, &ssize, &denom);
-
- nut->stream[i].rate_num= nom;
- nut->stream[i].rate_den= denom;
- av_set_pts_info(s->streams[i], 60, denom, nom);
-
- put_v(bc, codec->bit_rate);
- put_vb(bc, 0); /* no language code */
- put_v(bc, nom);
- put_v(bc, denom);
- if(nom / denom < 1000)
- nut->stream[i].msb_timestamp_shift = 7;
- else
- nut->stream[i].msb_timestamp_shift = 14;
- put_v(bc, nut->stream[i].msb_timestamp_shift);
- put_v(bc, codec->has_b_frames);
- put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
-
- if(codec->extradata_size){
- put_v(bc, 1);
- put_v(bc, codec->extradata_size);
- put_buffer(bc, codec->extradata, codec->extradata_size);
- }
- put_v(bc, 0); /* end of codec specific headers */
-
- switch(codec->codec_type)
- {
- case CODEC_TYPE_AUDIO:
- put_v(bc, codec->sample_rate);
- put_v(bc, 1);
- put_v(bc, codec->channels);
- break;
- case CODEC_TYPE_VIDEO:
- put_v(bc, codec->width);
- put_v(bc, codec->height);
- put_v(bc, codec->sample_aspect_ratio.num);
- put_v(bc, codec->sample_aspect_ratio.den);
- put_v(bc, 0); /* csp type -- unknown */
- break;
- default:
- break;
- }
- update_packetheader(nut, bc, 0, 1);
- }
-
- /* info header */
- put_be64(bc, INFO_STARTCODE);
- put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+
- strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1);
- if (s->author[0])
- {
- put_v(bc, 9); /* type */
- put_str(bc, s->author);
- }
- if (s->title[0])
- {
- put_v(bc, 10); /* type */
- put_str(bc, s->title);
- }
- if (s->comment[0])
- {
- put_v(bc, 11); /* type */
- put_str(bc, s->comment);
- }
- if (s->copyright[0])
- {
- put_v(bc, 12); /* type */
- put_str(bc, s->copyright);
- }
- /* encoder */
- if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)){
- put_v(bc, 13); /* type */
- put_str(bc, LIBAVFORMAT_IDENT);
- }
-
- put_v(bc, 0); /* eof info */
- update_packetheader(nut, bc, 0, 1);
-
- put_flush_packet(bc);
-
- return 0;
-}
-
-static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
-{
- NUTContext *nut = s->priv_data;
- StreamContext *stream= &nut->stream[pkt->stream_index];
- ByteIOContext *bc = &s->pb;
- int key_frame = 0, full_pts=0;
- AVCodecContext *enc;
- int64_t coded_pts;
- int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb, time_delta;
- const int64_t frame_start= url_ftell(bc);
- int64_t pts= pkt->pts;
- int size= pkt->size;
- int stream_index= pkt->stream_index;
-
- enc = s->streams[stream_index]->codec;
- key_frame = !!(pkt->flags & PKT_FLAG_KEY);
-
- frame_type=0;
- if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)
- frame_type=2;
- if(key_frame && !stream->last_key_frame)
- frame_type=2;
-
- if(frame_type>1){
- int64_t global_ts= av_rescale(pts, stream->rate_den*(int64_t)nut->rate_num, stream->rate_num*(int64_t)nut->rate_den);
- reset(s, global_ts);
- put_be64(bc, KEYFRAME_STARTCODE);
- put_v(bc, global_ts);
- }
- assert(stream->last_pts != AV_NOPTS_VALUE);
- coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);
- if(lsb2full(stream, coded_pts) != pts)
- full_pts=1;
-
- if(full_pts)
- coded_pts= pts + (1<<stream->msb_timestamp_shift);
-
- best_length=INT_MAX;
- frame_code= -1;
- for(i=0; i<256; i++){
- int stream_id_plus1= nut->frame_code[i].stream_id_plus1;
- int fc_key_frame;
- int length=0;
- size_mul= nut->frame_code[i].size_mul;
- size_lsb= nut->frame_code[i].size_lsb;
- time_delta= nut->frame_code[i].timestamp_delta;
- flags= nut->frame_code[i].flags;
-
- assert(size_mul > size_lsb);
-
- if(stream_id_plus1 == 0) length+= get_length(stream_index);
- else if(stream_id_plus1 - 1 != stream_index)
- continue;
- fc_key_frame= !!(flags & FLAG_KEY_FRAME);
-
- assert(key_frame==0 || key_frame==1);
- if(fc_key_frame != key_frame)
- continue;
-
- if(flags & FLAG_DATA_SIZE){
- if(size % size_mul != size_lsb)
- continue;
- length += get_length(size / size_mul);
- }else if(size != size_lsb)
- continue;
-
- if(full_pts && time_delta)
- continue;
-
- if(!time_delta){
- length += get_length(coded_pts);
- }else{
- if(time_delta != pts - stream->last_pts)
- continue;
- }
-
- if(length < best_length){
- best_length= length;
- frame_code=i;
- }
-// av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);
- }
-
- assert(frame_code != -1);
- flags= nut->frame_code[frame_code].flags;
- size_mul= nut->frame_code[frame_code].size_mul;
- size_lsb= nut->frame_code[frame_code].size_lsb;
- time_delta= nut->frame_code[frame_code].timestamp_delta;
-#ifdef TRACE
- best_length /= 7;
- best_length ++; //frame_code
- if(frame_type==2){
- best_length += 8; // startcode
- }
- av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d pts:%"PRId64" fs:%"PRId64"\n", key_frame, frame_type, full_pts ? 1 : 0, frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts), pts, frame_start);
-// av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
-#endif
-
- assert(frame_type != 1); //short startcode not implemented yet
- put_byte(bc, frame_code);
-
- if(nut->frame_code[frame_code].stream_id_plus1 == 0)
- put_v(bc, stream_index);
- if (!time_delta){
- put_v(bc, coded_pts);
- }
- if(flags & FLAG_DATA_SIZE)
- put_v(bc, size / size_mul);
- else
- assert(size == size_lsb);
- if(size > MAX_DISTANCE){
- assert(frame_type > 1);
- }
-
- put_buffer(bc, pkt->data, size);
-
- update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);
-
- return 0;
+int ff_nut_sp_pos_cmp(syncpoint_t *a, syncpoint_t *b){
+ return ((a->pos - b->pos) >> 32) - ((b->pos - a->pos) >> 32);
}
-static int nut_write_trailer(AVFormatContext *s)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
-
-#if 0
- int i;
-
- /* WRITE INDEX */
-
- for (i = 0; s->nb_streams; i++)
- {
- put_be64(bc, INDEX_STARTCODE);
- put_packetheader(nut, bc, 64, 1);
- put_v(bc, s->streams[i]->id);
- put_v(bc, ...);
- update_packetheader(nut, bc, 0, 1);
- }
-#endif
-
- put_flush_packet(bc);
-
- av_freep(&nut->stream);
-
- return 0;
+int ff_nut_sp_pts_cmp(syncpoint_t *a, syncpoint_t *b){
+ return ((a->ts - b->ts) >> 32) - ((b->ts - a->ts) >> 32);
}
-#endif //CONFIG_MUXERS
-static int nut_probe(AVProbeData *p)
-{
- int i;
- uint64_t code= 0xff;
+void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){
+ syncpoint_t *sp= av_mallocz(sizeof(syncpoint_t));
+ struct AVTreeNode *node= av_mallocz(av_tree_node_size);
- for (i = 0; i < p->buf_size; i++) {
- code = (code << 8) | p->buf[i];
- if (code == MAIN_STARTCODE)
- return AVPROBE_SCORE_MAX;
+ sp->pos= pos;
+ sp->back_ptr= back_ptr;
+ sp->ts= ts;
+ av_tree_insert(&nut->syncpoints, sp, ff_nut_sp_pos_cmp, &node);
+ if(node){
+ av_free(sp);
+ av_free(node);
}
- return 0;
}
-
-static int decode_main_header(NUTContext *nut){
- AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
- uint64_t tmp;
- int i, j, tmp_stream, tmp_mul, tmp_time, tmp_size, count, tmp_res;
-
- get_packetheader(nut, bc, 1);
-
- tmp = get_v(bc);
- if (tmp != 2){
- av_log(s, AV_LOG_ERROR, "bad version (%"PRId64")\n", tmp);
- return -1;
- }
-
- nut->stream_count = get_v(bc);
- if(nut->stream_count > MAX_STREAMS){
- av_log(s, AV_LOG_ERROR, "too many streams\n");
- return -1;
- }
- nut->max_distance = get_v(bc);
- nut->max_short_distance = get_v(bc);
- nut->rate_num= get_v(bc);
- nut->rate_den= get_v(bc);
- nut->short_startcode= get_v(bc);
- if(nut->short_startcode>>16 != 'N'){
- av_log(s, AV_LOG_ERROR, "invalid short startcode %X\n", nut->short_startcode);
- return -1;
- }
-
- for(i=0; i<256;){
- int tmp_flags = get_v(bc);
- int tmp_fields= get_v(bc);
- if(tmp_fields>0) tmp_time = get_s(bc);
- if(tmp_fields>1) tmp_mul = get_v(bc);
- if(tmp_fields>2) tmp_stream= get_v(bc);
- if(tmp_fields>3) tmp_size = get_v(bc);
- else tmp_size = 0;
- if(tmp_fields>4) tmp_res = get_v(bc);
- else tmp_res = 0;
- if(tmp_fields>5) count = get_v(bc);
- else count = tmp_mul - tmp_size;
-
- while(tmp_fields-- > 6)
- get_v(bc);
-
- if(count == 0 || i+count > 256){
- av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
- return -1;
- }
- if(tmp_stream > nut->stream_count + 1){
- av_log(s, AV_LOG_ERROR, "illegal stream number\n");
- return -1;
- }
-
- for(j=0; j<count; j++,i++){
- nut->frame_code[i].flags = tmp_flags ;
- nut->frame_code[i].timestamp_delta = tmp_time ;
- nut->frame_code[i].stream_id_plus1 = tmp_stream;
- nut->frame_code[i].size_mul = tmp_mul ;
- nut->frame_code[i].size_lsb = tmp_size+j;
- nut->frame_code[i].reserved_count = tmp_res ;
- }
- }
- if(nut->frame_code['N'].flags != FLAG_INVALID){
- av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");
- return -1;
- }
-
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Main header checksum mismatch\n");
- return -1;
- }
-
- return 0;
-}
-
-static int decode_stream_header(NUTContext *nut){
- AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
- int class, nom, denom, stream_id;
- uint64_t tmp;
- AVStream *st;
-
- get_packetheader(nut, bc, 1);
- stream_id= get_v(bc);
- if(stream_id >= nut->stream_count || s->streams[stream_id])
- return -1;
-
- st = av_new_stream(s, stream_id);
- if (!st)
- return AVERROR_NOMEM;
-
- class = get_v(bc);
- tmp = get_vb(bc);
- st->codec->codec_tag= tmp;
- switch(class)
- {
- case 0:
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = codec_get_bmp_id(tmp);
- if (st->codec->codec_id == CODEC_ID_NONE)
- av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
- break;
- case 1:
- case 32: //compatibility
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = codec_get_wav_id(tmp);
- if (st->codec->codec_id == CODEC_ID_NONE)
- av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
- break;
- case 2:
-// st->codec->codec_type = CODEC_TYPE_TEXT;
-// break;
- case 3:
- st->codec->codec_type = CODEC_TYPE_DATA;
- break;
- default:
- av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
- return -1;
- }
- s->bit_rate += get_v(bc);
- get_vb(bc); /* language code */
- nom = get_v(bc);
- denom = get_v(bc);
- nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
- st->codec->has_b_frames=
- nut->stream[stream_id].decode_delay= get_v(bc);
- get_byte(bc); /* flags */
-
- /* codec specific data headers */
- while(get_v(bc) != 0){
- st->codec->extradata_size= get_v(bc);
- if((unsigned)st->codec->extradata_size > (1<<30))
- return -1;
- st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- get_buffer(bc, st->codec->extradata, st->codec->extradata_size);
-// url_fskip(bc, get_v(bc));
- }
-
- if (st->codec->codec_type == CODEC_TYPE_VIDEO) /* VIDEO */
- {
- st->codec->width = get_v(bc);
- st->codec->height = get_v(bc);
- st->codec->sample_aspect_ratio.num= get_v(bc);
- st->codec->sample_aspect_ratio.den= get_v(bc);
- get_v(bc); /* csp type */
- }
- if (st->codec->codec_type == CODEC_TYPE_AUDIO) /* AUDIO */
- {
- st->codec->sample_rate = get_v(bc);
- get_v(bc); // samplerate_den
- st->codec->channels = get_v(bc);
- }
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Stream header %d checksum mismatch\n", stream_id);
- return -1;
- }
- av_set_pts_info(s->streams[stream_id], 60, denom, nom);
- nut->stream[stream_id].rate_num= nom;
- nut->stream[stream_id].rate_den= denom;
- return 0;
-}
-
-static int decode_info_header(NUTContext *nut){
- AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
-
- get_packetheader(nut, bc, 1);
-
- for(;;){
- int id= get_v(bc);
- char *name, *type, custom_name[256], custom_type[256];
-
- if(!id)
- break;
- else if(id >= sizeof(info_table)/sizeof(info_table[0])){
- av_log(s, AV_LOG_ERROR, "info id is too large %d %zd\n", id, sizeof(info_table)/sizeof(info_table[0]));
- return -1;
- }
-
- type= info_table[id][1];
- name= info_table[id][0];
-//av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
-
- if(!type){
- get_str(bc, custom_type, sizeof(custom_type));
- type= custom_type;
- }
- if(!name){
- get_str(bc, custom_name, sizeof(custom_name));
- name= custom_name;
- }
-
- if(!strcmp(type, "v")){
- get_v(bc);
- }else{
- if(!strcmp(name, "Author"))
- get_str(bc, s->author, sizeof(s->author));
- else if(!strcmp(name, "Title"))
- get_str(bc, s->title, sizeof(s->title));
- else if(!strcmp(name, "Copyright"))
- get_str(bc, s->copyright, sizeof(s->copyright));
- else if(!strcmp(name, "Description"))
- get_str(bc, s->comment, sizeof(s->comment));
- else
- get_str(bc, NULL, 0);
- }
- }
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
- return -1;
- }
- return 0;
-}
-
-static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
- int64_t pos;
- int inited_stream_count;
-
- nut->avf= s;
-
- /* main header */
- pos=0;
- for(;;){
- pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
- if (pos<0){
- av_log(s, AV_LOG_ERROR, "no main startcode found\n");
- return -1;
- }
- if(decode_main_header(nut) >= 0)
- break;
- }
-
-
- s->bit_rate = 0;
-
- nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
-
- /* stream headers */
- pos=0;
- for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
- pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
- if (pos<0+1){
- av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
- return -1;
- }
- if(decode_stream_header(nut) >= 0)
- inited_stream_count++;
- }
-
- /* info headers */
- pos=0;
- for(;;){
- uint64_t startcode= find_any_startcode(bc, pos);
- pos= url_ftell(bc);
-
- if(startcode==0){
- av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
- return -1;
- }else if(startcode == KEYFRAME_STARTCODE){
- nut->next_startcode= startcode;
- break;
- }else if(startcode != INFO_STARTCODE){
- continue;
- }
-
- decode_info_header(nut);
- }
-
- return 0;
-}
-
-static int decode_frame_header(NUTContext *nut, int *key_frame_ret, int64_t *pts_ret, int *stream_id_ret, int frame_code, int frame_type, int64_t frame_start){
- AVFormatContext *s= nut->avf;
- StreamContext *stream;
- ByteIOContext *bc = &s->pb;
- int size, flags, size_mul, size_lsb, stream_id, time_delta;
- int64_t pts = 0;
-
- if(frame_type < 2 && frame_start - nut->packet_start[2] > nut->max_distance){
- av_log(s, AV_LOG_ERROR, "last frame must have been damaged\n");
- return -1;
- }
-
- if(frame_type)
- nut->packet_start[ frame_type ]= frame_start; //otherwise 1 goto 1 may happen
-
- flags= nut->frame_code[frame_code].flags;
- size_mul= nut->frame_code[frame_code].size_mul;
- size_lsb= nut->frame_code[frame_code].size_lsb;
- stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1;
- time_delta= nut->frame_code[frame_code].timestamp_delta;
-
- if(stream_id==-1)
- stream_id= get_v(bc);
- if(stream_id >= s->nb_streams){
- av_log(s, AV_LOG_ERROR, "illegal stream_id\n");
- return -1;
- }
- stream= &nut->stream[stream_id];
-
-// av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
-
- *key_frame_ret= !!(flags & FLAG_KEY_FRAME);
-
- if(!time_delta){
- int64_t mask = (1<<stream->msb_timestamp_shift)-1;
- pts= get_v(bc);
- if(pts > mask){
- pts -= mask+1;
- }else{
- if(stream->last_pts == AV_NOPTS_VALUE){
- av_log(s, AV_LOG_ERROR, "no reference pts available\n");
- return -1;
- }
- pts= lsb2full(stream, pts);
- }
- }else{
- if(stream->last_pts == AV_NOPTS_VALUE){
- av_log(s, AV_LOG_ERROR, "no reference pts available\n");
- return -1;
- }
- pts= stream->last_pts + time_delta;
- }
-
- if(*key_frame_ret){
-// av_log(s, AV_LOG_DEBUG, "stream:%d start:%"PRId64" pts:%"PRId64" length:%"PRId64"\n",stream_id, frame_start, av_pts, frame_start - nut->stream[stream_id].last_sync_pos);
- av_add_index_entry(
- s->streams[stream_id],
- frame_start,
- pts,
- 0,
- frame_start - nut->stream[stream_id].last_sync_pos,
- AVINDEX_KEYFRAME);
- nut->stream[stream_id].last_sync_pos= frame_start;
-// assert(nut->packet_start == frame_start);
- }
-
- assert(size_mul > size_lsb);
- size= size_lsb;
- if(flags & FLAG_DATA_SIZE)
- size+= size_mul*get_v(bc);
-
-#ifdef TRACE
-av_log(s, AV_LOG_DEBUG, "fs:%"PRId64" fc:%d ft:%d kf:%d pts:%"PRId64" size:%d mul:%d lsb:%d flags:%d delta:%d\n", frame_start, frame_code, frame_type, *key_frame_ret, pts, size, size_mul, size_lsb, flags, time_delta);
-#endif
-
- if(frame_type==0 && url_ftell(bc) - nut->packet_start[2] + size > nut->max_distance){
- av_log(s, AV_LOG_ERROR, "frame size too large\n");
- return -1;
- }
-
- *stream_id_ret = stream_id;
- *pts_ret = pts;
-
- update(nut, stream_id, frame_start, frame_type, frame_code, *key_frame_ret, size, pts);
-
- return size;
-}
-
-static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type, int64_t frame_start){
- AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
- int size, stream_id, key_frame, discard;
- int64_t pts, last_IP_pts;
-
- size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, frame_start);
- if(size < 0)
- return -1;
-
- discard= s->streams[ stream_id ]->discard;
- last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
- if( (discard >= AVDISCARD_NONKEY && !key_frame)
- ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
- || discard >= AVDISCARD_ALL){
- url_fskip(bc, size);
- return 1;
- }
-
- av_get_packet(bc, pkt, size);
- pkt->stream_index = stream_id;
- if (key_frame)
- pkt->flags |= PKT_FLAG_KEY;
- pkt->pts = pts;
-
- return 0;
-}
-
-static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
-{
- NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
- int i, frame_code=0, ret;
-
- for(;;){
- int64_t pos= url_ftell(bc);
- int frame_type= 0;
- uint64_t tmp= nut->next_startcode;
- nut->next_startcode=0;
-
- if (url_feof(bc))
- return -1;
-
- if(tmp){
- pos-=8;
- }else{
- frame_code = get_byte(bc);
- if(frame_code == 'N'){
- tmp= frame_code;
- for(i=1; i<8; i++)
- tmp = (tmp<<8) + get_byte(bc);
- }
- }
- switch(tmp){
- case MAIN_STARTCODE:
- case STREAM_STARTCODE:
- case INDEX_STARTCODE:
- get_packetheader(nut, bc, 0);
- assert(nut->packet_start[2] == pos);
- url_fseek(bc, nut->written_packet_size, SEEK_CUR);
- break;
- case INFO_STARTCODE:
- if(decode_info_header(nut)<0)
- goto resync;
- break;
- case KEYFRAME_STARTCODE:
- frame_type = 2;
- reset(s, get_v(bc));
- frame_code = get_byte(bc);
- case 0:
- ret= decode_frame(nut, pkt, frame_code, frame_type, pos);
- if(ret==0)
- return 0;
- else if(ret==1) //ok but discard packet
- break;
- default:
-resync:
-av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
- tmp= find_any_startcode(bc, nut->packet_start[2]+1);
- if(tmp==0)
- return -1;
-av_log(s, AV_LOG_DEBUG, "sync\n");
- nut->next_startcode= tmp;
- }
- }
-}
-
-static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
- NUTContext *nut = s->priv_data;
- StreamContext *stream;
- ByteIOContext *bc = &s->pb;
- int64_t pos, pts;
- uint64_t code;
- int frame_code,step, stream_id, i,size, key_frame;
-av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
-
- if(*pos_arg < 0)
- return AV_NOPTS_VALUE;
-
- pos= *pos_arg;
- step= FFMIN(16*1024, pos);
- do{
- pos-= step;
- code= find_any_startcode(bc, pos);
-
- if(code && url_ftell(bc) - 8 <= *pos_arg)
- break;
- step= FFMIN(2*step, pos);
- }while(step);
-
- if(!code) //nothing found, not even after pos_arg
- return AV_NOPTS_VALUE;
-
- url_fseek(bc, -8, SEEK_CUR);
- for(i=0; i<s->nb_streams; i++)
- nut->stream[i].last_sync_pos= url_ftell(bc);
-
- for(;;){
- int frame_type=0;
- int64_t pos= url_ftell(bc);
- uint64_t tmp=0;
-
- if(pos > pos_limit || url_feof(bc))
- return AV_NOPTS_VALUE;
-
- frame_code = get_byte(bc);
- if(frame_code == 'N'){
- tmp= frame_code;
- for(i=1; i<8; i++)
- tmp = (tmp<<8) + get_byte(bc);
- }
-//av_log(s, AV_LOG_DEBUG, "before switch %"PRIX64" at=%"PRId64"\n", tmp, pos);
-
- switch(tmp){
- case MAIN_STARTCODE:
- case STREAM_STARTCODE:
- case INDEX_STARTCODE:
- case INFO_STARTCODE:
- get_packetheader(nut, bc, 0);
- assert(nut->packet_start[2]==pos);
- url_fseek(bc, nut->written_packet_size, SEEK_CUR);
- break;
- case KEYFRAME_STARTCODE:
- frame_type=2;
- reset(s, get_v(bc));
- frame_code = get_byte(bc);
- case 0:
- size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, pos);
- if(size < 0)
- goto resync;
-
- stream= &nut->stream[stream_id];
- if(stream_id != stream_index || !key_frame || pos < *pos_arg){
- url_fseek(bc, size, SEEK_CUR);
- break;
- }
-
- *pos_arg= pos;
- return pts;
- default:
-resync:
-av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
- if(!find_any_startcode(bc, nut->packet_start[2]+1))
- return AV_NOPTS_VALUE;
-
- url_fseek(bc, -8, SEEK_CUR);
- }
- }
- return AV_NOPTS_VALUE;
-}
-
-static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
-// NUTContext *nut = s->priv_data;
- int64_t pos;
-
- if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
- return -1;
-
- pos= url_ftell(&s->pb);
- nut_read_timestamp(s, stream_index, &pos, pos-1);
-
- return 0;
-}
-
-static int nut_read_close(AVFormatContext *s)
-{
- NUTContext *nut = s->priv_data;
-
- av_freep(&nut->stream);
-
- return 0;
-}
-
-#ifdef CONFIG_NUT_DEMUXER
-AVInputFormat nut_demuxer = {
- "nut",
- "nut format",
- sizeof(NUTContext),
- nut_probe,
- nut_read_header,
- nut_read_packet,
- nut_read_close,
- nut_read_seek,
- nut_read_timestamp,
- .extensions = "nut",
-};
-#endif
-#ifdef CONFIG_NUT_MUXER
-AVOutputFormat nut_muxer = {
- "nut",
- "nut format",
- "video/x-nut",
- "nut",
- sizeof(NUTContext),
-#ifdef CONFIG_LIBVORBIS
- CODEC_ID_VORBIS,
-#elif defined(CONFIG_LIBMP3LAME)
- CODEC_ID_MP3,
-#else
- CODEC_ID_MP2, /* AC3 needs liba52 decoder */
-#endif
- CODEC_ID_MPEG4,
- nut_write_header,
- nut_write_packet,
- nut_write_trailer,
- .flags = AVFMT_GLOBALHEADER,
-};
-#endif
diff --git a/contrib/ffmpeg/libavformat/nut.h b/contrib/ffmpeg/libavformat/nut.h
index 82bbf6f17..943914603 100644
--- a/contrib/ffmpeg/libavformat/nut.h
+++ b/contrib/ffmpeg/libavformat/nut.h
@@ -17,12 +17,13 @@
* 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 FFMPEG_NUT_H
+#define FFMPEG_NUT_H
+
//#include <limits.h>
#include "avformat.h"
-#include "crc.h"
//#include "mpegaudio.h"
#include "riff.h"
//#include "adler32.h"
@@ -43,10 +44,12 @@ typedef enum{
FLAG_CODED_PTS = 8, ///<if set, coded_pts is in the frame header
FLAG_STREAM_ID = 16, ///<if set, stream_id is coded in the frame header
FLAG_SIZE_MSB = 32, ///<if set, data_size_msb is at frame header, otherwise data_size_msb is 0
- FLAG_CHECKSUM = 64, ///<if set then the frame header contains a checksum
+ 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_CODED =4096, ///<if set, coded_flags are stored in the frame header.
- FLAG_INVALID =8192, ///<if set, frame_code is invalid.
+ 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
+ FLAG_INVALID =8192, ///<if set, frame_code is invalid
}flag_t;
typedef struct {
@@ -63,14 +66,15 @@ typedef struct {
uint16_t size_lsb;
int16_t pts_delta;
uint8_t reserved_count;
-} FrameCode; // maybe s/FrameCode/framecode_t/ or change all to java style but dont mix
+ uint8_t header_idx;
+} FrameCode; // maybe s/FrameCode/framecode_t/ or change all to Java style but do not mix
typedef struct {
int last_flags;
int skip_until_key_frame;
int64_t last_pts;
int time_base_id;
- AVRational time_base;
+ AVRational *time_base;
int msb_pts_shift;
int max_pts_distance;
int decode_delay; //FIXME duplicate of has_b_frames
@@ -79,19 +83,24 @@ typedef struct {
typedef struct {
AVFormatContext *avf;
// int written_packet_size;
-// int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
+// int64_t packet_start;
FrameCode frame_code[256];
- uint64_t next_startcode; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
+ uint8_t header_len[128];
+ const uint8_t *header[128];
+ uint64_t next_startcode; ///< stores the next startcode if it has already been parsed but the stream is not seekable
StreamContext *stream;
unsigned int max_distance;
unsigned int time_base_count;
int64_t last_syncpoint_pos;
+ int header_count;
AVRational *time_base;
struct AVTreeNode *syncpoints;
} NUTContext;
+void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val);
+int64_t ff_lsb2full(StreamContext *stream, int64_t lsb);
+int ff_nut_sp_pos_cmp(syncpoint_t *a, syncpoint_t *b);
+int ff_nut_sp_pts_cmp(syncpoint_t *a, syncpoint_t *b);
+void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts);
-//FIXME move to a common spot, like crc.c/h
-static unsigned long av_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len){
- return av_crc(av_crc04C11DB7, checksum, buf, len);
-}
+#endif /* FFMPEG_NUT_H */
diff --git a/contrib/ffmpeg/libavformat/nutdec.c b/contrib/ffmpeg/libavformat/nutdec.c
index c0f331c27..e072e7ed7 100644
--- a/contrib/ffmpeg/libavformat/nutdec.c
+++ b/contrib/ffmpeg/libavformat/nutdec.c
@@ -18,28 +18,17 @@
* 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 "tree.h"
#include "nut.h"
+#include "avstring.h"
#undef NDEBUG
#include <assert.h>
-static uint64_t get_v(ByteIOContext *bc){
- uint64_t val = 0;
- int tmp;
-
- do{
- tmp = get_byte(bc);
- val= (val<<7) + (tmp&127);
- }while(tmp&128);
- return val;
-}
-
static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
- unsigned int len= get_v(bc);
+ unsigned int len= ff_get_v(bc);
if(len && maxlen)
get_buffer(bc, string, FFMIN(len, maxlen));
@@ -58,14 +47,14 @@ static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
}
static int64_t get_s(ByteIOContext *bc){
- int64_t v = get_v(bc) + 1;
+ int64_t v = ff_get_v(bc) + 1;
if (v&1) return -(v>>1);
else return (v>>1);
}
static uint64_t get_fourcc(ByteIOContext *bc){
- unsigned int len= get_v(bc);
+ unsigned int len= ff_get_v(bc);
if (len==2) return get_le16(bc);
else if(len==4) return get_le32(bc);
@@ -74,43 +63,46 @@ static uint64_t get_fourcc(ByteIOContext *bc){
#ifdef TRACE
static inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){
- uint64_t v= get_v(bc);
+ uint64_t v= ff_get_v(bc);
- printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
return v;
}
static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){
int64_t v= get_s(bc);
- printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
return v;
}
static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){
uint64_t v= get_vb(bc);
- printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ av_log(NULL, AV_LOG_DEBUG, "get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
return v;
}
-#define get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define ff_get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#endif
-static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
+static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum, uint64_t startcode)
{
- int64_t start, size;
+ int64_t size;
// start= url_ftell(bc) - 8;
- size= get_v(bc);
- if(size > 4096)
- get_be32(bc); //FIXME check this
+ startcode= be2me_64(startcode);
+ startcode= ff_crc04C11DB7_update(0, &startcode, 8);
- init_checksum(bc, calculate_checksum ? av_crc04C11DB7_update : NULL, 0);
+ init_checksum(bc, ff_crc04C11DB7_update, startcode);
+ size= ff_get_v(bc);
+ if(size > 4096)
+ get_be32(bc);
+ if(get_checksum(bc) && size > 4096)
+ return -1;
-// nut->packet_start[2] = start;
-// nut->written_packet_size= size;
+ init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
return size;
}
@@ -119,7 +111,7 @@ static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
uint64_t state=0;
if(pos >= 0)
- url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
+ url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream is not seekable, but that should not matter, as in this case we simply start where we are currently
while(!url_feof(bc)){
state= (state<<8) | get_byte(bc);
@@ -139,7 +131,7 @@ static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
}
/**
- * find the given startcode.
+ * Find the given startcode.
* @param code the startcode
* @param pos the start position of the search, or -1 if the current position
* @returns the position of the startcode or -1 if not found
@@ -155,12 +147,6 @@ static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
}
}
-static int64_t lsb2full(StreamContext *stream, int64_t lsb){
- int64_t mask = (1<<stream->msb_pts_shift)-1;
- int64_t delta= stream->last_pts - mask/2;
- return ((lsb - delta)&mask) + delta;
-}
-
static int nut_probe(AVProbeData *p){
int i;
uint64_t code= 0;
@@ -174,7 +160,7 @@ static int nut_probe(AVProbeData *p){
}
#define GET_V(dst, check) \
- tmp= get_v(bc);\
+ tmp= ff_get_v(bc);\
if(!(check)){\
av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
return -1;\
@@ -195,18 +181,19 @@ static int skip_reserved(ByteIOContext *bc, int64_t pos){
static int decode_main_header(NUTContext *nut){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
uint64_t tmp, end;
unsigned int stream_count;
- int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res;
+ int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx;
+ int64_t tmp_match;
- end= get_packetheader(nut, bc, 1);
+ end= get_packetheader(nut, bc, 1, MAIN_STARTCODE);
end += url_ftell(bc);
GET_V(tmp , tmp >=2 && tmp <= 3)
GET_V(stream_count , tmp > 0 && tmp <=MAX_STREAMS)
- nut->max_distance = get_v(bc);
+ nut->max_distance = ff_get_v(bc);
if(nut->max_distance > 65536){
av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
nut->max_distance= 65536;
@@ -226,21 +213,25 @@ static int decode_main_header(NUTContext *nut){
tmp_pts=0;
tmp_mul=1;
tmp_stream=0;
+ tmp_match= 1-(1LL<<62);
+ tmp_head_idx= 0;
for(i=0; i<256;){
- int tmp_flags = get_v(bc);
- int tmp_fields= get_v(bc);
+ int tmp_flags = ff_get_v(bc);
+ int tmp_fields= ff_get_v(bc);
if(tmp_fields>0) tmp_pts = get_s(bc);
- if(tmp_fields>1) tmp_mul = get_v(bc);
- if(tmp_fields>2) tmp_stream= get_v(bc);
- if(tmp_fields>3) tmp_size = get_v(bc);
+ if(tmp_fields>1) tmp_mul = ff_get_v(bc);
+ if(tmp_fields>2) tmp_stream= ff_get_v(bc);
+ if(tmp_fields>3) tmp_size = ff_get_v(bc);
else tmp_size = 0;
- if(tmp_fields>4) tmp_res = get_v(bc);
+ if(tmp_fields>4) tmp_res = ff_get_v(bc);
else tmp_res = 0;
- if(tmp_fields>5) count = get_v(bc);
+ if(tmp_fields>5) count = ff_get_v(bc);
else count = tmp_mul - tmp_size;
+ if(tmp_fields>6) tmp_match = get_s(bc);
+ if(tmp_fields>7) tmp_head_idx= ff_get_v(bc);
- while(tmp_fields-- > 6)
- get_v(bc);
+ while(tmp_fields-- > 8)
+ ff_get_v(bc);
if(count == 0 || i+count > 256){
av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
@@ -263,12 +254,30 @@ static int decode_main_header(NUTContext *nut){
nut->frame_code[i].size_mul = tmp_mul ;
nut->frame_code[i].size_lsb = tmp_size+j;
nut->frame_code[i].reserved_count = tmp_res ;
+ nut->frame_code[i].header_idx = tmp_head_idx;
}
}
assert(nut->frame_code['N'].flags == FLAG_INVALID);
+ if(end > url_ftell(bc) + 4){
+ int rem= 1024;
+ GET_V(nut->header_count, tmp<128U)
+ nut->header_count++;
+ for(i=1; i<nut->header_count; i++){
+ GET_V(nut->header_len[i], tmp>0 && tmp<256);
+ rem -= nut->header_len[i];
+ if(rem < 0){
+ av_log(s, AV_LOG_ERROR, "invalid elision header\n");
+ return -1;
+ }
+ nut->header[i]= av_malloc(nut->header_len[i]);
+ get_buffer(bc, nut->header[i], nut->header_len[i]);
+ }
+ assert(nut->header_len[0]==0);
+ }
+
if(skip_reserved(bc, end) || get_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Main header checksum mismatch\n");
+ av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
return -1;
}
@@ -282,36 +291,36 @@ static int decode_main_header(NUTContext *nut){
static int decode_stream_header(NUTContext *nut){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
StreamContext *stc;
int class, stream_id;
uint64_t tmp, end;
AVStream *st;
- end= get_packetheader(nut, bc, 1);
+ end= get_packetheader(nut, bc, 1, STREAM_STARTCODE);
end += url_ftell(bc);
- GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base.num);
+ GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
stc= &nut->stream[stream_id];
st = s->streams[stream_id];
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
- class = get_v(bc);
+ class = ff_get_v(bc);
tmp = get_fourcc(bc);
st->codec->codec_tag= tmp;
switch(class)
{
case 0:
st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = codec_get_bmp_id(tmp);
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, tmp);
if (st->codec->codec_id == CODEC_ID_NONE)
av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
break;
case 1:
st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = codec_get_wav_id(tmp);
+ st->codec->codec_id = codec_get_id(codec_wav_tags, tmp);
if (st->codec->codec_id == CODEC_ID_NONE)
av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
break;
@@ -322,15 +331,15 @@ static int decode_stream_header(NUTContext *nut){
st->codec->codec_type = CODEC_TYPE_DATA;
break;
default:
- av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
+ av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
return -1;
}
GET_V(stc->time_base_id , tmp < nut->time_base_count);
GET_V(stc->msb_pts_shift , tmp < 16);
- stc->max_pts_distance= get_v(bc);
- GET_V(stc->decode_delay , tmp < 1000); //sanity limit, raise this if moors law is true
+ stc->max_pts_distance= ff_get_v(bc);
+ GET_V(stc->decode_delay , tmp < 1000); //sanity limit, raise this if Moore's law is true
st->codec->has_b_frames= stc->decode_delay;
- get_v(bc); //stream flags
+ ff_get_v(bc); //stream flags
GET_V(st->codec->extradata_size, tmp < (1<<30));
if(st->codec->extradata_size){
@@ -341,48 +350,45 @@ static int decode_stream_header(NUTContext *nut){
if (st->codec->codec_type == CODEC_TYPE_VIDEO){
GET_V(st->codec->width , tmp > 0)
GET_V(st->codec->height, tmp > 0)
- st->codec->sample_aspect_ratio.num= get_v(bc);
- st->codec->sample_aspect_ratio.den= get_v(bc);
+ st->codec->sample_aspect_ratio.num= ff_get_v(bc);
+ st->codec->sample_aspect_ratio.den= ff_get_v(bc);
if((!st->codec->sample_aspect_ratio.num) != (!st->codec->sample_aspect_ratio.den)){
- av_log(s, AV_LOG_ERROR, "invalid aspect ratio\n");
+ av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->codec->sample_aspect_ratio.num, st->codec->sample_aspect_ratio.den);
return -1;
}
- get_v(bc); /* csp type */
+ ff_get_v(bc); /* csp type */
}else if (st->codec->codec_type == CODEC_TYPE_AUDIO){
GET_V(st->codec->sample_rate , tmp > 0)
- tmp= get_v(bc); // samplerate_den
- if(tmp > st->codec->sample_rate){
- av_log(s, AV_LOG_ERROR, "bleh, libnut muxed this ;)\n");
- st->codec->sample_rate= tmp;
- }
+ ff_get_v(bc); // samplerate_den
GET_V(st->codec->channels, tmp > 0)
}
if(skip_reserved(bc, end) || get_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Stream header %d checksum mismatch\n", stream_id);
+ av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id);
return -1;
}
- stc->time_base= nut->time_base[stc->time_base_id];
- av_set_pts_info(s->streams[stream_id], 63, stc->time_base.num, stc->time_base.den);
+ stc->time_base= &nut->time_base[stc->time_base_id];
+ av_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, stc->time_base->den);
return 0;
}
static int decode_info_header(NUTContext *nut){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
uint64_t tmp;
unsigned int stream_id_plus1, chapter_start, chapter_len, count;
int chapter_id, i;
int64_t value, end;
- char name[256], str_value[1024], type_str[256], *type= type_str;
+ char name[256], str_value[1024], type_str[256];
+ const char *type;
- end= get_packetheader(nut, bc, 1);
+ end= get_packetheader(nut, bc, 1, INFO_STARTCODE);
end += url_ftell(bc);
GET_V(stream_id_plus1, tmp <= s->nb_streams)
chapter_id = get_s(bc);
- chapter_start= get_v(bc);
- chapter_len = get_v(bc);
- count = get_v(bc);
+ chapter_start= ff_get_v(bc);
+ chapter_len = ff_get_v(bc);
+ count = ff_get_v(bc);
for(i=0; i<count; i++){
get_str(bc, name, sizeof(name));
value= get_s(bc);
@@ -390,14 +396,15 @@ static int decode_info_header(NUTContext *nut){
type= "UTF-8";
get_str(bc, str_value, sizeof(str_value));
}else if(value == -2){
- get_str(bc, type, sizeof(type));
+ get_str(bc, type_str, sizeof(type_str));
+ type= type_str;
get_str(bc, str_value, sizeof(str_value));
}else if(value == -3){
type= "s";
value= get_s(bc);
}else if(value == -4){
type= "t";
- value= get_v(bc);
+ value= ff_get_v(bc);
}else if(value < -4){
type= "r";
get_s(bc);
@@ -407,69 +414,39 @@ static int decode_info_header(NUTContext *nut){
if(chapter_id==0 && !strcmp(type, "UTF-8")){
if (!strcmp(name, "Author"))
- pstrcpy(s->author , sizeof(s->author) , str_value);
+ av_strlcpy(s->author , str_value, sizeof(s->author));
else if(!strcmp(name, "Title"))
- pstrcpy(s->title , sizeof(s->title) , str_value);
+ av_strlcpy(s->title , str_value, sizeof(s->title));
else if(!strcmp(name, "Copyright"))
- pstrcpy(s->copyright, sizeof(s->copyright), str_value);
+ av_strlcpy(s->copyright, str_value, sizeof(s->copyright));
else if(!strcmp(name, "Description"))
- pstrcpy(s->comment , sizeof(s->comment) , str_value);
+ av_strlcpy(s->comment , str_value, sizeof(s->comment));
}
}
if(skip_reserved(bc, end) || get_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
+ av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
return -1;
}
return 0;
}
-int sp_pos_cmp(syncpoint_t *a, syncpoint_t *b){
- return (a->pos - b->pos>>32) - (b->pos - a->pos>>32);
-}
-
-int sp_pts_cmp(syncpoint_t *a, syncpoint_t *b){
- return (a->ts - b->ts>>32) - (b->ts - a->ts>>32);
-}
-
-static void add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){
- syncpoint_t *sp2, *sp= av_mallocz(sizeof(syncpoint_t));
-
- sp->pos= pos;
- sp->back_ptr= back_ptr;
- sp->ts= ts;
- sp2= av_tree_insert(&nut->syncpoints, sp, sp_pos_cmp);
- if(sp2 && sp2 != sp)
- av_free(sp);
-}
-
static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
int64_t end, tmp;
- int i;
- AVRational time_base;
nut->last_syncpoint_pos= url_ftell(bc)-8;
- end= get_packetheader(nut, bc, 1);
+ end= get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
end += url_ftell(bc);
- tmp= get_v(bc);
- *back_ptr= nut->last_syncpoint_pos - 16*get_v(bc);
+ tmp= ff_get_v(bc);
+ *back_ptr= nut->last_syncpoint_pos - 16*ff_get_v(bc);
if(*back_ptr < 0)
return -1;
- time_base= nut->time_base[tmp % nut->time_base_count];
- for(i=0; i<s->nb_streams; i++){
- nut->stream[i].last_pts= av_rescale_rnd(
- tmp / nut->time_base_count,
- time_base.num * (int64_t)nut->stream[i].time_base.den,
- time_base.den * (int64_t)nut->stream[i].time_base.num,
- AV_ROUND_DOWN);
- //last_key_frame ?
- }
- //FIXME put this in a reset func maybe
+ ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count);
if(skip_reserved(bc, end) || get_checksum(bc)){
av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
@@ -477,14 +454,14 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
}
*ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE;
- add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
+ ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
return 0;
}
static int find_and_decode_index(NUTContext *nut){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
uint64_t tmp, end;
int i, j, syncpoint_count;
int64_t filesize= url_fsize(bc);
@@ -498,10 +475,10 @@ static int find_and_decode_index(NUTContext *nut){
return -1;
}
- end= get_packetheader(nut, bc, 1);
+ end= get_packetheader(nut, bc, 1, INDEX_STARTCODE);
end += url_ftell(bc);
- get_v(bc); //max_pts
+ ff_get_v(bc); //max_pts
GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
@@ -514,7 +491,7 @@ static int find_and_decode_index(NUTContext *nut){
for(i=0; i<s->nb_streams; i++){
int64_t last_pts= -1;
for(j=0; j<syncpoint_count;){
- uint64_t x= get_v(bc);
+ uint64_t x= ff_get_v(bc);
int type= x&1;
int n= j;
x>>=1;
@@ -543,12 +520,12 @@ static int find_and_decode_index(NUTContext *nut){
return -1;
}
assert(n<=syncpoint_count+1);
- for(; j<n; j++){
+ for(; j<n && j<syncpoint_count; j++){
if(has_keyframe[j]){
- uint64_t B, A= get_v(bc);
+ uint64_t B, A= ff_get_v(bc);
if(!A){
- A= get_v(bc);
- B= get_v(bc);
+ A= ff_get_v(bc);
+ B= ff_get_v(bc);
//eor_pts[j][i] = last_pts + A + B
}else
B= 0;
@@ -566,7 +543,7 @@ static int find_and_decode_index(NUTContext *nut){
}
if(skip_reserved(bc, end) || get_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Index checksum mismatch\n");
+ av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
return -1;
}
return 0;
@@ -575,9 +552,9 @@ static int find_and_decode_index(NUTContext *nut){
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
int64_t pos;
- int inited_stream_count;
+ int initialized_stream_count;
nut->avf= s;
@@ -586,21 +563,21 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
do{
pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
if (pos<0+1){
- av_log(s, AV_LOG_ERROR, "no main startcode found\n");
+ av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
return -1;
}
}while(decode_main_header(nut) < 0);
/* stream headers */
pos=0;
- for(inited_stream_count=0; inited_stream_count < s->nb_streams;){
+ for(initialized_stream_count=0; initialized_stream_count < s->nb_streams;){
pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
if (pos<0+1){
- av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
+ av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
return -1;
}
if(decode_stream_header(nut) >= 0)
- inited_stream_count++;
+ initialized_stream_count++;
}
/* info headers */
@@ -634,15 +611,15 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
return 0;
}
-static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, int frame_code){
+static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, uint8_t *header_idx, int frame_code){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
StreamContext *stc;
int size, flags, size_mul, pts_delta, i, reserved_count;
uint64_t tmp;
if(url_ftell(bc) > nut->last_syncpoint_pos + nut->max_distance){
- av_log(s, AV_LOG_ERROR, "last frame must have been damaged %Ld > %Ld + %d\n", url_ftell(bc), nut->last_syncpoint_pos, nut->max_distance);
+ av_log(s, AV_LOG_ERROR, "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", url_ftell(bc), nut->last_syncpoint_pos, nut->max_distance);
return -1;
}
@@ -652,31 +629,45 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, in
*stream_id = nut->frame_code[frame_code].stream_id;
pts_delta = nut->frame_code[frame_code].pts_delta;
reserved_count = nut->frame_code[frame_code].reserved_count;
+ *header_idx = nut->frame_code[frame_code].header_idx;
if(flags & FLAG_INVALID)
return -1;
if(flags & FLAG_CODED)
- flags ^= get_v(bc);
+ flags ^= ff_get_v(bc);
if(flags & FLAG_STREAM_ID){
GET_V(*stream_id, tmp < s->nb_streams)
}
stc= &nut->stream[*stream_id];
if(flags&FLAG_CODED_PTS){
- int coded_pts= get_v(bc);
+ int coded_pts= ff_get_v(bc);
//FIXME check last_pts validity?
if(coded_pts < (1<<stc->msb_pts_shift)){
- *pts=lsb2full(stc, coded_pts);
+ *pts=ff_lsb2full(stc, coded_pts);
}else
*pts=coded_pts - (1<<stc->msb_pts_shift);
}else
*pts= stc->last_pts + pts_delta;
if(flags&FLAG_SIZE_MSB){
- size += size_mul*get_v(bc);
+ size += size_mul*ff_get_v(bc);
}
+ if(flags&FLAG_MATCH_TIME)
+ get_s(bc);
+ if(flags&FLAG_HEADER_IDX)
+ *header_idx= ff_get_v(bc);
if(flags&FLAG_RESERVED)
- reserved_count= get_v(bc);
+ reserved_count= ff_get_v(bc);
for(i=0; i<reserved_count; i++)
- get_v(bc);
+ ff_get_v(bc);
+
+ if(*header_idx >= (unsigned)nut->header_count){
+ av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
+ return -1;
+ }
+ if(size > 4096)
+ *header_idx=0;
+ size -= nut->header_len[*header_idx];
+
if(flags&FLAG_CHECKSUM){
get_be32(bc); //FIXME check this
}else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){
@@ -692,12 +683,13 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, in
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
AVFormatContext *s= nut->avf;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
int size, stream_id, discard;
int64_t pts, last_IP_pts;
StreamContext *stc;
+ uint8_t header_idx;
- size= decode_frame_header(nut, &pts, &stream_id, frame_code);
+ size= decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
if(size < 0)
return -1;
@@ -716,7 +708,11 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
return 1;
}
- av_get_packet(bc, pkt, size);
+ av_new_packet(pkt, size + nut->header_len[header_idx]);
+ memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
+ pkt->pos= url_ftell(bc); //FIXME
+ get_buffer(bc, pkt->data + nut->header_len[header_idx], size);
+
pkt->stream_index = stream_id;
if (stc->last_flags & FLAG_KEY)
pkt->flags |= PKT_FLAG_KEY;
@@ -728,7 +724,7 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
{
NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
int i, frame_code=0, ret, skip;
int64_t ts, back_ptr;
@@ -753,7 +749,7 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
case MAIN_STARTCODE:
case STREAM_STARTCODE:
case INDEX_STARTCODE:
- skip= get_packetheader(nut, bc, 0);
+ skip= get_packetheader(nut, bc, 0, tmp);
url_fseek(bc, skip, SEEK_CUR);
break;
case INFO_STARTCODE:
@@ -784,24 +780,23 @@ av_log(s, AV_LOG_DEBUG, "sync\n");
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
NUTContext *nut = s->priv_data;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
int64_t pos, pts, back_ptr;
av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
pos= *pos_arg;
-resync:
do{
pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1;
if(pos < 1){
assert(nut->next_startcode == 0);
- av_log(s, AV_LOG_ERROR, "read_timestamp failed\n");
+ av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
return AV_NOPTS_VALUE;
}
}while(decode_syncpoint(nut, &pts, &back_ptr) < 0);
*pos_arg = pos-1;
assert(nut->last_syncpoint_pos == *pos_arg);
- av_log(s, AV_LOG_DEBUG, "return %Ld %Ld\n", pts,back_ptr );
+ av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts,back_ptr );
if (stream_index == -1) return pts;
else if(stream_index == -2) return back_ptr;
@@ -825,8 +820,8 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flag
pos2= st->index_entries[index].pos;
ts = st->index_entries[index].timestamp;
}else{
- av_tree_find(nut->syncpoints, &dummy, sp_pts_cmp, next_node);
- av_log(s, AV_LOG_DEBUG, "%Ld-%Ld %Ld-%Ld\n", next_node[0]->pos, next_node[1]->pos,
+ av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pts_cmp, next_node);
+ av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", next_node[0]->pos, next_node[1]->pos,
next_node[0]->ts , next_node[1]->ts);
pos= av_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos,
next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);
@@ -834,22 +829,22 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flag
if(!(flags & AVSEEK_FLAG_BACKWARD)){
dummy.pos= pos+16;
next_node[1]= &nopts_sp;
- av_tree_find(nut->syncpoints, &dummy, sp_pos_cmp, next_node);
+ av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, next_node);
pos2= av_gen_search(s, -2, dummy.pos, next_node[0]->pos , next_node[1]->pos, next_node[1]->pos,
next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp);
if(pos2>=0)
pos= pos2;
- //FIXME dir but i think it doesnt matter
+ //FIXME dir but i think it does not matter
}
dummy.pos= pos;
- sp= av_tree_find(nut->syncpoints, &dummy, sp_pos_cmp, NULL);
+ sp= av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, NULL);
assert(sp);
pos2= sp->back_ptr - 15;
}
av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
- pos= find_startcode(&s->pb, SYNCPOINT_STARTCODE, pos2);
- url_fseek(&s->pb, pos, SEEK_SET);
+ pos= find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
+ url_fseek(s->pb, pos, SEEK_SET);
av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
if(pos2 > pos || pos2 + 15 < pos){
av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
diff --git a/contrib/ffmpeg/libavformat/nutenc.c b/contrib/ffmpeg/libavformat/nutenc.c
new file mode 100644
index 000000000..5c0975c28
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nutenc.c
@@ -0,0 +1,775 @@
+/*
+ * nut muxer
+ * Copyright (c) 2004-2007 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 "nut.h"
+#include "tree.h"
+#include "mpegaudiodata.h"
+
+static int find_expected_header(AVCodecContext *c, int size, int key_frame, uint8_t out[64]){
+ int sample_rate= c->sample_rate;
+
+ if(size>4096)
+ return 0;
+
+ AV_WB24(out, 1);
+
+ if(c->codec_id == CODEC_ID_MPEG4){
+ if(key_frame){
+ return 3;
+ }else{
+ out[3]= 0xB6;
+ return 4;
+ }
+ }else if(c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MPEG2VIDEO){
+ return 3;
+ }else if(c->codec_id == CODEC_ID_H264){
+ return 3;
+ }else if(c->codec_id == CODEC_ID_MP3 || c->codec_id == CODEC_ID_MP2){
+ int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size;
+ int layer= c->codec_id == CODEC_ID_MP3 ? 3 : 2;
+ unsigned int header= 0xFFF00000;
+
+ lsf = sample_rate < (24000+32000)/2;
+ mpeg25 = sample_rate < (12000+16000)/2;
+ sample_rate <<= lsf + mpeg25;
+ if (sample_rate < (32000 + 44100)/2) sample_rate_index=2;
+ else if(sample_rate < (44100 + 48000)/2) sample_rate_index=0;
+ else sample_rate_index=1;
+
+ sample_rate= ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25);
+
+ for(bitrate_index=2; bitrate_index<30; bitrate_index++){
+ frame_size = ff_mpa_bitrate_tab[lsf][layer-1][bitrate_index>>1];
+ frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1);
+
+ if(frame_size == size)
+ break;
+ }
+
+ header |= (!lsf)<<19;
+ header |= (4-layer)<<17;
+ header |= 1<<16; //no crc
+ AV_WB32(out, header);
+ if(size <= 0)
+ return 2; //we guess theres no crc, if there is one the user clearly doesnt care about overhead
+ if(bitrate_index == 30)
+ return -1; //something is wrong ...
+
+ header |= (bitrate_index>>1)<<12;
+ header |= sample_rate_index<<10;
+ header |= (bitrate_index&1)<<9;
+
+ return 2; //FIXME actually put the needed ones in build_elision_headers()
+ return 3; //we guess that the private bit isnt set
+//FIXME the above asumtations should be checked, if these turn out false too often something should be done
+ }
+ return 0;
+}
+
+static int find_header_idx(AVFormatContext *s, AVCodecContext *c, int size, int frame_type){
+ NUTContext *nut = s->priv_data;
+ uint8_t out[64];
+ int i;
+ int len= find_expected_header(c, size, frame_type, out);
+
+//av_log(NULL, AV_LOG_ERROR, "expected_h len=%d size=%d codec_id=%d\n", len, size, c->codec_id);
+
+ for(i=1; i<nut->header_count; i++){
+ if( len == nut->header_len[i]
+ && !memcmp(out, nut->header[i], len)){
+// av_log(NULL, AV_LOG_ERROR, "found %d\n", i);
+ return i;
+ }
+ }
+// av_log(NULL, AV_LOG_ERROR, "nothing found\n");
+ return 0;
+}
+
+static void build_elision_headers(AVFormatContext *s){
+ NUTContext *nut = s->priv_data;
+ int i;
+ //FIXME this is lame
+ //FIXME write a 2pass mode to find the maximal headers
+ const static uint8_t headers[][5]={
+ {3, 0x00, 0x00, 0x01},
+ {4, 0x00, 0x00, 0x01, 0xB6},
+ {2, 0xFF, 0xFA}, //mp3+crc
+ {2, 0xFF, 0xFB}, //mp3
+ {2, 0xFF, 0xFC}, //mp2+crc
+ {2, 0xFF, 0xFD}, //mp2
+ };
+
+ nut->header_count= 7;
+ for(i=1; i<nut->header_count; i++){
+ nut->header_len[i]= headers[i-1][0];
+ nut->header [i]= &headers[i-1][1];
+ }
+}
+
+static void build_frame_code(AVFormatContext *s){
+ NUTContext *nut = s->priv_data;
+ int key_frame, index, pred, stream_id;
+ int start=1;
+ int end= 254;
+ int keyframe_0_esc= s->nb_streams > 2;
+ int pred_table[10];
+ FrameCode *ft;
+
+ ft= &nut->frame_code[start];
+ ft->flags= FLAG_CODED;
+ ft->size_mul=1;
+ ft->pts_delta=1;
+ start++;
+
+ if(keyframe_0_esc){
+ /* keyframe = 0 escape */
+ FrameCode *ft= &nut->frame_code[start];
+ ft->flags= FLAG_STREAM_ID | FLAG_SIZE_MSB | FLAG_CODED_PTS;
+ ft->size_mul=1;
+ start++;
+ }
+
+ for(stream_id= 0; stream_id<s->nb_streams; stream_id++){
+ int start2= start + (end-start)*stream_id / s->nb_streams;
+ int end2 = start + (end-start)*(stream_id+1) / s->nb_streams;
+ AVCodecContext *codec = s->streams[stream_id]->codec;
+ int is_audio= codec->codec_type == CODEC_TYPE_AUDIO;
+ int intra_only= /*codec->intra_only || */is_audio;
+ int pred_count;
+
+ for(key_frame=0; key_frame<2; key_frame++){
+ if(intra_only && keyframe_0_esc && key_frame==0)
+ continue;
+
+ {
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY*key_frame;
+ ft->flags|= FLAG_SIZE_MSB | FLAG_CODED_PTS;
+ ft->stream_id= stream_id;
+ ft->size_mul=1;
+ if(is_audio)
+ ft->header_idx= find_header_idx(s, codec, -1, key_frame);
+ start2++;
+ }
+ }
+
+ key_frame= intra_only;
+#if 1
+ if(is_audio){
+ int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);
+ int pts;
+ for(pts=0; pts<2; pts++){
+ for(pred=0; pred<2; pred++){
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY*key_frame;
+ ft->stream_id= stream_id;
+ ft->size_mul=frame_bytes + 2;
+ ft->size_lsb=frame_bytes + pred;
+ ft->pts_delta=pts;
+ ft->header_idx= find_header_idx(s, codec, frame_bytes + pred, key_frame);
+ start2++;
+ }
+ }
+ }else{
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY | FLAG_SIZE_MSB;
+ ft->stream_id= stream_id;
+ ft->size_mul=1;
+ ft->pts_delta=1;
+ start2++;
+ }
+#endif
+
+ if(codec->has_b_frames){
+ pred_count=5;
+ pred_table[0]=-2;
+ pred_table[1]=-1;
+ pred_table[2]=1;
+ pred_table[3]=3;
+ pred_table[4]=4;
+ }else if(codec->codec_id == CODEC_ID_VORBIS){
+ pred_count=3;
+ pred_table[0]=2;
+ pred_table[1]=9;
+ pred_table[2]=16;
+ }else{
+ pred_count=1;
+ pred_table[0]=1;
+ }
+
+ for(pred=0; pred<pred_count; pred++){
+ int start3= start2 + (end2-start2)*pred / pred_count;
+ int end3 = start2 + (end2-start2)*(pred+1) / pred_count;
+
+ for(index=start3; index<end3; index++){
+ FrameCode *ft= &nut->frame_code[index];
+ ft->flags= FLAG_KEY*key_frame;
+ ft->flags|= FLAG_SIZE_MSB;
+ ft->stream_id= stream_id;
+//FIXME use single byte size and pred from last
+ ft->size_mul= end3-start3;
+ ft->size_lsb= index - start3;
+ ft->pts_delta= pred_table[pred];
+ if(is_audio)
+ ft->header_idx= find_header_idx(s, codec, -1, key_frame);
+ }
+ }
+ }
+ memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));
+ nut->frame_code[ 0].flags=
+ nut->frame_code[255].flags=
+ nut->frame_code['N'].flags= FLAG_INVALID;
+}
+
+/**
+ * Gets the length in bytes which is needed to store val as v.
+ */
+static int get_length(uint64_t val){
+ int i=1;
+
+ while(val>>=7)
+ i++;
+
+ return i;
+}
+
+static void put_v(ByteIOContext *bc, uint64_t val){
+ int i= get_length(val);
+
+ while(--i>0)
+ put_byte(bc, 128 | (val>>(7*i)));
+
+ put_byte(bc, val&127);
+}
+
+static void put_t(NUTContext *nut, StreamContext *nus, ByteIOContext *bc, uint64_t val){
+ val *= nut->time_base_count;
+ val += nus->time_base - nut->time_base;
+ put_v(bc, val);
+}
+
+/**
+ * Stores a string as vb.
+ */
+static void put_str(ByteIOContext *bc, const char *string){
+ int len= strlen(string);
+
+ put_v(bc, len);
+ put_buffer(bc, string, len);
+}
+
+static void put_s(ByteIOContext *bc, int64_t val){
+ put_v(bc, 2*FFABS(val) - (val>0));
+}
+
+#ifdef TRACE
+static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
+ av_log(NULL, AV_LOG_DEBUG, "put_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+
+ put_v(bc, v);
+}
+
+static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){
+ av_log(NULL, AV_LOG_DEBUG, "put_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+
+ put_s(bc, v);
+}
+#define put_v(bc, v) put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif
+
+//FIXME remove calculate_checksum
+static void put_packet(NUTContext *nut, ByteIOContext *bc, ByteIOContext *dyn_bc, int calculate_checksum, uint64_t startcode){
+ uint8_t *dyn_buf=NULL;
+ int dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf);
+ int forw_ptr= dyn_size + 4*calculate_checksum;
+
+ if(forw_ptr > 4096)
+ init_checksum(bc, ff_crc04C11DB7_update, 0);
+ put_be64(bc, startcode);
+ put_v(bc, forw_ptr);
+ if(forw_ptr > 4096)
+ put_le32(bc, get_checksum(bc));
+
+ if(calculate_checksum)
+ init_checksum(bc, ff_crc04C11DB7_update, 0);
+ put_buffer(bc, dyn_buf, dyn_size);
+ if(calculate_checksum)
+ put_le32(bc, get_checksum(bc));
+
+ av_free(dyn_buf);
+}
+
+static void write_mainheader(NUTContext *nut, ByteIOContext *bc){
+ int i, j, tmp_pts, tmp_flags, tmp_stream, tmp_mul, tmp_size, tmp_fields, tmp_head_idx;
+ int64_t tmp_match;
+
+ put_v(bc, 3); /* version */
+ put_v(bc, nut->avf->nb_streams);
+ put_v(bc, nut->max_distance);
+ put_v(bc, nut->time_base_count);
+
+ for(i=0; i<nut->time_base_count; i++){
+ put_v(bc, nut->time_base[i].num);
+ put_v(bc, nut->time_base[i].den);
+ }
+
+ tmp_pts=0;
+ tmp_mul=1;
+ tmp_stream=0;
+ tmp_match= 1-(1LL<<62);
+ tmp_head_idx= 0;
+ for(i=0; i<256;){
+ tmp_fields=0;
+ tmp_size=0;
+// tmp_res=0;
+ if(tmp_pts != nut->frame_code[i].pts_delta) tmp_fields=1;
+ if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2;
+ if(tmp_stream != nut->frame_code[i].stream_id) tmp_fields=3;
+ if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4;
+// if(tmp_res != nut->frame_code[i].res ) tmp_fields=5;
+ if(tmp_head_idx!=nut->frame_code[i].header_idx)tmp_fields=8;
+
+ tmp_pts = nut->frame_code[i].pts_delta;
+ tmp_flags = nut->frame_code[i].flags;
+ tmp_stream= nut->frame_code[i].stream_id;
+ tmp_mul = nut->frame_code[i].size_mul;
+ tmp_size = nut->frame_code[i].size_lsb;
+// tmp_res = nut->frame_code[i].res;
+ tmp_head_idx= nut->frame_code[i].header_idx;
+
+ for(j=0; i<256; j++,i++){
+ if(i == 'N'){
+ j--;
+ continue;
+ }
+ if(nut->frame_code[i].pts_delta != tmp_pts ) break;
+ if(nut->frame_code[i].flags != tmp_flags ) break;
+ if(nut->frame_code[i].stream_id != tmp_stream) break;
+ if(nut->frame_code[i].size_mul != tmp_mul ) break;
+ if(nut->frame_code[i].size_lsb != tmp_size+j) break;
+// if(nut->frame_code[i].res != tmp_res ) break;
+ if(nut->frame_code[i].header_idx!= tmp_head_idx) break;
+ }
+ if(j != tmp_mul - tmp_size) tmp_fields=6;
+
+ put_v(bc, tmp_flags);
+ put_v(bc, tmp_fields);
+ if(tmp_fields>0) put_s(bc, tmp_pts);
+ if(tmp_fields>1) put_v(bc, tmp_mul);
+ if(tmp_fields>2) put_v(bc, tmp_stream);
+ if(tmp_fields>3) put_v(bc, tmp_size);
+ if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/);
+ if(tmp_fields>5) put_v(bc, j);
+ if(tmp_fields>6) put_v(bc, tmp_match);
+ if(tmp_fields>7) put_v(bc, tmp_head_idx);
+ }
+ put_v(bc, nut->header_count-1);
+ for(i=1; i<nut->header_count; i++){
+ put_v(bc, nut->header_len[i]);
+ put_buffer(bc, nut->header[i], nut->header_len[i]);
+ }
+}
+
+static int write_streamheader(NUTContext *nut, ByteIOContext *bc, AVCodecContext *codec, int i){
+ put_v(bc, i);
+ switch(codec->codec_type){
+ case CODEC_TYPE_VIDEO: put_v(bc, 0); break;
+ case CODEC_TYPE_AUDIO: put_v(bc, 1); break;
+// case CODEC_TYPE_TEXT : put_v(bc, 2); break;
+ default : put_v(bc, 3); break;
+ }
+ put_v(bc, 4);
+ if (codec->codec_tag){
+ put_le32(bc, codec->codec_tag);
+ }else
+ return -1;
+
+ put_v(bc, nut->stream[i].time_base - nut->time_base);
+ put_v(bc, nut->stream[i].msb_pts_shift);
+ put_v(bc, nut->stream[i].max_pts_distance);
+ put_v(bc, codec->has_b_frames);
+ put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
+
+ put_v(bc, codec->extradata_size);
+ put_buffer(bc, codec->extradata, codec->extradata_size);
+
+ switch(codec->codec_type){
+ case CODEC_TYPE_AUDIO:
+ put_v(bc, codec->sample_rate);
+ put_v(bc, 1);
+ put_v(bc, codec->channels);
+ break;
+ case CODEC_TYPE_VIDEO:
+ put_v(bc, codec->width);
+ put_v(bc, codec->height);
+
+ if(codec->sample_aspect_ratio.num<=0 || codec->sample_aspect_ratio.den<=0){
+ put_v(bc, 0);
+ put_v(bc, 0);
+ }else{
+ put_v(bc, codec->sample_aspect_ratio.num);
+ put_v(bc, codec->sample_aspect_ratio.den);
+ }
+ put_v(bc, 0); /* csp type -- unknown */
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int add_info(ByteIOContext *bc, const char *type, const char *value){
+ put_str(bc, type);
+ put_s(bc, -1);
+ put_str(bc, value);
+ return 1;
+}
+
+static int write_globalinfo(NUTContext *nut, ByteIOContext *bc){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *dyn_bc;
+ uint8_t *dyn_buf=NULL;
+ int count=0, dyn_size;
+ int ret = url_open_dyn_buf(&dyn_bc);
+ if(ret < 0)
+ return ret;
+
+ if(s->title [0]) count+= add_info(dyn_bc, "Title" , s->title);
+ if(s->author [0]) count+= add_info(dyn_bc, "Author" , s->author);
+ if(s->copyright[0]) count+= add_info(dyn_bc, "Copyright", s->copyright);
+ if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
+ count+= add_info(dyn_bc, "Encoder" , LIBAVFORMAT_IDENT);
+
+ put_v(bc, 0); //stream_if_plus1
+ put_v(bc, 0); //chapter_id
+ put_v(bc, 0); //timestamp_start
+ put_v(bc, 0); //length
+
+ put_v(bc, count);
+
+ dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf);
+ put_buffer(bc, dyn_buf, dyn_size);
+ av_free(dyn_buf);
+ return 0;
+}
+
+static int write_headers(NUTContext *nut, ByteIOContext *bc){
+ ByteIOContext *dyn_bc;
+ int i, ret;
+
+ ret = url_open_dyn_buf(&dyn_bc);
+ if(ret < 0)
+ return ret;
+ write_mainheader(nut, dyn_bc);
+ put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE);
+
+ for (i=0; i < nut->avf->nb_streams; i++){
+ AVCodecContext *codec = nut->avf->streams[i]->codec;
+
+ ret = url_open_dyn_buf(&dyn_bc);
+ if(ret < 0)
+ return ret;
+ write_streamheader(nut, dyn_bc, codec, i);
+ put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE);
+ }
+
+ ret = url_open_dyn_buf(&dyn_bc);
+ if(ret < 0)
+ return ret;
+ write_globalinfo(nut, dyn_bc);
+ put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE);
+
+ nut->last_syncpoint_pos= INT_MIN;
+ nut->header_count++;
+ return 0;
+}
+
+static int write_header(AVFormatContext *s){
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = s->pb;
+ int i, j;
+
+ nut->avf= s;
+
+ nut->stream = av_mallocz(sizeof(StreamContext)*s->nb_streams);
+ nut->time_base= av_mallocz(sizeof(AVRational )*s->nb_streams);
+
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st= s->streams[i];
+ int ssize;
+ AVRational time_base;
+ ff_parse_specific_params(st->codec, &time_base.den, &ssize, &time_base.num);
+
+ av_set_pts_info(st, 64, time_base.num, time_base.den);
+
+ for(j=0; j<nut->time_base_count; j++){
+ if(!memcmp(&time_base, &nut->time_base[j], sizeof(AVRational))){
+ break;
+ }
+ }
+ nut->time_base[j]= time_base;
+ nut->stream[i].time_base= &nut->time_base[j];
+ if(j==nut->time_base_count)
+ nut->time_base_count++;
+
+ if(av_q2d(time_base) >= 0.001)
+ nut->stream[i].msb_pts_shift = 7;
+ else
+ nut->stream[i].msb_pts_shift = 14;
+ nut->stream[i].max_pts_distance= FFMAX(1/av_q2d(time_base), 1);
+ }
+
+ nut->max_distance = MAX_DISTANCE;
+ build_elision_headers(s);
+ build_frame_code(s);
+ assert(nut->frame_code['N'].flags == FLAG_INVALID);
+
+ put_buffer(bc, ID_STRING, strlen(ID_STRING));
+ put_byte(bc, 0);
+
+ write_headers(nut, bc);
+
+ put_flush_packet(bc);
+
+ //FIXME index
+
+ return 0;
+}
+
+static int get_needed_flags(NUTContext *nut, StreamContext *nus, FrameCode *fc, AVPacket *pkt){
+ int flags= 0;
+
+ if(pkt->flags & PKT_FLAG_KEY ) flags |= FLAG_KEY;
+ if(pkt->stream_index != fc->stream_id ) flags |= FLAG_STREAM_ID;
+ if(pkt->size / fc->size_mul ) flags |= FLAG_SIZE_MSB;
+ if(pkt->pts - nus->last_pts != fc->pts_delta) flags |= FLAG_CODED_PTS;
+ if(pkt->size > 2*nut->max_distance ) flags |= FLAG_CHECKSUM;
+ if(FFABS(pkt->pts - nus->last_pts)
+ > nus->max_pts_distance) flags |= FLAG_CHECKSUM;
+ if( pkt->size < nut->header_len[fc->header_idx]
+ || (pkt->size > 4096 && fc->header_idx)
+ || memcmp(pkt->data, nut->header[fc->header_idx], nut->header_len[fc->header_idx]))
+ flags |= FLAG_HEADER_IDX;
+
+ return flags | (fc->flags & FLAG_CODED);
+}
+
+static int find_best_header_idx(NUTContext *nut, AVPacket *pkt){
+ int i;
+ int best_i = 0;
+ int best_len= 0;
+
+ if(pkt->size > 4096)
+ return 0;
+
+ for(i=1; i<nut->header_count; i++){
+ if( pkt->size >= nut->header_len[i]
+ && nut->header_len[i] > best_len
+ && !memcmp(pkt->data, nut->header[i], nut->header_len[i])){
+ best_i= i;
+ best_len= nut->header_len[i];
+ }
+ }
+ return best_i;
+}
+
+static int write_packet(AVFormatContext *s, AVPacket *pkt){
+ NUTContext *nut = s->priv_data;
+ StreamContext *nus= &nut->stream[pkt->stream_index];
+ ByteIOContext *bc = s->pb, *dyn_bc;
+ FrameCode *fc;
+ int64_t coded_pts;
+ int best_length, frame_code, flags, needed_flags, i, header_idx, best_header_idx;
+ int key_frame = !!(pkt->flags & PKT_FLAG_KEY);
+ int store_sp=0;
+ int ret;
+
+ if(1LL<<(20+3*nut->header_count) <= url_ftell(bc))
+ write_headers(nut, bc);
+
+ if(key_frame && !(nus->last_flags & FLAG_KEY))
+ store_sp= 1;
+
+ if(pkt->size + 30/*FIXME check*/ + url_ftell(bc) >= nut->last_syncpoint_pos + nut->max_distance)
+ store_sp= 1;
+
+//FIXME: Ensure store_sp is 1 in the first place.
+
+ if(store_sp){
+ syncpoint_t *sp, dummy= {.pos= INT64_MAX};
+
+ ff_nut_reset_ts(nut, *nus->time_base, pkt->dts);
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st= s->streams[i];
+ int64_t dts_tb = av_rescale_rnd(pkt->dts,
+ nus->time_base->num * (int64_t)nut->stream[i].time_base->den,
+ nus->time_base->den * (int64_t)nut->stream[i].time_base->num,
+ AV_ROUND_DOWN);
+ int index= av_index_search_timestamp(st, dts_tb, AVSEEK_FLAG_BACKWARD);
+ if(index>=0) dummy.pos= FFMIN(dummy.pos, st->index_entries[index].pos);
+ }
+ if(dummy.pos == INT64_MAX)
+ dummy.pos= 0;
+ sp= av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, NULL);
+
+ nut->last_syncpoint_pos= url_ftell(bc);
+ ret = url_open_dyn_buf(&dyn_bc);
+ if(ret < 0)
+ return ret;
+ put_t(nut, nus, dyn_bc, pkt->dts);
+ put_v(dyn_bc, sp ? (nut->last_syncpoint_pos - sp->pos)>>4 : 0);
+ put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE);
+
+ ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0/*unused*/, pkt->dts);
+ }
+ assert(nus->last_pts != AV_NOPTS_VALUE);
+
+ coded_pts = pkt->pts & ((1<<nus->msb_pts_shift)-1);
+ if(ff_lsb2full(nus, coded_pts) != pkt->pts)
+ coded_pts= pkt->pts + (1<<nus->msb_pts_shift);
+
+ best_header_idx= find_best_header_idx(nut, pkt);
+
+ best_length=INT_MAX;
+ frame_code= -1;
+ for(i=0; i<256; i++){
+ int length= 0;
+ FrameCode *fc= &nut->frame_code[i];
+ int flags= fc->flags;
+
+ if(flags & FLAG_INVALID)
+ continue;
+ needed_flags= get_needed_flags(nut, nus, fc, pkt);
+
+ if(flags & FLAG_CODED){
+ length++;
+ flags = needed_flags;
+ }
+
+ if((flags & needed_flags) != needed_flags)
+ continue;
+
+ if((flags ^ needed_flags) & FLAG_KEY)
+ continue;
+
+ if(flags & FLAG_STREAM_ID)
+ length+= get_length(pkt->stream_index);
+
+ if(pkt->size % fc->size_mul != fc->size_lsb)
+ continue;
+ if(flags & FLAG_SIZE_MSB)
+ length += get_length(pkt->size / fc->size_mul);
+
+ if(flags & FLAG_CHECKSUM)
+ length+=4;
+
+ if(flags & FLAG_CODED_PTS)
+ length += get_length(coded_pts);
+
+ if( (flags & FLAG_CODED)
+ && nut->header_len[best_header_idx] > nut->header_len[fc->header_idx]+1){
+ flags |= FLAG_HEADER_IDX;
+ }
+
+ if(flags & FLAG_HEADER_IDX){
+ length += 1 - nut->header_len[best_header_idx];
+ }else{
+ length -= nut->header_len[fc->header_idx];
+ }
+
+ length*=4;
+ length+= !(flags & FLAG_CODED_PTS);
+ length+= !(flags & FLAG_CHECKSUM);
+
+ if(length < best_length){
+ best_length= length;
+ frame_code=i;
+ }
+ }
+ assert(frame_code != -1);
+ fc= &nut->frame_code[frame_code];
+ flags= fc->flags;
+ needed_flags= get_needed_flags(nut, nus, fc, pkt);
+ header_idx= fc->header_idx;
+
+ init_checksum(bc, ff_crc04C11DB7_update, 0);
+ put_byte(bc, frame_code);
+ if(flags & FLAG_CODED){
+ put_v(bc, (flags^needed_flags) & ~(FLAG_CODED));
+ flags = needed_flags;
+ }
+ if(flags & FLAG_STREAM_ID) put_v(bc, pkt->stream_index);
+ if(flags & FLAG_CODED_PTS) put_v(bc, coded_pts);
+ if(flags & FLAG_SIZE_MSB) put_v(bc, pkt->size / fc->size_mul);
+ if(flags & FLAG_HEADER_IDX) put_v(bc, header_idx= best_header_idx);
+
+ if(flags & FLAG_CHECKSUM) put_le32(bc, get_checksum(bc));
+ else get_checksum(bc);
+
+ put_buffer(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]);
+ nus->last_flags= flags;
+ nus->last_pts= pkt->pts;
+
+ //FIXME just store one per syncpoint
+ if(flags & FLAG_KEY)
+ av_add_index_entry(
+ s->streams[pkt->stream_index],
+ nut->last_syncpoint_pos,
+ pkt->pts,
+ 0,
+ 0,
+ AVINDEX_KEYFRAME);
+
+ return 0;
+}
+
+static int write_trailer(AVFormatContext *s){
+ NUTContext *nut= s->priv_data;
+ ByteIOContext *bc= s->pb;
+
+ while(nut->header_count<3)
+ write_headers(nut, bc);
+ put_flush_packet(bc);
+
+ return 0;
+}
+
+AVOutputFormat nut_muxer = {
+ "nut",
+ "nut format",
+ "video/x-nut",
+ "nut",
+ sizeof(NUTContext),
+#ifdef CONFIG_LIBVORBIS
+ CODEC_ID_VORBIS,
+#elif defined(CONFIG_LIBMP3LAME)
+ CODEC_ID_MP3,
+#else
+ CODEC_ID_MP2, /* AC3 needs liba52 decoder */
+#endif
+ CODEC_ID_MPEG4,
+ write_header,
+ write_packet,
+ write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+ .codec_tag= (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
+};
diff --git a/contrib/ffmpeg/libavformat/nuv.c b/contrib/ffmpeg/libavformat/nuv.c
index 7e04222ee..f56d116ff 100644
--- a/contrib/ffmpeg/libavformat/nuv.c
+++ b/contrib/ffmpeg/libavformat/nuv.c
@@ -24,6 +24,7 @@
typedef struct {
int v_id;
int a_id;
+ int rtjpg_video;
} NUVContext;
typedef enum {
@@ -35,8 +36,6 @@ typedef enum {
} frametype_t;
static int nuv_probe(AVProbeData *p) {
- if (p->buf_size < 12)
- return 0;
if (!memcmp(p->buf, "NuppelVideo", 12))
return AVPROBE_SCORE_MAX;
if (!memcmp(p->buf, "MythTVVideo", 12))
@@ -86,6 +85,8 @@ static int get_codec_data(ByteIOContext *pb, AVStream *vst,
vst->codec->codec_tag = get_le32(pb);
vst->codec->codec_id =
codec_get_id(codec_bmp_tags, vst->codec->codec_tag);
+ if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G'))
+ vst->codec->codec_id = CODEC_ID_NUV;
} else
url_fskip(pb, 4);
@@ -97,6 +98,7 @@ static int get_codec_data(ByteIOContext *pb, AVStream *vst,
ast->codec->codec_id =
wav_codec_get_id(ast->codec->codec_tag,
ast->codec->bits_per_sample);
+ ast->need_parsing = AVSTREAM_PARSE_FULL;
} else
url_fskip(pb, 4 * 4);
@@ -117,8 +119,8 @@ static int get_codec_data(ByteIOContext *pb, AVStream *vst,
}
static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) {
- NUVContext *ctx = (NUVContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ NUVContext *ctx = s->priv_data;
+ ByteIOContext *pb = s->pb;
char id_string[12], version_string[5];
double aspect, fps;
int is_mythtv, width, height, v_packs, a_packs;
@@ -149,7 +151,6 @@ static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) {
vst = av_new_stream(s, ctx->v_id);
vst->codec->codec_type = CODEC_TYPE_VIDEO;
vst->codec->codec_id = CODEC_ID_NUV;
- vst->codec->codec_tag = MKTAG('R', 'J', 'P', 'G');
vst->codec->width = width;
vst->codec->height = height;
vst->codec->bits_per_sample = 10;
@@ -174,39 +175,45 @@ static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) {
ctx->a_id = -1;
get_codec_data(pb, vst, ast, is_mythtv);
+ ctx->rtjpg_video = vst->codec->codec_id == CODEC_ID_NUV;
return 0;
}
#define HDRSIZE 12
static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
- NUVContext *ctx = (NUVContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ NUVContext *ctx = s->priv_data;
+ ByteIOContext *pb = s->pb;
uint8_t hdr[HDRSIZE];
frametype_t frametype;
int ret, size;
while (!url_feof(pb)) {
+ int copyhdrsize = ctx->rtjpg_video ? HDRSIZE : 0;
ret = get_buffer(pb, hdr, HDRSIZE);
if (ret <= 0)
return ret ? ret : -1;
frametype = hdr[0];
size = PKTSIZE(AV_RL32(&hdr[8]));
switch (frametype) {
- case NUV_VIDEO:
case NUV_EXTRADATA:
+ if (!ctx->rtjpg_video) {
+ url_fskip(pb, size);
+ break;
+ }
+ case NUV_VIDEO:
if (ctx->v_id < 0) {
av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n");
url_fskip(pb, size);
break;
}
- ret = av_new_packet(pkt, HDRSIZE + size);
+ ret = av_new_packet(pkt, copyhdrsize + size);
if (ret < 0)
return ret;
- pkt->pos = url_ftell(pb);
+ pkt->pos = url_ftell(pb) - copyhdrsize;
pkt->pts = AV_RL32(&hdr[4]);
pkt->stream_index = ctx->v_id;
- memcpy(pkt->data, hdr, HDRSIZE);
- ret = get_buffer(pb, pkt->data + HDRSIZE, size);
+ memcpy(pkt->data, hdr, copyhdrsize);
+ ret = get_buffer(pb, pkt->data + copyhdrsize, size);
return ret;
case NUV_AUDIO:
if (ctx->a_id < 0) {
@@ -226,7 +233,7 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
break;
}
}
- return AVERROR_IO;
+ return AVERROR(EIO);
}
AVInputFormat nuv_demuxer = {
diff --git a/contrib/ffmpeg/libavformat/ogg.c b/contrib/ffmpeg/libavformat/ogg.c
deleted file mode 100644
index c98bb2273..000000000
--- a/contrib/ffmpeg/libavformat/ogg.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Ogg bitstream support
- * Mark Hills <mark@pogo.org.uk>
- *
- * Uses libogg, but requires libvorbisenc to construct correct headers
- * when containing Vorbis stream -- currently the only format supported
- *
- * 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 <stdio.h>
-
-#include <ogg/ogg.h>
-
-#include "avformat.h"
-
-#undef NDEBUG
-#include <assert.h>
-
-#define DECODER_BUFFER_SIZE 4096
-
-
-typedef struct OggContext {
- /* output */
- ogg_stream_state os ;
- int header_handled ;
- ogg_packet op;
-
- /* input */
- ogg_sync_state oy ;
-} OggContext ;
-
-
-#ifdef CONFIG_MUXERS
-static int ogg_write_header(AVFormatContext *avfcontext)
-{
- OggContext *context = avfcontext->priv_data;
- ogg_packet *op= &context->op;
- int n;
-
- ogg_stream_init(&context->os, 31415);
-
- for(n = 0 ; n < avfcontext->nb_streams ; n++) {
- AVCodecContext *codec = avfcontext->streams[n]->codec;
- uint8_t *headers = codec->extradata;
- int headers_len = codec->extradata_size;
- uint8_t *header_start[3];
- int header_len[3];
- int i, j;
-
- av_set_pts_info(avfcontext->streams[n], 60, 1, AV_TIME_BASE);
-
- for(j=1,i=0;i<2;++i, ++j) {
- header_len[i]=0;
- while(j<headers_len && headers[j]==0xff) {
- header_len[i]+=0xff;
- ++j;
- }
- header_len[i]+=headers[j];
- }
- header_len[2]=headers_len-header_len[0]-header_len[1]-j;
- headers+=j;
- header_start[0] = headers;
- header_start[1] = header_start[0] + header_len[0];
- header_start[2] = header_start[1] + header_len[1];
-
- for(i=0; i < 3; ++i){
- op->bytes = header_len[i];
-
- op->packet= header_start[i];
- op->b_o_s= op->packetno==0;
-
- ogg_stream_packetin(&context->os, op);
-
- op->packetno++; //FIXME multiple streams
- }
-
- context->header_handled = 0 ;
- }
-
- return 0 ;
-}
-
-static int ogg_write_packet(AVFormatContext *avfcontext, AVPacket *pkt)
-{
- OggContext *context = avfcontext->priv_data ;
- AVCodecContext *avctx= avfcontext->streams[pkt->stream_index]->codec;
- ogg_packet *op= &context->op;
- ogg_page og ;
- int64_t pts;
-
- pts= av_rescale(pkt->pts, avctx->sample_rate, AV_TIME_BASE);
-
-// av_log(avfcontext, AV_LOG_DEBUG, "M%d\n", size);
-
- /* flush header packets so audio starts on a new page */
-
- if(!context->header_handled) {
- while(ogg_stream_flush(&context->os, &og)) {
- put_buffer(&avfcontext->pb, og.header, og.header_len) ;
- put_buffer(&avfcontext->pb, og.body, og.body_len) ;
- put_flush_packet(&avfcontext->pb);
- }
- context->header_handled = 1 ;
- }
-
- op->packet = (uint8_t*) pkt->data;
- op->bytes = pkt->size;
- op->b_o_s = op->packetno == 0;
- op->granulepos= pts;
-
- /* correct the fields in the packet -- essential for streaming */
-
- ogg_stream_packetin(&context->os, op);
-
- while(ogg_stream_pageout(&context->os, &og)) {
- put_buffer(&avfcontext->pb, og.header, og.header_len);
- put_buffer(&avfcontext->pb, og.body, og.body_len);
- put_flush_packet(&avfcontext->pb);
- }
- op->packetno++;
-
- return 0;
-}
-
-
-static int ogg_write_trailer(AVFormatContext *avfcontext) {
- OggContext *context = avfcontext->priv_data ;
- ogg_page og ;
-
- while(ogg_stream_flush(&context->os, &og)) {
- put_buffer(&avfcontext->pb, og.header, og.header_len) ;
- put_buffer(&avfcontext->pb, og.body, og.body_len) ;
- put_flush_packet(&avfcontext->pb);
- }
-
- ogg_stream_clear(&context->os) ;
- return 0 ;
-}
-
-
-AVOutputFormat ogg_muxer = {
- "ogg",
- "Ogg format",
- "application/ogg",
- "ogg",
- sizeof(OggContext),
- CODEC_ID_VORBIS,
- 0,
- ogg_write_header,
- ogg_write_packet,
- ogg_write_trailer,
-} ;
-#endif //CONFIG_MUXERS
-
-#if 0
-static int next_packet(AVFormatContext *avfcontext, ogg_packet *op) {
- OggContext *context = avfcontext->priv_data ;
- ogg_page og ;
- char *buf ;
-
- while(ogg_stream_packetout(&context->os, op) != 1) {
-
- /* while no pages are available, read in more data to the sync */
- while(ogg_sync_pageout(&context->oy, &og) != 1) {
- buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
- if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
- return 1 ;
- ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
- }
-
- /* got a page. Feed it into the stream and get the packet */
- if(ogg_stream_pagein(&context->os, &og) != 0)
- return 1 ;
- }
-
- return 0 ;
-}
-
-
-static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap)
-{
- OggContext *context = avfcontext->priv_data;
- ogg_packet op ;
- char *buf ;
- ogg_page og ;
- AVStream *ast ;
- AVCodecContext *codec;
- uint8_t *p;
- int i;
-
- ogg_sync_init(&context->oy) ;
- buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
-
- if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
- return AVERROR_IO ;
-
- ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
- ogg_sync_pageout(&context->oy, &og) ;
- ogg_stream_init(&context->os, ogg_page_serialno(&og)) ;
- ogg_stream_pagein(&context->os, &og) ;
-
- /* currently only one vorbis stream supported */
-
- ast = av_new_stream(avfcontext, 0) ;
- if(!ast)
- return AVERROR_NOMEM ;
- av_set_pts_info(ast, 60, 1, AV_TIME_BASE);
-
- codec= &ast->codec;
- codec->codec_type = CODEC_TYPE_AUDIO;
- codec->codec_id = CODEC_ID_VORBIS;
- for(i=0; i<3; i++){
- if(next_packet(avfcontext, &op)){
- return -1;
- }
- if(op.bytes >= (1<<16) || op.bytes < 0)
- return -1;
- codec->extradata_size+= 2 + op.bytes;
- codec->extradata= av_realloc(codec->extradata, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- memset(codec->extradata + codec->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- p= codec->extradata + codec->extradata_size - 2 - op.bytes;
- *(p++)= op.bytes>>8;
- *(p++)= op.bytes&0xFF;
- memcpy(p, op.packet, op.bytes);
- }
-
- return 0 ;
-}
-
-
-static int ogg_read_packet(AVFormatContext *avfcontext, AVPacket *pkt) {
- ogg_packet op ;
-
- if(next_packet(avfcontext, &op))
- return AVERROR_IO ;
- if(av_new_packet(pkt, op.bytes) < 0)
- return AVERROR_IO ;
- pkt->stream_index = 0 ;
- memcpy(pkt->data, op.packet, op.bytes);
- if(avfcontext->streams[0]->codec.sample_rate && op.granulepos!=-1)
- pkt->pts= av_rescale(op.granulepos, AV_TIME_BASE, avfcontext->streams[0]->codec.sample_rate);
-// printf("%"PRId64" %d %d\n", pkt->pts, (int)op.granulepos, avfcontext->streams[0]->codec.sample_rate);
-
- return op.bytes;
-}
-
-
-static int ogg_read_close(AVFormatContext *avfcontext) {
- OggContext *context = avfcontext->priv_data ;
-
- ogg_stream_clear(&context->os) ;
- ogg_sync_clear(&context->oy) ;
-
- return 0 ;
-}
-
-
-static AVInputFormat ogg_iformat = {
- "ogg",
- "Ogg Vorbis",
- sizeof(OggContext),
- NULL,
- ogg_read_header,
- ogg_read_packet,
- ogg_read_close,
- .extensions = "ogg",
-} ;
-#endif
diff --git a/contrib/ffmpeg/libavformat/ogg2.c b/contrib/ffmpeg/libavformat/oggdec.c
index 8ca7b2d13..96d16a873 100644
--- a/contrib/ffmpeg/libavformat/ogg2.c
+++ b/contrib/ffmpeg/libavformat/oggdec.c
@@ -31,54 +31,25 @@
#include <stdio.h>
-#include "ogg2.h"
+#include "oggdec.h"
#include "avformat.h"
#define MAX_PAGE_SIZE 65307
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
static ogg_codec_t *ogg_codecs[] = {
+ &speex_codec,
&vorbis_codec,
&theora_codec,
&flac_codec,
+ &old_flac_codec,
&ogm_video_codec,
&ogm_audio_codec,
+ &ogm_text_codec,
&ogm_old_codec,
NULL
};
-#if 0 // CONFIG_MUXERS
-static int
-ogg_write_header (AVFormatContext * avfcontext)
-{
-}
-
-static int
-ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
-{
-}
-
-
-static int
-ogg_write_trailer (AVFormatContext * avfcontext)
-{
-}
-
-
-AVOutputFormat ogg_muxer = {
- "ogg",
- "Ogg format",
- "application/ogg",
- "ogg",
- sizeof (OggContext),
- CODEC_ID_VORBIS,
- 0,
- ogg_write_header,
- ogg_write_packet,
- ogg_write_trailer,
-};
-#endif //CONFIG_MUXERS
-
//FIXME We could avoid some structure duplication
static int
ogg_save (AVFormatContext * s)
@@ -87,7 +58,7 @@ ogg_save (AVFormatContext * s)
ogg_state_t *ost =
av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
int i;
- ost->pos = url_ftell (&s->pb);;
+ ost->pos = url_ftell (s->pb);
ost->curidx = ogg->curidx;
ost->next = ogg->state;
ost->nstreams = ogg->nstreams;
@@ -109,7 +80,7 @@ static int
ogg_restore (AVFormatContext * s, int discard)
{
ogg_t *ogg = s->priv_data;
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
ogg_state_t *ost = ogg->state;
int i;
@@ -200,7 +171,7 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial)
st = av_new_stream (s, idx);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 64, 1, 1000000);
@@ -227,7 +198,7 @@ ogg_new_buf(ogg_t *ogg, int idx)
static int
ogg_read_page (AVFormatContext * s, int *str)
{
- ByteIOContext *bc = &s->pb;
+ ByteIOContext *bc = s->pb;
ogg_t *ogg = s->priv_data;
ogg_stream_t *os;
int i = 0;
@@ -408,6 +379,7 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
}
if (os->header > -1 && os->seq > os->header){
+ os->pflags = 0;
if (os->codec && os->codec->packet)
os->codec->packet (s, idx);
if (str)
@@ -468,20 +440,20 @@ ogg_get_length (AVFormatContext * s)
int idx = -1, i;
offset_t size, end;
- if(s->pb.is_streamed)
+ if(url_is_streamed(s->pb))
return 0;
// already set
if (s->duration != AV_NOPTS_VALUE)
return 0;
- size = url_fsize(&s->pb);
+ size = url_fsize(s->pb);
if(size < 0)
return 0;
end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
ogg_save (s);
- url_fseek (&s->pb, end, SEEK_SET);
+ url_fseek (s->pb, end, SEEK_SET);
while (!ogg_read_page (s, &i)){
if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
@@ -540,7 +512,7 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
//Get an ogg packet
do{
if (ogg_packet (s, &idx, &pstart, &psize) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
}while (idx < 0 || !s->streams[idx]);
ogg = s->priv_data;
@@ -548,7 +520,7 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
//Alloc a pkt
if (av_new_packet (pkt, psize) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = idx;
memcpy (pkt->data, os->buf + pstart, psize);
if (os->lastgp != -1LL){
@@ -556,6 +528,8 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
os->lastgp = -1;
}
+ pkt->flags = os->pflags;
+
return psize;
}
@@ -575,109 +549,31 @@ ogg_read_close (AVFormatContext * s)
}
-static int
-ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
- int flags)
+static int64_t
+ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
+ int64_t pos_limit)
{
- AVStream *st = s->streams[stream_index];
ogg_t *ogg = s->priv_data;
- ByteIOContext *bc = &s->pb;
- uint64_t min = 0, max = ogg->size;
- uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
+ ByteIOContext *bc = s->pb;
int64_t pts = AV_NOPTS_VALUE;
-
- ogg_save (s);
-
- if ((uint64_t)target_ts < tmin || target_ts < 0)
- target_ts = tmin;
- while (min <= max && tmin < tmax){
- uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
- int i = -1;
-
- url_fseek (bc, p, SEEK_SET);
-
- while (!ogg_read_page (s, &i)){
- if (i == stream_index && ogg->streams[i].granule != 0 &&
- ogg->streams[i].granule != -1)
- break;
- }
-
- if (i == -1)
- break;
-
- pts = ogg_gptopts (s, i, ogg->streams[i].granule);
- p = url_ftell (bc);
-
- if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
+ int i;
+ url_fseek(bc, *pos_arg, SEEK_SET);
+ while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) {
+ if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
+ ogg->streams[i].codec && i == stream_index) {
+ pts = ogg_gptopts(s, i, ogg->streams[i].granule);
+ // FIXME: this is the position of the packet after the one with above
+ // pts.
+ *pos_arg = url_ftell(bc);
break;
-
- if (pts > target_ts){
- if (max == p && tmax == pts) {
- // probably our tmin is wrong, causing us to always end up too late in the file
- tmin = (target_ts + tmin + 1) / 2;
- if (tmin == target_ts) {
- url_fseek(bc, min, SEEK_SET);
- break;
- }
- }
- max = p;
- tmax = pts;
- }else{
- if (min == p && tmin == pts) {
- // probably our tmax is wrong, causing us to always end up too early in the file
- tmax = (target_ts + tmax) / 2;
- if (tmax == target_ts) {
- url_fseek(bc, max, SEEK_SET);
- break;
- }
- }
- min = p;
- tmin = pts;
}
}
-
- if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
- ogg_restore (s, 1);
- ogg_reset (ogg);
- }else{
- ogg_restore (s, 0);
- pts = AV_NOPTS_VALUE;
- }
-
- av_update_cur_dts(s, st, pts);
- return 0;
-
-#if 0
- //later...
- int64_t pos;
- if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
- return -1;
- pos = url_ftell (&s->pb);
- ogg_read_timestamp (s, stream_index, &pos, pos - 1);
-#endif
-
-}
-
-#if 0
-static int64_t
-ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
- int64_t pos_limit)
-{
- ogg_t *ogg = s->priv_data;
- ByteIOContext *bc = &s->pb;
- int64_t pos, pts;
-
- if (*pos_arg < 0)
- return AV_NOPTS_VALUE;
-
- pos = *pos_arg;
+ ogg_reset(ogg);
+ return pts;
}
-#endif
static int ogg_probe(AVProbeData *p)
{
- if (p->buf_size < 6)
- return 0;
if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
p->buf[2] == 'g' && p->buf[3] == 'S' &&
p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
@@ -694,7 +590,7 @@ AVInputFormat ogg_demuxer = {
ogg_read_header,
ogg_read_packet,
ogg_read_close,
- ogg_read_seek,
-// ogg_read_timestamp,
+ NULL,
+ ogg_read_timestamp,
.extensions = "ogg",
};
diff --git a/contrib/ffmpeg/libavformat/ogg2.h b/contrib/ffmpeg/libavformat/oggdec.h
index 6b7c6b22e..4e88d0e39 100644
--- a/contrib/ffmpeg/libavformat/ogg2.h
+++ b/contrib/ffmpeg/libavformat/oggdec.h
@@ -22,15 +22,15 @@
DEALINGS IN THE SOFTWARE.
**/
-#ifndef OGG_H
-#define OGG_H
+#ifndef FFMPEG_OGGDEC_H
+#define FFMPEG_OGGDEC_H
#include "avformat.h"
typedef struct ogg_codec {
- int8_t *magic;
+ const int8_t *magic;
uint8_t magicsize;
- int8_t *name;
+ const int8_t *name;
int (*header)(AVFormatContext *, int);
int (*packet)(AVFormatContext *, int);
uint64_t (*gptopts)(AVFormatContext *, int, uint64_t);
@@ -42,6 +42,7 @@ typedef struct ogg_stream {
unsigned int bufpos;
unsigned int pstart;
unsigned int psize;
+ unsigned int pflags;
uint32_t serial;
uint32_t seq;
uint64_t granule, lastgp;
@@ -74,13 +75,16 @@ typedef struct ogg {
#define OGG_FLAG_BOS 2
#define OGG_FLAG_EOS 4
-extern ogg_codec_t vorbis_codec;
-extern ogg_codec_t theora_codec;
extern ogg_codec_t flac_codec;
-extern ogg_codec_t ogm_video_codec;
extern ogg_codec_t ogm_audio_codec;
extern ogg_codec_t ogm_old_codec;
+extern ogg_codec_t ogm_text_codec;
+extern ogg_codec_t ogm_video_codec;
+extern ogg_codec_t old_flac_codec;
+extern ogg_codec_t speex_codec;
+extern ogg_codec_t theora_codec;
+extern ogg_codec_t vorbis_codec;
extern int vorbis_comment(AVFormatContext *ms, uint8_t *buf, int size);
-#endif
+#endif /* FFMPEG_OGGDEC_H */
diff --git a/contrib/ffmpeg/libavformat/oggenc.c b/contrib/ffmpeg/libavformat/oggenc.c
new file mode 100644
index 000000000..af2c5de12
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggenc.c
@@ -0,0 +1,292 @@
+/*
+ * Ogg muxer
+ * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
+ *
+ * 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 "avformat.h"
+#include "crc.h"
+#include "xiph.h"
+#include "bytestream.h"
+
+typedef struct {
+ int64_t duration;
+ unsigned page_counter;
+ uint8_t *header[3];
+ int header_len[3];
+ /** for theora granule */
+ int kfgshift;
+ int64_t last_kf_pts;
+ int vrev;
+ int eos;
+} OGGStreamContext;
+
+static void ogg_update_checksum(AVFormatContext *s, offset_t crc_offset)
+{
+ offset_t pos = url_ftell(s->pb);
+ uint32_t checksum = get_checksum(s->pb);
+ url_fseek(s->pb, crc_offset, SEEK_SET);
+ put_be32(s->pb, checksum);
+ url_fseek(s->pb, pos, SEEK_SET);
+}
+
+static int ogg_write_page(AVFormatContext *s, const uint8_t *data, int size,
+ int64_t granule, int stream_index, int flags)
+{
+ OGGStreamContext *oggstream = s->streams[stream_index]->priv_data;
+ offset_t crc_offset;
+ int page_segments, i;
+
+ if (size >= 255*255) {
+ granule = -1;
+ size = 255*255;
+ } else if (oggstream->eos)
+ flags |= 4;
+
+ page_segments = FFMIN((size/255)+!!size, 255);
+
+ init_checksum(s->pb, ff_crc04C11DB7_update, 0);
+ put_tag(s->pb, "OggS");
+ put_byte(s->pb, 0);
+ put_byte(s->pb, flags);
+ put_le64(s->pb, granule);
+ put_le32(s->pb, stream_index);
+ put_le32(s->pb, oggstream->page_counter++);
+ crc_offset = url_ftell(s->pb);
+ put_le32(s->pb, 0); // crc
+ put_byte(s->pb, page_segments);
+ for (i = 0; i < page_segments-1; i++)
+ put_byte(s->pb, 255);
+ if (size) {
+ put_byte(s->pb, size - (page_segments-1)*255);
+ put_buffer(s->pb, data, size);
+ }
+ ogg_update_checksum(s, crc_offset);
+ put_flush_packet(s->pb);
+ return size;
+}
+
+static int ogg_build_flac_headers(const uint8_t *extradata, int extradata_size,
+ OGGStreamContext *oggstream, int bitexact)
+{
+ const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
+ uint8_t *p;
+ if (extradata_size != 34)
+ return -1;
+ oggstream->header_len[0] = 79;
+ oggstream->header[0] = av_mallocz(79); // per ogg flac specs
+ p = oggstream->header[0];
+ bytestream_put_byte(&p, 0x7F);
+ bytestream_put_buffer(&p, "FLAC", 4);
+ bytestream_put_byte(&p, 1); // major version
+ bytestream_put_byte(&p, 0); // minor version
+ bytestream_put_be16(&p, 1); // headers packets without this one
+ bytestream_put_buffer(&p, "fLaC", 4);
+ bytestream_put_byte(&p, 0x00); // streaminfo
+ bytestream_put_be24(&p, 34);
+ bytestream_put_buffer(&p, extradata, 34);
+ oggstream->header_len[1] = 1+3+4+strlen(vendor)+4;
+ oggstream->header[1] = av_mallocz(oggstream->header_len[1]);
+ p = oggstream->header[1];
+ bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment
+ bytestream_put_be24(&p, oggstream->header_len[1] - 4);
+ bytestream_put_le32(&p, strlen(vendor));
+ bytestream_put_buffer(&p, vendor, strlen(vendor));
+ bytestream_put_le32(&p, 0); // user comment list length
+ return 0;
+}
+
+static int ogg_write_header(AVFormatContext *s)
+{
+ OGGStreamContext *oggstream;
+ int i, j;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO)
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ else if (st->codec->codec_type == CODEC_TYPE_VIDEO)
+ av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
+ if (st->codec->codec_id != CODEC_ID_VORBIS &&
+ st->codec->codec_id != CODEC_ID_THEORA &&
+ st->codec->codec_id != CODEC_ID_FLAC) {
+ av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
+ return -1;
+ }
+
+ if (!st->codec->extradata || !st->codec->extradata_size) {
+ av_log(s, AV_LOG_ERROR, "No extradata present\n");
+ return -1;
+ }
+ oggstream = av_mallocz(sizeof(*oggstream));
+ st->priv_data = oggstream;
+ if (st->codec->codec_id == CODEC_ID_FLAC) {
+ if (ogg_build_flac_headers(st->codec->extradata, st->codec->extradata_size,
+ oggstream, st->codec->flags & CODEC_FLAG_BITEXACT) < 0) {
+ av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
+ av_freep(&st->priv_data);
+ }
+ } else {
+ if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,
+ st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42,
+ oggstream->header, oggstream->header_len) < 0) {
+ av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
+ av_freep(&st->priv_data);
+ return -1;
+ }
+ if (st->codec->codec_id == CODEC_ID_THEORA) {
+ /** KFGSHIFT is the width of the less significant section of the granule position
+ The less significant section is the frame count since the last keyframe */
+ oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);
+ oggstream->vrev = oggstream->header[0][9];
+ av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n",
+ oggstream->kfgshift, oggstream->vrev);
+ }
+ }
+ }
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < s->nb_streams; j++) {
+ AVStream *st = s->streams[j];
+ OGGStreamContext *oggstream = st->priv_data;
+ if (oggstream && oggstream->header_len[i]) {
+ ogg_write_page(s, oggstream->header[i], oggstream->header_len[i],
+ 0, st->index, i ? 0 : 2); // bos
+ }
+ }
+ }
+ return 0;
+}
+
+static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ OGGStreamContext *oggstream = st->priv_data;
+ uint8_t *ptr = pkt->data;
+ int ret, size = pkt->size;
+ int64_t granule;
+
+ if (st->codec->codec_id == CODEC_ID_THEORA) {
+ int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration;
+ int pframe_count;
+ if (pkt->flags & PKT_FLAG_KEY)
+ oggstream->last_kf_pts = pts;
+ pframe_count = pts - oggstream->last_kf_pts;
+ // prevent frame count from overflow if key frame flag is not set
+ if (pframe_count >= (1<<oggstream->kfgshift)) {
+ oggstream->last_kf_pts += pframe_count;
+ pframe_count = 0;
+ }
+ granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count;
+ } else
+ granule = pkt->pts + pkt->duration;
+ oggstream->duration = granule;
+ do {
+ ret = ogg_write_page(s, ptr, size, granule, pkt->stream_index, ptr != pkt->data);
+ ptr += ret; size -= ret;
+ } while (size > 0 || ret == 255*255); // need to output a last nil page
+
+ return 0;
+}
+
+int ogg_interleave_per_granule(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
+{
+ AVPacketList *pktl, **next_point, *this_pktl;
+ int stream_count = 0;
+ int streams[MAX_STREAMS] = {0};
+ int interleaved = 0;
+
+ if (pkt) {
+ AVStream *st = s->streams[pkt->stream_index];
+ this_pktl = av_mallocz(sizeof(AVPacketList));
+ this_pktl->pkt = *pkt;
+ if (pkt->destruct == av_destruct_packet)
+ pkt->destruct = NULL; // not shared -> must keep original from being freed
+ else
+ av_dup_packet(&this_pktl->pkt); // shared -> must dup
+ next_point = &s->packet_buffer;
+ while (*next_point) {
+ AVStream *st2 = s->streams[(*next_point)->pkt.stream_index];
+ AVPacket *next_pkt = &(*next_point)->pkt;
+ int64_t cur_granule, next_granule;
+ next_granule = av_rescale_q(next_pkt->pts + next_pkt->duration,
+ st2->time_base, AV_TIME_BASE_Q);
+ cur_granule = av_rescale_q(pkt->pts + pkt->duration,
+ st->time_base, AV_TIME_BASE_Q);
+ if (next_granule > cur_granule)
+ break;
+ next_point= &(*next_point)->next;
+ }
+ this_pktl->next= *next_point;
+ *next_point= this_pktl;
+ }
+
+ pktl = s->packet_buffer;
+ while (pktl) {
+ if (streams[pktl->pkt.stream_index] == 0)
+ stream_count++;
+ streams[pktl->pkt.stream_index]++;
+ // need to buffer at least one packet to set eos flag
+ if (streams[pktl->pkt.stream_index] == 2)
+ interleaved++;
+ pktl = pktl->next;
+ }
+
+ if ((s->nb_streams == stream_count && interleaved == stream_count) ||
+ (flush && stream_count)) {
+ pktl= s->packet_buffer;
+ *out= pktl->pkt;
+ s->packet_buffer = pktl->next;
+ if (flush && streams[out->stream_index] == 1) {
+ OGGStreamContext *ogg = s->streams[out->stream_index]->priv_data;
+ ogg->eos = 1;
+ }
+ av_freep(&pktl);
+ return 1;
+ } else {
+ av_init_packet(out);
+ return 0;
+ }
+}
+
+static int ogg_write_trailer(AVFormatContext *s)
+{
+ int i;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ OGGStreamContext *oggstream = st->priv_data;
+ if (st->codec->codec_id == CODEC_ID_FLAC) {
+ av_free(oggstream->header[0]);
+ av_free(oggstream->header[1]);
+ }
+ av_freep(&st->priv_data);
+ }
+ return 0;
+}
+
+AVOutputFormat ogg_muxer = {
+ "ogg",
+ "Ogg format",
+ "application/ogg",
+ "ogg",
+ 0,
+ CODEC_ID_FLAC,
+ CODEC_ID_THEORA,
+ ogg_write_header,
+ ogg_write_packet,
+ ogg_write_trailer,
+ .interleave_packet = ogg_interleave_per_granule,
+};
diff --git a/contrib/ffmpeg/libavformat/oggparseflac.c b/contrib/ffmpeg/libavformat/oggparseflac.c
index 8960088d8..611a8c5a1 100644
--- a/contrib/ffmpeg/libavformat/oggparseflac.c
+++ b/contrib/ffmpeg/libavformat/oggparseflac.c
@@ -21,7 +21,7 @@
#include <stdlib.h>
#include "avformat.h"
#include "bitstream.h"
-#include "ogg2.h"
+#include "oggdec.h"
#define FLAC_STREAMINFO_SIZE 0x22
@@ -49,7 +49,7 @@ flac_header (AVFormatContext * s, int idx)
skip_bits(&gb, 4*8); /* "fLaC" */
/* METADATA_BLOCK_HEADER */
- if (get_bits(&gb, 32) != FLAC_STREAMINFO_SIZE)
+ if (get_bits_long(&gb, 32) != FLAC_STREAMINFO_SIZE)
return -1;
skip_bits(&gb, 16*2+24*2);
@@ -75,8 +75,24 @@ flac_header (AVFormatContext * s, int idx)
return 1;
}
+static int
+old_flac_header (AVFormatContext * s, int idx)
+{
+ AVStream *st = s->streams[idx];
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_FLAC;
+
+ return 0;
+}
+
ogg_codec_t flac_codec = {
.magic = "\177FLAC",
.magicsize = 5,
.header = flac_header
};
+
+ogg_codec_t old_flac_codec = {
+ .magic = "fLaC",
+ .magicsize = 4,
+ .header = old_flac_header
+};
diff --git a/contrib/ffmpeg/libavformat/oggparseogm.c b/contrib/ffmpeg/libavformat/oggparseogm.c
index 8788e5d41..70e53948f 100644
--- a/contrib/ffmpeg/libavformat/oggparseogm.c
+++ b/contrib/ffmpeg/libavformat/oggparseogm.c
@@ -25,8 +25,9 @@
#include <stdlib.h>
#include "avformat.h"
#include "bitstream.h"
-#include "bswap.h"
-#include "ogg2.h"
+#include "bytestream.h"
+#include "intreadwrite.h"
+#include "oggdec.h"
#include "riff.h"
static int
@@ -35,7 +36,7 @@ ogm_header(AVFormatContext *s, int idx)
ogg_t *ogg = s->priv_data;
ogg_stream_t *os = ogg->streams + idx;
AVStream *st = s->streams[idx];
- uint8_t *p = os->buf + os->pstart;
+ const uint8_t *p = os->buf + os->pstart;
uint64_t time_unit;
uint64_t spu;
uint32_t default_len;
@@ -51,42 +52,42 @@ ogm_header(AVFormatContext *s, int idx)
int tag;
st->codec->codec_type = CODEC_TYPE_VIDEO;
p += 8;
- tag = le2me_32(unaligned32(p));
- st->codec->codec_id = codec_get_bmp_id(tag);
+ tag = bytestream_get_le32(&p);
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, tag);
st->codec->codec_tag = tag;
+ } else if (*p == 't') {
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ st->codec->codec_id = CODEC_ID_TEXT;
+ p += 12;
} else {
+ uint8_t acid[5];
int cid;
st->codec->codec_type = CODEC_TYPE_AUDIO;
p += 8;
- p[4] = 0;
- cid = strtol(p, NULL, 16);
- st->codec->codec_id = codec_get_wav_id(cid);
+ bytestream_get_buffer(&p, acid, 4);
+ acid[4] = 0;
+ cid = strtol(acid, NULL, 16);
+ st->codec->codec_id = codec_get_id(codec_wav_tags, cid);
}
- p += 4;
p += 4; /* useless size field */
- time_unit = le2me_64(unaligned64(p));
- p += 8;
- spu = le2me_64(unaligned64(p));
- p += 8;
- default_len = le2me_32(unaligned32(p));
- p += 4;
+ time_unit = bytestream_get_le64(&p);
+ spu = bytestream_get_le64(&p);
+ default_len = bytestream_get_le32(&p);
p += 8; /* buffersize + bits_per_sample */
if(st->codec->codec_type == CODEC_TYPE_VIDEO){
- st->codec->width = le2me_32(unaligned32(p));
- p += 4;
- st->codec->height = le2me_32(unaligned32(p));
+ st->codec->width = bytestream_get_le32(&p);
+ st->codec->height = bytestream_get_le32(&p);
st->codec->time_base.den = spu * 10000000;
st->codec->time_base.num = time_unit;
st->time_base = st->codec->time_base;
} else {
- st->codec->channels = le2me_16(unaligned16(p));
- p += 2;
+ st->codec->channels = bytestream_get_le16(&p);
p += 2; /* block_align */
- st->codec->bit_rate = le2me_32(unaligned32(p)) * 8;
+ st->codec->bit_rate = bytestream_get_le32(&p) * 8;
st->codec->sample_rate = spu * 10000000 / time_unit;
st->time_base.num = 1;
st->time_base.den = st->codec->sample_rate;
@@ -109,21 +110,21 @@ ogm_dshow_header(AVFormatContext *s, int idx)
if(*p != 1)
return 1;
- t = le2me_32(unaligned32(p + 96));
+ t = AV_RL32(p + 96);
if(t == 0x05589f80){
st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = codec_get_bmp_id(le2me_32(unaligned32(p + 68)));
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, AV_RL32(p + 68));
st->codec->time_base.den = 10000000;
- st->codec->time_base.num = le2me_64(unaligned64(p + 164));
- st->codec->width = le2me_32(unaligned32(p + 176));
- st->codec->height = le2me_32(unaligned32(p + 180));
+ st->codec->time_base.num = AV_RL64(p + 164);
+ st->codec->width = AV_RL32(p + 176);
+ st->codec->height = AV_RL32(p + 180);
} else if(t == 0x05589f81){
st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = codec_get_wav_id(le2me_16(unaligned16(p+124)));
- st->codec->channels = le2me_16(unaligned16(p + 126));
- st->codec->sample_rate = le2me_32(unaligned32(p + 128));
- st->codec->bit_rate = le2me_32(unaligned32(p + 132)) * 8;
+ st->codec->codec_id = codec_get_id(codec_wav_tags, AV_RL16(p + 124));
+ st->codec->channels = AV_RL16(p + 126);
+ st->codec->sample_rate = AV_RL32(p + 128);
+ st->codec->bit_rate = AV_RL32(p + 132) * 8;
}
return 1;
@@ -137,6 +138,9 @@ ogm_packet(AVFormatContext *s, int idx)
uint8_t *p = os->buf + os->pstart;
int lb;
+ if(*p & 8)
+ os->pflags |= PKT_FLAG_KEY;
+
lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
os->pstart += lb + 1;
os->psize -= lb + 1;
@@ -158,6 +162,13 @@ ogg_codec_t ogm_audio_codec = {
.packet = ogm_packet
};
+ogg_codec_t ogm_text_codec = {
+ .magic = "\001text",
+ .magicsize = 5,
+ .header = ogm_header,
+ .packet = ogm_packet
+};
+
ogg_codec_t ogm_old_codec = {
.magic = "\001Direct Show Samples embedded in Ogg",
.magicsize = 35,
diff --git a/contrib/ffmpeg/libavformat/oggparsespeex.c b/contrib/ffmpeg/libavformat/oggparsespeex.c
new file mode 100644
index 000000000..a6c44271e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggparsespeex.c
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2008 Reimar Döffinger
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+**/
+
+#include <stdlib.h>
+#include "avformat.h"
+#include "bitstream.h"
+#include "bytestream.h"
+#include "bswap.h"
+#include "oggdec.h"
+#include "avstring.h"
+
+static int speex_header(AVFormatContext *s, int idx) {
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ uint8_t *p = os->buf + os->pstart;
+
+ if (os->psize < 80)
+ return 1;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_SPEEX;
+
+ st->codec->sample_rate = AV_RL32(p + 36);
+ st->codec->channels = AV_RL32(p + 48);
+ st->codec->extradata_size = os->psize;
+ st->codec->extradata = av_malloc(st->codec->extradata_size);
+ memcpy(st->codec->extradata, p, st->codec->extradata_size);
+
+ st->time_base.num = 1;
+ st->time_base.den = st->codec->sample_rate;
+
+ return 0;
+}
+
+ogg_codec_t speex_codec = {
+ .magic = "Speex ",
+ .magicsize = 8,
+ .header = speex_header
+};
diff --git a/contrib/ffmpeg/libavformat/oggparsetheora.c b/contrib/ffmpeg/libavformat/oggparsetheora.c
index 9052bbbea..b976dcb70 100644
--- a/contrib/ffmpeg/libavformat/oggparsetheora.c
+++ b/contrib/ffmpeg/libavformat/oggparsetheora.c
@@ -26,7 +26,7 @@
#include "avformat.h"
#include "bitstream.h"
#include "bswap.h"
-#include "ogg2.h"
+#include "oggdec.h"
typedef struct theora_params {
int gpshift;
@@ -53,16 +53,14 @@ theora_header (AVFormatContext * s, int idx)
if (os->buf[os->pstart] == 0x80) {
GetBitContext gb;
+ int width, height;
int version;
init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
skip_bits(&gb, 7*8); /* 0x80"theora" */
- version = get_bits(&gb, 8) << 16;
- version |= get_bits(&gb, 8) << 8;
- version |= get_bits(&gb, 8);
-
+ version = get_bits_long(&gb, 24);
if (version < 0x030100)
{
av_log(s, AV_LOG_ERROR,
@@ -70,19 +68,27 @@ theora_header (AVFormatContext * s, int idx)
return -1;
}
- st->codec->width = get_bits(&gb, 16) << 4;
- st->codec->height = get_bits(&gb, 16) << 4;
+ width = get_bits(&gb, 16) << 4;
+ height = get_bits(&gb, 16) << 4;
+ avcodec_set_dimensions(st->codec, width, height);
if (version >= 0x030400)
- skip_bits(&gb, 164);
- else if (version >= 0x030200)
- skip_bits(&gb, 64);
- st->codec->time_base.den = get_bits(&gb, 32);
- st->codec->time_base.num = get_bits(&gb, 32);
+ skip_bits(&gb, 100);
+
+ width = get_bits_long(&gb, 24);
+ height = get_bits_long(&gb, 24);
+ if ( width <= st->codec->width && width > st->codec->width-16
+ && height <= st->codec->height && height > st->codec->height-16)
+ avcodec_set_dimensions(st->codec, width, height);
+
+ if (version >= 0x030200)
+ skip_bits(&gb, 16);
+ st->codec->time_base.den = get_bits_long(&gb, 32);
+ st->codec->time_base.num = get_bits_long(&gb, 32);
st->time_base = st->codec->time_base;
- st->codec->sample_aspect_ratio.num = get_bits(&gb, 24);
- st->codec->sample_aspect_ratio.den = get_bits(&gb, 24);
+ st->codec->sample_aspect_ratio.num = get_bits_long(&gb, 24);
+ st->codec->sample_aspect_ratio.den = get_bits_long(&gb, 24);
if (version >= 0x030200)
skip_bits(&gb, 38);
@@ -118,6 +124,9 @@ theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
uint64_t iframe = gp >> thp->gpshift;
uint64_t pframe = gp & thp->gpmask;
+ if(!pframe)
+ os->pflags |= PKT_FLAG_KEY;
+
return iframe + pframe;
}
diff --git a/contrib/ffmpeg/libavformat/oggparsevorbis.c b/contrib/ffmpeg/libavformat/oggparsevorbis.c
index 5de221cb4..cc914ce39 100644
--- a/contrib/ffmpeg/libavformat/oggparsevorbis.c
+++ b/contrib/ffmpeg/libavformat/oggparsevorbis.c
@@ -25,49 +25,44 @@
#include <stdlib.h>
#include "avformat.h"
#include "bitstream.h"
+#include "bytestream.h"
#include "bswap.h"
-#include "ogg2.h"
+#include "oggdec.h"
+#include "avstring.h"
extern int
-vorbis_comment (AVFormatContext * as, uint8_t *buf, int size)
+vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
{
- char *p = buf;
- int s, n, j;
+ const uint8_t *p = buf;
+ const uint8_t *end = buf + size;
+ unsigned s, n, j;
- if (size < 4)
+ if (size < 8) /* must have vendor_length and user_comment_list_length */
return -1;
- s = le2me_32 (unaligned32 (p));
- p += 4;
- size -= 4;
+ s = bytestream_get_le32(&p);
- if (size < s + 4)
+ if (end - p < s)
return -1;
p += s;
- size -= s;
- n = le2me_32 (unaligned32 (p));
- p += 4;
- size -= 4;
+ n = bytestream_get_le32(&p);
- while (size >= 4){
- char *t, *v;
+ while (p < end && n > 0) {
+ const char *t, *v;
int tl, vl;
- s = le2me_32 (unaligned32 (p));
- p += 4;
- size -= 4;
+ s = bytestream_get_le32(&p);
- if (size < s)
+ if (end - p < s)
break;
t = p;
p += s;
- size -= s;
n--;
- v = memchr (t, '=', s);
+ v = memchr(t, '=', s);
if (!v)
continue;
@@ -75,39 +70,40 @@ vorbis_comment (AVFormatContext * as, uint8_t *buf, int size)
vl = s - tl - 1;
v++;
- if (tl && vl){
+ if (tl && vl) {
char tt[tl + 1];
char ct[vl + 1];
for (j = 0; j < tl; j++)
- tt[j] = toupper (t[j]);
+ tt[j] = toupper(t[j]);
tt[tl] = 0;
- memcpy (ct, v, vl);
+ memcpy(ct, v, vl);
ct[vl] = 0;
// took from Vorbis_I_spec
- if (!strcmp (tt, "AUTHOR"))
- strncpy (as->author, ct, FFMIN(sizeof (as->author), vl));
- else if (!strcmp (tt, "TITLE"))
- strncpy (as->title, ct, FFMIN(sizeof (as->title), vl));
- else if (!strcmp (tt, "COPYRIGHT"))
- strncpy (as->copyright, ct, FFMIN(sizeof (as->copyright), vl));
- else if (!strcmp (tt, "DESCRIPTION"))
- strncpy (as->comment, ct, FFMIN(sizeof (as->comment), vl));
- else if (!strcmp (tt, "GENRE"))
- strncpy (as->genre, ct, FFMIN(sizeof (as->genre), vl));
- else if (!strcmp (tt, "TRACKNUMBER"))
- as->track = atoi (ct);
- //Too bored to add others for today
+ if (!strcmp(tt, "AUTHOR") || !strcmp(tt, "ARTIST"))
+ av_strlcpy(as->author, ct, sizeof(as->author));
+ else if (!strcmp(tt, "TITLE"))
+ av_strlcpy(as->title, ct, sizeof(as->title));
+ else if (!strcmp(tt, "COPYRIGHT"))
+ av_strlcpy(as->copyright, ct, sizeof(as->copyright));
+ else if (!strcmp(tt, "DESCRIPTION"))
+ av_strlcpy(as->comment, ct, sizeof(as->comment));
+ else if (!strcmp(tt, "GENRE"))
+ av_strlcpy(as->genre, ct, sizeof(as->genre));
+ else if (!strcmp(tt, "TRACKNUMBER"))
+ as->track = atoi(ct);
+ else if (!strcmp(tt, "ALBUM"))
+ av_strlcpy(as->album, ct, sizeof(as->album));
}
}
- if (size > 0)
- av_log (as, AV_LOG_INFO, "%i bytes of comment header remain\n", size);
+ if (p != end)
+ av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", p-end);
if (n > 0)
- av_log (as, AV_LOG_INFO,
- "truncated comment header, %i comments not found\n", n);
+ av_log(as, AV_LOG_INFO,
+ "truncated comment header, %i comments not found\n", n);
return 0;
}
@@ -134,7 +130,7 @@ typedef struct {
static unsigned int
fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv,
- void **buf)
+ uint8_t **buf)
{
int i,offset, len;
unsigned char *ptr;
@@ -146,7 +142,7 @@ fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv,
offset = 1;
offset += av_xiphlacing(&ptr[offset], priv->len[0]);
offset += av_xiphlacing(&ptr[offset], priv->len[1]);
- for(i = 0; i < 3; i++) {
+ for (i = 0; i < 3; i++) {
memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
offset += priv->len[i];
}
@@ -166,22 +162,46 @@ vorbis_header (AVFormatContext * s, int idx)
if (os->seq > 2)
return 0;
- if(os->seq == 0) {
+ if (os->seq == 0) {
os->private = av_mallocz(sizeof(oggvorbis_private_t));
- if(!os->private)
+ if (!os->private)
return 0;
}
+ if (os->psize < 1)
+ return -1;
+
priv = os->private;
priv->len[os->seq] = os->psize;
priv->packet[os->seq] = av_mallocz(os->psize);
memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
if (os->buf[os->pstart] == 1) {
- uint8_t *p = os->buf + os->pstart + 11; //skip up to the audio channels
- st->codec->channels = *p++;
- st->codec->sample_rate = le2me_32 (unaligned32 (p));
- p += 8; //skip maximum and and nominal bitrate
- st->codec->bit_rate = le2me_32 (unaligned32 (p)); //Minimum bitrate
+ const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
+ unsigned blocksize, bs0, bs1;
+
+ if (os->psize != 30)
+ return -1;
+
+ if (bytestream_get_le32(&p) != 0) /* vorbis_version */
+ return -1;
+
+ st->codec->channels = bytestream_get_byte(&p);
+ st->codec->sample_rate = bytestream_get_le32(&p);
+ p += 4; // skip maximum bitrate
+ st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
+ p += 4; // skip minimum bitrate
+
+ blocksize = bytestream_get_byte(&p);
+ bs0 = blocksize & 15;
+ bs1 = blocksize >> 4;
+
+ if (bs0 > bs1)
+ return -1;
+ if (bs0 < 6 || bs1 > 13)
+ return -1;
+
+ if (bytestream_get_byte(&p) != 1) /* framing_flag */
+ return -1;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_VORBIS;
@@ -189,7 +209,8 @@ vorbis_header (AVFormatContext * s, int idx)
st->time_base.num = 1;
st->time_base.den = st->codec->sample_rate;
} else if (os->buf[os->pstart] == 3) {
- vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
+ if (os->psize > 8)
+ vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
} else {
st->codec->extradata_size =
fixup_vorbis_headers(s, priv, &st->codec->extradata);
diff --git a/contrib/ffmpeg/libavformat/os_support.c b/contrib/ffmpeg/libavformat/os_support.c
index 7a4be8fa7..cc109d596 100644
--- a/contrib/ffmpeg/libavformat/os_support.c
+++ b/contrib/ffmpeg/libavformat/os_support.c
@@ -21,90 +21,69 @@
*/
#include "config.h"
#include "avformat.h"
-#if defined(CONFIG_WINCE)
-/* Skip includes on WinCE. */
-#elif defined(__MINGW32__)
-#include <sys/types.h>
-#include <sys/timeb.h>
-#elif defined(CONFIG_OS2)
-#include <string.h>
-#include <sys/time.h>
-#else
#include <unistd.h>
#include <fcntl.h>
-#include <sys/time.h>
-#endif
-#include <time.h>
+#include "os_support.h"
-#ifndef HAVE_SYS_POLL_H
-#if defined(__MINGW32__)
+#ifdef CONFIG_NETWORK
+#ifndef HAVE_POLL_H
+#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#else
+#elif defined (HAVE_SYS_SELECT_H)
#include <sys/select.h>
#endif
#endif
-/**
- * gets the current time in micro seconds.
- */
-int64_t av_gettime(void)
-{
-#if defined(CONFIG_WINCE)
- return timeGetTime() * INT64_C(1000);
-#elif defined(__MINGW32__)
- struct timeb tb;
- _ftime(&tb);
- return ((int64_t)tb.time * INT64_C(1000) + (int64_t)tb.millitm) * INT64_C(1000);
-#else
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-#endif
-}
-
-#if !defined(CONFIG_WINCE) && !defined(HAVE_LOCALTIME_R)
-struct tm *localtime_r(const time_t *t, struct tm *tp)
-{
- struct tm *l;
-
- l = localtime(t);
- if (!l)
- return 0;
- *tp = *l;
- return tp;
-}
-#endif /* !defined(CONFIG_WINCE) && !defined(HAVE_LOCALTIME_R) */
+#include "network.h"
-#if !defined(HAVE_INET_ATON) && defined(CONFIG_NETWORK)
+#if !defined(HAVE_INET_ATON)
#include <stdlib.h>
#include <strings.h>
-#include "network.h"
int inet_aton (const char * str, struct in_addr * add)
{
- const char * pch = str;
unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0;
- add1 = atoi(pch);
- pch = strpbrk(pch,".");
- if (pch == 0 || ++pch == 0) goto done;
- add2 = atoi(pch);
- pch = strpbrk(pch,".");
- if (pch == 0 || ++pch == 0) goto done;
- add3 = atoi(pch);
- pch = strpbrk(pch,".");
- if (pch == 0 || ++pch == 0) goto done;
- add4 = atoi(pch);
-
-done:
+ if (sscanf(str, "%d.%d.%d.%d", &add1, &add2, &add3, &add4) != 4)
+ return 0;
+
+ if (!add1 || (add1|add2|add3|add4) > 255) return 0;
+
add->s_addr=(add4<<24)+(add3<<16)+(add2<<8)+add1;
return 1;
}
-#endif /* !defined(HAVE_INET_ATON) && defined(CONFIG_NETWORK) */
+#endif /* !defined(HAVE_INET_ATON) */
+
+/* resolve host with also IP address parsing */
+int resolve_host(struct in_addr *sin_addr, const char *hostname)
+{
+ struct hostent *hp;
+
+ if (!inet_aton(hostname, sin_addr)) {
+ hp = gethostbyname(hostname);
+ if (!hp)
+ return -1;
+ memcpy(sin_addr, hp->h_addr, sizeof(struct in_addr));
+ }
+ return 0;
+}
+
+int ff_socket_nonblock(int socket, int enable)
+{
+#ifdef HAVE_WINSOCK2_H
+ return ioctlsocket(socket, FIONBIO, &enable);
+#else
+ if (enable)
+ return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+ else
+ return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
+#endif
+}
+#endif /* CONFIG_NETWORK */
#ifdef CONFIG_FFSERVER
-#ifndef HAVE_SYS_POLL_H
+#ifndef HAVE_POLL_H
int poll(struct pollfd *fds, nfds_t numfds, int timeout)
{
fd_set read_set;
@@ -114,6 +93,13 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
int n;
int rc;
+#ifdef HAVE_WINSOCK2_H
+ if (numfds >= FD_SETSIZE) {
+ errno = EINVAL;
+ return -1;
+ }
+#endif
+
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_ZERO(&exception_set);
@@ -122,10 +108,12 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
for(i = 0; i < numfds; i++) {
if (fds[i].fd < 0)
continue;
+#ifndef HAVE_WINSOCK2_H
if (fds[i].fd >= FD_SETSIZE) {
errno = EINVAL;
return -1;
}
+#endif
if (fds[i].events & POLLIN) FD_SET(fds[i].fd, &read_set);
if (fds[i].events & POLLOUT) FD_SET(fds[i].fd, &write_set);
@@ -162,6 +150,6 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
return rc;
}
-#endif /* HAVE_SYS_POLL_H */
+#endif /* HAVE_POLL_H */
#endif /* CONFIG_FFSERVER */
diff --git a/contrib/ffmpeg/libavformat/os_support.h b/contrib/ffmpeg/libavformat/os_support.h
index 424d6dabd..67d586ab6 100644
--- a/contrib/ffmpeg/libavformat/os_support.h
+++ b/contrib/ffmpeg/libavformat/os_support.h
@@ -19,23 +19,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef _OS_SUPPORT_H
-#define _OS_SUPPORT_H
+#ifndef FFMPEG_OS_SUPPORT_H
+#define FFMPEG_OS_SUPPORT_H
/**
* @file os_support.h
* miscellaneous OS support macros and functions.
- *
- * - socklen_t typedef (BeOS, Innotek libc)
- * - usleep() (Win32, BeOS, OS/2)
- * - lseek() (Win32)
- * - floatf() (OS/2)
- * - strcasecmp() (OS/2)
- * - closesocket()
- * - poll() (BeOS, MinGW)
*/
-#if defined(__BEOS__) || defined(__INNOTEK_LIBC__)
+#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
#endif
@@ -45,16 +37,12 @@ __declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
# define usleep(t) Sleep((t) / 1000)
# include <fcntl.h>
# define lseek(f,p,w) _lseeki64((f), (p), (w))
-# define HAVE_CLOSESOCKET 1
#endif
#ifdef __BEOS__
# include <sys/socket.h>
# include <netinet/in.h>
/* not net_server ? */
-# if IPPROTO_TCP != 6
-# define HAVE_CLOSESOCKET 1
-# endif
# include <BeBuild.h>
/* R5 didn't have usleep, fake it. Haiku and Zeta has it now. */
# if B_BEOS_VERSION <= B_BEOS_VERSION_5
@@ -68,19 +56,13 @@ __declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
# endif
#endif
-#if defined(CONFIG_OS2)
-#include <stdlib.h>
-static inline int usleep(unsigned int t) { return _sleep2(t / 1000); }
-static inline int strcasecmp(const char* s1, const char* s2) { return stricmp(s1,s2); }
-#endif
-
/* most of the time closing a socket is just closing an fd */
-#if HAVE_CLOSESOCKET != 1
+#ifndef HAVE_CLOSESOCKET
#define closesocket close
#endif
#ifdef CONFIG_FFSERVER
-#ifndef HAVE_SYS_POLL_H
+#ifndef HAVE_POLL_H
typedef unsigned long nfds_t;
struct pollfd {
@@ -105,7 +87,7 @@ struct pollfd {
extern int poll(struct pollfd *fds, nfds_t numfds, int timeout);
-#endif /* HAVE_SYS_POLL_H */
+#endif /* HAVE_POLL_H */
#endif /* CONFIG_FFSERVER */
-#endif /* _OS_SUPPORT_H */
+#endif /* FFMPEG_OS_SUPPORT_H */
diff --git a/contrib/ffmpeg/libavformat/psxstr.c b/contrib/ffmpeg/libavformat/psxstr.c
index 2f1a3dc73..3d4cac7f8 100644
--- a/contrib/ffmpeg/libavformat/psxstr.c
+++ b/contrib/ffmpeg/libavformat/psxstr.c
@@ -125,8 +125,8 @@ static void dump(unsigned char *buf,size_t len)
static int str_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
- StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+ ByteIOContext *pb = s->pb;
+ StrDemuxContext *str = s->priv_data;
AVStream *st;
unsigned char sector[RAW_CD_SECTOR_SIZE];
int start;
@@ -142,7 +142,7 @@ static int str_read_header(AVFormatContext *s,
/* skip over any RIFF header */
if (get_buffer(pb, sector, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (AV_RL32(&sector[0]) == RIFF_TAG)
start = RIFF_HEADER_SIZE;
else
@@ -153,7 +153,7 @@ static int str_read_header(AVFormatContext *s,
/* check through the first 32 sectors for individual channels */
for (i = 0; i < 32; i++) {
if (get_buffer(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
//printf("%02x %02x %02x %02x\n",sector[0x10],sector[0x11],sector[0x12],sector[0x13]);
@@ -178,7 +178,7 @@ static int str_read_header(AVFormatContext *s,
/* allocate a new AVStream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 64, 1, 15);
str->channels[channel].video_stream_index = st->index;
@@ -207,7 +207,7 @@ static int str_read_header(AVFormatContext *s,
/* allocate a new AVStream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 64, 128, str->channels[channel].sample_rate);
str->channels[channel].audio_stream_index = st->index;
@@ -249,8 +249,8 @@ if (str->audio_channel != -1)
static int str_read_packet(AVFormatContext *s,
AVPacket *ret_pkt)
{
- ByteIOContext *pb = &s->pb;
- StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+ ByteIOContext *pb = s->pb;
+ StrDemuxContext *str = s->priv_data;
unsigned char sector[RAW_CD_SECTOR_SIZE];
int channel;
int packet_read = 0;
@@ -260,7 +260,7 @@ static int str_read_packet(AVFormatContext *s,
while (!packet_read) {
if (get_buffer(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
channel = sector[0x11];
if (channel >= 32)
@@ -282,7 +282,7 @@ static int str_read_packet(AVFormatContext *s,
pkt = &str->tmp_pkt;
if (current_sector == 0) {
if (av_new_packet(pkt, frame_size))
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->pos= url_ftell(pb) - RAW_CD_SECTOR_SIZE;
pkt->stream_index =
@@ -319,7 +319,7 @@ printf (" dropping audio sector\n");
if (channel == str->audio_channel) {
pkt = ret_pkt;
if (av_new_packet(pkt, 2304))
- return AVERROR_IO;
+ return AVERROR(EIO);
memcpy(pkt->data,sector+24,2304);
pkt->stream_index =
@@ -338,7 +338,7 @@ printf (" dropping other sector\n");
}
if (url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
}
return ret;
@@ -346,7 +346,7 @@ printf (" dropping other sector\n");
static int str_read_close(AVFormatContext *s)
{
- StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+ StrDemuxContext *str = s->priv_data;
av_free(str->video_chunk);
diff --git a/contrib/ffmpeg/libavformat/pva.c b/contrib/ffmpeg/libavformat/pva.c
new file mode 100644
index 000000000..03b92bf3d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/pva.c
@@ -0,0 +1,211 @@
+/*
+ * TechnoTrend PVA (.pva) demuxer
+ * Copyright (c) 2007, 2008 Ivo van Poorten
+ *
+ * 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 "avformat.h"
+#include "mpeg.h"
+
+#define PVA_MAX_PAYLOAD_LENGTH 0x17f8
+#define PVA_VIDEO_PAYLOAD 0x01
+#define PVA_AUDIO_PAYLOAD 0x02
+#define PVA_MAGIC (('A' << 8) + 'V')
+
+typedef struct {
+ int continue_pes;
+} PVAContext;
+
+static int pva_probe(AVProbeData * pd) {
+ unsigned char *buf = pd->buf;
+
+ if (AV_RB16(buf) == PVA_MAGIC && buf[2] && buf[2] < 3 && buf[4] == 0x55)
+ return AVPROBE_SCORE_MAX / 2;
+
+ return 0;
+}
+
+static int pva_read_header(AVFormatContext *s, AVFormatParameters *ap) {
+ AVStream *st;
+
+ if (!(st = av_new_stream(s, 0)))
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ av_set_pts_info(st, 32, 1, 90000);
+ av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
+
+ if (!(st = av_new_stream(s, 1)))
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_MP2;
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
+ av_set_pts_info(st, 33, 1, 90000);
+ av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
+
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+#define pva_log if (read_packet) av_log
+
+static int read_part_of_packet(AVFormatContext *s, int64_t *pts,
+ int *len, int *strid, int read_packet) {
+ ByteIOContext *pb = s->pb;
+ PVAContext *pvactx = s->priv_data;
+ int syncword, streamid, reserved, flags, length, pts_flag;
+ int64_t pva_pts = AV_NOPTS_VALUE, startpos;
+
+recover:
+ startpos = url_ftell(pb);
+
+ syncword = get_be16(pb);
+ streamid = get_byte(pb);
+ get_byte(pb); /* counter not used */
+ reserved = get_byte(pb);
+ flags = get_byte(pb);
+ length = get_be16(pb);
+
+ pts_flag = flags & 0x10;
+
+ if (syncword != PVA_MAGIC) {
+ pva_log(s, AV_LOG_ERROR, "invalid syncword\n");
+ return AVERROR(EIO);
+ }
+ if (streamid != PVA_VIDEO_PAYLOAD && streamid != PVA_AUDIO_PAYLOAD) {
+ pva_log(s, AV_LOG_ERROR, "invalid streamid\n");
+ return AVERROR(EIO);
+ }
+ if (reserved != 0x55) {
+ pva_log(s, AV_LOG_WARNING, "expected reserved byte to be 0x55\n");
+ }
+ if (length > PVA_MAX_PAYLOAD_LENGTH) {
+ pva_log(s, AV_LOG_ERROR, "invalid payload length %u\n", length);
+ return AVERROR(EIO);
+ }
+
+ if (streamid == PVA_VIDEO_PAYLOAD && pts_flag) {
+ pva_pts = get_be32(pb);
+ length -= 4;
+ } else if (streamid == PVA_AUDIO_PAYLOAD) {
+ /* PVA Audio Packets either start with a signaled PES packet or
+ * are a continuation of the previous PES packet. New PES packets
+ * always start at the beginning of a PVA Packet, never somewhere in
+ * the middle. */
+ if (!pvactx->continue_pes) {
+ int pes_signal, pes_header_data_length, pes_packet_length,
+ pes_flags;
+ unsigned char pes_header_data[256];
+
+ pes_signal = get_be24(pb);
+ get_byte(pb);
+ pes_packet_length = get_be16(pb);
+ pes_flags = get_be16(pb);
+ pes_header_data_length = get_byte(pb);
+
+ if (pes_signal != 1) {
+ pva_log(s, AV_LOG_WARNING, "expected signaled PES packet, "
+ "trying to recover\n");
+ url_fskip(pb, length - 9);
+ if (!read_packet)
+ return AVERROR(EIO);
+ goto recover;
+ }
+
+ get_buffer(pb, pes_header_data, pes_header_data_length);
+ 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)
+ pva_pts = ff_parse_pes_pts(pes_header_data);
+ }
+
+ pvactx->continue_pes -= length;
+
+ if (pvactx->continue_pes < 0) {
+ pva_log(s, AV_LOG_WARNING, "audio data corruption\n");
+ pvactx->continue_pes = 0;
+ }
+ }
+
+ if (pva_pts != AV_NOPTS_VALUE)
+ av_add_index_entry(s->streams[streamid-1], startpos, pva_pts, 0, 0, AVINDEX_KEYFRAME);
+
+ *pts = pva_pts;
+ *len = length;
+ *strid = streamid;
+ return 0;
+}
+
+static int pva_read_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = s->pb;
+ int64_t pva_pts;
+ int ret, length, streamid;
+
+ if (read_part_of_packet(s, &pva_pts, &length, &streamid, 1) < 0 ||
+ (ret = av_get_packet(pb, pkt, length)) <= 0)
+ return AVERROR(EIO);
+
+ pkt->stream_index = streamid - 1;
+ pkt->pts = pva_pts;
+
+ return ret;
+}
+
+static int64_t pva_read_timestamp(struct AVFormatContext *s, int stream_index,
+ int64_t *pos, int64_t pos_limit) {
+ ByteIOContext *pb = s->pb;
+ PVAContext *pvactx = s->priv_data;
+ int length, streamid;
+ int64_t res;
+
+ pos_limit = FFMIN(*pos+PVA_MAX_PAYLOAD_LENGTH*8, (uint64_t)*pos+pos_limit);
+
+ while (*pos < pos_limit) {
+ res = AV_NOPTS_VALUE;
+ url_fseek(pb, *pos, SEEK_SET);
+
+ pvactx->continue_pes = 0;
+ if (read_part_of_packet(s, &res, &length, &streamid, 0)) {
+ (*pos)++;
+ continue;
+ }
+ if (streamid - 1 != stream_index || res == AV_NOPTS_VALUE) {
+ *pos = url_ftell(pb) + length;
+ continue;
+ }
+ break;
+ }
+
+ pvactx->continue_pes = 0;
+ return res;
+}
+
+AVInputFormat pva_demuxer = {
+ "pva",
+ "pva file and stream format",
+ sizeof(PVAContext),
+ pva_probe,
+ pva_read_header,
+ pva_read_packet,
+ .read_timestamp = pva_read_timestamp
+};
diff --git a/contrib/ffmpeg/libavformat/qtpalette.h b/contrib/ffmpeg/libavformat/qtpalette.h
index 183600fde..0c6c44f47 100644
--- a/contrib/ffmpeg/libavformat/qtpalette.h
+++ b/contrib/ffmpeg/libavformat/qtpalette.h
@@ -20,17 +20,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef QTPALETTE_H
-#define QTPALETTE_H
+#ifndef FFMPEG_QTPALETTE_H
+#define FFMPEG_QTPALETTE_H
-unsigned char ff_qt_default_palette_4[4 * 4] = {
+#include <inttypes.h>
+
+static const uint8_t ff_qt_default_palette_4[4 * 4] = {
0x93, 0x65, 0x5E, 0x00,
0xFF, 0xFF, 0xFF, 0x00,
0xDF, 0xD0, 0xAB, 0x00,
0x00, 0x00, 0x00, 0x00
};
-unsigned char ff_qt_default_palette_16[16 * 4] = {
+static const uint8_t ff_qt_default_palette_16[16 * 4] = {
0xFF, 0xFB, 0xFF, 0x00,
0xEF, 0xD9, 0xBB, 0x00,
0xE8, 0xC9, 0xB1, 0x00,
@@ -49,7 +51,7 @@ unsigned char ff_qt_default_palette_16[16 * 4] = {
0x00, 0x00, 0x00, 0x00
};
-unsigned char ff_qt_default_palette_256[256 * 4] = {
+static const uint8_t ff_qt_default_palette_256[256 * 4] = {
/* 0, 0x00 */ 0xFF, 0xFF, 0xFF, 0x00,
/* 1, 0x01 */ 0xFF, 0xFF, 0xCC, 0x00,
/* 2, 0x02 */ 0xFF, 0xFF, 0x99, 0x00,
@@ -308,4 +310,4 @@ unsigned char ff_qt_default_palette_256[256 * 4] = {
/* 255, 0xFF */ 0x00, 0x00, 0x00, 0x00
};
-#endif
+#endif /* FFMPEG_QTPALETTE_H */
diff --git a/contrib/ffmpeg/libavformat/raw.c b/contrib/ffmpeg/libavformat/raw.c
index 73a20379a..d4b138953 100644
--- a/contrib/ffmpeg/libavformat/raw.c
+++ b/contrib/ffmpeg/libavformat/raw.c
@@ -20,15 +20,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "ac3.h"
+#include "ac3_parser.h"
+#include "raw.h"
#ifdef CONFIG_MUXERS
/* simple formats */
-static int raw_write_header(struct AVFormatContext *s)
-{
- return 0;
-}
-
static int flac_write_header(struct AVFormatContext *s)
{
static const uint8_t header[8] = {
@@ -37,21 +33,29 @@ static int flac_write_header(struct AVFormatContext *s)
uint8_t *streaminfo = s->streams[0]->codec->extradata;
int len = s->streams[0]->codec->extradata_size;
if(streaminfo != NULL && len > 0) {
- put_buffer(&s->pb, header, 8);
- put_buffer(&s->pb, streaminfo, len);
+ put_buffer(s->pb, header, 8);
+ put_buffer(s->pb, streaminfo, len);
}
return 0;
}
-static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+
+static int roq_write_header(struct AVFormatContext *s)
{
- put_buffer(&s->pb, pkt->data, pkt->size);
- put_flush_packet(&s->pb);
+ static const uint8_t header[] = {
+ 0x84, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x00
+ };
+
+ put_buffer(s->pb, header, 8);
+ put_flush_packet(s->pb);
+
return 0;
}
-static int raw_write_trailer(struct AVFormatContext *s)
+static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt)
{
+ put_buffer(s->pb, pkt->data, pkt->size);
+ put_flush_packet(s->pb);
return 0;
}
#endif //CONFIG_MUXERS
@@ -64,7 +68,7 @@ static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
id = s->iformat->value;
if (id == CODEC_ID_RAWVIDEO) {
@@ -81,7 +85,10 @@ static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_set_pts_info(st, 64, 1, st->codec->sample_rate);
break;
case CODEC_TYPE_VIDEO:
- av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
+ if(ap->time_base.num)
+ av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
+ else
+ av_set_pts_info(st, 64, 1, 25);
st->codec->width = ap->width;
st->codec->height = ap->height;
st->codec->pix_fmt = ap->pix_fmt;
@@ -98,20 +105,26 @@ static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- int ret, size;
+ int ret, size, bps;
// AVStream *st = s->streams[0];
size= RAW_PACKET_SIZE;
- ret= av_get_packet(&s->pb, pkt, size);
+ ret= av_get_packet(s->pb, pkt, size);
pkt->stream_index = 0;
if (ret <= 0) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
/* note: we need to modify the packet size here to handle the last
packet */
pkt->size = ret;
+
+ bps= av_get_bits_per_sample(s->streams[0]->codec->codec_id);
+ assert(bps); // if false there IS a bug elsewhere (NOT in this function)
+ pkt->dts=
+ pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codec->channels);
+
return ret;
}
@@ -122,14 +135,14 @@ static int raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt)
size = RAW_PACKET_SIZE;
if (av_new_packet(pkt, size) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
- pkt->pos= url_ftell(&s->pb);
+ pkt->pos= url_ftell(s->pb);
pkt->stream_index = 0;
- ret = get_partial_buffer(&s->pb, pkt->data, size);
+ ret = get_partial_buffer(s->pb, pkt->data, size);
if (ret <= 0) {
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->size = ret;
return ret;
@@ -140,32 +153,32 @@ static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, size, w, h, unk1, unk2;
- if (get_le32(&s->pb) != MKTAG('M', 'J', 'P', 'G'))
- return AVERROR_IO; // FIXME
+ if (get_le32(s->pb) != MKTAG('M', 'J', 'P', 'G'))
+ return AVERROR(EIO); // FIXME
- size = get_le32(&s->pb);
+ size = get_le32(s->pb);
- w = get_le16(&s->pb);
- h = get_le16(&s->pb);
+ w = get_le16(s->pb);
+ h = get_le16(s->pb);
- url_fskip(&s->pb, 8); // zero + size (padded?)
- url_fskip(&s->pb, 2);
- unk1 = get_le16(&s->pb);
- unk2 = get_le16(&s->pb);
- url_fskip(&s->pb, 22); // ascii timestamp
+ url_fskip(s->pb, 8); // zero + size (padded?)
+ url_fskip(s->pb, 2);
+ unk1 = get_le16(s->pb);
+ unk2 = get_le16(s->pb);
+ url_fskip(s->pb, 22); // ascii timestamp
av_log(NULL, AV_LOG_DEBUG, "Ingenient packet: size=%d, width=%d, height=%d, unk1=%d unk2=%d\n",
size, w, h, unk1, unk2);
if (av_new_packet(pkt, size) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
- pkt->pos = url_ftell(&s->pb);
+ pkt->pos = url_ftell(s->pb);
pkt->stream_index = 0;
- ret = get_buffer(&s->pb, pkt->data, size);
+ ret = get_buffer(s->pb, pkt->data, size);
if (ret <= 0) {
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->size = ret;
return ret;
@@ -202,7 +215,7 @@ int pcm_read_seek(AVFormatContext *s,
/* recompute exact position */
st->cur_dts = av_rescale(pos, st->time_base.den, byte_rate * (int64_t)st->time_base.num);
- url_fseek(&s->pb, pos + s->data_offset, SEEK_SET);
+ url_fseek(s->pb, pos + s->data_offset, SEEK_SET);
return 0;
}
@@ -214,11 +227,11 @@ static int ac3_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_AC3;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -230,10 +243,10 @@ static int shorten_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_SHORTEN;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -246,10 +259,10 @@ static int flac_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_FLAC;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -262,11 +275,11 @@ static int dts_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_DTS;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -279,11 +292,11 @@ static int aac_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_AAC;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
@@ -296,14 +309,14 @@ static int video_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = s->iformat->value;
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* for mjpeg, specify frame rate */
- /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/
+ /* for mpeg4 specify it too (most mpeg4 streams do not have the fixed_vop_rate set ...)*/
if (ap->time_base.num) {
av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
} else if ( st->codec->codec_id == CODEC_ID_MJPEG ||
@@ -347,32 +360,29 @@ static int mpegvideo_probe(AVProbeData *p)
return 0;
}
-#define VIDEO_OBJECT_START_CODE 0x00000100
-#define VIDEO_OBJECT_LAYER_START_CODE 0x00000120
#define VISUAL_OBJECT_START_CODE 0x000001b5
#define VOP_START_CODE 0x000001b6
static int mpeg4video_probe(AVProbeData *probe_packet)
{
uint32_t temp_buffer= -1;
- int VO=0, VOL=0, VOP = 0, VISO = 0;
+ int VO=0, VOL=0, VOP = 0, VISO = 0, res=0;
int i;
for(i=0; i<probe_packet->buf_size; i++){
temp_buffer = (temp_buffer<<8) + probe_packet->buf[i];
- if ((temp_buffer & 0xffffff00) == 0x100) {
- switch(temp_buffer){
- case VOP_START_CODE: VOP++; break;
- case VISUAL_OBJECT_START_CODE: VISO++; break;
- }
- switch(temp_buffer & 0xfffffff0){
- case VIDEO_OBJECT_START_CODE: VO++; break;
- case VIDEO_OBJECT_LAYER_START_CODE: VOL++; break;
- }
- }
+ if ((temp_buffer & 0xffffff00) != 0x100)
+ continue;
+
+ if (temp_buffer == VOP_START_CODE) VOP++;
+ else if (temp_buffer == VISUAL_OBJECT_START_CODE) VISO++;
+ else if (temp_buffer < 0x120) VO++;
+ else if (temp_buffer < 0x130) VOL++;
+ else if ( !(0x1AF < temp_buffer && temp_buffer < 0x1B7)
+ && !(0x1B9 < temp_buffer && temp_buffer < 0x1C4)) res++;
}
- if ( VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0)
+ if ( VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res==0)
return AVPROBE_SCORE_MAX/2;
return 0;
}
@@ -382,8 +392,6 @@ static int h263_probe(AVProbeData *p)
int code;
const uint8_t *d;
- if (p->buf_size < 6)
- return 0;
d = p->buf;
code = (d[0] << 14) | (d[1] << 6) | (d[2] >> 2);
if (code == 0x20) {
@@ -397,8 +405,6 @@ static int h261_probe(AVProbeData *p)
int code;
const uint8_t *d;
- if (p->buf_size < 6)
- return 0;
d = p->buf;
code = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4);
if (code == 0x10) {
@@ -409,16 +415,13 @@ static int h261_probe(AVProbeData *p)
static int ac3_probe(AVProbeData *p)
{
- int max_frames, first_frames, frames;
+ int max_frames, first_frames = 0, frames;
uint8_t *buf, *buf2, *end;
AC3HeaderInfo hdr;
- if(p->buf_size < 7)
- return 0;
-
max_frames = 0;
buf = p->buf;
- end = buf + FFMIN(4096, p->buf_size - 7);
+ end = buf + p->buf_size;
for(; buf < end; buf++) {
buf2 = buf;
@@ -438,6 +441,12 @@ static int ac3_probe(AVProbeData *p)
else return 0;
}
+static int flac_probe(AVProbeData *p)
+{
+ if(memcmp(p->buf, "fLaC", 4)) return 0;
+ else return AVPROBE_SCORE_MAX / 2;
+}
+
AVInputFormat shorten_demuxer = {
"shn",
"raw shorten",
@@ -454,7 +463,7 @@ AVInputFormat flac_demuxer = {
"flac",
"raw flac",
0,
- NULL,
+ flac_probe,
flac_read_header,
raw_read_partial_packet,
raw_read_close,
@@ -473,11 +482,11 @@ AVOutputFormat flac_muxer = {
0,
flac_write_header,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
+#ifdef CONFIG_AC3_DEMUXER
AVInputFormat ac3_demuxer = {
"ac3",
"raw ac3",
@@ -489,6 +498,7 @@ AVInputFormat ac3_demuxer = {
.flags= AVFMT_GENERIC_INDEX,
.extensions = "ac3",
};
+#endif
#ifdef CONFIG_MUXERS
AVOutputFormat ac3_muxer = {
@@ -499,9 +509,8 @@ AVOutputFormat ac3_muxer = {
0,
CODEC_ID_AC3,
0,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -530,6 +539,21 @@ AVInputFormat aac_demuxer = {
.extensions = "aac",
};
+#ifdef CONFIG_ROQ_MUXER
+AVOutputFormat roq_muxer =
+{
+ "RoQ",
+ "Id RoQ format",
+ NULL,
+ "roq",
+ 0,
+ CODEC_ID_ROQ_DPCM,
+ CODEC_ID_ROQ,
+ roq_write_header,
+ raw_write_packet,
+};
+#endif //CONFIG_ROQ_MUXER
+
AVInputFormat h261_demuxer = {
"h261",
"raw h261",
@@ -552,9 +576,8 @@ AVOutputFormat h261_muxer = {
0,
0,
CODEC_ID_H261,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -581,9 +604,8 @@ AVOutputFormat h263_muxer = {
0,
0,
CODEC_ID_H263,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -610,9 +632,8 @@ AVOutputFormat m4v_muxer = {
0,
CODEC_ID_NONE,
CODEC_ID_MPEG4,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -639,9 +660,8 @@ AVOutputFormat h264_muxer = {
0,
CODEC_ID_NONE,
CODEC_ID_H264,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -667,9 +687,8 @@ AVOutputFormat mpeg1video_muxer = {
0,
0,
CODEC_ID_MPEG1VIDEO,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -683,9 +702,8 @@ AVOutputFormat mpeg2video_muxer = {
0,
0,
CODEC_ID_MPEG2VIDEO,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -725,9 +743,8 @@ AVOutputFormat mjpeg_muxer = {
0,
0,
CODEC_ID_MJPEG,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -770,9 +787,8 @@ AVOutputFormat pcm_ ## name ## _muxer = {\
0,\
codec,\
0,\
- raw_write_header,\
+ NULL,\
raw_write_packet,\
- raw_write_trailer,\
.flags= AVFMT_NOTIMESTAMPS,\
};
@@ -836,11 +852,13 @@ static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
if (packet_size < 0)
return -1;
- ret= av_get_packet(&s->pb, pkt, packet_size);
+ ret= av_get_packet(s->pb, pkt, packet_size);
+ pkt->pts=
+ pkt->dts= pkt->pos / packet_size;
pkt->stream_index = 0;
if (ret != packet_size) {
- return AVERROR_IO;
+ return AVERROR(EIO);
} else {
return 0;
}
@@ -855,7 +873,7 @@ AVInputFormat rawvideo_demuxer = {
rawvideo_read_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
- .extensions = "yuv,cif,qcif",
+ .extensions = "yuv,cif,qcif,rgb",
.value = CODEC_ID_RAWVIDEO,
};
@@ -864,13 +882,12 @@ AVOutputFormat rawvideo_muxer = {
"rawvideo",
"raw video format",
NULL,
- "yuv",
+ "yuv,rgb",
0,
CODEC_ID_NONE,
CODEC_ID_RAWVIDEO,
- raw_write_header,
+ NULL,
raw_write_packet,
- raw_write_trailer,
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
@@ -893,9 +910,8 @@ AVOutputFormat null_muxer = {
CODEC_ID_PCM_S16LE,
#endif
CODEC_ID_RAWVIDEO,
- raw_write_header,
+ NULL,
null_write_packet,
- raw_write_trailer,
.flags = AVFMT_NOFILE | AVFMT_RAWPICTURE | AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
diff --git a/contrib/ffmpeg/libavformat/raw.h b/contrib/ffmpeg/libavformat/raw.h
new file mode 100644
index 000000000..3d851c829
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/raw.h
@@ -0,0 +1,30 @@
+/*
+ * RAW muxer and demuxer
+ * Copyright (C) 2007 Aurelien Jacobs <aurel@gnuage.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
+ */
+
+#ifndef FFMPEG_RAW_H
+#define FFMPEG_RAW_H
+
+#include "avformat.h"
+
+int pcm_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags);
+
+#endif /* FFMPEG_RAW_H */
diff --git a/contrib/ffmpeg/libavformat/riff.c b/contrib/ffmpeg/libavformat/riff.c
index 4a5553fa4..64891db3e 100644
--- a/contrib/ffmpeg/libavformat/riff.c
+++ b/contrib/ffmpeg/libavformat/riff.c
@@ -22,7 +22,6 @@
#include "avformat.h"
#include "avcodec.h"
#include "riff.h"
-#include "allformats.h" // for asf_muxer
/* Note: when encoding, the first matching tag is used, so order is
important if multiple tags possible for a given codec. */
@@ -88,6 +87,8 @@ const AVCodecTag codec_bmp_tags[] = {
{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') },
{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') },
{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', '0') },
+ { CODEC_ID_DVVIDEO, MKTAG('c', 'd', 'v', 'c') }, // Canopus DV
{ CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') },
{ CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },
{ CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') },
@@ -97,15 +98,16 @@ const AVCodecTag codec_bmp_tags[] = {
{ CODEC_ID_MPEG1VIDEO, 0x10000001 },
{ CODEC_ID_MPEG2VIDEO, 0x10000002 },
{ CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') },
+ { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') },
{ CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
{ CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
+ { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
{ CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
{ CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') },
{ CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') },
- { CODEC_ID_JPEGLS, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
{ CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
{ CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') },
{ CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
@@ -117,8 +119,11 @@ const AVCodecTag codec_bmp_tags[] = {
{ CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') },
{ CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') },
{ CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') },
+ { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') },
{ CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
{ CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
+ { CODEC_ID_INDEO4, MKTAG('I', 'V', '4', '1') },
+ { CODEC_ID_INDEO5, MKTAG('I', 'V', '5', '0') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
@@ -175,107 +180,49 @@ const AVCodecTag codec_bmp_tags[] = {
};
const AVCodecTag codec_wav_tags[] = {
- { CODEC_ID_MP2, 0x50 },
- { CODEC_ID_MP3, 0x55 },
- { CODEC_ID_AC3, 0x2000 },
- { CODEC_ID_DTS, 0x2001 },
- { CODEC_ID_PCM_S16LE, 0x01 },
- { CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
- { CODEC_ID_PCM_S24LE, 0x01 },
- { CODEC_ID_PCM_S32LE, 0x01 },
- { CODEC_ID_PCM_ALAW, 0x06 },
- { CODEC_ID_PCM_MULAW, 0x07 },
- { CODEC_ID_ADPCM_MS, 0x02 },
- { CODEC_ID_ADPCM_IMA_WAV, 0x11 },
- { CODEC_ID_ADPCM_YAMAHA, 0x20 },
- { CODEC_ID_ADPCM_G726, 0x45 },
- { CODEC_ID_ADPCM_IMA_DK4, 0x61 }, /* rogue format number */
- { CODEC_ID_ADPCM_IMA_DK3, 0x62 }, /* rogue format number */
- { CODEC_ID_WMAV1, 0x160 },
- { CODEC_ID_WMAV2, 0x161 },
- { CODEC_ID_AAC, 0x706d },
- { CODEC_ID_AAC, 0xff },
- { CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
- { CODEC_ID_SONIC, 0x2048 },
- { CODEC_ID_SONIC_LS, 0x2048 },
- { CODEC_ID_ADPCM_CT, 0x200 },
- { CODEC_ID_ADPCM_SWF, ('S'<<8)+'F' },
- { CODEC_ID_TRUESPEECH, 0x22 },
- { CODEC_ID_FLAC, 0xF1AC },
- { CODEC_ID_IMC, 0x401 },
- { CODEC_ID_GSM_MS, 0x31 },
+ { CODEC_ID_PCM_S16LE, 0x0001 },
+ { CODEC_ID_PCM_U8, 0x0001 }, /* must come after s16le in this list */
+ { CODEC_ID_PCM_S24LE, 0x0001 },
+ { CODEC_ID_PCM_S32LE, 0x0001 },
+ { CODEC_ID_ADPCM_MS, 0x0002 },
+ { CODEC_ID_PCM_ALAW, 0x0006 },
+ { CODEC_ID_PCM_MULAW, 0x0007 },
+ { CODEC_ID_WMAVOICE, 0x000A },
+ { CODEC_ID_ADPCM_IMA_WAV, 0x0011 },
+ { CODEC_ID_ADPCM_YAMAHA, 0x0020 },
+ { CODEC_ID_TRUESPEECH, 0x0022 },
+ { CODEC_ID_GSM_MS, 0x0031 },
+ { CODEC_ID_ADPCM_G726, 0x0045 },
+ { CODEC_ID_MP2, 0x0050 },
+ { CODEC_ID_MP3, 0x0055 },
+ { CODEC_ID_ADPCM_IMA_DK4, 0x0061 }, /* rogue format number */
+ { CODEC_ID_ADPCM_IMA_DK3, 0x0062 }, /* rogue format number */
+ { CODEC_ID_VOXWARE, 0x0075 },
+ { CODEC_ID_AAC, 0x00ff },
+ { CODEC_ID_WMAV1, 0x0160 },
+ { CODEC_ID_WMAV2, 0x0161 },
+ { CODEC_ID_WMAPRO, 0x0162 },
+ { CODEC_ID_WMALOSSLESS, 0x0163 },
+ { CODEC_ID_ADPCM_CT, 0x0200 },
+ { CODEC_ID_ATRAC3, 0x0270 },
+ { CODEC_ID_IMC, 0x0401 },
+ { CODEC_ID_AC3, 0x2000 },
+ { CODEC_ID_DTS, 0x2001 },
+ { CODEC_ID_SONIC, 0x2048 },
+ { CODEC_ID_SONIC_LS, 0x2048 },
+ { CODEC_ID_AAC, 0x706d },
+ { CODEC_ID_FLAC, 0xF1AC },
+ { CODEC_ID_ADPCM_SWF, ('S'<<8)+'F' },
+ { CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
/* FIXME: All of the IDs below are not 16 bit and thus illegal. */
// for NuppelVideo (nuv.c)
{ CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') },
- { CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
- { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
+ { CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
+ { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
{ 0, 0 },
};
-unsigned int codec_get_tag(const AVCodecTag *tags, int id)
-{
- while (tags->id != CODEC_ID_NONE) {
- if (tags->id == id)
- return tags->tag;
- tags++;
- }
- return 0;
-}
-
-enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag)
-{
- while (tags->id != CODEC_ID_NONE) {
- if( toupper((tag >> 0)&0xFF) == toupper((tags->tag >> 0)&0xFF)
- && toupper((tag >> 8)&0xFF) == toupper((tags->tag >> 8)&0xFF)
- && toupper((tag >>16)&0xFF) == toupper((tags->tag >>16)&0xFF)
- && toupper((tag >>24)&0xFF) == toupper((tags->tag >>24)&0xFF))
- return tags->id;
- tags++;
- }
- return CODEC_ID_NONE;
-}
-
-unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id)
-{
- int i;
- for(i=0; tags && tags[i]; i++){
- int tag= codec_get_tag(tags[i], id);
- if(tag) return tag;
- }
- return 0;
-}
-
-enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag)
-{
- int i;
- for(i=0; tags && tags[i]; i++){
- enum CodecID id= codec_get_id(tags[i], tag);
- if(id!=CODEC_ID_NONE) return id;
- }
- return CODEC_ID_NONE;
-}
-
-unsigned int codec_get_bmp_tag(int id)
-{
- return codec_get_tag(codec_bmp_tags, id);
-}
-
-unsigned int codec_get_wav_tag(int id)
-{
- return codec_get_tag(codec_wav_tags, id);
-}
-
-enum CodecID codec_get_bmp_id(unsigned int tag)
-{
- return codec_get_id(codec_bmp_tags, tag);
-}
-
-enum CodecID codec_get_wav_id(unsigned int tag)
-{
- return codec_get_id(codec_wav_tags, tag);
-}
-
#ifdef CONFIG_MUXERS
offset_t start_tag(ByteIOContext *pb, const char *tag)
{
@@ -327,7 +274,7 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
}
if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) {
- blkalign = enc->frame_size; //this is wrong, but seems many demuxers dont work if this is set correctly
+ blkalign = enc->frame_size; //this is wrong, but it seems many demuxers do not work if this is set correctly
//blkalign = 144 * enc->bit_rate/enc->sample_rate;
} else if (enc->codec_id == CODEC_ID_ADPCM_G726) { //
blkalign = 1;
@@ -475,6 +422,8 @@ int wav_codec_get_id(unsigned int tag, int bps)
id = CODEC_ID_PCM_S24LE;
if (id == CODEC_ID_PCM_S16LE && bps == 32)
id = CODEC_ID_PCM_S32LE;
+ if (id == CODEC_ID_ADPCM_IMA_WAV && bps == 8)
+ id = CODEC_ID_PCM_ZORK;
return id;
}
#endif // CONFIG_DEMUXERS
diff --git a/contrib/ffmpeg/libavformat/riff.h b/contrib/ffmpeg/libavformat/riff.h
index 45c72dde6..dc970f619 100644
--- a/contrib/ffmpeg/libavformat/riff.h
+++ b/contrib/ffmpeg/libavformat/riff.h
@@ -25,8 +25,11 @@
* do NOT include this in end user applications
*/
-#ifndef FF_RIFF_H
-#define FF_RIFF_H
+#ifndef FFMPEG_RIFF_H
+#define FFMPEG_RIFF_H
+
+#include "avcodec.h"
+#include "avio.h"
offset_t start_tag(ByteIOContext *pb, const char *tag);
void end_tag(ByteIOContext *pb, offset_t start);
@@ -46,10 +49,6 @@ extern const AVCodecTag codec_wav_tags[];
unsigned int codec_get_tag(const AVCodecTag *tags, int id);
enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag);
-unsigned int codec_get_bmp_tag(int id) attribute_deprecated; //use av_codec_get_tag
-unsigned int codec_get_wav_tag(int id) attribute_deprecated; //use av_codec_get_tag
-enum CodecID codec_get_bmp_id(unsigned int tag) attribute_deprecated; //use av_codec_get_id
-enum CodecID codec_get_wav_id(unsigned int tag) attribute_deprecated; //use av_codec_get_id
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale);
-#endif
+#endif /* FFMPEG_RIFF_H */
diff --git a/contrib/ffmpeg/libavformat/rm.c b/contrib/ffmpeg/libavformat/rm.c
deleted file mode 100644
index ad2f5ff27..000000000
--- a/contrib/ffmpeg/libavformat/rm.c
+++ /dev/null
@@ -1,1147 +0,0 @@
-/*
- * "Real" compatible muxer and demuxer.
- * Copyright (c) 2000, 2001 Fabrice Bellard.
- *
- * 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 "avformat.h"
-
-/* in ms */
-#define BUFFER_DURATION 0
-
-typedef struct {
- int nb_packets;
- int packet_total_size;
- int packet_max_size;
- /* codec related output */
- int bit_rate;
- float frame_rate;
- int nb_frames; /* current frame number */
- int total_frames; /* total number of frames */
- int num;
- AVCodecContext *enc;
-} StreamInfo;
-
-typedef struct {
- StreamInfo streams[2];
- StreamInfo *audio_stream, *video_stream;
- int data_pos; /* position of the data after the header */
- int nb_packets;
- int old_format;
- int current_stream;
- int remaining_len;
- /// Audio descrambling matrix parameters
- uint8_t *audiobuf; ///< place to store reordered audio data
- int64_t audiotimestamp; ///< Audio packet timestamp
- int sub_packet_cnt; // Subpacket counter, used while reading
- int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
- int audio_stream_num; ///< Stream number for audio packets
- int audio_pkt_cnt; ///< Output packet counter
- int audio_framesize; /// Audio frame size from container
- int sub_packet_lengths[16]; /// Length of each aac subpacket
-} RMContext;
-
-#ifdef CONFIG_MUXERS
-static void put_str(ByteIOContext *s, const char *tag)
-{
- put_be16(s,strlen(tag));
- while (*tag) {
- put_byte(s, *tag++);
- }
-}
-
-static void put_str8(ByteIOContext *s, const char *tag)
-{
- put_byte(s, strlen(tag));
- while (*tag) {
- put_byte(s, *tag++);
- }
-}
-
-static void rv10_write_header(AVFormatContext *ctx,
- int data_size, int index_pos)
-{
- RMContext *rm = ctx->priv_data;
- ByteIOContext *s = &ctx->pb;
- StreamInfo *stream;
- unsigned char *data_offset_ptr, *start_ptr;
- const char *desc, *mimetype;
- int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
- int bit_rate, v, duration, flags, data_pos;
-
- start_ptr = s->buf_ptr;
-
- put_tag(s, ".RMF");
- put_be32(s,18); /* header size */
- put_be16(s,0);
- put_be32(s,0);
- put_be32(s,4 + ctx->nb_streams); /* num headers */
-
- put_tag(s,"PROP");
- put_be32(s, 50);
- put_be16(s, 0);
- packet_max_size = 0;
- packet_total_size = 0;
- nb_packets = 0;
- bit_rate = 0;
- duration = 0;
- for(i=0;i<ctx->nb_streams;i++) {
- StreamInfo *stream = &rm->streams[i];
- bit_rate += stream->bit_rate;
- if (stream->packet_max_size > packet_max_size)
- packet_max_size = stream->packet_max_size;
- nb_packets += stream->nb_packets;
- packet_total_size += stream->packet_total_size;
- /* select maximum duration */
- v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
- if (v > duration)
- duration = v;
- }
- put_be32(s, bit_rate); /* max bit rate */
- put_be32(s, bit_rate); /* avg bit rate */
- put_be32(s, packet_max_size); /* max packet size */
- if (nb_packets > 0)
- packet_avg_size = packet_total_size / nb_packets;
- else
- packet_avg_size = 0;
- put_be32(s, packet_avg_size); /* avg packet size */
- put_be32(s, nb_packets); /* num packets */
- put_be32(s, duration); /* duration */
- put_be32(s, BUFFER_DURATION); /* preroll */
- put_be32(s, index_pos); /* index offset */
- /* computation of data the data offset */
- data_offset_ptr = s->buf_ptr;
- put_be32(s, 0); /* data offset : will be patched after */
- put_be16(s, ctx->nb_streams); /* num streams */
- flags = 1 | 2; /* save allowed & perfect play */
- if (url_is_streamed(s))
- flags |= 4; /* live broadcast */
- put_be16(s, flags);
-
- /* comments */
-
- put_tag(s,"CONT");
- size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
- strlen(ctx->comment) + 4 * 2 + 10;
- put_be32(s,size);
- put_be16(s,0);
- put_str(s, ctx->title);
- put_str(s, ctx->author);
- put_str(s, ctx->copyright);
- put_str(s, ctx->comment);
-
- for(i=0;i<ctx->nb_streams;i++) {
- int codec_data_size;
-
- stream = &rm->streams[i];
-
- if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
- desc = "The Audio Stream";
- mimetype = "audio/x-pn-realaudio";
- codec_data_size = 73;
- } else {
- desc = "The Video Stream";
- mimetype = "video/x-pn-realvideo";
- codec_data_size = 34;
- }
-
- put_tag(s,"MDPR");
- size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
- put_be32(s, size);
- put_be16(s, 0);
-
- put_be16(s, i); /* stream number */
- put_be32(s, stream->bit_rate); /* max bit rate */
- put_be32(s, stream->bit_rate); /* avg bit rate */
- put_be32(s, stream->packet_max_size); /* max packet size */
- if (stream->nb_packets > 0)
- packet_avg_size = stream->packet_total_size /
- stream->nb_packets;
- else
- packet_avg_size = 0;
- put_be32(s, packet_avg_size); /* avg packet size */
- put_be32(s, 0); /* start time */
- put_be32(s, BUFFER_DURATION); /* preroll */
- /* duration */
- if (url_is_streamed(s) || !stream->total_frames)
- put_be32(s, (int)(3600 * 1000));
- else
- put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
- put_str8(s, desc);
- put_str8(s, mimetype);
- put_be32(s, codec_data_size);
-
- if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
- int coded_frame_size, fscode, sample_rate;
- sample_rate = stream->enc->sample_rate;
- coded_frame_size = (stream->enc->bit_rate *
- stream->enc->frame_size) / (8 * sample_rate);
- /* audio codec info */
- put_tag(s, ".ra");
- put_byte(s, 0xfd);
- put_be32(s, 0x00040000); /* version */
- put_tag(s, ".ra4");
- put_be32(s, 0x01b53530); /* stream length */
- put_be16(s, 4); /* unknown */
- put_be32(s, 0x39); /* header size */
-
- switch(sample_rate) {
- case 48000:
- case 24000:
- case 12000:
- fscode = 1;
- break;
- default:
- case 44100:
- case 22050:
- case 11025:
- fscode = 2;
- break;
- case 32000:
- case 16000:
- case 8000:
- fscode = 3;
- }
- put_be16(s, fscode); /* codec additional info, for AC3, seems
- to be a frequency code */
- /* special hack to compensate rounding errors... */
- if (coded_frame_size == 557)
- coded_frame_size--;
- put_be32(s, coded_frame_size); /* frame length */
- put_be32(s, 0x51540); /* unknown */
- put_be32(s, 0x249f0); /* unknown */
- put_be32(s, 0x249f0); /* unknown */
- put_be16(s, 0x01);
- /* frame length : seems to be very important */
- put_be16(s, coded_frame_size);
- put_be32(s, 0); /* unknown */
- put_be16(s, stream->enc->sample_rate); /* sample rate */
- put_be32(s, 0x10); /* unknown */
- put_be16(s, stream->enc->channels);
- put_str8(s, "Int0"); /* codec name */
- put_str8(s, "dnet"); /* codec name */
- put_be16(s, 0); /* title length */
- put_be16(s, 0); /* author length */
- put_be16(s, 0); /* copyright length */
- put_byte(s, 0); /* end of header */
- } else {
- /* video codec info */
- put_be32(s,34); /* size */
- if(stream->enc->codec_id == CODEC_ID_RV10)
- put_tag(s,"VIDORV10");
- else
- put_tag(s,"VIDORV20");
- put_be16(s, stream->enc->width);
- put_be16(s, stream->enc->height);
- put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */
- put_be32(s,0); /* unknown meaning */
- put_be16(s, (int) stream->frame_rate); /* unknown meaning */
- put_be32(s,0); /* unknown meaning */
- put_be16(s, 8); /* unknown meaning */
- /* Seems to be the codec version: only use basic H263. The next
- versions seems to add a diffential DC coding as in
- MPEG... nothing new under the sun */
- if(stream->enc->codec_id == CODEC_ID_RV10)
- put_be32(s,0x10000000);
- else
- put_be32(s,0x20103001);
- //put_be32(s,0x10003000);
- }
- }
-
- /* patch data offset field */
- data_pos = s->buf_ptr - start_ptr;
- rm->data_pos = data_pos;
- data_offset_ptr[0] = data_pos >> 24;
- data_offset_ptr[1] = data_pos >> 16;
- data_offset_ptr[2] = data_pos >> 8;
- data_offset_ptr[3] = data_pos;
-
- /* data stream */
- put_tag(s,"DATA");
- put_be32(s,data_size + 10 + 8);
- put_be16(s,0);
-
- put_be32(s, nb_packets); /* number of packets */
- put_be32(s,0); /* next data header */
-}
-
-static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
- int length, int key_frame)
-{
- int timestamp;
- ByteIOContext *s = &ctx->pb;
-
- stream->nb_packets++;
- stream->packet_total_size += length;
- if (length > stream->packet_max_size)
- stream->packet_max_size = length;
-
- put_be16(s,0); /* version */
- put_be16(s,length + 12);
- put_be16(s, stream->num); /* stream number */
- timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
- put_be32(s, timestamp); /* timestamp */
- put_byte(s, 0); /* reserved */
- put_byte(s, key_frame ? 2 : 0); /* flags */
-}
-
-static int rm_write_header(AVFormatContext *s)
-{
- RMContext *rm = s->priv_data;
- StreamInfo *stream;
- int n;
- AVCodecContext *codec;
-
- for(n=0;n<s->nb_streams;n++) {
- s->streams[n]->id = n;
- codec = s->streams[n]->codec;
- stream = &rm->streams[n];
- memset(stream, 0, sizeof(StreamInfo));
- stream->num = n;
- stream->bit_rate = codec->bit_rate;
- stream->enc = codec;
-
- switch(codec->codec_type) {
- case CODEC_TYPE_AUDIO:
- rm->audio_stream = stream;
- stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
- /* XXX: dummy values */
- stream->packet_max_size = 1024;
- stream->nb_packets = 0;
- stream->total_frames = stream->nb_packets;
- break;
- case CODEC_TYPE_VIDEO:
- rm->video_stream = stream;
- stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
- /* XXX: dummy values */
- stream->packet_max_size = 4096;
- stream->nb_packets = 0;
- stream->total_frames = stream->nb_packets;
- break;
- default:
- return -1;
- }
- }
-
- rv10_write_header(s, 0, 0);
- put_flush_packet(&s->pb);
- return 0;
-}
-
-static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
-{
- uint8_t *buf1;
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- StreamInfo *stream = rm->audio_stream;
- int i;
-
- /* XXX: suppress this malloc */
- buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
-
- write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY));
-
- /* for AC3, the words seems to be reversed */
- for(i=0;i<size;i+=2) {
- buf1[i] = buf[i+1];
- buf1[i+1] = buf[i];
- }
- put_buffer(pb, buf1, size);
- put_flush_packet(pb);
- stream->nb_frames++;
- av_free(buf1);
- return 0;
-}
-
-static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
-{
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- StreamInfo *stream = rm->video_stream;
- int key_frame = !!(flags & PKT_FLAG_KEY);
-
- /* XXX: this is incorrect: should be a parameter */
-
- /* Well, I spent some time finding the meaning of these bits. I am
- not sure I understood everything, but it works !! */
-#if 1
- write_packet_header(s, stream, size + 7, key_frame);
- /* bit 7: '1' if final packet of a frame converted in several packets */
- put_byte(pb, 0x81);
- /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
- frame starting from 1 */
- if (key_frame) {
- put_byte(pb, 0x81);
- } else {
- put_byte(pb, 0x01);
- }
- put_be16(pb, 0x4000 + (size)); /* total frame size */
- put_be16(pb, 0x4000 + (size)); /* offset from the start or the end */
-#else
- /* full frame */
- write_packet_header(s, size + 6);
- put_byte(pb, 0xc0);
- put_be16(pb, 0x4000 + size); /* total frame size */
- put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */
-#endif
- put_byte(pb, stream->nb_frames & 0xff);
-
- put_buffer(pb, buf, size);
- put_flush_packet(pb);
-
- stream->nb_frames++;
- return 0;
-}
-
-static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
-{
- if (s->streams[pkt->stream_index]->codec->codec_type ==
- CODEC_TYPE_AUDIO)
- return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
- else
- return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
-}
-
-static int rm_write_trailer(AVFormatContext *s)
-{
- RMContext *rm = s->priv_data;
- int data_size, index_pos, i;
- ByteIOContext *pb = &s->pb;
-
- if (!url_is_streamed(&s->pb)) {
- /* end of file: finish to write header */
- index_pos = url_fseek(pb, 0, SEEK_CUR);
- data_size = index_pos - rm->data_pos;
-
- /* index */
- put_tag(pb, "INDX");
- put_be32(pb, 10 + 10 * s->nb_streams);
- put_be16(pb, 0);
-
- for(i=0;i<s->nb_streams;i++) {
- put_be32(pb, 0); /* zero indices */
- put_be16(pb, i); /* stream number */
- put_be32(pb, 0); /* next index */
- }
- /* undocumented end header */
- put_be32(pb, 0);
- put_be32(pb, 0);
-
- url_fseek(pb, 0, SEEK_SET);
- for(i=0;i<s->nb_streams;i++)
- rm->streams[i].total_frames = rm->streams[i].nb_frames;
- rv10_write_header(s, data_size, index_pos);
- } else {
- /* undocumented end header */
- put_be32(pb, 0);
- put_be32(pb, 0);
- }
- put_flush_packet(pb);
- return 0;
-}
-#endif //CONFIG_MUXERS
-
-/***************************************************/
-
-static void get_str(ByteIOContext *pb, char *buf, int buf_size)
-{
- int len, i;
- char *q;
-
- len = get_be16(pb);
- q = buf;
- for(i=0;i<len;i++) {
- if (i < buf_size - 1)
- *q++ = get_byte(pb);
- }
- *q = '\0';
-}
-
-static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
-{
- int len, i;
- char *q;
-
- len = get_byte(pb);
- q = buf;
- for(i=0;i<len;i++) {
- if (i < buf_size - 1)
- *q++ = get_byte(pb);
- }
- *q = '\0';
-}
-
-static int rm_read_audio_stream_info(AVFormatContext *s, AVStream *st,
- int read_all)
-{
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- char buf[256];
- uint32_t version;
- int i;
-
- /* ra type header */
- version = get_be32(pb); /* version */
- if (((version >> 16) & 0xff) == 3) {
- int64_t startpos = url_ftell(pb);
- /* very old version */
- for(i = 0; i < 14; i++)
- get_byte(pb);
- get_str8(pb, s->title, sizeof(s->title));
- get_str8(pb, s->author, sizeof(s->author));
- get_str8(pb, s->copyright, sizeof(s->copyright));
- get_str8(pb, s->comment, sizeof(s->comment));
- if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) {
- // fourcc (should always be "lpcJ")
- get_byte(pb);
- get_str8(pb, buf, sizeof(buf));
- }
- // Skip extra header crap (this should never happen)
- if ((startpos + (version & 0xffff)) > url_ftell(pb))
- url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb));
- st->codec->sample_rate = 8000;
- st->codec->channels = 1;
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- st->codec->codec_id = CODEC_ID_RA_144;
- } else {
- int flavor, sub_packet_h, coded_framesize, sub_packet_size;
- /* old version (4) */
- get_be32(pb); /* .ra4 */
- get_be32(pb); /* data size */
- get_be16(pb); /* version2 */
- get_be32(pb); /* header size */
- flavor= get_be16(pb); /* add codec info / flavor */
- rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
- get_be32(pb); /* ??? */
- get_be32(pb); /* ??? */
- get_be32(pb); /* ??? */
- rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
- st->codec->block_align= get_be16(pb); /* frame size */
- rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
- get_be16(pb); /* ??? */
- if (((version >> 16) & 0xff) == 5) {
- get_be16(pb); get_be16(pb); get_be16(pb); }
- st->codec->sample_rate = get_be16(pb);
- get_be32(pb);
- st->codec->channels = get_be16(pb);
- if (((version >> 16) & 0xff) == 5) {
- get_be32(pb);
- buf[0] = get_byte(pb);
- buf[1] = get_byte(pb);
- buf[2] = get_byte(pb);
- buf[3] = get_byte(pb);
- buf[4] = 0;
- } else {
- get_str8(pb, buf, sizeof(buf)); /* desc */
- get_str8(pb, buf, sizeof(buf)); /* desc */
- }
- st->codec->codec_type = CODEC_TYPE_AUDIO;
- if (!strcmp(buf, "dnet")) {
- st->codec->codec_id = CODEC_ID_AC3;
- } else if (!strcmp(buf, "28_8")) {
- st->codec->codec_id = CODEC_ID_RA_288;
- st->codec->extradata_size= 0;
- rm->audio_framesize = st->codec->block_align;
- st->codec->block_align = coded_framesize;
-
- if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
- av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
- return -1;
- }
-
- rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
- } else if (!strcmp(buf, "cook")) {
- int codecdata_length, i;
- get_be16(pb); get_byte(pb);
- if (((version >> 16) & 0xff) == 5)
- get_byte(pb);
- codecdata_length = get_be32(pb);
- if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
- av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
- return -1;
- }
-
- st->codec->codec_id = CODEC_ID_COOK;
- st->codec->extradata_size= codecdata_length;
- st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- for(i = 0; i < codecdata_length; i++)
- ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
- rm->audio_framesize = st->codec->block_align;
- st->codec->block_align = rm->sub_packet_size;
-
- if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
- av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
- return -1;
- }
-
- rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
- } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) {
- int codecdata_length, i;
- get_be16(pb); get_byte(pb);
- if (((version >> 16) & 0xff) == 5)
- get_byte(pb);
- st->codec->codec_id = CODEC_ID_AAC;
- codecdata_length = get_be32(pb);
- if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
- av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
- return -1;
- }
- if (codecdata_length >= 1) {
- st->codec->extradata_size = codecdata_length - 1;
- st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- get_byte(pb);
- for(i = 0; i < st->codec->extradata_size; i++)
- ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
- }
- } else {
- st->codec->codec_id = CODEC_ID_NONE;
- pstrcpy(st->codec->codec_name, sizeof(st->codec->codec_name),
- buf);
- }
- if (read_all) {
- get_byte(pb);
- get_byte(pb);
- get_byte(pb);
-
- get_str8(pb, s->title, sizeof(s->title));
- get_str8(pb, s->author, sizeof(s->author));
- get_str8(pb, s->copyright, sizeof(s->copyright));
- get_str8(pb, s->comment, sizeof(s->comment));
- }
- }
- return 0;
-}
-
-static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
-{
- RMContext *rm = s->priv_data;
- AVStream *st;
-
- rm->old_format = 1;
- st = av_new_stream(s, 0);
- if (!st)
- return -1;
- return rm_read_audio_stream_info(s, st, 1);
-}
-
-static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
-{
- RMContext *rm = s->priv_data;
- AVStream *st;
- ByteIOContext *pb = &s->pb;
- unsigned int tag, v;
- int tag_size, size, codec_data_size, i;
- int64_t codec_pos;
- unsigned int start_time, duration;
- char buf[128];
- int flags = 0;
-
- tag = get_le32(pb);
- if (tag == MKTAG('.', 'r', 'a', 0xfd)) {
- /* very old .ra format */
- return rm_read_header_old(s, ap);
- } else if (tag != MKTAG('.', 'R', 'M', 'F')) {
- return AVERROR_IO;
- }
-
- get_be32(pb); /* header size */
- get_be16(pb);
- get_be32(pb);
- get_be32(pb); /* number of headers */
-
- for(;;) {
- if (url_feof(pb))
- goto fail;
- tag = get_le32(pb);
- tag_size = get_be32(pb);
- get_be16(pb);
-#if 0
- printf("tag=%c%c%c%c (%08x) size=%d\n",
- (tag) & 0xff,
- (tag >> 8) & 0xff,
- (tag >> 16) & 0xff,
- (tag >> 24) & 0xff,
- tag,
- tag_size);
-#endif
- if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
- goto fail;
- switch(tag) {
- case MKTAG('P', 'R', 'O', 'P'):
- /* file header */
- get_be32(pb); /* max bit rate */
- get_be32(pb); /* avg bit rate */
- get_be32(pb); /* max packet size */
- get_be32(pb); /* avg packet size */
- get_be32(pb); /* nb packets */
- get_be32(pb); /* duration */
- get_be32(pb); /* preroll */
- get_be32(pb); /* index offset */
- get_be32(pb); /* data offset */
- get_be16(pb); /* nb streams */
- flags = get_be16(pb); /* flags */
- break;
- case MKTAG('C', 'O', 'N', 'T'):
- get_str(pb, s->title, sizeof(s->title));
- get_str(pb, s->author, sizeof(s->author));
- get_str(pb, s->copyright, sizeof(s->copyright));
- get_str(pb, s->comment, sizeof(s->comment));
- break;
- case MKTAG('M', 'D', 'P', 'R'):
- st = av_new_stream(s, 0);
- if (!st)
- goto fail;
- st->id = get_be16(pb);
- get_be32(pb); /* max bit rate */
- st->codec->bit_rate = get_be32(pb); /* bit rate */
- get_be32(pb); /* max packet size */
- get_be32(pb); /* avg packet size */
- start_time = get_be32(pb); /* start time */
- get_be32(pb); /* preroll */
- duration = get_be32(pb); /* duration */
- st->start_time = start_time;
- st->duration = duration;
- get_str8(pb, buf, sizeof(buf)); /* desc */
- get_str8(pb, buf, sizeof(buf)); /* mimetype */
- codec_data_size = get_be32(pb);
- codec_pos = url_ftell(pb);
- st->codec->codec_type = CODEC_TYPE_DATA;
- av_set_pts_info(st, 64, 1, 1000);
-
- v = get_be32(pb);
- if (v == MKTAG(0xfd, 'a', 'r', '.')) {
- /* ra type header */
- if (rm_read_audio_stream_info(s, st, 0))
- return -1;
- } else {
- int fps, fps2;
- if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
- fail1:
- av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
- goto skip;
- }
- st->codec->codec_tag = get_le32(pb);
-// av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
- if ( st->codec->codec_tag != MKTAG('R', 'V', '1', '0')
- && st->codec->codec_tag != MKTAG('R', 'V', '2', '0')
- && st->codec->codec_tag != MKTAG('R', 'V', '3', '0')
- && st->codec->codec_tag != MKTAG('R', 'V', '4', '0'))
- goto fail1;
- st->codec->width = get_be16(pb);
- st->codec->height = get_be16(pb);
- st->codec->time_base.num= 1;
- fps= get_be16(pb);
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- get_be32(pb);
- fps2= get_be16(pb);
- get_be16(pb);
-
- st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);
-
- if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
- //check is redundant as get_buffer() will catch this
- av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n");
- return -1;
- }
- st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
-
-// av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
- st->codec->time_base.den = fps * st->codec->time_base.num;
- switch(((uint8_t*)st->codec->extradata)[4]>>4){
- case 1: st->codec->codec_id = CODEC_ID_RV10; break;
- case 2: st->codec->codec_id = CODEC_ID_RV20; break;
- case 3: st->codec->codec_id = CODEC_ID_RV30; break;
- case 4: st->codec->codec_id = CODEC_ID_RV40; break;
- default: goto fail1;
- }
- }
-skip:
- /* skip codec info */
- size = url_ftell(pb) - codec_pos;
- url_fskip(pb, codec_data_size - size);
- break;
- case MKTAG('D', 'A', 'T', 'A'):
- goto header_end;
- default:
- /* unknown tag: skip it */
- url_fskip(pb, tag_size - 10);
- break;
- }
- }
- header_end:
- rm->nb_packets = get_be32(pb); /* number of packets */
- if (!rm->nb_packets && (flags & 4))
- rm->nb_packets = 3600 * 25;
- get_be32(pb); /* next data header */
- return 0;
-
- fail:
- for(i=0;i<s->nb_streams;i++) {
- av_free(s->streams[i]);
- }
- return AVERROR_IO;
-}
-
-static int get_num(ByteIOContext *pb, int *len)
-{
- int n, n1;
-
- n = get_be16(pb);
- (*len)-=2;
- if (n >= 0x4000) {
- return n - 0x4000;
- } else {
- n1 = get_be16(pb);
- (*len)-=2;
- return (n << 16) | n1;
- }
-}
-
-/* multiple of 20 bytes for ra144 (ugly) */
-#define RAW_PACKET_SIZE 1000
-
-static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- int len, num, res, i;
- AVStream *st;
- uint32_t state=0xFFFFFFFF;
-
- while(!url_feof(pb)){
- *pos= url_ftell(pb);
- if(rm->remaining_len > 0){
- num= rm->current_stream;
- len= rm->remaining_len;
- *timestamp = AV_NOPTS_VALUE;
- *flags= 0;
- }else{
- state= (state<<8) + get_byte(pb);
-
- if(state == MKBETAG('I', 'N', 'D', 'X')){
- len = get_be16(pb) - 6;
- if(len<0)
- continue;
- goto skip;
- }
-
- if(state > (unsigned)0xFFFF || state < 12)
- continue;
- len=state;
- state= 0xFFFFFFFF;
-
- num = get_be16(pb);
- *timestamp = get_be32(pb);
- res= get_byte(pb); /* reserved */
- *flags = get_byte(pb); /* flags */
-
-
- len -= 12;
- }
- for(i=0;i<s->nb_streams;i++) {
- st = s->streams[i];
- if (num == st->id)
- break;
- }
- if (i == s->nb_streams) {
-skip:
- /* skip packet if unknown number */
- url_fskip(pb, len);
- rm->remaining_len -= len;
- continue;
- }
- *stream_index= i;
-
- return len;
- }
- return -1;
-}
-
-static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
-{
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- AVStream *st;
- int i, len, tmp, j;
- int64_t timestamp, pos;
- uint8_t *ptr;
- int flags;
-
- if (rm->audio_pkt_cnt) {
- // If there are queued audio packet return them first
- st = s->streams[rm->audio_stream_num];
- if (st->codec->codec_id == CODEC_ID_AAC)
- av_get_packet(pb, pkt, rm->sub_packet_lengths[rm->sub_packet_cnt - rm->audio_pkt_cnt]);
- else {
- av_new_packet(pkt, st->codec->block_align);
- memcpy(pkt->data, rm->audiobuf + st->codec->block_align *
- (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
- st->codec->block_align);
- }
- rm->audio_pkt_cnt--;
- pkt->flags = 0;
- pkt->stream_index = rm->audio_stream_num;
- } else if (rm->old_format) {
- st = s->streams[0];
- if (st->codec->codec_id == CODEC_ID_RA_288) {
- int x, y;
-
- for (y = 0; y < rm->sub_packet_h; y++)
- for (x = 0; x < rm->sub_packet_h/2; x++)
- if (get_buffer(pb, rm->audiobuf+x*2*rm->audio_framesize+y*rm->coded_framesize, rm->coded_framesize) <= 0)
- return AVERROR_IO;
- rm->audio_stream_num = 0;
- rm->audio_pkt_cnt = rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - 1;
- // Release first audio packet
- av_new_packet(pkt, st->codec->block_align);
- memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
- pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe
- pkt->stream_index = 0;
- } else {
- /* just read raw bytes */
- len = RAW_PACKET_SIZE;
- len= av_get_packet(pb, pkt, len);
- pkt->stream_index = 0;
- if (len <= 0) {
- return AVERROR_IO;
- }
- pkt->size = len;
- }
- } else {
- int seq=1;
-resync:
- len=sync(s, &timestamp, &flags, &i, &pos);
- if(len<0)
- return AVERROR_IO;
- st = s->streams[i];
-
- if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
- int h, pic_num, len2, pos;
-
- h= get_byte(pb); len--;
- if(!(h & 0x40)){
- seq = get_byte(pb); len--;
- }
-
- if((h & 0xc0) == 0x40){
- len2= pos= 0;
- }else{
- len2 = get_num(pb, &len);
- pos = get_num(pb, &len);
- }
- /* picture number */
- pic_num= get_byte(pb); len--;
- rm->remaining_len= len;
- rm->current_stream= st->id;
-
-// av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num);
- if(len2 && len2<len)
- len=len2;
- rm->remaining_len-= len;
- av_get_packet(pb, pkt, len);
-
- } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
- if ((st->codec->codec_id == CODEC_ID_RA_288) ||
- (st->codec->codec_id == CODEC_ID_COOK)) {
- int x;
- int sps = rm->sub_packet_size;
- int cfs = rm->coded_framesize;
- int h = rm->sub_packet_h;
- int y = rm->sub_packet_cnt;
- int w = rm->audio_framesize;
-
- if (flags & 2)
- y = rm->sub_packet_cnt = 0;
- if (!y)
- rm->audiotimestamp = timestamp;
-
- switch(st->codec->codec_id) {
- case CODEC_ID_RA_288:
- for (x = 0; x < h/2; x++)
- get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs);
- break;
- case CODEC_ID_COOK:
- for (x = 0; x < w/sps; x++)
- get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
- break;
- }
-
- if (++(rm->sub_packet_cnt) < h)
- goto resync;
- else {
- rm->sub_packet_cnt = 0;
- rm->audio_stream_num = i;
- rm->audio_pkt_cnt = h * w / st->codec->block_align - 1;
- // Release first audio packet
- av_new_packet(pkt, st->codec->block_align);
- memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
- timestamp = rm->audiotimestamp;
- flags = 2; // Mark first packet as keyframe
- }
- } else if (st->codec->codec_id == CODEC_ID_AAC) {
- int x;
- rm->audio_stream_num = i;
- rm->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4;
- if (rm->sub_packet_cnt) {
- for (x = 0; x < rm->sub_packet_cnt; x++)
- rm->sub_packet_lengths[x] = get_be16(pb);
- // Release first audio packet
- rm->audio_pkt_cnt = rm->sub_packet_cnt - 1;
- av_get_packet(pb, pkt, rm->sub_packet_lengths[0]);
- flags = 2; // Mark first packet as keyframe
- }
- } else
- av_get_packet(pb, pkt, len);
-
- } else
- av_get_packet(pb, pkt, len);
-
- if( (st->discard >= AVDISCARD_NONKEY && !(flags&2))
- || st->discard >= AVDISCARD_ALL){
- av_free_packet(pkt);
- goto resync;
- }
-
- pkt->stream_index = i;
-
-#if 0
- if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
- if(st->codec->codec_id == CODEC_ID_RV20){
- int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
- av_log(NULL, AV_LOG_DEBUG, "%d %"PRId64" %d\n", timestamp, timestamp*512LL/25, seq);
-
- seq |= (timestamp&~0x3FFF);
- if(seq - timestamp > 0x2000) seq -= 0x4000;
- if(seq - timestamp < -0x2000) seq += 0x4000;
- }
- }
-#endif
- pkt->pts= timestamp;
- if(flags&2){
- pkt->flags |= PKT_FLAG_KEY;
- if((seq&0x7F) == 1)
- av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
- }
- }
-
- /* for AC3, needs to swap bytes */
- if (st->codec->codec_id == CODEC_ID_AC3) {
- ptr = pkt->data;
- for(j=0;j<len;j+=2) {
- tmp = ptr[0];
- ptr[0] = ptr[1];
- ptr[1] = tmp;
- ptr += 2;
- }
- }
- return 0;
-}
-
-static int rm_read_close(AVFormatContext *s)
-{
- RMContext *rm = s->priv_data;
-
- av_free(rm->audiobuf);
- return 0;
-}
-
-static int rm_probe(AVProbeData *p)
-{
- /* check file header */
- if (p->buf_size <= 32)
- return 0;
- if ((p->buf[0] == '.' && p->buf[1] == 'R' &&
- p->buf[2] == 'M' && p->buf[3] == 'F' &&
- p->buf[4] == 0 && p->buf[5] == 0) ||
- (p->buf[0] == '.' && p->buf[1] == 'r' &&
- p->buf[2] == 'a' && p->buf[3] == 0xfd))
- return AVPROBE_SCORE_MAX;
- else
- return 0;
-}
-
-static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
- int64_t *ppos, int64_t pos_limit)
-{
- RMContext *rm = s->priv_data;
- int64_t pos, dts;
- int stream_index2, flags, len, h;
-
- pos = *ppos;
-
- if(rm->old_format)
- return AV_NOPTS_VALUE;
-
- url_fseek(&s->pb, pos, SEEK_SET);
- rm->remaining_len=0;
- for(;;){
- int seq=1;
- AVStream *st;
-
- len=sync(s, &dts, &flags, &stream_index2, &pos);
- if(len<0)
- return AV_NOPTS_VALUE;
-
- st = s->streams[stream_index2];
- if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
- h= get_byte(&s->pb); len--;
- if(!(h & 0x40)){
- seq = get_byte(&s->pb); len--;
- }
- }
-
- if((flags&2) && (seq&0x7F) == 1){
-// av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq);
- av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
- if(stream_index2 == stream_index)
- break;
- }
-
- url_fskip(&s->pb, len);
- }
- *ppos = pos;
- return dts;
-}
-
-#ifdef CONFIG_RM_DEMUXER
-AVInputFormat rm_demuxer = {
- "rm",
- "rm format",
- sizeof(RMContext),
- rm_probe,
- rm_read_header,
- rm_read_packet,
- rm_read_close,
- NULL,
- rm_read_dts,
-};
-#endif
-#ifdef CONFIG_RM_MUXER
-AVOutputFormat rm_muxer = {
- "rm",
- "rm format",
- "application/vnd.rn-realmedia",
- "rm,ra",
- sizeof(RMContext),
- CODEC_ID_AC3,
- CODEC_ID_RV10,
- rm_write_header,
- rm_write_packet,
- rm_write_trailer,
-};
-#endif
diff --git a/contrib/ffmpeg/libavformat/rm.h b/contrib/ffmpeg/libavformat/rm.h
new file mode 100644
index 000000000..2f7f8df2e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rm.h
@@ -0,0 +1,108 @@
+/*
+ * "Real" compatible muxer and demuxer.
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ *
+ * 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 FFMPEG_RM_H
+#define FFMPEG_RM_H
+
+#include "avformat.h"
+
+
+typedef struct {
+ int nb_packets;
+ int packet_total_size;
+ int packet_max_size;
+ /* codec related output */
+ int bit_rate;
+ float frame_rate;
+ int nb_frames; /* current frame number */
+ int total_frames; /* total number of frames */
+ int num;
+ AVCodecContext *enc;
+} StreamInfo;
+
+typedef struct {
+ StreamInfo streams[2];
+ StreamInfo *audio_stream, *video_stream;
+ int data_pos; /* position of the data after the header */
+ int nb_packets;
+ int old_format;
+ int current_stream;
+ int remaining_len;
+ uint8_t *videobuf; ///< place to store merged video frame
+ int videobufsize; ///< current assembled frame size
+ int videobufpos; ///< position for the next slice in the video buffer
+ int curpic_num; ///< picture number of current frame
+ int cur_slice, slices;
+ int64_t pktpos; ///< first slice position in file
+ /// Audio descrambling matrix parameters
+ uint8_t *audiobuf; ///< place to store reordered audio data
+ int64_t audiotimestamp; ///< Audio packet timestamp
+ int sub_packet_cnt; // Subpacket counter, used while reading
+ int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
+ int audio_stream_num; ///< Stream number for audio packets
+ int audio_pkt_cnt; ///< Output packet counter
+ int audio_framesize; /// Audio frame size from container
+ int sub_packet_lengths[16]; /// Length of each aac subpacket
+} RMContext;
+
+/**
+ * Read the MDPR chunk, which contains stream-specific codec initialization
+ * parameters.
+ *
+ * @param s context containing RMContext and ByteIOContext for stream reading
+ * @param st the stream that the MDPR chunk belongs to and where to store the
+ * parameters read from the chunk into
+ * @return 0 on success, errno codes on error
+ */
+int ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVStream *st);
+
+/**
+ * Parse one rm-stream packet from the input bytestream.
+ *
+ * @param s context containing RMContext and ByteIOContext for stream reading
+ * @param st stream to which the packet to be read belongs
+ * @param len packet length to read from the input
+ * @param pkt packet location to store the parsed packet data
+ * @param seq pointer to an integer containing the sequence number, may be
+ * updated
+ * @param flags pointer to an integer containing the packet flags, may be
+ updated
+ * @param ts pointer to timestamp, may be updated
+ * @return 0 on success, errno codes on error
+ */
+int ff_rm_parse_packet (AVFormatContext *s, AVStream *st, int len,
+ AVPacket *pkt, int *seq, int *flags, int64_t *ts);
+
+/**
+ * Retrieve one cached packet from the rm-context. The real container can
+ * store several packets (as interpreted by the codec) in a single container
+ * packet, which means the demuxer holds some back when the first container
+ * packet is parsed and returned. The result is that rm->audio_pkt_cnt is
+ * a positive number, the amount of cached packets. Using this function, each
+ * of those packets can be retrieved sequentially.
+ *
+ * @param s context containing RMContext and ByteIOContext for stream reading
+ * @param st stream that this packet belongs to
+ * @param pkt location to store the packet data
+ */
+void ff_rm_retrieve_cache (AVFormatContext *s, AVStream *st, AVPacket *pkt);
+
+#endif /* FFMPEG_RM_H */
diff --git a/contrib/ffmpeg/libavformat/rmdec.c b/contrib/ffmpeg/libavformat/rmdec.c
new file mode 100644
index 000000000..9a770cf4d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rmdec.c
@@ -0,0 +1,801 @@
+/*
+ * "Real" compatible demuxer.
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "rm.h"
+#include "avstring.h"
+
+static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len)
+{
+ int i;
+ char *q, r;
+
+ q = buf;
+ for(i=0;i<len;i++) {
+ r = get_byte(pb);
+ if (i < buf_size - 1)
+ *q++ = r;
+ }
+ if (buf_size > 0) *q = '\0';
+}
+
+static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
+{
+ get_strl(pb, buf, buf_size, get_be16(pb));
+}
+
+static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
+{
+ get_strl(pb, buf, buf_size, get_byte(pb));
+}
+
+static int rm_read_audio_stream_info(AVFormatContext *s, AVStream *st,
+ int read_all)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ char buf[256];
+ uint32_t version;
+ int i;
+
+ /* ra type header */
+ version = get_be32(pb); /* version */
+ if (((version >> 16) & 0xff) == 3) {
+ int64_t startpos = url_ftell(pb);
+ /* very old version */
+ for(i = 0; i < 14; i++)
+ get_byte(pb);
+ get_str8(pb, s->title, sizeof(s->title));
+ get_str8(pb, s->author, sizeof(s->author));
+ get_str8(pb, s->copyright, sizeof(s->copyright));
+ get_str8(pb, s->comment, sizeof(s->comment));
+ if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) {
+ // fourcc (should always be "lpcJ")
+ get_byte(pb);
+ get_str8(pb, buf, sizeof(buf));
+ }
+ // Skip extra header crap (this should never happen)
+ if ((startpos + (version & 0xffff)) > url_ftell(pb))
+ url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb));
+ st->codec->sample_rate = 8000;
+ st->codec->channels = 1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_RA_144;
+ } else {
+ int flavor, sub_packet_h, coded_framesize, sub_packet_size;
+ /* old version (4) */
+ get_be32(pb); /* .ra4 */
+ get_be32(pb); /* data size */
+ get_be16(pb); /* version2 */
+ get_be32(pb); /* header size */
+ flavor= get_be16(pb); /* add codec info / flavor */
+ rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
+ st->codec->block_align= get_be16(pb); /* frame size */
+ rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
+ get_be16(pb); /* ??? */
+ if (((version >> 16) & 0xff) == 5) {
+ get_be16(pb); get_be16(pb); get_be16(pb); }
+ st->codec->sample_rate = get_be16(pb);
+ get_be32(pb);
+ st->codec->channels = get_be16(pb);
+ if (((version >> 16) & 0xff) == 5) {
+ get_be32(pb);
+ buf[0] = get_byte(pb);
+ buf[1] = get_byte(pb);
+ buf[2] = get_byte(pb);
+ buf[3] = get_byte(pb);
+ buf[4] = 0;
+ } else {
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ }
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ if (!strcmp(buf, "dnet")) {
+ st->codec->codec_id = CODEC_ID_AC3;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ } else if (!strcmp(buf, "28_8")) {
+ st->codec->codec_id = CODEC_ID_RA_288;
+ st->codec->extradata_size= 0;
+ rm->audio_framesize = st->codec->block_align;
+ st->codec->block_align = coded_framesize;
+
+ if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
+ av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
+ return -1;
+ }
+
+ rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
+ } else if ((!strcmp(buf, "cook")) || (!strcmp(buf, "atrc"))) {
+ int codecdata_length, i;
+ get_be16(pb); get_byte(pb);
+ if (((version >> 16) & 0xff) == 5)
+ get_byte(pb);
+ codecdata_length = get_be32(pb);
+ if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
+ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
+ return -1;
+ }
+
+ if (!strcmp(buf, "cook")) st->codec->codec_id = CODEC_ID_COOK;
+ else st->codec->codec_id = CODEC_ID_ATRAC3;
+ st->codec->extradata_size= codecdata_length;
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ for(i = 0; i < codecdata_length; i++)
+ ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
+ rm->audio_framesize = st->codec->block_align;
+ st->codec->block_align = rm->sub_packet_size;
+
+ if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
+ av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
+ return -1;
+ }
+
+ rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
+ } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) {
+ int codecdata_length, i;
+ get_be16(pb); get_byte(pb);
+ if (((version >> 16) & 0xff) == 5)
+ get_byte(pb);
+ st->codec->codec_id = CODEC_ID_AAC;
+ codecdata_length = get_be32(pb);
+ if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
+ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
+ return -1;
+ }
+ if (codecdata_length >= 1) {
+ st->codec->extradata_size = codecdata_length - 1;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_byte(pb);
+ for(i = 0; i < st->codec->extradata_size; i++)
+ ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
+ }
+ } else {
+ st->codec->codec_id = CODEC_ID_NONE;
+ av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name));
+ }
+ if (read_all) {
+ get_byte(pb);
+ get_byte(pb);
+ get_byte(pb);
+
+ get_str8(pb, s->title, sizeof(s->title));
+ get_str8(pb, s->author, sizeof(s->author));
+ get_str8(pb, s->copyright, sizeof(s->copyright));
+ get_str8(pb, s->comment, sizeof(s->comment));
+ }
+ }
+ return 0;
+}
+
+int
+ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVStream *st)
+{
+ ByteIOContext *pb = s->pb;
+ unsigned int v;
+ int codec_data_size, size;
+ int64_t codec_pos;
+
+ codec_data_size = get_be32(pb);
+ codec_pos = url_ftell(pb);
+ v = get_be32(pb);
+ if (v == MKTAG(0xfd, 'a', 'r', '.')) {
+ /* ra type header */
+ if (rm_read_audio_stream_info(s, st, 0))
+ return -1;
+ } else {
+ int fps, fps2;
+ if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
+ fail1:
+ av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
+ goto skip;
+ }
+ st->codec->codec_tag = get_le32(pb);
+// av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
+ if ( st->codec->codec_tag != MKTAG('R', 'V', '1', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '2', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '3', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '4', '0'))
+ goto fail1;
+ st->codec->width = get_be16(pb);
+ st->codec->height = get_be16(pb);
+ st->codec->time_base.num= 1;
+ fps= get_be16(pb);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ get_be32(pb);
+ fps2= get_be16(pb);
+ get_be16(pb);
+
+ st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);
+
+ if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
+ //check is redundant as get_buffer() will catch this
+ av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n");
+ return -1;
+ }
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+
+// av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
+ st->codec->time_base.den = fps * st->codec->time_base.num;
+ switch(((uint8_t*)st->codec->extradata)[4]>>4){
+ case 1: st->codec->codec_id = CODEC_ID_RV10; break;
+ case 2: st->codec->codec_id = CODEC_ID_RV20; break;
+ case 3: st->codec->codec_id = CODEC_ID_RV30; break;
+ case 4: st->codec->codec_id = CODEC_ID_RV40; break;
+ default: goto fail1;
+ }
+ }
+
+skip:
+ /* skip codec info */
+ size = url_ftell(pb) - codec_pos;
+ url_fskip(pb, codec_data_size - size);
+
+ return 0;
+}
+
+
+static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
+{
+ RMContext *rm = s->priv_data;
+ AVStream *st;
+
+ rm->old_format = 1;
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ return rm_read_audio_stream_info(s, st, 1);
+}
+
+static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ RMContext *rm = s->priv_data;
+ AVStream *st;
+ ByteIOContext *pb = s->pb;
+ unsigned int tag;
+ int tag_size, i;
+ unsigned int start_time, duration;
+ char buf[128];
+ int flags = 0;
+
+ tag = get_le32(pb);
+ if (tag == MKTAG('.', 'r', 'a', 0xfd)) {
+ /* very old .ra format */
+ return rm_read_header_old(s, ap);
+ } else if (tag != MKTAG('.', 'R', 'M', 'F')) {
+ return AVERROR(EIO);
+ }
+
+ get_be32(pb); /* header size */
+ get_be16(pb);
+ get_be32(pb);
+ get_be32(pb); /* number of headers */
+
+ for(;;) {
+ if (url_feof(pb))
+ goto fail;
+ tag = get_le32(pb);
+ tag_size = get_be32(pb);
+ get_be16(pb);
+#if 0
+ printf("tag=%c%c%c%c (%08x) size=%d\n",
+ (tag) & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ tag,
+ tag_size);
+#endif
+ if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
+ goto fail;
+ switch(tag) {
+ case MKTAG('P', 'R', 'O', 'P'):
+ /* file header */
+ get_be32(pb); /* max bit rate */
+ get_be32(pb); /* avg bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ get_be32(pb); /* nb packets */
+ get_be32(pb); /* duration */
+ get_be32(pb); /* preroll */
+ get_be32(pb); /* index offset */
+ get_be32(pb); /* data offset */
+ get_be16(pb); /* nb streams */
+ flags = get_be16(pb); /* flags */
+ break;
+ case MKTAG('C', 'O', 'N', 'T'):
+ get_str16(pb, s->title, sizeof(s->title));
+ get_str16(pb, s->author, sizeof(s->author));
+ get_str16(pb, s->copyright, sizeof(s->copyright));
+ get_str16(pb, s->comment, sizeof(s->comment));
+ break;
+ case MKTAG('M', 'D', 'P', 'R'):
+ st = av_new_stream(s, 0);
+ if (!st)
+ goto fail;
+ st->id = get_be16(pb);
+ get_be32(pb); /* max bit rate */
+ st->codec->bit_rate = get_be32(pb); /* bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ start_time = get_be32(pb); /* start time */
+ get_be32(pb); /* preroll */
+ duration = get_be32(pb); /* duration */
+ st->start_time = start_time;
+ st->duration = duration;
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* mimetype */
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ av_set_pts_info(st, 64, 1, 1000);
+ if (ff_rm_read_mdpr_codecdata(s, st) < 0)
+ return -1;
+ break;
+ case MKTAG('D', 'A', 'T', 'A'):
+ goto header_end;
+ default:
+ /* unknown tag: skip it */
+ url_fskip(pb, tag_size - 10);
+ break;
+ }
+ }
+ header_end:
+ rm->nb_packets = get_be32(pb); /* number of packets */
+ if (!rm->nb_packets && (flags & 4))
+ rm->nb_packets = 3600 * 25;
+ get_be32(pb); /* next data header */
+ rm->curpic_num = -1;
+ return 0;
+
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ av_free(s->streams[i]);
+ }
+ return AVERROR(EIO);
+}
+
+static int get_num(ByteIOContext *pb, int *len)
+{
+ int n, n1;
+
+ n = get_be16(pb);
+ (*len)-=2;
+ n &= 0x7FFF;
+ if (n >= 0x4000) {
+ return n - 0x4000;
+ } else {
+ n1 = get_be16(pb);
+ (*len)-=2;
+ return (n << 16) | n1;
+ }
+}
+
+/* multiple of 20 bytes for ra144 (ugly) */
+#define RAW_PACKET_SIZE 1000
+
+static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int len, num, res, i;
+ AVStream *st;
+ uint32_t state=0xFFFFFFFF;
+
+ while(!url_feof(pb)){
+ *pos= url_ftell(pb);
+ if(rm->remaining_len > 0){
+ num= rm->current_stream;
+ len= rm->remaining_len;
+ *timestamp = AV_NOPTS_VALUE;
+ *flags= 0;
+ }else{
+ state= (state<<8) + get_byte(pb);
+
+ if(state == MKBETAG('I', 'N', 'D', 'X')){
+ len = get_be16(pb) - 6;
+ if(len<0)
+ continue;
+ goto skip;
+ }
+
+ if(state > (unsigned)0xFFFF || state < 12)
+ continue;
+ len=state;
+ state= 0xFFFFFFFF;
+
+ num = get_be16(pb);
+ *timestamp = get_be32(pb);
+ res= get_byte(pb); /* reserved */
+ *flags = get_byte(pb); /* flags */
+
+
+ len -= 12;
+ }
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (num == st->id)
+ break;
+ }
+ if (i == s->nb_streams) {
+skip:
+ /* skip packet if unknown number */
+ url_fskip(pb, len);
+ rm->remaining_len -= len;
+ continue;
+ }
+ *stream_index= i;
+
+ return len;
+ }
+ return -1;
+}
+
+static int rm_assemble_video_frame(AVFormatContext *s, RMContext *rm, AVPacket *pkt, int len)
+{
+ ByteIOContext *pb = s->pb;
+ int hdr, seq, pic_num, len2, pos;
+ int type;
+
+ hdr = get_byte(pb); len--;
+ type = hdr >> 6;
+ switch(type){
+ case 0: // slice
+ case 2: // last slice
+ seq = get_byte(pb); len--;
+ len2 = get_num(pb, &len);
+ pos = get_num(pb, &len);
+ pic_num = get_byte(pb); len--;
+ rm->remaining_len = len;
+ break;
+ case 1: //whole frame
+ seq = get_byte(pb); len--;
+ if(av_new_packet(pkt, len + 9) < 0)
+ return AVERROR(EIO);
+ pkt->data[0] = 0;
+ AV_WL32(pkt->data + 1, 1);
+ AV_WL32(pkt->data + 5, 0);
+ get_buffer(pb, pkt->data + 9, len);
+ rm->remaining_len = 0;
+ return 0;
+ case 3: //frame as a part of packet
+ len2 = get_num(pb, &len);
+ pos = get_num(pb, &len);
+ pic_num = get_byte(pb); len--;
+ rm->remaining_len = len - len2;
+ if(av_new_packet(pkt, len2 + 9) < 0)
+ return AVERROR(EIO);
+ pkt->data[0] = 0;
+ AV_WL32(pkt->data + 1, 1);
+ AV_WL32(pkt->data + 5, 0);
+ get_buffer(pb, pkt->data + 9, len2);
+ return 0;
+ }
+ //now we have to deal with single slice
+
+ if((seq & 0x7F) == 1 || rm->curpic_num != pic_num){
+ rm->slices = ((hdr & 0x3F) << 1) + 1;
+ rm->videobufsize = len2 + 8*rm->slices + 1;
+ av_free(rm->videobuf);
+ if(!(rm->videobuf = av_malloc(rm->videobufsize)))
+ return AVERROR(ENOMEM);
+ rm->videobufpos = 8*rm->slices + 1;
+ rm->cur_slice = 0;
+ rm->curpic_num = pic_num;
+ rm->pktpos = url_ftell(pb);
+ }
+ if(type == 2)
+ len = FFMIN(len, pos);
+
+ if(++rm->cur_slice > rm->slices)
+ return 1;
+ AV_WL32(rm->videobuf - 7 + 8*rm->cur_slice, 1);
+ AV_WL32(rm->videobuf - 3 + 8*rm->cur_slice, rm->videobufpos - 8*rm->slices - 1);
+ if(rm->videobufpos + len > rm->videobufsize)
+ return 1;
+ if (get_buffer(pb, rm->videobuf + rm->videobufpos, len) != len)
+ return AVERROR(EIO);
+ rm->videobufpos += len;
+ rm->remaining_len-= len;
+
+ if(type == 2 || (rm->videobufpos) == rm->videobufsize){
+ rm->videobuf[0] = rm->cur_slice-1;
+ if(av_new_packet(pkt, rm->videobufpos - 8*(rm->slices - rm->cur_slice)) < 0)
+ return AVERROR(ENOMEM);
+ memcpy(pkt->data, rm->videobuf, 1 + 8*rm->cur_slice);
+ memcpy(pkt->data + 1 + 8*rm->cur_slice, rm->videobuf + 1 + 8*rm->slices,
+ rm->videobufpos - 1 - 8*rm->slices);
+ pkt->pts = AV_NOPTS_VALUE;
+ pkt->pos = rm->pktpos;
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline void
+rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt)
+{
+ uint8_t *ptr;
+ int j;
+
+ if (st->codec->codec_id == CODEC_ID_AC3) {
+ ptr = pkt->data;
+ for (j=0;j<pkt->size;j+=2) {
+ FFSWAP(int, ptr[0], ptr[1]);
+ ptr += 2;
+ }
+ }
+}
+
+int
+ff_rm_parse_packet (AVFormatContext *s, AVStream *st, int len, AVPacket *pkt,
+ int *seq, int *flags, int64_t *timestamp)
+{
+ ByteIOContext *pb = s->pb;
+ RMContext *rm = s->priv_data;
+
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ rm->current_stream= st->id;
+ if(rm_assemble_video_frame(s, rm, pkt, len) == 1)
+ return -1; //got partial frame
+ } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if ((st->codec->codec_id == CODEC_ID_RA_288) ||
+ (st->codec->codec_id == CODEC_ID_COOK) ||
+ (st->codec->codec_id == CODEC_ID_ATRAC3)) {
+ int x;
+ int sps = rm->sub_packet_size;
+ int cfs = rm->coded_framesize;
+ int h = rm->sub_packet_h;
+ int y = rm->sub_packet_cnt;
+ int w = rm->audio_framesize;
+
+ if (*flags & 2)
+ y = rm->sub_packet_cnt = 0;
+ if (!y)
+ rm->audiotimestamp = *timestamp;
+
+ switch(st->codec->codec_id) {
+ case CODEC_ID_RA_288:
+ for (x = 0; x < h/2; x++)
+ get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs);
+ break;
+ case CODEC_ID_ATRAC3:
+ case CODEC_ID_COOK:
+ for (x = 0; x < w/sps; x++)
+ get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
+ break;
+ }
+
+ if (++(rm->sub_packet_cnt) < h)
+ return -1;
+ else {
+ rm->sub_packet_cnt = 0;
+ rm->audio_stream_num = st->index;
+ rm->audio_pkt_cnt = h * w / st->codec->block_align - 1;
+ // Release first audio packet
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
+ *timestamp = rm->audiotimestamp;
+ *flags = 2; // Mark first packet as keyframe
+ }
+ } else if (st->codec->codec_id == CODEC_ID_AAC) {
+ int x;
+ rm->audio_stream_num = st->index;
+ rm->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4;
+ if (rm->sub_packet_cnt) {
+ for (x = 0; x < rm->sub_packet_cnt; x++)
+ rm->sub_packet_lengths[x] = get_be16(pb);
+ // Release first audio packet
+ rm->audio_pkt_cnt = rm->sub_packet_cnt - 1;
+ av_get_packet(pb, pkt, rm->sub_packet_lengths[0]);
+ *flags = 2; // Mark first packet as keyframe
+ }
+ } else {
+ av_get_packet(pb, pkt, len);
+ rm_ac3_swap_bytes(st, pkt);
+ }
+ } else
+ av_get_packet(pb, pkt, len);
+
+ if( (st->discard >= AVDISCARD_NONKEY && !(*flags&2))
+ || st->discard >= AVDISCARD_ALL){
+ av_free_packet(pkt);
+ return -1;
+ }
+
+ pkt->stream_index = st->index;
+
+#if 0
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ if(st->codec->codec_id == CODEC_ID_RV20){
+ int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
+ av_log(NULL, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq);
+
+ seq |= (*timestamp&~0x3FFF);
+ if(seq - *timestamp > 0x2000) seq -= 0x4000;
+ if(seq - *timestamp < -0x2000) seq += 0x4000;
+ }
+ }
+#endif
+
+ pkt->pts= *timestamp;
+ if (*flags & 2)
+ pkt->flags |= PKT_FLAG_KEY;
+
+ return 0;
+}
+
+void
+ff_rm_retrieve_cache (AVFormatContext *s, AVStream *st, AVPacket *pkt)
+{
+ ByteIOContext *pb = s->pb;
+ RMContext *rm = s->priv_data;
+
+ assert (rm->audio_pkt_cnt > 0);
+
+ if (st->codec->codec_id == CODEC_ID_AAC)
+ av_get_packet(pb, pkt, rm->sub_packet_lengths[rm->sub_packet_cnt - rm->audio_pkt_cnt]);
+ else {
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf + st->codec->block_align *
+ (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
+ st->codec->block_align);
+ }
+ rm->audio_pkt_cnt--;
+ pkt->flags = 0;
+ pkt->stream_index = st->index;
+}
+
+static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVStream *st;
+ int i, len;
+ int64_t timestamp, pos;
+ int flags;
+
+ if (rm->audio_pkt_cnt) {
+ // If there are queued audio packet return them first
+ st = s->streams[rm->audio_stream_num];
+ ff_rm_retrieve_cache(s, st, pkt);
+ } else if (rm->old_format) {
+ st = s->streams[0];
+ if (st->codec->codec_id == CODEC_ID_RA_288) {
+ int x, y;
+
+ for (y = 0; y < rm->sub_packet_h; y++)
+ for (x = 0; x < rm->sub_packet_h/2; x++)
+ if (get_buffer(pb, rm->audiobuf+x*2*rm->audio_framesize+y*rm->coded_framesize, rm->coded_framesize) <= 0)
+ return AVERROR(EIO);
+ rm->audio_stream_num = 0;
+ rm->audio_pkt_cnt = rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - 1;
+ // Release first audio packet
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
+ pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe
+ pkt->stream_index = 0;
+ } else {
+ /* just read raw bytes */
+ len = RAW_PACKET_SIZE;
+ len= av_get_packet(pb, pkt, len);
+ pkt->stream_index = 0;
+ if (len <= 0) {
+ return AVERROR(EIO);
+ }
+ pkt->size = len;
+ }
+ rm_ac3_swap_bytes(st, pkt);
+ } else {
+ int seq=1;
+resync:
+ len=sync(s, &timestamp, &flags, &i, &pos);
+ if(len<0)
+ return AVERROR(EIO);
+ st = s->streams[i];
+
+ if (ff_rm_parse_packet (s, st, len, pkt, &seq, &flags, &timestamp) < 0)
+ goto resync;
+
+ if((flags&2) && (seq&0x7F) == 1)
+ av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
+ }
+
+ return 0;
+}
+
+static int rm_read_close(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+
+ av_free(rm->audiobuf);
+ av_free(rm->videobuf);
+ return 0;
+}
+
+static int rm_probe(AVProbeData *p)
+{
+ /* check file header */
+ if ((p->buf[0] == '.' && p->buf[1] == 'R' &&
+ p->buf[2] == 'M' && p->buf[3] == 'F' &&
+ p->buf[4] == 0 && p->buf[5] == 0) ||
+ (p->buf[0] == '.' && p->buf[1] == 'r' &&
+ p->buf[2] == 'a' && p->buf[3] == 0xfd))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ RMContext *rm = s->priv_data;
+ int64_t pos, dts;
+ int stream_index2, flags, len, h;
+
+ pos = *ppos;
+
+ if(rm->old_format)
+ return AV_NOPTS_VALUE;
+
+ url_fseek(s->pb, pos, SEEK_SET);
+ rm->remaining_len=0;
+ for(;;){
+ int seq=1;
+ AVStream *st;
+
+ len=sync(s, &dts, &flags, &stream_index2, &pos);
+ if(len<0)
+ return AV_NOPTS_VALUE;
+
+ st = s->streams[stream_index2];
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ h= get_byte(s->pb); len--;
+ if(!(h & 0x40)){
+ seq = get_byte(s->pb); len--;
+ }
+ }
+
+ if((flags&2) && (seq&0x7F) == 1){
+// av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq);
+ av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
+ if(stream_index2 == stream_index)
+ break;
+ }
+
+ url_fskip(s->pb, len);
+ }
+ *ppos = pos;
+ return dts;
+}
+
+AVInputFormat rm_demuxer = {
+ "rm",
+ "rm format",
+ sizeof(RMContext),
+ rm_probe,
+ rm_read_header,
+ rm_read_packet,
+ rm_read_close,
+ NULL,
+ rm_read_dts,
+};
diff --git a/contrib/ffmpeg/libavformat/rmenc.c b/contrib/ffmpeg/libavformat/rmenc.c
new file mode 100644
index 000000000..3a3525d96
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rmenc.c
@@ -0,0 +1,444 @@
+/*
+ * "Real" compatible muxer.
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "rm.h"
+
+/* in ms */
+#define BUFFER_DURATION 0
+
+
+static void put_str(ByteIOContext *s, const char *tag)
+{
+ put_be16(s,strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void put_str8(ByteIOContext *s, const char *tag)
+{
+ put_byte(s, strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void rv10_write_header(AVFormatContext *ctx,
+ int data_size, int index_pos)
+{
+ RMContext *rm = ctx->priv_data;
+ ByteIOContext *s = ctx->pb;
+ StreamInfo *stream;
+ unsigned char *data_offset_ptr, *start_ptr;
+ const char *desc, *mimetype;
+ int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
+ int bit_rate, v, duration, flags, data_pos;
+
+ start_ptr = s->buf_ptr;
+
+ put_tag(s, ".RMF");
+ put_be32(s,18); /* header size */
+ put_be16(s,0);
+ put_be32(s,0);
+ put_be32(s,4 + ctx->nb_streams); /* num headers */
+
+ put_tag(s,"PROP");
+ put_be32(s, 50);
+ put_be16(s, 0);
+ packet_max_size = 0;
+ packet_total_size = 0;
+ nb_packets = 0;
+ bit_rate = 0;
+ duration = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = &rm->streams[i];
+ bit_rate += stream->bit_rate;
+ if (stream->packet_max_size > packet_max_size)
+ packet_max_size = stream->packet_max_size;
+ nb_packets += stream->nb_packets;
+ packet_total_size += stream->packet_total_size;
+ /* select maximum duration */
+ v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
+ if (v > duration)
+ duration = v;
+ }
+ put_be32(s, bit_rate); /* max bit rate */
+ put_be32(s, bit_rate); /* avg bit rate */
+ put_be32(s, packet_max_size); /* max packet size */
+ if (nb_packets > 0)
+ packet_avg_size = packet_total_size / nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, nb_packets); /* num packets */
+ put_be32(s, duration); /* duration */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ put_be32(s, index_pos); /* index offset */
+ /* computation of data the data offset */
+ data_offset_ptr = s->buf_ptr;
+ put_be32(s, 0); /* data offset : will be patched after */
+ put_be16(s, ctx->nb_streams); /* num streams */
+ flags = 1 | 2; /* save allowed & perfect play */
+ if (url_is_streamed(s))
+ flags |= 4; /* live broadcast */
+ put_be16(s, flags);
+
+ /* comments */
+
+ put_tag(s,"CONT");
+ size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
+ strlen(ctx->comment) + 4 * 2 + 10;
+ put_be32(s,size);
+ put_be16(s,0);
+ put_str(s, ctx->title);
+ put_str(s, ctx->author);
+ put_str(s, ctx->copyright);
+ put_str(s, ctx->comment);
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ int codec_data_size;
+
+ stream = &rm->streams[i];
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ desc = "The Audio Stream";
+ mimetype = "audio/x-pn-realaudio";
+ codec_data_size = 73;
+ } else {
+ desc = "The Video Stream";
+ mimetype = "video/x-pn-realvideo";
+ codec_data_size = 34;
+ }
+
+ put_tag(s,"MDPR");
+ size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
+ put_be32(s, size);
+ put_be16(s, 0);
+
+ put_be16(s, i); /* stream number */
+ put_be32(s, stream->bit_rate); /* max bit rate */
+ put_be32(s, stream->bit_rate); /* avg bit rate */
+ put_be32(s, stream->packet_max_size); /* max packet size */
+ if (stream->nb_packets > 0)
+ packet_avg_size = stream->packet_total_size /
+ stream->nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, 0); /* start time */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ /* duration */
+ if (url_is_streamed(s) || !stream->total_frames)
+ put_be32(s, (int)(3600 * 1000));
+ else
+ put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
+ put_str8(s, desc);
+ put_str8(s, mimetype);
+ put_be32(s, codec_data_size);
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ int coded_frame_size, fscode, sample_rate;
+ sample_rate = stream->enc->sample_rate;
+ coded_frame_size = (stream->enc->bit_rate *
+ stream->enc->frame_size) / (8 * sample_rate);
+ /* audio codec info */
+ put_tag(s, ".ra");
+ put_byte(s, 0xfd);
+ put_be32(s, 0x00040000); /* version */
+ put_tag(s, ".ra4");
+ put_be32(s, 0x01b53530); /* stream length */
+ put_be16(s, 4); /* unknown */
+ put_be32(s, 0x39); /* header size */
+
+ switch(sample_rate) {
+ case 48000:
+ case 24000:
+ case 12000:
+ fscode = 1;
+ break;
+ default:
+ case 44100:
+ case 22050:
+ case 11025:
+ fscode = 2;
+ break;
+ case 32000:
+ case 16000:
+ case 8000:
+ fscode = 3;
+ }
+ put_be16(s, fscode); /* codec additional info, for AC3, seems
+ to be a frequency code */
+ /* special hack to compensate rounding errors... */
+ if (coded_frame_size == 557)
+ coded_frame_size--;
+ put_be32(s, coded_frame_size); /* frame length */
+ put_be32(s, 0x51540); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be16(s, 0x01);
+ /* frame length : seems to be very important */
+ put_be16(s, coded_frame_size);
+ put_be32(s, 0); /* unknown */
+ put_be16(s, stream->enc->sample_rate); /* sample rate */
+ put_be32(s, 0x10); /* unknown */
+ put_be16(s, stream->enc->channels);
+ put_str8(s, "Int0"); /* codec name */
+ put_str8(s, "dnet"); /* codec name */
+ put_be16(s, 0); /* title length */
+ put_be16(s, 0); /* author length */
+ put_be16(s, 0); /* copyright length */
+ put_byte(s, 0); /* end of header */
+ } else {
+ /* video codec info */
+ put_be32(s,34); /* size */
+ if(stream->enc->codec_id == CODEC_ID_RV10)
+ put_tag(s,"VIDORV10");
+ else
+ put_tag(s,"VIDORV20");
+ put_be16(s, stream->enc->width);
+ put_be16(s, stream->enc->height);
+ put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, (int) stream->frame_rate); /* unknown meaning */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, 8); /* unknown meaning */
+ /* Seems to be the codec version: only use basic H263. The next
+ versions seems to add a diffential DC coding as in
+ MPEG... nothing new under the sun */
+ if(stream->enc->codec_id == CODEC_ID_RV10)
+ put_be32(s,0x10000000);
+ else
+ put_be32(s,0x20103001);
+ //put_be32(s,0x10003000);
+ }
+ }
+
+ /* patch data offset field */
+ data_pos = s->buf_ptr - start_ptr;
+ rm->data_pos = data_pos;
+ data_offset_ptr[0] = data_pos >> 24;
+ data_offset_ptr[1] = data_pos >> 16;
+ data_offset_ptr[2] = data_pos >> 8;
+ data_offset_ptr[3] = data_pos;
+
+ /* data stream */
+ put_tag(s,"DATA");
+ put_be32(s,data_size + 10 + 8);
+ put_be16(s,0);
+
+ put_be32(s, nb_packets); /* number of packets */
+ put_be32(s,0); /* next data header */
+}
+
+static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
+ int length, int key_frame)
+{
+ int timestamp;
+ ByteIOContext *s = ctx->pb;
+
+ stream->nb_packets++;
+ stream->packet_total_size += length;
+ if (length > stream->packet_max_size)
+ stream->packet_max_size = length;
+
+ put_be16(s,0); /* version */
+ put_be16(s,length + 12);
+ put_be16(s, stream->num); /* stream number */
+ timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
+ put_be32(s, timestamp); /* timestamp */
+ put_byte(s, 0); /* reserved */
+ put_byte(s, key_frame ? 2 : 0); /* flags */
+}
+
+static int rm_write_header(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ StreamInfo *stream;
+ int n;
+ AVCodecContext *codec;
+
+ for(n=0;n<s->nb_streams;n++) {
+ s->streams[n]->id = n;
+ codec = s->streams[n]->codec;
+ stream = &rm->streams[n];
+ memset(stream, 0, sizeof(StreamInfo));
+ stream->num = n;
+ stream->bit_rate = codec->bit_rate;
+ stream->enc = codec;
+
+ switch(codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ rm->audio_stream = stream;
+ stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
+ /* XXX: dummy values */
+ stream->packet_max_size = 1024;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ case CODEC_TYPE_VIDEO:
+ rm->video_stream = stream;
+ stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
+ /* XXX: dummy values */
+ stream->packet_max_size = 4096;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ rv10_write_header(s, 0, 0);
+ put_flush_packet(s->pb);
+ return 0;
+}
+
+static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
+{
+ uint8_t *buf1;
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ StreamInfo *stream = rm->audio_stream;
+ int i;
+
+ /* XXX: suppress this malloc */
+ buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
+
+ write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY));
+
+ /* for AC3, the words seems to be reversed */
+ for(i=0;i<size;i+=2) {
+ buf1[i] = buf[i+1];
+ buf1[i+1] = buf[i];
+ }
+ put_buffer(pb, buf1, size);
+ put_flush_packet(pb);
+ stream->nb_frames++;
+ av_free(buf1);
+ return 0;
+}
+
+static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ StreamInfo *stream = rm->video_stream;
+ int key_frame = !!(flags & PKT_FLAG_KEY);
+
+ /* XXX: this is incorrect: should be a parameter */
+
+ /* Well, I spent some time finding the meaning of these bits. I am
+ not sure I understood everything, but it works !! */
+#if 1
+ write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame);
+ /* bit 7: '1' if final packet of a frame converted in several packets */
+ put_byte(pb, 0x81);
+ /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
+ frame starting from 1 */
+ if (key_frame) {
+ put_byte(pb, 0x81);
+ } else {
+ put_byte(pb, 0x01);
+ }
+ if(size >= 0x4000){
+ put_be32(pb, size); /* total frame size */
+ put_be32(pb, size); /* offset from the start or the end */
+ }else{
+ put_be16(pb, 0x4000 | size); /* total frame size */
+ put_be16(pb, 0x4000 | size); /* offset from the start or the end */
+ }
+#else
+ /* full frame */
+ write_packet_header(s, size + 6);
+ put_byte(pb, 0xc0);
+ put_be16(pb, 0x4000 + size); /* total frame size */
+ put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */
+#endif
+ put_byte(pb, stream->nb_frames & 0xff);
+
+ put_buffer(pb, buf, size);
+ put_flush_packet(pb);
+
+ stream->nb_frames++;
+ return 0;
+}
+
+static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ if (s->streams[pkt->stream_index]->codec->codec_type ==
+ CODEC_TYPE_AUDIO)
+ return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
+ else
+ return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
+}
+
+static int rm_write_trailer(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ int data_size, index_pos, i;
+ ByteIOContext *pb = s->pb;
+
+ if (!url_is_streamed(s->pb)) {
+ /* end of file: finish to write header */
+ index_pos = url_fseek(pb, 0, SEEK_CUR);
+ data_size = index_pos - rm->data_pos;
+
+ /* index */
+ put_tag(pb, "INDX");
+ put_be32(pb, 10 + 10 * s->nb_streams);
+ put_be16(pb, 0);
+
+ for(i=0;i<s->nb_streams;i++) {
+ put_be32(pb, 0); /* zero indices */
+ put_be16(pb, i); /* stream number */
+ put_be32(pb, 0); /* next index */
+ }
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+
+ url_fseek(pb, 0, SEEK_SET);
+ for(i=0;i<s->nb_streams;i++)
+ rm->streams[i].total_frames = rm->streams[i].nb_frames;
+ rv10_write_header(s, data_size, index_pos);
+ } else {
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+
+AVOutputFormat rm_muxer = {
+ "rm",
+ "rm format",
+ "application/vnd.rn-realmedia",
+ "rm,ra",
+ sizeof(RMContext),
+ CODEC_ID_AC3,
+ CODEC_ID_RV10,
+ rm_write_header,
+ rm_write_packet,
+ rm_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/rtp.c b/contrib/ffmpeg/libavformat/rtp.c
index 493a89cf3..6b038c825 100644
--- a/contrib/ffmpeg/libavformat/rtp.c
+++ b/contrib/ffmpeg/libavformat/rtp.c
@@ -19,29 +19,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "mpegts.h"
#include "bitstream.h"
#include <unistd.h>
#include "network.h"
#include "rtp_internal.h"
-#include "rtp_h264.h"
//#define DEBUG
-
-/* TODO: - add RTCP statistics reporting (should be optional).
-
- - add support for h263/mpeg4 packetized output : IDEA: send a
- buffer to 'rtp_write_packet' contains all the packets for ONE
- frame. Each packet should have a four byte header containing
- the length in big endian format (same trick as
- 'url_open_dyn_packet_buf')
-*/
-
/* from http://www.iana.org/assignments/rtp-parameters last updated 05 January 2005 */
-AVRtpPayloadType_t AVRtpPayloadTypes[]=
+static const struct
+{
+ int pt;
+ const char enc_name[50]; /* XXX: why 50 ? */
+ enum CodecType codec_type;
+ enum CodecID codec_id;
+ int clock_rate;
+ int audio_channels;
+} AVRtpPayloadTypes[]=
{
{0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8000, 1},
{1, "Reserved", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
@@ -76,6 +72,7 @@ AVRtpPayloadType_t AVRtpPayloadTypes[]=
{30, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
{31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1},
{32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1},
+ {32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1},
{33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1},
{34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1},
{35, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
@@ -174,36 +171,22 @@ AVRtpPayloadType_t AVRtpPayloadTypes[]=
{-1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1}
};
-/* statistics functions */
-RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
-
-static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4};
-static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC};
-
-static void register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
-{
- handler->next= RTPFirstDynamicPayloadHandler;
- RTPFirstDynamicPayloadHandler= handler;
-}
-
-void av_register_rtp_dynamic_payload_handlers()
-{
- register_dynamic_payload_handler(&mp4v_es_handler);
- register_dynamic_payload_handler(&mpeg4_generic_handler);
- register_dynamic_payload_handler(&ff_h264_dynamic_handler);
-}
-
int rtp_get_codec_info(AVCodecContext *codec, int payload_type)
{
- if (AVRtpPayloadTypes[payload_type].codec_id != CODEC_ID_NONE) {
- codec->codec_type = AVRtpPayloadTypes[payload_type].codec_type;
- codec->codec_id = AVRtpPayloadTypes[payload_type].codec_id;
- if (AVRtpPayloadTypes[payload_type].audio_channels > 0)
- codec->channels = AVRtpPayloadTypes[payload_type].audio_channels;
- if (AVRtpPayloadTypes[payload_type].clock_rate > 0)
- codec->sample_rate = AVRtpPayloadTypes[payload_type].clock_rate;
- return 0;
- }
+ int i = 0;
+
+ for (i = 0; AVRtpPayloadTypes[i].pt >= 0; i++)
+ if (AVRtpPayloadTypes[i].pt == payload_type) {
+ if (AVRtpPayloadTypes[i].codec_id != CODEC_ID_NONE) {
+ codec->codec_type = AVRtpPayloadTypes[i].codec_type;
+ codec->codec_id = AVRtpPayloadTypes[i].codec_id;
+ if (AVRtpPayloadTypes[i].audio_channels > 0)
+ codec->channels = AVRtpPayloadTypes[i].audio_channels;
+ if (AVRtpPayloadTypes[i].clock_rate > 0)
+ codec->sample_rate = AVRtpPayloadTypes[i].clock_rate;
+ return 0;
+ }
+ }
return -1;
}
@@ -222,864 +205,26 @@ int rtp_get_payload_type(AVCodecContext *codec)
return payload_type;
}
-static inline uint32_t decode_be32(const uint8_t *p)
-{
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
-}
-
-static inline uint64_t decode_be64(const uint8_t *p)
-{
- return ((uint64_t)decode_be32(p) << 32) | decode_be32(p + 4);
-}
-
-static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len)
-{
- if (buf[1] != 200)
- return -1;
- s->last_rtcp_ntp_time = decode_be64(buf + 8);
- if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE)
- s->first_rtcp_ntp_time = s->last_rtcp_ntp_time;
- s->last_rtcp_timestamp = decode_be32(buf + 16);
- return 0;
-}
-
-#define RTP_SEQ_MOD (1<<16)
-
-/**
-* called on parse open packet
-*/
-static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet.
-{
- memset(s, 0, sizeof(RTPStatistics));
- s->max_seq= base_sequence;
- s->probation= 1;
-}
-
-/**
-* called whenever there is a large jump in sequence numbers, or when they get out of probation...
-*/
-static void rtp_init_sequence(RTPStatistics *s, uint16_t seq)
-{
- s->max_seq= seq;
- s->cycles= 0;
- s->base_seq= seq -1;
- s->bad_seq= RTP_SEQ_MOD + 1;
- s->received= 0;
- s->expected_prior= 0;
- s->received_prior= 0;
- s->jitter= 0;
- s->transit= 0;
-}
-
-/**
-* returns 1 if we should handle this packet.
-*/
-static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
-{
- uint16_t udelta= seq - s->max_seq;
- const int MAX_DROPOUT= 3000;
- const int MAX_MISORDER = 100;
- const int MIN_SEQUENTIAL = 2;
-
- /* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
- if(s->probation)
- {
- if(seq==s->max_seq + 1) {
- s->probation--;
- s->max_seq= seq;
- if(s->probation==0) {
- rtp_init_sequence(s, seq);
- s->received++;
- return 1;
- }
- } else {
- s->probation= MIN_SEQUENTIAL - 1;
- s->max_seq = seq;
- }
- } else if (udelta < MAX_DROPOUT) {
- // in order, with permissible gap
- if(seq < s->max_seq) {
- //sequence number wrapped; count antother 64k cycles
- s->cycles += RTP_SEQ_MOD;
- }
- s->max_seq= seq;
- } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
- // sequence made a large jump...
- if(seq==s->bad_seq) {
- // two sequential packets-- assume that the other side restarted without telling us; just resync.
- rtp_init_sequence(s, seq);
- } else {
- s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1);
- return 0;
- }
- } else {
- // duplicate or reordered packet...
- }
- s->received++;
- return 1;
-}
-
-#if 0
-/**
-* This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
-* difference between the arrival and sent timestamp. As a result, the jitter and transit statistics values
-* never change. I left this in in case someone else can see a way. (rdm)
-*/
-static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
-{
- uint32_t transit= arrival_timestamp - sent_timestamp;
- int d;
- s->transit= transit;
- d= FFABS(transit - s->transit);
- s->jitter += d - ((s->jitter + 8)>>4);
-}
-#endif
-
-int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
-{
- ByteIOContext pb;
- uint8_t *buf;
- int len;
- int rtcp_bytes;
- RTPStatistics *stats= &s->statistics;
- uint32_t lost;
- uint32_t extended_max;
- uint32_t expected_interval;
- uint32_t received_interval;
- uint32_t lost_interval;
- uint32_t expected;
- uint32_t fraction;
- uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
-
- if (!s->rtp_ctx || (count < 1))
- return -1;
-
- /* TODO: I think this is way too often; RFC 1889 has algorithm for this */
- /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
- s->octet_count += count;
- rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
- RTCP_TX_RATIO_DEN;
- rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !?
- if (rtcp_bytes < 28)
- return -1;
- s->last_octet_count = s->octet_count;
-
- if (url_open_dyn_buf(&pb) < 0)
- return -1;
-
- // Receiver Report
- put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
- put_byte(&pb, 201);
- put_be16(&pb, 7); /* length in words - 1 */
- put_be32(&pb, s->ssrc); // our own SSRC
- put_be32(&pb, s->ssrc); // XXX: should be the server's here!
- // some placeholders we should really fill...
- // RFC 1889/p64
- extended_max= stats->cycles + stats->max_seq;
- expected= extended_max - stats->base_seq + 1;
- lost= expected - stats->received;
- lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
- expected_interval= expected - stats->expected_prior;
- stats->expected_prior= expected;
- received_interval= stats->received - stats->received_prior;
- stats->received_prior= stats->received;
- lost_interval= expected_interval - received_interval;
- if (expected_interval==0 || lost_interval<=0) fraction= 0;
- else fraction = (lost_interval<<8)/expected_interval;
-
- fraction= (fraction<<24) | lost;
-
- put_be32(&pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
- put_be32(&pb, extended_max); /* max sequence received */
- put_be32(&pb, stats->jitter>>4); /* jitter */
-
- if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
- {
- put_be32(&pb, 0); /* last SR timestamp */
- put_be32(&pb, 0); /* delay since last SR */
- } else {
- uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special?
- uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time;
-
- put_be32(&pb, middle_32_bits); /* last SR timestamp */
- put_be32(&pb, delay_since_last); /* delay since last SR */
- }
-
- // CNAME
- put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
- put_byte(&pb, 202);
- len = strlen(s->hostname);
- put_be16(&pb, (6 + len + 3) / 4); /* length in words - 1 */
- put_be32(&pb, s->ssrc);
- put_byte(&pb, 0x01);
- put_byte(&pb, len);
- put_buffer(&pb, s->hostname, len);
- // padding
- for (len = (6 + len) % 4; len % 4; len++) {
- put_byte(&pb, 0);
- }
-
- put_flush_packet(&pb);
- len = url_close_dyn_buf(&pb, &buf);
- if ((len > 0) && buf) {
- int result;
-#if defined(DEBUG)
- printf("sending %d bytes of RR\n", len);
-#endif
- result= url_write(s->rtp_ctx, buf, len);
-#if defined(DEBUG)
- printf("result from url_write: %d\n", result);
-#endif
- av_free(buf);
- }
- return 0;
-}
-
-/**
- * open a new RTP parse context for stream 'st'. 'st' can be NULL for
- * MPEG2TS streams to indicate that they should be demuxed inside the
- * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
- * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
- */
-RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_t *rtp_payload_data)
-{
- RTPDemuxContext *s;
-
- s = av_mallocz(sizeof(RTPDemuxContext));
- if (!s)
- return NULL;
- s->payload_type = payload_type;
- s->last_rtcp_ntp_time = AV_NOPTS_VALUE;
- s->first_rtcp_ntp_time = AV_NOPTS_VALUE;
- s->ic = s1;
- s->st = st;
- s->rtp_payload_data = rtp_payload_data;
- rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp?
- if (!strcmp(AVRtpPayloadTypes[payload_type].enc_name, "MP2T")) {
- s->ts = mpegts_parse_open(s->ic);
- if (s->ts == NULL) {
- av_free(s);
- return NULL;
- }
- } else {
- switch(st->codec->codec_id) {
- case CODEC_ID_MPEG1VIDEO:
- case CODEC_ID_MPEG2VIDEO:
- case CODEC_ID_MP2:
- case CODEC_ID_MP3:
- case CODEC_ID_MPEG4:
- case CODEC_ID_H264:
- st->need_parsing = 1;
- break;
- default:
- break;
- }
- }
- // needed to send back RTCP RR in RTSP sessions
- s->rtp_ctx = rtpc;
- gethostname(s->hostname, sizeof(s->hostname));
- return s;
-}
-
-static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf)
-{
- int au_headers_length, au_header_size, i;
- GetBitContext getbitcontext;
- rtp_payload_data_t *infos;
-
- infos = s->rtp_payload_data;
-
- if (infos == NULL)
- return -1;
-
- /* decode the first 2 bytes where are stored the AUHeader sections
- length in bits */
- au_headers_length = AV_RB16(buf);
-
- if (au_headers_length > RTP_MAX_PACKET_LENGTH)
- return -1;
-
- infos->au_headers_length_bytes = (au_headers_length + 7) / 8;
-
- /* skip AU headers length section (2 bytes) */
- buf += 2;
-
- init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
-
- /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
- au_header_size = infos->sizelength + infos->indexlength;
- if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
- return -1;
-
- infos->nb_au_headers = au_headers_length / au_header_size;
- infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers);
-
- /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
- In my test, the faad decoder doesnt behave correctly when sending each AU one by one
- but does when sending the whole as one big packet... */
- infos->au_headers[0].size = 0;
- infos->au_headers[0].index = 0;
- for (i = 0; i < infos->nb_au_headers; ++i) {
- infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
- infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
- }
-
- infos->nb_au_headers = 1;
-
- return 0;
-}
-
-/**
- * This was the second switch in rtp_parse packet. Normalizes time, if required, sets stream_index, etc.
- */
-static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp)
-{
- switch(s->st->codec->codec_id) {
- case CODEC_ID_MP2:
- case CODEC_ID_MPEG1VIDEO:
- if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
- int64_t addend;
-
- int delta_timestamp;
- /* XXX: is it really necessary to unify the timestamp base ? */
- /* compute pts from timestamp with received ntp_time */
- delta_timestamp = timestamp - s->last_rtcp_timestamp;
- /* convert to 90 kHz without overflow */
- addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14;
- addend = (addend * 5625) >> 14;
- pkt->pts = addend + delta_timestamp;
- }
- break;
- case CODEC_ID_AAC:
- case CODEC_ID_H264:
- case CODEC_ID_MPEG4:
- pkt->pts = timestamp;
- break;
- default:
- /* no timestamp info yet */
- break;
- }
- pkt->stream_index = s->st->index;
-}
-
-/**
- * Parse an RTP or RTCP packet directly sent as a buffer.
- * @param s RTP parse context.
- * @param pkt returned packet
- * @param buf input buffer or NULL to read the next packets
- * @param len buffer len
- * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
- * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
- */
-int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
- const uint8_t *buf, int len)
-{
- unsigned int ssrc, h;
- int payload_type, seq, ret;
- AVStream *st;
- uint32_t timestamp;
- int rv= 0;
-
- if (!buf) {
- /* return the next packets, if any */
- if(s->st && s->parse_packet) {
- timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
- rv= s->parse_packet(s, pkt, &timestamp, NULL, 0);
- finalize_packet(s, pkt, timestamp);
- return rv;
- } else {
- // TODO: Move to a dynamic packet handler (like above)
- if (s->read_buf_index >= s->read_buf_size)
- return -1;
- ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
- s->read_buf_size - s->read_buf_index);
- if (ret < 0)
- return -1;
- s->read_buf_index += ret;
- if (s->read_buf_index < s->read_buf_size)
- return 1;
- else
- return 0;
- }
- }
-
- if (len < 12)
- return -1;
-
- if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
- return -1;
- if (buf[1] >= 200 && buf[1] <= 204) {
- rtcp_parse_packet(s, buf, len);
- return -1;
- }
- payload_type = buf[1] & 0x7f;
- seq = (buf[2] << 8) | buf[3];
- timestamp = decode_be32(buf + 4);
- ssrc = decode_be32(buf + 8);
- /* store the ssrc in the RTPDemuxContext */
- s->ssrc = ssrc;
-
- /* NOTE: we can handle only one payload type */
- if (s->payload_type != payload_type)
- return -1;
-
- st = s->st;
- // only do something with this if all the rtp checks pass...
- if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
- {
- av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
- payload_type, seq, ((s->seq + 1) & 0xffff));
- return -1;
- }
-
- s->seq = seq;
- len -= 12;
- buf += 12;
-
- if (!st) {
- /* specific MPEG2TS demux support */
- ret = mpegts_parse_packet(s->ts, pkt, buf, len);
- if (ret < 0)
- return -1;
- if (ret < len) {
- s->read_buf_size = len - ret;
- memcpy(s->buf, buf + ret, s->read_buf_size);
- s->read_buf_index = 0;
- return 1;
- }
- } else {
- // at this point, the RTP header has been stripped; This is ASSUMING that there is only 1 CSRC, which in't wise.
- switch(st->codec->codec_id) {
- case CODEC_ID_MP2:
- /* better than nothing: skip mpeg audio RTP header */
- if (len <= 4)
- return -1;
- h = decode_be32(buf);
- len -= 4;
- buf += 4;
- av_new_packet(pkt, len);
- memcpy(pkt->data, buf, len);
- break;
- case CODEC_ID_MPEG1VIDEO:
- /* better than nothing: skip mpeg video RTP header */
- if (len <= 4)
- return -1;
- h = decode_be32(buf);
- buf += 4;
- len -= 4;
- if (h & (1 << 26)) {
- /* mpeg2 */
- if (len <= 4)
- return -1;
- buf += 4;
- len -= 4;
- }
- av_new_packet(pkt, len);
- memcpy(pkt->data, buf, len);
- break;
- // moved from below, verbatim. this is because this section handles packets, and the lower switch handles
- // timestamps.
- // TODO: Put this into a dynamic packet handler...
- case CODEC_ID_AAC:
- if (rtp_parse_mp4_au(s, buf))
- return -1;
- {
- rtp_payload_data_t *infos = s->rtp_payload_data;
- if (infos == NULL)
- return -1;
- buf += infos->au_headers_length_bytes + 2;
- len -= infos->au_headers_length_bytes + 2;
-
- /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
- one au_header */
- av_new_packet(pkt, infos->au_headers[0].size);
- memcpy(pkt->data, buf, infos->au_headers[0].size);
- buf += infos->au_headers[0].size;
- len -= infos->au_headers[0].size;
- }
- s->read_buf_size = len;
- s->buf_ptr = buf;
- rv= 0;
- break;
- default:
- if(s->parse_packet) {
- rv= s->parse_packet(s, pkt, &timestamp, buf, len);
- } else {
- av_new_packet(pkt, len);
- memcpy(pkt->data, buf, len);
- }
- break;
- }
-
- // now perform timestamp things....
- finalize_packet(s, pkt, timestamp);
- }
- return rv;
-}
-
-void rtp_parse_close(RTPDemuxContext *s)
-{
- // TODO: fold this into the protocol specific data fields.
- if (!strcmp(AVRtpPayloadTypes[s->payload_type].enc_name, "MP2T")) {
- mpegts_parse_close(s->ts);
- }
- av_free(s);
-}
-
-/* rtp output */
-
-static int rtp_write_header(AVFormatContext *s1)
-{
- RTPDemuxContext *s = s1->priv_data;
- int payload_type, max_packet_size, n;
- AVStream *st;
-
- if (s1->nb_streams != 1)
- return -1;
- st = s1->streams[0];
-
- payload_type = rtp_get_payload_type(st->codec);
- if (payload_type < 0)
- payload_type = RTP_PT_PRIVATE; /* private payload type */
- s->payload_type = payload_type;
-
-// following 2 FIXMies could be set based on the current time, theres normaly no info leak, as rtp will likely be transmitted immedeatly
- s->base_timestamp = 0; /* FIXME: was random(), what should this be? */
- s->timestamp = s->base_timestamp;
- s->ssrc = 0; /* FIXME: was random(), what should this be? */
- s->first_packet = 1;
-
- max_packet_size = url_fget_max_packet_size(&s1->pb);
- if (max_packet_size <= 12)
- return AVERROR_IO;
- s->max_payload_size = max_packet_size - 12;
-
- switch(st->codec->codec_id) {
- case CODEC_ID_MP2:
- case CODEC_ID_MP3:
- s->buf_ptr = s->buf + 4;
- s->cur_timestamp = 0;
- break;
- case CODEC_ID_MPEG1VIDEO:
- s->cur_timestamp = 0;
- break;
- case CODEC_ID_MPEG2TS:
- n = s->max_payload_size / TS_PACKET_SIZE;
- if (n < 1)
- n = 1;
- s->max_payload_size = n * TS_PACKET_SIZE;
- s->buf_ptr = s->buf;
- break;
- default:
- s->buf_ptr = s->buf;
- break;
- }
-
- return 0;
-}
-
-/* send an rtcp sender report packet */
-static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time)
-{
- RTPDemuxContext *s = s1->priv_data;
-#if defined(DEBUG)
- printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp);
-#endif
- put_byte(&s1->pb, (RTP_VERSION << 6));
- put_byte(&s1->pb, 200);
- put_be16(&s1->pb, 6); /* length in words - 1 */
- put_be32(&s1->pb, s->ssrc);
- put_be64(&s1->pb, ntp_time);
- put_be32(&s1->pb, s->timestamp);
- put_be32(&s1->pb, s->packet_count);
- put_be32(&s1->pb, s->octet_count);
- put_flush_packet(&s1->pb);
-}
-
-/* send an rtp packet. sequence number is incremented, but the caller
- must update the timestamp itself */
-static void rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m)
-{
- RTPDemuxContext *s = s1->priv_data;
-
-#ifdef DEBUG
- printf("rtp_send_data size=%d\n", len);
-#endif
-
- /* build the RTP header */
- put_byte(&s1->pb, (RTP_VERSION << 6));
- put_byte(&s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7));
- put_be16(&s1->pb, s->seq);
- put_be32(&s1->pb, s->timestamp);
- put_be32(&s1->pb, s->ssrc);
-
- put_buffer(&s1->pb, buf1, len);
- put_flush_packet(&s1->pb);
-
- s->seq++;
- s->octet_count += len;
- s->packet_count++;
-}
-
-/* send an integer number of samples and compute time stamp and fill
- the rtp send buffer before sending. */
-static void rtp_send_samples(AVFormatContext *s1,
- const uint8_t *buf1, int size, int sample_size)
+const char *ff_rtp_enc_name(int payload_type)
{
- RTPDemuxContext *s = s1->priv_data;
- int len, max_packet_size, n;
+ int i;
- max_packet_size = (s->max_payload_size / sample_size) * sample_size;
- /* not needed, but who nows */
- if ((size % sample_size) != 0)
- av_abort();
- while (size > 0) {
- len = (max_packet_size - (s->buf_ptr - s->buf));
- if (len > size)
- len = size;
-
- /* copy data */
- memcpy(s->buf_ptr, buf1, len);
- s->buf_ptr += len;
- buf1 += len;
- size -= len;
- n = (s->buf_ptr - s->buf);
- /* if buffer full, then send it */
- if (n >= max_packet_size) {
- rtp_send_data(s1, s->buf, n, 0);
- s->buf_ptr = s->buf;
- /* update timestamp */
- s->timestamp += n / sample_size;
+ for (i = 0; AVRtpPayloadTypes[i].pt >= 0; i++)
+ if (AVRtpPayloadTypes[i].pt == payload_type) {
+ return AVRtpPayloadTypes[i].enc_name;
}
- }
-}
-/* NOTE: we suppose that exactly one frame is given as argument here */
-/* XXX: test it */
-static void rtp_send_mpegaudio(AVFormatContext *s1,
- const uint8_t *buf1, int size)
-{
- RTPDemuxContext *s = s1->priv_data;
- AVStream *st = s1->streams[0];
- int len, count, max_packet_size;
-
- max_packet_size = s->max_payload_size;
-
- /* test if we must flush because not enough space */
- len = (s->buf_ptr - s->buf);
- if ((len + size) > max_packet_size) {
- if (len > 4) {
- rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
- s->buf_ptr = s->buf + 4;
- /* 90 KHz time stamp */
- s->timestamp = s->base_timestamp +
- (s->cur_timestamp * 90000LL) / st->codec->sample_rate;
- }
- }
-
- /* add the packet */
- if (size > max_packet_size) {
- /* big packet: fragment */
- count = 0;
- while (size > 0) {
- len = max_packet_size - 4;
- if (len > size)
- len = size;
- /* build fragmented packet */
- s->buf[0] = 0;
- s->buf[1] = 0;
- s->buf[2] = count >> 8;
- s->buf[3] = count;
- memcpy(s->buf + 4, buf1, len);
- rtp_send_data(s1, s->buf, len + 4, 0);
- size -= len;
- buf1 += len;
- count += len;
- }
- } else {
- if (s->buf_ptr == s->buf + 4) {
- /* no fragmentation possible */
- s->buf[0] = 0;
- s->buf[1] = 0;
- s->buf[2] = 0;
- s->buf[3] = 0;
- }
- memcpy(s->buf_ptr, buf1, size);
- s->buf_ptr += size;
- }
- s->cur_timestamp += st->codec->frame_size;
+ return "";
}
-/* NOTE: a single frame must be passed with sequence header if
- needed. XXX: use slices. */
-static void rtp_send_mpegvideo(AVFormatContext *s1,
- const uint8_t *buf1, int size)
+enum CodecID ff_rtp_codec_id(const char *buf, enum CodecType codec_type)
{
- RTPDemuxContext *s = s1->priv_data;
- AVStream *st = s1->streams[0];
- int len, h, max_packet_size;
- uint8_t *q;
-
- max_packet_size = s->max_payload_size;
-
- while (size > 0) {
- /* XXX: more correct headers */
- h = 0;
- if (st->codec->sub_id == 2)
- h |= 1 << 26; /* mpeg 2 indicator */
- q = s->buf;
- *q++ = h >> 24;
- *q++ = h >> 16;
- *q++ = h >> 8;
- *q++ = h;
+ int i;
- if (st->codec->sub_id == 2) {
- h = 0;
- *q++ = h >> 24;
- *q++ = h >> 16;
- *q++ = h >> 8;
- *q++ = h;
+ for (i = 0; AVRtpPayloadTypes[i].pt >= 0; i++)
+ if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec_type == AVRtpPayloadTypes[i].codec_type)){
+ return AVRtpPayloadTypes[i].codec_id;
}
- len = max_packet_size - (q - s->buf);
- if (len > size)
- len = size;
-
- memcpy(q, buf1, len);
- q += len;
-
- /* 90 KHz time stamp */
- s->timestamp = s->base_timestamp +
- av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
- rtp_send_data(s1, s->buf, q - s->buf, (len == size));
-
- buf1 += len;
- size -= len;
- }
- s->cur_timestamp++;
+ return CODEC_ID_NONE;
}
-
-static void rtp_send_raw(AVFormatContext *s1,
- const uint8_t *buf1, int size)
-{
- RTPDemuxContext *s = s1->priv_data;
- AVStream *st = s1->streams[0];
- int len, max_packet_size;
-
- max_packet_size = s->max_payload_size;
-
- while (size > 0) {
- len = max_packet_size;
- if (len > size)
- len = size;
-
- /* 90 KHz time stamp */
- s->timestamp = s->base_timestamp +
- av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
- rtp_send_data(s1, buf1, len, (len == size));
-
- buf1 += len;
- size -= len;
- }
- s->cur_timestamp++;
-}
-
-/* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */
-static void rtp_send_mpegts_raw(AVFormatContext *s1,
- const uint8_t *buf1, int size)
-{
- RTPDemuxContext *s = s1->priv_data;
- int len, out_len;
-
- while (size >= TS_PACKET_SIZE) {
- len = s->max_payload_size - (s->buf_ptr - s->buf);
- if (len > size)
- len = size;
- memcpy(s->buf_ptr, buf1, len);
- buf1 += len;
- size -= len;
- s->buf_ptr += len;
-
- out_len = s->buf_ptr - s->buf;
- if (out_len >= s->max_payload_size) {
- rtp_send_data(s1, s->buf, out_len, 0);
- s->buf_ptr = s->buf;
- }
- }
-}
-
-/* write an RTP packet. 'buf1' must contain a single specific frame. */
-static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- RTPDemuxContext *s = s1->priv_data;
- AVStream *st = s1->streams[0];
- int rtcp_bytes;
- int64_t ntp_time;
- int size= pkt->size;
- uint8_t *buf1= pkt->data;
-
-#ifdef DEBUG
- printf("%d: write len=%d\n", pkt->stream_index, size);
-#endif
-
- /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
- rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
- RTCP_TX_RATIO_DEN;
- if (s->first_packet || rtcp_bytes >= 28) {
- /* compute NTP time */
- /* XXX: 90 kHz timestamp hardcoded */
- ntp_time = (pkt->pts << 28) / 5625;
- rtcp_send_sr(s1, ntp_time);
- s->last_octet_count = s->octet_count;
- s->first_packet = 0;
- }
-
- switch(st->codec->codec_id) {
- case CODEC_ID_PCM_MULAW:
- case CODEC_ID_PCM_ALAW:
- case CODEC_ID_PCM_U8:
- case CODEC_ID_PCM_S8:
- rtp_send_samples(s1, buf1, size, 1 * st->codec->channels);
- break;
- case CODEC_ID_PCM_U16BE:
- case CODEC_ID_PCM_U16LE:
- case CODEC_ID_PCM_S16BE:
- case CODEC_ID_PCM_S16LE:
- rtp_send_samples(s1, buf1, size, 2 * st->codec->channels);
- break;
- case CODEC_ID_MP2:
- case CODEC_ID_MP3:
- rtp_send_mpegaudio(s1, buf1, size);
- break;
- case CODEC_ID_MPEG1VIDEO:
- rtp_send_mpegvideo(s1, buf1, size);
- break;
- case CODEC_ID_MPEG2TS:
- rtp_send_mpegts_raw(s1, buf1, size);
- break;
- default:
- /* better than nothing : send the codec raw data */
- rtp_send_raw(s1, buf1, size);
- break;
- }
- return 0;
-}
-
-static int rtp_write_trailer(AVFormatContext *s1)
-{
- // RTPDemuxContext *s = s1->priv_data;
- return 0;
-}
-
-AVOutputFormat rtp_muxer = {
- "rtp",
- "RTP output format",
- NULL,
- NULL,
- sizeof(RTPDemuxContext),
- CODEC_ID_PCM_MULAW,
- CODEC_ID_NONE,
- rtp_write_header,
- rtp_write_packet,
- rtp_write_trailer,
-};
diff --git a/contrib/ffmpeg/libavformat/rtp.h b/contrib/ffmpeg/libavformat/rtp.h
index fec763051..21cfdb4cf 100644
--- a/contrib/ffmpeg/libavformat/rtp.h
+++ b/contrib/ffmpeg/libavformat/rtp.h
@@ -18,13 +18,15 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef RTP_H
-#define RTP_H
+#ifndef FFMPEG_RTP_H
+#define FFMPEG_RTP_H
+
+#include "avcodec.h"
+#include "avformat.h"
#define RTP_MIN_PACKET_LENGTH 12
#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */
-int rtp_init(void);
int rtp_get_codec_info(AVCodecContext *codec, int payload_type);
/** return < 0 if unknown payload type */
@@ -37,9 +39,6 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
const uint8_t *buf, int len);
void rtp_parse_close(RTPDemuxContext *s);
-extern AVOutputFormat rtp_muxer;
-extern AVInputFormat rtp_demuxer;
-
int rtp_get_local_port(URLContext *h);
int rtp_set_remote_url(URLContext *h, const char *uri);
void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
@@ -51,8 +50,6 @@ void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
*/
int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count);
-extern URLProtocol rtp_protocol;
-
#define RTP_PT_PRIVATE 96
#define RTP_VERSION 2
#define RTP_MAX_SDES 256 /**< maximum text length for SDES */
@@ -88,16 +85,6 @@ typedef struct rtp_payload_data_s
int cur_au_index;
} rtp_payload_data_t;
-typedef struct AVRtpPayloadType_s
-{
- int pt;
- const char enc_name[50]; /* XXX: why 50 ? */
- enum CodecType codec_type;
- enum CodecID codec_id;
- int clock_rate;
- int audio_channels;
-} AVRtpPayloadType_t;
-
#if 0
typedef enum {
RTCP_SR = 200,
@@ -123,5 +110,4 @@ typedef enum {
} rtcp_sdes_type_t;
#endif
-extern AVRtpPayloadType_t AVRtpPayloadTypes[];
-#endif /* RTP_H */
+#endif /* FFMPEG_RTP_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_aac.c b/contrib/ffmpeg/libavformat/rtp_aac.c
new file mode 100644
index 000000000..4cd8e129d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_aac.c
@@ -0,0 +1,88 @@
+/*
+ * copyright (c) 2007 Luca Abeni
+ *
+ * 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 "avformat.h"
+#include "rtp_aac.h"
+#include "rtp_internal.h"
+
+#define MAX_FRAMES_PER_PACKET (s->max_frames_per_packet ? s->max_frames_per_packet : 5)
+#define MAX_AU_HEADERS_SIZE (2 + 2 * MAX_FRAMES_PER_PACKET)
+
+void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, max_packet_size;
+ uint8_t *p;
+
+ /* skip ADTS header, if present */
+ if ((s1->streams[0]->codec->extradata_size) == 0) {
+ size -= 7;
+ buff += 7;
+ }
+ max_packet_size = s->max_payload_size - MAX_AU_HEADERS_SIZE;
+
+ /* test if the packet must be sent */
+ len = (s->buf_ptr - s->buf);
+ if ((s->read_buf_index == MAX_FRAMES_PER_PACKET) || (len && (len + size) > max_packet_size)) {
+ int au_size = s->read_buf_index * 2;
+
+ p = s->buf + MAX_AU_HEADERS_SIZE - au_size - 2;
+ if (p != s->buf) {
+ memmove(p + 2, s->buf + 2, au_size);
+ }
+ /* Write the AU header size */
+ p[0] = ((au_size * 8) & 0xFF) >> 8;
+ p[1] = (au_size * 8) & 0xFF;
+
+ ff_rtp_send_data(s1, p, s->buf_ptr - p, 1);
+
+ s->read_buf_index = 0;
+ }
+ if (s->read_buf_index == 0) {
+ s->buf_ptr = s->buf + MAX_AU_HEADERS_SIZE;
+ s->timestamp = s->cur_timestamp;
+ }
+
+ if (size < max_packet_size) {
+ p = s->buf + s->read_buf_index++ * 2 + 2;
+ *p++ = size >> 5;
+ *p = (size & 0x1F) << 3;
+ memcpy(s->buf_ptr, buff, size);
+ s->buf_ptr += size;
+ } else {
+ if (s->buf_ptr != s->buf + MAX_AU_HEADERS_SIZE) {
+ av_log(s1, AV_LOG_ERROR, "Strange...\n");
+ av_abort();
+ }
+ max_packet_size = s->max_payload_size - 4;
+ p = s->buf;
+ p[0] = 0;
+ p[1] = 16;
+ while (size > 0) {
+ len = FFMIN(size, max_packet_size);
+ p[2] = len >> 5;
+ p[3] = (size & 0x1F) << 3;
+ memcpy(p + 4, buff, len);
+ ff_rtp_send_data(s1, p, len + 4, len == size);
+ size -= len;
+ buff += len;
+ }
+ }
+}
diff --git a/contrib/ffmpeg/libavformat/rtp_aac.h b/contrib/ffmpeg/libavformat/rtp_aac.h
new file mode 100644
index 000000000..24b41cc42
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_aac.h
@@ -0,0 +1,27 @@
+/*
+ * RTP definitions
+ *
+ * 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 FFMPEG_RTP_AAC_H
+#define FFMPEG_RTP_AAC_H
+
+#include "avformat.h"
+
+void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size);
+
+#endif /* FFMPEG_RTP_AAC_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_h264.c b/contrib/ffmpeg/libavformat/rtp_h264.c
index d38e8780d..3e0fc3add 100644
--- a/contrib/ffmpeg/libavformat/rtp_h264.c
+++ b/contrib/ffmpeg/libavformat/rtp_h264.c
@@ -47,6 +47,7 @@
#include "rtp_internal.h"
#include "rtp_h264.h"
#include "base64.h"
+#include "avstring.h"
/**
RTP/H264 specific private data.
@@ -77,8 +78,8 @@ static void sdp_parse_fmtp_config_h264(AVStream * stream,
assert(h264_data != NULL);
if (!strcmp(attr, "packetization-mode")) {
- av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Packetization Mode: %d\n", atoi(attr));
- h264_data->packetization_mode = atoi(attr);
+ av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Packetization Mode: %d\n", atoi(value));
+ h264_data->packetization_mode = atoi(value);
/*
Packetization Mode:
0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
@@ -162,7 +163,7 @@ static int h264_handle_packet(RTPDemuxContext * s,
AVPacket * pkt,
uint32_t * timestamp,
const uint8_t * buf,
- int len)
+ int len, int flags)
{
#ifdef DEBUG
h264_rtp_extra_data *data = s->dynamic_protocol_context;
@@ -270,14 +271,14 @@ static int h264_handle_packet(RTPDemuxContext * s,
// these are the same as above, we just redo them here for clarity...
uint8_t fu_indicator = nal;
uint8_t fu_header = *buf; // read the fu_header.
- uint8_t start_bit = (fu_header & 0x80) >> 7;
+ uint8_t start_bit = fu_header >> 7;
// uint8_t end_bit = (fu_header & 0x40) >> 6;
uint8_t nal_type = (fu_header & 0x1f);
uint8_t reconstructed_nal;
// reconstruct this packet's true nal; only the data follows..
reconstructed_nal = fu_indicator & (0xe0); // the original nal forbidden bit and NRI are stored in this packet's nal;
- reconstructed_nal |= (nal_type & 0x1f);
+ reconstructed_nal |= nal_type;
// skip the fu_header...
buf++;
@@ -285,7 +286,7 @@ static int h264_handle_packet(RTPDemuxContext * s,
#ifdef DEBUG
if (start_bit)
- data->packet_types_received[nal_type & 0x1f]++;
+ data->packet_types_received[nal_type]++;
#endif
if(start_bit) {
// copy in the start sequence, and the reconstructed nal....
@@ -312,7 +313,7 @@ static int h264_handle_packet(RTPDemuxContext * s,
}
/* ---------------- public code */
-static void *h264_new_extradata()
+static void *h264_new_extradata(void)
{
h264_rtp_extra_data *data =
av_mallocz(sizeof(h264_rtp_extra_data) +
@@ -357,7 +358,7 @@ static int parse_h264_sdp_line(AVStream * stream, void *data,
assert(h264_data->cookie == MAGIC_COOKIE);
- if (strstart(p, "framesize:", &p)) {
+ if (av_strstart(p, "framesize:", &p)) {
char buf1[50];
char *dst = buf1;
@@ -375,7 +376,7 @@ static int parse_h264_sdp_line(AVStream * stream, void *data,
codec->width = atoi(buf1);
codec->height = atoi(p + 1); // skip the -
codec->pix_fmt = PIX_FMT_YUV420P;
- } else if (strstart(p, "fmtp:", &p)) {
+ } else if (av_strstart(p, "fmtp:", &p)) {
char attr[256];
char value[4096];
@@ -390,7 +391,7 @@ static int parse_h264_sdp_line(AVStream * stream, void *data,
/* grab the codec extra_data from the config parameter of the fmtp line */
sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
}
- } else if (strstart(p, "cliprect:", &p)) {
+ } else if (av_strstart(p, "cliprect:", &p)) {
// could use this if we wanted.
}
diff --git a/contrib/ffmpeg/libavformat/rtp_h264.h b/contrib/ffmpeg/libavformat/rtp_h264.h
index 19508574d..0f23e525c 100644
--- a/contrib/ffmpeg/libavformat/rtp_h264.h
+++ b/contrib/ffmpeg/libavformat/rtp_h264.h
@@ -19,8 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef RTP_H264_H
-#define RTP_H264_H
+#ifndef FFMPEG_RTP_H264_H
+#define FFMPEG_RTP_H264_H
+
+#include "rtp_internal.h"
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
-#endif /* RTP_H264_H */
+void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size);
+
+#endif /* FFMPEG_RTP_H264_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_internal.h b/contrib/ffmpeg/libavformat/rtp_internal.h
index 3edcf49c8..e9d6cb390 100644
--- a/contrib/ffmpeg/libavformat/rtp_internal.h
+++ b/contrib/ffmpeg/libavformat/rtp_internal.h
@@ -20,8 +20,12 @@
*/
// this is a bit of a misnomer, because rtp & rtsp internal structures and prototypes are in here.
-#ifndef RTP_INTERNAL_H
-#define RTP_INTERNAL_H
+#ifndef FFMPEG_RTP_INTERNAL_H
+#define FFMPEG_RTP_INTERNAL_H
+
+#include <stdint.h>
+#include "avcodec.h"
+#include "rtp.h"
// these statistics are used for rtcp receiver reports...
typedef struct {
@@ -37,12 +41,21 @@ typedef struct {
uint32_t jitter; ///< estimated jitter.
} RTPStatistics;
-
+/**
+ * Packet parsing for "private" payloads in the RTP specs.
+ *
+ * @param s stream context
+ * @param pkt packet in which to write the parsed data
+ * @param timestamp pointer in which to write the timestamp of this RTP packet
+ * @param buf pointer to raw RTP packet data
+ * @param len length of buf
+ * @param flags flags from the RTP packet header (PKT_FLAG_*)
+ */
typedef int (*DynamicPayloadPacketHandlerProc) (struct RTPDemuxContext * s,
AVPacket * pkt,
uint32_t *timestamp,
const uint8_t * buf,
- int len);
+ int len, int flags);
typedef struct RTPDynamicProtocolHandler_s {
// fields from AVRtpDynamicPayloadType_s
@@ -101,10 +114,18 @@ struct RTPDemuxContext {
/* dynamic payload stuff */
DynamicPayloadPacketHandlerProc parse_packet; ///< This is also copied from the dynamic protocol handler structure
void *dynamic_protocol_context; ///< This is a copy from the values setup from the sdp parsing, in rtsp.c don't free me.
+ int max_frames_per_packet;
};
extern RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler;
int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size); ///< from rtsp.c, but used by rtp dynamic protocol handlers.
-#endif /* RTP_INTERNAL_H */
+
+void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m);
+const char *ff_rtp_enc_name(int payload_type);
+enum CodecID ff_rtp_codec_id(const char *buf, enum CodecType codec_type);
+
+void av_register_rtp_dynamic_payload_handlers(void);
+
+#endif /* FFMPEG_RTP_INTERNAL_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_mpv.c b/contrib/ffmpeg/libavformat/rtp_mpv.c
new file mode 100644
index 000000000..c8bf81f9a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_mpv.c
@@ -0,0 +1,118 @@
+/*
+ * RTP packetization for MPEG video
+ * Copyright (c) 2002 Fabrice Bellard.
+ * Copyright (c) 2007 Luca Abeni.
+ *
+ * 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 "avformat.h"
+#include "rtp_internal.h"
+
+#include "mpegvideo.h"
+
+/* NOTE: a single frame must be passed with sequence header if
+ needed. XXX: use slices. */
+void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, h, max_packet_size;
+ uint8_t *q;
+ int begin_of_slice, end_of_slice, frame_type, temporal_reference;
+
+ max_packet_size = s->max_payload_size;
+ begin_of_slice = 1;
+ end_of_slice = 0;
+ frame_type = 0;
+ temporal_reference = 0;
+
+ while (size > 0) {
+ int begin_of_sequence;
+
+ begin_of_sequence = 0;
+ len = max_packet_size - 4;
+
+ if (len >= size) {
+ len = size;
+ end_of_slice = 1;
+ } else {
+ const uint8_t *r, *r1;
+ int start_code;
+
+ r1 = buf1;
+ while (1) {
+ start_code = -1;
+ r = ff_find_start_code(r1, buf1 + size, &start_code);
+ if((start_code & 0xFFFFFF00) == 0x100) {
+ /* New start code found */
+ if (start_code == 0x100) {
+ frame_type = (r[1] & 0x38) >> 3;
+ temporal_reference = (int)r[0] << 2 | r[1] >> 6;
+ }
+ if (start_code == 0x1B8) {
+ begin_of_sequence = 1;
+ }
+
+ if (r - buf1 < len) {
+ /* The current slice fits in the packet */
+ if (begin_of_slice == 0) {
+ /* no slice at the beginning of the packet... */
+ end_of_slice = 1;
+ len = r - buf1 - 4;
+ break;
+ }
+ r1 = r;
+ } else {
+ if (r - r1 < max_packet_size) {
+ len = r1 - buf1 - 4;
+ end_of_slice = 1;
+ }
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ h = 0;
+ h |= temporal_reference << 16;
+ h |= begin_of_sequence << 13;
+ h |= begin_of_slice << 12;
+ h |= end_of_slice << 11;
+ h |= frame_type << 8;
+
+ q = s->buf;
+ *q++ = h >> 24;
+ *q++ = h >> 16;
+ *q++ = h >> 8;
+ *q++ = h;
+
+ memcpy(q, buf1, len);
+ q += len;
+
+ /* 90 KHz time stamp */
+ s->timestamp = s->cur_timestamp;
+ ff_rtp_send_data(s1, s->buf, q - s->buf, (len == size));
+
+ buf1 += len;
+ size -= len;
+ begin_of_slice = end_of_slice;
+ end_of_slice = 0;
+ }
+}
+
+
diff --git a/contrib/ffmpeg/libavformat/rtp_mpv.h b/contrib/ffmpeg/libavformat/rtp_mpv.h
new file mode 100644
index 000000000..36e649a89
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_mpv.h
@@ -0,0 +1,27 @@
+/*
+ * RTP definitions
+ *
+ * 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 FFMPEG_RTP_MPV_H
+#define FFMPEG_RTP_MPV_H
+
+#include "avformat.h"
+
+void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size);
+
+#endif /* FFMPEG_RTP_MPV_H */
diff --git a/contrib/ffmpeg/libavformat/rtpdec.c b/contrib/ffmpeg/libavformat/rtpdec.c
new file mode 100644
index 000000000..7bdfca30a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtpdec.c
@@ -0,0 +1,552 @@
+/*
+ * RTP input format
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "mpegts.h"
+#include "bitstream.h"
+
+#include <unistd.h>
+#include "network.h"
+
+#include "rtp_internal.h"
+#include "rtp_h264.h"
+
+//#define DEBUG
+
+/* TODO: - add RTCP statistics reporting (should be optional).
+
+ - add support for h263/mpeg4 packetized output : IDEA: send a
+ buffer to 'rtp_write_packet' contains all the packets for ONE
+ frame. Each packet should have a four byte header containing
+ the length in big endian format (same trick as
+ 'url_open_dyn_packet_buf')
+*/
+
+/* statistics functions */
+RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
+
+static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4};
+static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC};
+
+static void register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
+{
+ handler->next= RTPFirstDynamicPayloadHandler;
+ RTPFirstDynamicPayloadHandler= handler;
+}
+
+void av_register_rtp_dynamic_payload_handlers(void)
+{
+ register_dynamic_payload_handler(&mp4v_es_handler);
+ register_dynamic_payload_handler(&mpeg4_generic_handler);
+ register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+}
+
+static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len)
+{
+ if (buf[1] != 200)
+ return -1;
+ s->last_rtcp_ntp_time = AV_RB64(buf + 8);
+ if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE)
+ s->first_rtcp_ntp_time = s->last_rtcp_ntp_time;
+ s->last_rtcp_timestamp = AV_RB32(buf + 16);
+ return 0;
+}
+
+#define RTP_SEQ_MOD (1<<16)
+
+/**
+* called on parse open packet
+*/
+static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet.
+{
+ memset(s, 0, sizeof(RTPStatistics));
+ s->max_seq= base_sequence;
+ s->probation= 1;
+}
+
+/**
+* called whenever there is a large jump in sequence numbers, or when they get out of probation...
+*/
+static void rtp_init_sequence(RTPStatistics *s, uint16_t seq)
+{
+ s->max_seq= seq;
+ s->cycles= 0;
+ s->base_seq= seq -1;
+ s->bad_seq= RTP_SEQ_MOD + 1;
+ s->received= 0;
+ s->expected_prior= 0;
+ s->received_prior= 0;
+ s->jitter= 0;
+ s->transit= 0;
+}
+
+/**
+* returns 1 if we should handle this packet.
+*/
+static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
+{
+ uint16_t udelta= seq - s->max_seq;
+ const int MAX_DROPOUT= 3000;
+ const int MAX_MISORDER = 100;
+ const int MIN_SEQUENTIAL = 2;
+
+ /* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
+ if(s->probation)
+ {
+ if(seq==s->max_seq + 1) {
+ s->probation--;
+ s->max_seq= seq;
+ if(s->probation==0) {
+ rtp_init_sequence(s, seq);
+ s->received++;
+ return 1;
+ }
+ } else {
+ s->probation= MIN_SEQUENTIAL - 1;
+ s->max_seq = seq;
+ }
+ } else if (udelta < MAX_DROPOUT) {
+ // in order, with permissible gap
+ if(seq < s->max_seq) {
+ //sequence number wrapped; count antother 64k cycles
+ s->cycles += RTP_SEQ_MOD;
+ }
+ s->max_seq= seq;
+ } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
+ // sequence made a large jump...
+ if(seq==s->bad_seq) {
+ // two sequential packets-- assume that the other side restarted without telling us; just resync.
+ rtp_init_sequence(s, seq);
+ } else {
+ s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1);
+ return 0;
+ }
+ } else {
+ // duplicate or reordered packet...
+ }
+ s->received++;
+ return 1;
+}
+
+#if 0
+/**
+* This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
+* difference between the arrival and sent timestamp. As a result, the jitter and transit statistics values
+* never change. I left this in in case someone else can see a way. (rdm)
+*/
+static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
+{
+ uint32_t transit= arrival_timestamp - sent_timestamp;
+ int d;
+ s->transit= transit;
+ d= FFABS(transit - s->transit);
+ s->jitter += d - ((s->jitter + 8)>>4);
+}
+#endif
+
+int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
+{
+ ByteIOContext *pb;
+ uint8_t *buf;
+ int len;
+ int rtcp_bytes;
+ RTPStatistics *stats= &s->statistics;
+ uint32_t lost;
+ uint32_t extended_max;
+ uint32_t expected_interval;
+ uint32_t received_interval;
+ uint32_t lost_interval;
+ uint32_t expected;
+ uint32_t fraction;
+ uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
+
+ if (!s->rtp_ctx || (count < 1))
+ return -1;
+
+ /* TODO: I think this is way too often; RFC 1889 has algorithm for this */
+ /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
+ s->octet_count += count;
+ rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
+ RTCP_TX_RATIO_DEN;
+ rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !?
+ if (rtcp_bytes < 28)
+ return -1;
+ s->last_octet_count = s->octet_count;
+
+ if (url_open_dyn_buf(&pb) < 0)
+ return -1;
+
+ // Receiver Report
+ put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
+ put_byte(pb, 201);
+ put_be16(pb, 7); /* length in words - 1 */
+ put_be32(pb, s->ssrc); // our own SSRC
+ put_be32(pb, s->ssrc); // XXX: should be the server's here!
+ // some placeholders we should really fill...
+ // RFC 1889/p64
+ extended_max= stats->cycles + stats->max_seq;
+ expected= extended_max - stats->base_seq + 1;
+ lost= expected - stats->received;
+ lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
+ expected_interval= expected - stats->expected_prior;
+ stats->expected_prior= expected;
+ received_interval= stats->received - stats->received_prior;
+ stats->received_prior= stats->received;
+ lost_interval= expected_interval - received_interval;
+ if (expected_interval==0 || lost_interval<=0) fraction= 0;
+ else fraction = (lost_interval<<8)/expected_interval;
+
+ fraction= (fraction<<24) | lost;
+
+ put_be32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
+ put_be32(pb, extended_max); /* max sequence received */
+ put_be32(pb, stats->jitter>>4); /* jitter */
+
+ if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
+ {
+ put_be32(pb, 0); /* last SR timestamp */
+ put_be32(pb, 0); /* delay since last SR */
+ } else {
+ uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special?
+ uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time;
+
+ put_be32(pb, middle_32_bits); /* last SR timestamp */
+ put_be32(pb, delay_since_last); /* delay since last SR */
+ }
+
+ // CNAME
+ put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
+ put_byte(pb, 202);
+ len = strlen(s->hostname);
+ put_be16(pb, (6 + len + 3) / 4); /* length in words - 1 */
+ put_be32(pb, s->ssrc);
+ put_byte(pb, 0x01);
+ put_byte(pb, len);
+ put_buffer(pb, s->hostname, len);
+ // padding
+ for (len = (6 + len) % 4; len % 4; len++) {
+ put_byte(pb, 0);
+ }
+
+ put_flush_packet(pb);
+ len = url_close_dyn_buf(pb, &buf);
+ if ((len > 0) && buf) {
+ int result;
+#if defined(DEBUG)
+ printf("sending %d bytes of RR\n", len);
+#endif
+ result= url_write(s->rtp_ctx, buf, len);
+#if defined(DEBUG)
+ printf("result from url_write: %d\n", result);
+#endif
+ av_free(buf);
+ }
+ return 0;
+}
+
+/**
+ * open a new RTP parse context for stream 'st'. 'st' can be NULL for
+ * MPEG2TS streams to indicate that they should be demuxed inside the
+ * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
+ * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
+ */
+RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_t *rtp_payload_data)
+{
+ RTPDemuxContext *s;
+
+ s = av_mallocz(sizeof(RTPDemuxContext));
+ if (!s)
+ return NULL;
+ s->payload_type = payload_type;
+ s->last_rtcp_ntp_time = AV_NOPTS_VALUE;
+ s->first_rtcp_ntp_time = AV_NOPTS_VALUE;
+ s->ic = s1;
+ s->st = st;
+ s->rtp_payload_data = rtp_payload_data;
+ rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp?
+ if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) {
+ s->ts = mpegts_parse_open(s->ic);
+ if (s->ts == NULL) {
+ av_free(s);
+ return NULL;
+ }
+ } else {
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ case CODEC_ID_MPEG4:
+ case CODEC_ID_H264:
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ break;
+ default:
+ break;
+ }
+ }
+ // needed to send back RTCP RR in RTSP sessions
+ s->rtp_ctx = rtpc;
+ gethostname(s->hostname, sizeof(s->hostname));
+ return s;
+}
+
+static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf)
+{
+ int au_headers_length, au_header_size, i;
+ GetBitContext getbitcontext;
+ rtp_payload_data_t *infos;
+
+ infos = s->rtp_payload_data;
+
+ if (infos == NULL)
+ return -1;
+
+ /* decode the first 2 bytes where are stored the AUHeader sections
+ length in bits */
+ au_headers_length = AV_RB16(buf);
+
+ if (au_headers_length > RTP_MAX_PACKET_LENGTH)
+ return -1;
+
+ infos->au_headers_length_bytes = (au_headers_length + 7) / 8;
+
+ /* skip AU headers length section (2 bytes) */
+ buf += 2;
+
+ init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
+
+ /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
+ au_header_size = infos->sizelength + infos->indexlength;
+ if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
+ return -1;
+
+ infos->nb_au_headers = au_headers_length / au_header_size;
+ infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers);
+
+ /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
+ In my test, the FAAD decoder does not behave correctly when sending each AU one by one
+ but does when sending the whole as one big packet... */
+ infos->au_headers[0].size = 0;
+ infos->au_headers[0].index = 0;
+ for (i = 0; i < infos->nb_au_headers; ++i) {
+ infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
+ infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
+ }
+
+ infos->nb_au_headers = 1;
+
+ return 0;
+}
+
+/**
+ * This was the second switch in rtp_parse packet. Normalizes time, if required, sets stream_index, etc.
+ */
+static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp)
+{
+ switch(s->st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
+ int64_t addend;
+
+ int delta_timestamp;
+ /* XXX: is it really necessary to unify the timestamp base ? */
+ /* compute pts from timestamp with received ntp_time */
+ delta_timestamp = timestamp - s->last_rtcp_timestamp;
+ /* convert to 90 kHz without overflow */
+ addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14;
+ addend = (addend * 5625) >> 14;
+ pkt->pts = addend + delta_timestamp;
+ }
+ break;
+ case CODEC_ID_AAC:
+ case CODEC_ID_H264:
+ case CODEC_ID_MPEG4:
+ pkt->pts = timestamp;
+ break;
+ default:
+ /* no timestamp info yet */
+ break;
+ }
+ pkt->stream_index = s->st->index;
+}
+
+/**
+ * Parse an RTP or RTCP packet directly sent as a buffer.
+ * @param s RTP parse context.
+ * @param pkt returned packet
+ * @param buf input buffer or NULL to read the next packets
+ * @param len buffer len
+ * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
+ * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
+ */
+int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
+ const uint8_t *buf, int len)
+{
+ unsigned int ssrc, h;
+ int payload_type, seq, ret, flags = 0;
+ AVStream *st;
+ uint32_t timestamp;
+ int rv= 0;
+
+ if (!buf) {
+ /* return the next packets, if any */
+ if(s->st && s->parse_packet) {
+ timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
+ rv= s->parse_packet(s, pkt, &timestamp, NULL, 0, flags);
+ finalize_packet(s, pkt, timestamp);
+ return rv;
+ } else {
+ // TODO: Move to a dynamic packet handler (like above)
+ if (s->read_buf_index >= s->read_buf_size)
+ return -1;
+ ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
+ s->read_buf_size - s->read_buf_index);
+ if (ret < 0)
+ return -1;
+ s->read_buf_index += ret;
+ if (s->read_buf_index < s->read_buf_size)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ if (len < 12)
+ return -1;
+
+ if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
+ return -1;
+ if (buf[1] >= 200 && buf[1] <= 204) {
+ rtcp_parse_packet(s, buf, len);
+ return -1;
+ }
+ payload_type = buf[1] & 0x7f;
+ seq = AV_RB16(buf + 2);
+ timestamp = AV_RB32(buf + 4);
+ ssrc = AV_RB32(buf + 8);
+ /* store the ssrc in the RTPDemuxContext */
+ s->ssrc = ssrc;
+
+ /* NOTE: we can handle only one payload type */
+ if (s->payload_type != payload_type)
+ return -1;
+
+ st = s->st;
+ // only do something with this if all the rtp checks pass...
+ if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
+ {
+ av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
+ payload_type, seq, ((s->seq + 1) & 0xffff));
+ return -1;
+ }
+
+ s->seq = seq;
+ len -= 12;
+ buf += 12;
+
+ if (!st) {
+ /* specific MPEG2TS demux support */
+ ret = mpegts_parse_packet(s->ts, pkt, buf, len);
+ if (ret < 0)
+ return -1;
+ if (ret < len) {
+ s->read_buf_size = len - ret;
+ memcpy(s->buf, buf + ret, s->read_buf_size);
+ s->read_buf_index = 0;
+ return 1;
+ }
+ } else if (s->parse_packet) {
+ rv = s->parse_packet(s, pkt, &timestamp, buf, len, flags);
+ } else {
+ // at this point, the RTP header has been stripped; This is ASSUMING that there is only 1 CSRC, which in't wise.
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ /* better than nothing: skip mpeg audio RTP header */
+ if (len <= 4)
+ return -1;
+ h = AV_RB32(buf);
+ len -= 4;
+ buf += 4;
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ /* better than nothing: skip mpeg video RTP header */
+ if (len <= 4)
+ return -1;
+ h = AV_RB32(buf);
+ buf += 4;
+ len -= 4;
+ if (h & (1 << 26)) {
+ /* mpeg2 */
+ if (len <= 4)
+ return -1;
+ buf += 4;
+ len -= 4;
+ }
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ break;
+ // moved from below, verbatim. this is because this section handles packets, and the lower switch handles
+ // timestamps.
+ // TODO: Put this into a dynamic packet handler...
+ case CODEC_ID_AAC:
+ if (rtp_parse_mp4_au(s, buf))
+ return -1;
+ {
+ rtp_payload_data_t *infos = s->rtp_payload_data;
+ if (infos == NULL)
+ return -1;
+ buf += infos->au_headers_length_bytes + 2;
+ len -= infos->au_headers_length_bytes + 2;
+
+ /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
+ one au_header */
+ av_new_packet(pkt, infos->au_headers[0].size);
+ memcpy(pkt->data, buf, infos->au_headers[0].size);
+ buf += infos->au_headers[0].size;
+ len -= infos->au_headers[0].size;
+ }
+ s->read_buf_size = len;
+ rv= 0;
+ break;
+ default:
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ break;
+ }
+
+ // now perform timestamp things....
+ finalize_packet(s, pkt, timestamp);
+ }
+ return rv;
+}
+
+void rtp_parse_close(RTPDemuxContext *s)
+{
+ // TODO: fold this into the protocol specific data fields.
+ if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) {
+ mpegts_parse_close(s->ts);
+ }
+ av_free(s);
+}
diff --git a/contrib/ffmpeg/libavformat/rtpenc.c b/contrib/ffmpeg/libavformat/rtpenc.c
new file mode 100644
index 000000000..19e4f19fe
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtpenc.c
@@ -0,0 +1,366 @@
+/*
+ * RTP output format
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * 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 "avformat.h"
+#include "mpegts.h"
+#include "bitstream.h"
+
+#include <unistd.h>
+#include "network.h"
+
+#include "rtp_internal.h"
+#include "rtp_mpv.h"
+#include "rtp_aac.h"
+#include "rtp_h264.h"
+
+//#define DEBUG
+
+#define RTCP_SR_SIZE 28
+#define NTP_OFFSET 2208988800ULL
+#define NTP_OFFSET_US (NTP_OFFSET * 1000000ULL)
+
+static uint64_t ntp_time(void)
+{
+ return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
+}
+
+static int rtp_write_header(AVFormatContext *s1)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int payload_type, max_packet_size, n;
+ AVStream *st;
+
+ if (s1->nb_streams != 1)
+ return -1;
+ st = s1->streams[0];
+
+ payload_type = rtp_get_payload_type(st->codec);
+ if (payload_type < 0)
+ payload_type = RTP_PT_PRIVATE; /* private payload type */
+ s->payload_type = payload_type;
+
+// following 2 FIXMEs could be set based on the current time, there is normally no info leak, as RTP will likely be transmitted immediately
+ s->base_timestamp = 0; /* FIXME: was random(), what should this be? */
+ s->timestamp = s->base_timestamp;
+ s->cur_timestamp = 0;
+ s->ssrc = 0; /* FIXME: was random(), what should this be? */
+ s->first_packet = 1;
+ s->first_rtcp_ntp_time = AV_NOPTS_VALUE;
+
+ max_packet_size = url_fget_max_packet_size(s1->pb);
+ if (max_packet_size <= 12)
+ return AVERROR(EIO);
+ s->max_payload_size = max_packet_size - 12;
+
+ s->max_frames_per_packet = 0;
+ if (s1->max_delay) {
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (st->codec->frame_size == 0) {
+ av_log(s1, AV_LOG_ERROR, "Cannot respect max delay: frame size = 0\n");
+ } else {
+ s->max_frames_per_packet = av_rescale_rnd(s1->max_delay, st->codec->sample_rate, AV_TIME_BASE * st->codec->frame_size, AV_ROUND_DOWN);
+ }
+ }
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ /* FIXME: We should round down here... */
+ s->max_frames_per_packet = av_rescale_q(s1->max_delay, AV_TIME_BASE_Q, st->codec->time_base);
+ }
+ }
+
+ av_set_pts_info(st, 32, 1, 90000);
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ s->buf_ptr = s->buf + 4;
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ break;
+ case CODEC_ID_MPEG2TS:
+ n = s->max_payload_size / TS_PACKET_SIZE;
+ if (n < 1)
+ n = 1;
+ s->max_payload_size = n * TS_PACKET_SIZE;
+ s->buf_ptr = s->buf;
+ break;
+ case CODEC_ID_AAC:
+ s->read_buf_index = 0;
+ default:
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ av_set_pts_info(st, 32, 1, st->codec->sample_rate);
+ }
+ s->buf_ptr = s->buf;
+ break;
+ }
+
+ return 0;
+}
+
+/* send an rtcp sender report packet */
+static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ uint32_t rtp_ts;
+
+#if defined(DEBUG)
+ printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp);
+#endif
+
+ if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) s->first_rtcp_ntp_time = ntp_time;
+ s->last_rtcp_ntp_time = ntp_time;
+ rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, AV_TIME_BASE_Q,
+ s1->streams[0]->time_base) + s->base_timestamp;
+ put_byte(s1->pb, (RTP_VERSION << 6));
+ put_byte(s1->pb, 200);
+ put_be16(s1->pb, 6); /* length in words - 1 */
+ put_be32(s1->pb, s->ssrc);
+ put_be32(s1->pb, ntp_time / 1000000);
+ put_be32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000);
+ put_be32(s1->pb, rtp_ts);
+ put_be32(s1->pb, s->packet_count);
+ put_be32(s1->pb, s->octet_count);
+ put_flush_packet(s1->pb);
+}
+
+/* send an rtp packet. sequence number is incremented, but the caller
+ must update the timestamp itself */
+void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m)
+{
+ RTPDemuxContext *s = s1->priv_data;
+
+#ifdef DEBUG
+ printf("rtp_send_data size=%d\n", len);
+#endif
+
+ /* build the RTP header */
+ put_byte(s1->pb, (RTP_VERSION << 6));
+ put_byte(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7));
+ put_be16(s1->pb, s->seq);
+ put_be32(s1->pb, s->timestamp);
+ put_be32(s1->pb, s->ssrc);
+
+ put_buffer(s1->pb, buf1, len);
+ put_flush_packet(s1->pb);
+
+ s->seq++;
+ s->octet_count += len;
+ s->packet_count++;
+}
+
+/* send an integer number of samples and compute time stamp and fill
+ the rtp send buffer before sending. */
+static void rtp_send_samples(AVFormatContext *s1,
+ const uint8_t *buf1, int size, int sample_size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, max_packet_size, n;
+
+ max_packet_size = (s->max_payload_size / sample_size) * sample_size;
+ /* not needed, but who nows */
+ if ((size % sample_size) != 0)
+ av_abort();
+ n = 0;
+ while (size > 0) {
+ s->buf_ptr = s->buf;
+ len = FFMIN(max_packet_size, size);
+
+ /* copy data */
+ memcpy(s->buf_ptr, buf1, len);
+ s->buf_ptr += len;
+ buf1 += len;
+ size -= len;
+ s->timestamp = s->cur_timestamp + n / sample_size;
+ ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
+ n += (s->buf_ptr - s->buf);
+ }
+}
+
+/* NOTE: we suppose that exactly one frame is given as argument here */
+/* XXX: test it */
+static void rtp_send_mpegaudio(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, count, max_packet_size;
+
+ max_packet_size = s->max_payload_size;
+
+ /* test if we must flush because not enough space */
+ len = (s->buf_ptr - s->buf);
+ if ((len + size) > max_packet_size) {
+ if (len > 4) {
+ ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
+ s->buf_ptr = s->buf + 4;
+ }
+ }
+ if (s->buf_ptr == s->buf + 4) {
+ s->timestamp = s->cur_timestamp;
+ }
+
+ /* add the packet */
+ if (size > max_packet_size) {
+ /* big packet: fragment */
+ count = 0;
+ while (size > 0) {
+ len = max_packet_size - 4;
+ if (len > size)
+ len = size;
+ /* build fragmented packet */
+ s->buf[0] = 0;
+ s->buf[1] = 0;
+ s->buf[2] = count >> 8;
+ s->buf[3] = count;
+ memcpy(s->buf + 4, buf1, len);
+ ff_rtp_send_data(s1, s->buf, len + 4, 0);
+ size -= len;
+ buf1 += len;
+ count += len;
+ }
+ } else {
+ if (s->buf_ptr == s->buf + 4) {
+ /* no fragmentation possible */
+ s->buf[0] = 0;
+ s->buf[1] = 0;
+ s->buf[2] = 0;
+ s->buf[3] = 0;
+ }
+ memcpy(s->buf_ptr, buf1, size);
+ s->buf_ptr += size;
+ }
+}
+
+static void rtp_send_raw(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, max_packet_size;
+
+ max_packet_size = s->max_payload_size;
+
+ while (size > 0) {
+ len = max_packet_size;
+ if (len > size)
+ len = size;
+
+ s->timestamp = s->cur_timestamp;
+ ff_rtp_send_data(s1, buf1, len, (len == size));
+
+ buf1 += len;
+ size -= len;
+ }
+}
+
+/* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */
+static void rtp_send_mpegts_raw(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, out_len;
+
+ while (size >= TS_PACKET_SIZE) {
+ len = s->max_payload_size - (s->buf_ptr - s->buf);
+ if (len > size)
+ len = size;
+ memcpy(s->buf_ptr, buf1, len);
+ buf1 += len;
+ size -= len;
+ s->buf_ptr += len;
+
+ out_len = s->buf_ptr - s->buf;
+ if (out_len >= s->max_payload_size) {
+ ff_rtp_send_data(s1, s->buf, out_len, 0);
+ s->buf_ptr = s->buf;
+ }
+ }
+}
+
+/* write an RTP packet. 'buf1' must contain a single specific frame. */
+static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int rtcp_bytes;
+ int size= pkt->size;
+ uint8_t *buf1= pkt->data;
+
+#ifdef DEBUG
+ printf("%d: write len=%d\n", pkt->stream_index, size);
+#endif
+
+ /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
+ rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
+ RTCP_TX_RATIO_DEN;
+ if (s->first_packet || ((rtcp_bytes >= RTCP_SR_SIZE) &&
+ (ntp_time() - s->last_rtcp_ntp_time > 5000000))) {
+ rtcp_send_sr(s1, ntp_time());
+ s->last_octet_count = s->octet_count;
+ s->first_packet = 0;
+ }
+ s->cur_timestamp = s->base_timestamp + pkt->pts;
+
+ switch(st->codec->codec_id) {
+ case CODEC_ID_PCM_MULAW:
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_U8:
+ case CODEC_ID_PCM_S8:
+ rtp_send_samples(s1, buf1, size, 1 * st->codec->channels);
+ break;
+ case CODEC_ID_PCM_U16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_S16LE:
+ rtp_send_samples(s1, buf1, size, 2 * st->codec->channels);
+ break;
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ rtp_send_mpegaudio(s1, buf1, size);
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ ff_rtp_send_mpegvideo(s1, buf1, size);
+ break;
+ case CODEC_ID_AAC:
+ ff_rtp_send_aac(s1, buf1, size);
+ break;
+ case CODEC_ID_MPEG2TS:
+ rtp_send_mpegts_raw(s1, buf1, size);
+ break;
+ case CODEC_ID_H264:
+ ff_rtp_send_h264(s1, buf1, size);
+ break;
+ default:
+ /* better than nothing : send the codec raw data */
+ rtp_send_raw(s1, buf1, size);
+ break;
+ }
+ return 0;
+}
+
+AVOutputFormat rtp_muxer = {
+ "rtp",
+ "RTP output format",
+ NULL,
+ NULL,
+ sizeof(RTPDemuxContext),
+ CODEC_ID_PCM_MULAW,
+ CODEC_ID_NONE,
+ rtp_write_header,
+ rtp_write_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/rtpenc_h264.c b/contrib/ffmpeg/libavformat/rtpenc_h264.c
new file mode 100644
index 000000000..95d5fff81
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtpenc_h264.c
@@ -0,0 +1,78 @@
+/*
+ * RTP packetization for H.264 (RFC3984)
+ * Copyright (c) 2008 Luca Abeni.
+ *
+ * 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 rtpenc_h264.c
+ * @brief H.264 packetization
+ * @author Luca Abeni <lucabe72@email.it>
+ */
+
+#include "avformat.h"
+#include "avc.h"
+#include "rtp_h264.h"
+
+static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last)
+{
+ RTPDemuxContext *s = s1->priv_data;
+
+ av_log(s1, AV_LOG_DEBUG, "Sending NAL %x of len %d M=%d\n", buf[0] & 0x1F, size, last);
+ if (size <= s->max_payload_size) {
+ ff_rtp_send_data(s1, buf, size, last);
+ } else {
+ uint8_t type = buf[0] & 0x1F;
+ uint8_t nri = buf[0] & 0x60;
+
+ av_log(s1, AV_LOG_DEBUG, "NAL size %d > %d\n", size, s->max_payload_size);
+ s->buf[0] = 28; /* FU Indicator; Type = 28 ---> FU-A */
+ s->buf[0] |= nri;
+ s->buf[1] = type;
+ s->buf[1] |= 1 << 7;
+ buf += 1;
+ size -= 1;
+ while (size + 2 > s->max_payload_size) {
+ memcpy(&s->buf[2], buf, s->max_payload_size - 2);
+ ff_rtp_send_data(s1, s->buf, s->max_payload_size, 0);
+ buf += s->max_payload_size - 2;
+ size -= s->max_payload_size - 2;
+ s->buf[1] &= ~(1 << 7);
+ }
+ s->buf[1] |= 1 << 6;
+ memcpy(&s->buf[2], buf, size);
+ ff_rtp_send_data(s1, s->buf, size + 2, 1);
+ }
+}
+
+void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size)
+{
+ const uint8_t *r;
+ RTPDemuxContext *s = s1->priv_data;
+
+ s->timestamp = s->cur_timestamp;
+ r = ff_avc_find_startcode(buf1, buf1 + size);
+ while (r < buf1 + size) {
+ const uint8_t *r1;
+
+ while(!*(r++));
+ r1 = ff_avc_find_startcode(r, buf1 + size);
+ nal_send(s1, r, r1 - r, (r1 == buf1 + size));
+ r = r1;
+ }
+}
diff --git a/contrib/ffmpeg/libavformat/rtpproto.c b/contrib/ffmpeg/libavformat/rtpproto.c
index 4d32e667d..d1d5a9247 100644
--- a/contrib/ffmpeg/libavformat/rtpproto.c
+++ b/contrib/ffmpeg/libavformat/rtpproto.c
@@ -19,10 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
+#include "avstring.h"
#include <unistd.h>
#include <stdarg.h>
#include "network.h"
+#include "os_support.h"
#include <fcntl.h>
#define RTP_TX_BUF_SIZE (64 * 1024)
@@ -72,11 +74,11 @@ static void url_add_option(char *buf, int buf_size, const char *fmt, ...)
va_start(ap, fmt);
if (strchr(buf, '?'))
- pstrcat(buf, buf_size, "&");
+ av_strlcat(buf, "&", buf_size);
else
- pstrcat(buf, buf_size, "?");
+ av_strlcat(buf, "?", buf_size);
vsnprintf(buf1, sizeof(buf1), fmt, ap);
- pstrcat(buf, buf_size, buf1);
+ av_strlcat(buf, buf1, buf_size);
va_end(ap);
}
@@ -138,7 +140,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
if (url_open(&s->rtp_hd, buf, flags) < 0)
goto fail;
local_port = udp_get_local_port(s->rtp_hd);
- /* XXX: need to open another connexion if the port is not even */
+ /* XXX: need to open another connection if the port is not even */
/* well, should suppress localport in path */
@@ -162,7 +164,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
if (s->rtcp_hd)
url_close(s->rtcp_hd);
av_free(s);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
static int rtp_read(URLContext *h, uint8_t *buf, int size)
@@ -178,9 +180,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
len = recvfrom (s->rtp_fd, buf, size, 0,
(struct sockaddr *)&from, &from_len);
if (len < 0) {
- if (errno == EAGAIN || errno == EINTR)
+ if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
+ ff_neterrno() == FF_NETERROR(EINTR))
continue;
- return AVERROR_IO;
+ return AVERROR(EIO);
}
break;
}
@@ -201,9 +204,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
len = recvfrom (s->rtcp_fd, buf, size, 0,
(struct sockaddr *)&from, &from_len);
if (len < 0) {
- if (errno == EAGAIN || errno == EINTR)
+ if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
+ ff_neterrno() == FF_NETERROR(EINTR))
continue;
- return AVERROR_IO;
+ return AVERROR(EIO);
}
break;
}
@@ -213,9 +217,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
len = recvfrom (s->rtp_fd, buf, size, 0,
(struct sockaddr *)&from, &from_len);
if (len < 0) {
- if (errno == EAGAIN || errno == EINTR)
+ if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
+ ff_neterrno() == FF_NETERROR(EINTR))
continue;
- return AVERROR_IO;
+ return AVERROR(EIO);
}
break;
}
@@ -262,7 +267,7 @@ static int rtp_close(URLContext *h)
}
/**
- * Return the local port used by the RTP connexion
+ * Return the local port used by the RTP connection
* @param s1 media file context
* @return the local port number
*/
diff --git a/contrib/ffmpeg/libavformat/rtsp.c b/contrib/ffmpeg/libavformat/rtsp.c
index 7d4c6bf78..14f0a5ce4 100644
--- a/contrib/ffmpeg/libavformat/rtsp.c
+++ b/contrib/ffmpeg/libavformat/rtsp.c
@@ -23,6 +23,8 @@
#include <sys/time.h>
#include <unistd.h> /* for select() prototype */
#include "network.h"
+#include "avstring.h"
+#include "rtsp.h"
#include "rtp_internal.h"
@@ -75,13 +77,13 @@ static int rtsp_read_play(AVFormatContext *s);
/* XXX: currently, the only way to change the protocols consists in
changing this variable */
+#if LIBAVFORMAT_VERSION_INT < (53 << 16)
int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP);
-
-FFRTSPCallback *ff_rtsp_callback = NULL;
+#endif
static int rtsp_probe(AVProbeData *p)
{
- if (strstart(p->filename, "rtsp:", NULL))
+ if (av_strstart(p->filename, "rtsp:", NULL))
return AVPROBE_SCORE_MAX;
return 0;
}
@@ -167,11 +169,7 @@ static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payl
} else {
/* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
/* search into AVRtpPayloadTypes[] */
- for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
- if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){
- codec->codec_id = AVRtpPayloadTypes[i].codec_id;
- break;
- }
+ codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
}
c = avcodec_find_decoder(codec->codec_id);
@@ -339,7 +337,7 @@ static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
char buf[256];
skip_spaces(&p);
- if (!stristart(p, "npt=", &p))
+ if (!av_stristart(p, "npt=", &p))
return;
*start = AV_NOPTS_VALUE;
@@ -407,11 +405,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
}
break;
case 's':
- pstrcpy(s->title, sizeof(s->title), p);
+ av_strlcpy(s->title, p, sizeof(s->title));
break;
case 'i':
if (s->nb_streams == 0) {
- pstrcpy(s->comment, sizeof(s->comment), p);
+ av_strlcpy(s->comment, p, sizeof(s->comment));
break;
}
break;
@@ -443,7 +441,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
get_word(buf1, sizeof(buf1), &p); /* format list */
rtsp_st->sdp_payload_type = atoi(buf1);
- if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) {
+ if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
/* no corresponding stream */
} else {
st = av_new_stream(s, 0);
@@ -458,10 +456,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
}
}
/* put a default control url */
- pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename);
+ av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url));
break;
case 'a':
- if (strstart(p, "control:", &p) && s->nb_streams > 0) {
+ if (av_strstart(p, "control:", &p) && s->nb_streams > 0) {
char proto[32];
/* get the control url */
st = s->streams[s->nb_streams - 1];
@@ -471,12 +469,12 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
if (proto[0] == '\0') {
/* relative control URL */
- pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
- pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
+ av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url));
+ av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
} else {
- pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
+ av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
}
- } else if (strstart(p, "rtpmap:", &p)) {
+ } else if (av_strstart(p, "rtpmap:", &p)) {
/* NOTE: rtpmap is only supported AFTER the 'm=' tag */
get_word(buf1, sizeof(buf1), &p);
payload_type = atoi(buf1);
@@ -487,7 +485,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
}
}
- } else if (strstart(p, "fmtp:", &p)) {
+ } else if (av_strstart(p, "fmtp:", &p)) {
/* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
get_word(buf1, sizeof(buf1), &p);
payload_type = atoi(buf1);
@@ -504,7 +502,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
}
}
}
- } else if(strstart(p, "framesize:", &p)) {
+ } else if(av_strstart(p, "framesize:", &p)) {
// let dynamic protocol handlers have a stab at the line.
get_word(buf1, sizeof(buf1), &p);
payload_type = atoi(buf1);
@@ -517,7 +515,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
}
}
}
- } else if(strstart(p, "range:", &p)) {
+ } else if(av_strstart(p, "range:", &p)) {
int64_t start, end;
// this is so that seeking on a streamed file can work.
@@ -608,12 +606,19 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
"/", &p);
if (*p == '/')
p++;
- get_word_sep(profile, sizeof(profile), "/;,", &p);
- lower_transport[0] = '\0';
- if (*p == '/') {
- p++;
- get_word_sep(lower_transport, sizeof(lower_transport),
- ";,", &p);
+ if (!strcasecmp (transport_protocol, "rtp")) {
+ get_word_sep(profile, sizeof(profile), "/;,", &p);
+ lower_transport[0] = '\0';
+ /* rtp/avp/<protocol> */
+ if (*p == '/') {
+ p++;
+ get_word_sep(lower_transport, sizeof(lower_transport),
+ ";,", &p);
+ }
+ } else if (!strcasecmp (transport_protocol, "x-pn-tng")) {
+ /* x-pn-tng/<protocol> */
+ get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
+ profile[0] = '\0';
}
if (!strcasecmp(lower_transport, "TCP"))
th->protocol = RTSP_PROTOCOL_RTP_TCP;
@@ -684,15 +689,15 @@ void rtsp_parse_line(RTSPHeader *reply, const char *buf)
/* NOTE: we do case independent match for broken servers */
p = buf;
- if (stristart(p, "Session:", &p)) {
+ if (av_stristart(p, "Session:", &p)) {
get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
- } else if (stristart(p, "Content-Length:", &p)) {
+ } else if (av_stristart(p, "Content-Length:", &p)) {
reply->content_length = strtol(p, NULL, 10);
- } else if (stristart(p, "Transport:", &p)) {
+ } else if (av_stristart(p, "Transport:", &p)) {
rtsp_parse_transport(reply, p);
- } else if (stristart(p, "CSeq:", &p)) {
+ } else if (av_stristart(p, "CSeq:", &p)) {
reply->seq = strtol(p, NULL, 10);
- } else if (stristart(p, "Range:", &p)) {
+ } else if (av_stristart(p, "Range:", &p)) {
rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
}
}
@@ -721,7 +726,7 @@ static void rtsp_skip_packet(AVFormatContext *s)
ret = url_readbuf(rt->rtsp_hd, buf, 3);
if (ret != 3)
return;
- len = (buf[1] << 8) | buf[2];
+ len = AV_RB16(buf + 1);
#ifdef DEBUG
printf("skipping RTP packet len=%d\n", len);
#endif
@@ -751,14 +756,14 @@ static void rtsp_send_cmd(AVFormatContext *s,
memset(reply, 0, sizeof(RTSPHeader));
rt->seq++;
- pstrcpy(buf, sizeof(buf), cmd);
+ av_strlcpy(buf, cmd, sizeof(buf));
snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
- pstrcat(buf, sizeof(buf), buf1);
+ av_strlcat(buf, buf1, sizeof(buf));
if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
- pstrcat(buf, sizeof(buf), buf1);
+ av_strlcat(buf, buf1, sizeof(buf));
}
- pstrcat(buf, sizeof(buf), "\r\n");
+ av_strlcat(buf, "\r\n", sizeof(buf));
#ifdef DEBUG
printf("Sending:\n%s--\n", buf);
#endif
@@ -797,14 +802,14 @@ static void rtsp_send_cmd(AVFormatContext *s,
reply->status_code = atoi(buf1);
} else {
rtsp_parse_line(reply, p);
- pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
- pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
+ av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
+ av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
}
line_count++;
}
if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
- pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
+ av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
content_length = reply->content_length;
if (content_length > 0) {
@@ -815,12 +820,8 @@ static void rtsp_send_cmd(AVFormatContext *s,
}
if (content_ptr)
*content_ptr = content;
-}
-
-
-void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
-{
- ff_rtsp_callback = rtsp_cb;
+ else
+ av_free(content);
}
@@ -849,13 +850,13 @@ static int rtsp_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
RTSPState *rt = s->priv_data;
- char host[1024], path[1024], tcpname[1024], cmd[2048];
+ char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
URLContext *rtsp_hd;
int port, i, j, ret, err;
RTSPHeader reply1, *reply = &reply1;
unsigned char *content = NULL;
RTSPStream *rtsp_st;
- int protocol_mask;
+ int protocol_mask = 0;
AVStream *st;
/* extract hostname and port */
@@ -864,10 +865,34 @@ static int rtsp_read_header(AVFormatContext *s,
if (port < 0)
port = RTSP_DEFAULT_PORT;
+ /* search for options */
+ option_list = strchr(path, '?');
+ if (option_list) {
+ /* remove the options from the path */
+ *option_list++ = 0;
+ while(option_list) {
+ /* move the option pointer */
+ option = option_list;
+ option_list = strchr(option_list, '&');
+ if (option_list)
+ *(option_list++) = 0;
+ /* handle the options */
+ if (strcmp(option, "udp") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP);
+ else if (strcmp(option, "multicast") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+ else if (strcmp(option, "tcp") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP);
+ }
+ }
+
+ if (!protocol_mask)
+ protocol_mask = rtsp_default_protocols;
+
/* open the tcp connexion */
snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
rt->rtsp_hd = rtsp_hd;
rt->seq = 0;
@@ -894,8 +919,6 @@ static int rtsp_read_header(AVFormatContext *s,
goto fail;
}
- protocol_mask = rtsp_default_protocols;
-
/* for each stream, make the setup request */
/* XXX: we assume the same server is used for the control of each
RTSP stream */
@@ -915,9 +938,9 @@ static int rtsp_read_header(AVFormatContext *s,
/* first try in specified port range */
if (RTSP_RTP_PORT_MIN != 0) {
while(j <= RTSP_RTP_PORT_MAX) {
- snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
+ snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j);
+ j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
- j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
goto rtp_opened;
}
}
@@ -933,7 +956,7 @@ static int rtsp_read_header(AVFormatContext *s,
rtp_opened:
port = rtp_get_local_port(rtsp_st->rtp_handle);
if (transport[0] != '\0')
- pstrcat(transport, sizeof(transport), ",");
+ av_strlcat(transport, ",", sizeof(transport));
snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
"RTP/AVP/UDP;unicast;client_port=%d-%d",
port, port + 1);
@@ -942,14 +965,14 @@ static int rtsp_read_header(AVFormatContext *s,
/* RTP/TCP */
else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
if (transport[0] != '\0')
- pstrcat(transport, sizeof(transport), ",");
+ av_strlcat(transport, ",", sizeof(transport));
snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
"RTP/AVP/TCP");
}
else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
if (transport[0] != '\0')
- pstrcat(transport, sizeof(transport), ",");
+ av_strlcat(transport, ",", sizeof(transport));
snprintf(transport + strlen(transport),
sizeof(transport) - strlen(transport) - 1,
"RTP/AVP/UDP;multicast");
@@ -1004,15 +1027,13 @@ static int rtsp_read_header(AVFormatContext *s,
case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
{
char url[1024];
- int ttl;
+ struct in_addr in;
- ttl = reply->transports[0].ttl;
- if (!ttl)
- ttl = 16;
+ in.s_addr = htonl(reply->transports[0].destination);
snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",
- host,
- reply->transports[0].server_port_min,
- ttl);
+ inet_ntoa(in),
+ reply->transports[0].port_min,
+ reply->transports[0].ttl);
if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
err = AVERROR_INVALIDDATA;
goto fail;
@@ -1029,7 +1050,7 @@ static int rtsp_read_header(AVFormatContext *s,
rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
if (!rtsp_st->rtp_ctx) {
- err = AVERROR_NOMEM;
+ err = AVERROR(ENOMEM);
goto fail;
} else {
if(rtsp_st->dynamic_handler) {
@@ -1039,16 +1060,6 @@ static int rtsp_read_header(AVFormatContext *s,
}
}
- /* use callback if available to extend setup */
- if (ff_rtsp_callback) {
- if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id,
- NULL, 0, rt->last_reply) < 0) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
-
-
rt->state = RTSP_STATE_IDLE;
rt->seek_timestamp = 0; /* default is to start stream at position
zero */
@@ -1093,7 +1104,7 @@ static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
if (ret != 3)
return -1;
id = buf[0];
- len = (buf[1] << 8) | buf[2];
+ len = AV_RB16(buf + 1);
#ifdef DEBUG_RTP_TCP
printf("id=%d len=%d\n", id, len);
#endif
@@ -1128,7 +1139,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
for(;;) {
if (url_interrupt_cb())
- return -1;
+ return AVERROR(EINTR);
FD_ZERO(&rfds);
fd_max = -1;
for(i = 0; i < rt->nb_rtsp_streams; i++) {
@@ -1189,12 +1200,12 @@ static int rtsp_read_packet(AVFormatContext *s,
case RTSP_PROTOCOL_RTP_UDP:
case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
- if (rtsp_st->rtp_ctx)
+ if (len >=0 && rtsp_st->rtp_ctx)
rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len);
break;
}
if (len < 0)
- return AVERROR_IO;
+ return len;
ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
if (ret < 0)
goto redo;
@@ -1262,7 +1273,7 @@ static int rtsp_read_seek(AVFormatContext *s, int stream_index,
{
RTSPState *rt = s->priv_data;
- rt->seek_timestamp = timestamp;
+ rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q);
switch(rt->state) {
default:
case RTSP_STATE_IDLE:
@@ -1295,16 +1306,12 @@ static int rtsp_read_close(AVFormatContext *s)
s->filename);
rtsp_send_cmd(s, cmd, reply, NULL);
- if (ff_rtsp_callback) {
- ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id,
- NULL, 0, NULL);
- }
-
rtsp_close_streams(rt);
url_close(rt->rtsp_hd);
return 0;
}
+#ifdef CONFIG_RTSP_DEMUXER
AVInputFormat rtsp_demuxer = {
"rtsp",
"RTSP input format",
@@ -1318,6 +1325,7 @@ AVInputFormat rtsp_demuxer = {
.read_play = rtsp_read_play,
.read_pause = rtsp_read_pause,
};
+#endif
static int sdp_probe(AVProbeData *p1)
{
@@ -1325,7 +1333,7 @@ static int sdp_probe(AVProbeData *p1)
/* we look for a line beginning "c=IN IP4" */
while (p < p_end && *p != '\0') {
- if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL))
+ if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL))
return AVPROBE_SCORE_MAX / 2;
while(p < p_end - 1 && *p != '\n') p++;
@@ -1352,7 +1360,7 @@ static int sdp_read_header(AVFormatContext *s,
/* read the whole sdp file */
/* XXX: better loading */
content = av_malloc(SDP_MAX_SIZE);
- size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);
+ size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
if (size <= 0) {
av_free(content);
return AVERROR_INVALIDDATA;
@@ -1382,7 +1390,7 @@ static int sdp_read_header(AVFormatContext *s,
s->ctx_flags |= AVFMTCTX_NOHEADER;
rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
if (!rtsp_st->rtp_ctx) {
- err = AVERROR_NOMEM;
+ err = AVERROR(ENOMEM);
goto fail;
} else {
if(rtsp_st->dynamic_handler) {
@@ -1422,6 +1430,7 @@ AVInputFormat sdp_demuxer = {
};
#endif
+#ifdef CONFIG_REDIR_DEMUXER
/* dummy redirector format (used directly in av_open_input_file now) */
static int redir_probe(AVProbeData *pd)
{
@@ -1429,18 +1438,18 @@ static int redir_probe(AVProbeData *pd)
p = pd->buf;
while (redir_isspace(*p))
p++;
- if (strstart(p, "http://", NULL) ||
- strstart(p, "rtsp://", NULL))
+ if (av_strstart(p, "http://", NULL) ||
+ av_strstart(p, "rtsp://", NULL))
return AVPROBE_SCORE_MAX;
return 0;
}
-/* called from utils.c */
-int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
+static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
char buf[4096], *q;
int c;
AVFormatContext *ic = NULL;
+ ByteIOContext *f = s->pb;
/* parse each URL and try to open it */
c = url_fgetc(f);
@@ -1468,11 +1477,13 @@ int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
break;
}
- *ic_ptr = ic;
if (!ic)
- return AVERROR_IO;
- else
- return 0;
+ return AVERROR(EIO);
+
+ *s = *ic;
+ url_fclose(f);
+
+ return 0;
}
AVInputFormat redir_demuxer = {
@@ -1480,7 +1491,8 @@ AVInputFormat redir_demuxer = {
"Redirector format",
0,
redir_probe,
- NULL,
+ redir_read_header,
NULL,
NULL,
};
+#endif
diff --git a/contrib/ffmpeg/libavformat/rtsp.h b/contrib/ffmpeg/libavformat/rtsp.h
index 481e2ba49..6adadbc81 100644
--- a/contrib/ffmpeg/libavformat/rtsp.h
+++ b/contrib/ffmpeg/libavformat/rtsp.h
@@ -18,9 +18,11 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef RTSP_H
-#define RTSP_H
+#ifndef FFMPEG_RTSP_H
+#define FFMPEG_RTSP_H
+#include <stdint.h>
+#include "avformat.h"
#include "rtspcodes.h"
enum RTSPProtocol {
@@ -76,19 +78,16 @@ typedef int FFRTSPCallback(enum RTSPCallbackAction action,
char *buf, int buf_size,
void *arg);
-/** useful for modules: set RTSP callback function */
-void rtsp_set_callback(FFRTSPCallback *rtsp_cb);
-
int rtsp_init(void);
void rtsp_parse_line(RTSPHeader *reply, const char *buf);
+#if LIBAVFORMAT_VERSION_INT < (53 << 16)
extern int rtsp_default_protocols;
+#endif
extern int rtsp_rtp_port_min;
extern int rtsp_rtp_port_max;
-extern FFRTSPCallback *ff_rtsp_callback;
-extern AVInputFormat rtsp_demuxer;
int rtsp_pause(AVFormatContext *s);
int rtsp_resume(AVFormatContext *s);
-#endif /* RTSP_H */
+#endif /* FFMPEG_RTSP_H */
diff --git a/contrib/ffmpeg/libavformat/rtspcodes.h b/contrib/ffmpeg/libavformat/rtspcodes.h
index 74cfb5d5b..d4ad25b76 100644
--- a/contrib/ffmpeg/libavformat/rtspcodes.h
+++ b/contrib/ffmpeg/libavformat/rtspcodes.h
@@ -19,6 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef FFMPEG_RTSPCODES_H
+#define FFMPEG_RTSPCODES_H
+
/** RTSP handling */
enum RTSPStatusCode {
RTSP_STATUS_OK =200, /**< OK */
@@ -34,3 +37,4 @@ RTSP_STATUS_SERVICE =503, /**< Service Unavailable */
RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */
};
+#endif /* FFMPEG_RTSPCODES_H */
diff --git a/contrib/ffmpeg/libavformat/sdp.c b/contrib/ffmpeg/libavformat/sdp.c
new file mode 100644
index 000000000..3a71afcbe
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/sdp.c
@@ -0,0 +1,320 @@
+/*
+ * copyright (c) 2007 Luca Abeni
+ *
+ * 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 "avstring.h"
+#include "avformat.h"
+#include "avc.h"
+#include "base64.h"
+#include "rtp.h"
+
+#ifdef CONFIG_RTP_MUXER
+#define MAX_EXTRADATA_SIZE ((INT_MAX - 10) / 2)
+
+struct sdp_session_level {
+ int sdp_version; /**< protocol version (currently 0) */
+ int id; /**< session id */
+ int version; /**< session version */
+ int start_time; /**< session start time (NTP time, in seconds),
+ or 0 in case of permanent session */
+ int end_time; /**< session end time (NTP time, in seconds),
+ or 0 if the session is not bounded */
+ int ttl; /**< TTL, in case of multicast stream */
+ const char *user; /**< username of the session's creator */
+ const char *src_addr; /**< IP address of the machine from which the session was created */
+ const char *dst_addr; /**< destination IP address (can be multicast) */
+ const char *name; /**< session name (can be an empty string) */
+};
+
+static void dest_write(char *buff, int size, const char *dest_addr, int ttl)
+{
+ if (dest_addr) {
+ if (ttl > 0) {
+ av_strlcatf(buff, size, "c=IN IP4 %s/%d\r\n", dest_addr, ttl);
+ } else {
+ av_strlcatf(buff, size, "c=IN IP4 %s\r\n", dest_addr);
+ }
+ }
+}
+
+static void sdp_write_header(char *buff, int size, struct sdp_session_level *s)
+{
+ av_strlcatf(buff, size, "v=%d\r\n"
+ "o=- %d %d IN IPV4 %s\r\n"
+ "t=%d %d\r\n"
+ "s=%s\r\n"
+ "a=tool:libavformat\r\n",
+ s->sdp_version,
+ s->id, s->version, s->src_addr,
+ s->start_time, s->end_time,
+ s->name[0] ? s->name : "No Name");
+ dest_write(buff, size, s->dst_addr, s->ttl);
+}
+
+static int get_address(char *dest_addr, int size, int *ttl, const char *url)
+{
+ int port;
+ const char *p;
+
+ url_split(NULL, 0, NULL, 0, dest_addr, size, &port, NULL, 0, url);
+
+ *ttl = 0;
+ p = strchr(url, '?');
+ if (p) {
+ char buff[64];
+ int is_multicast = find_info_tag(buff, sizeof(buff), "multicast", p);
+
+ if (is_multicast) {
+ if (find_info_tag(buff, sizeof(buff), "ttl", p)) {
+ *ttl = strtol(buff, NULL, 10);
+ } else {
+ *ttl = 5;
+ }
+ }
+ }
+
+ return port;
+}
+
+#define MAX_PSET_SIZE 1024
+static char *extradata2psets(AVCodecContext *c)
+{
+ char *psets, *p;
+ const uint8_t *r;
+ const char *pset_string = "; sprop-parameter-sets=";
+
+ if (c->extradata_size > MAX_EXTRADATA_SIZE) {
+ av_log(c, AV_LOG_ERROR, "Too many extra data!\n");
+
+ return NULL;
+ }
+
+ psets = av_mallocz(MAX_PSET_SIZE);
+ if (psets == NULL) {
+ av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets\n");
+ return NULL;
+ }
+ memcpy(psets, pset_string, strlen(pset_string));
+ p = psets + strlen(pset_string);
+ r = ff_avc_find_startcode(c->extradata, c->extradata + c->extradata_size);
+ while (r < c->extradata + c->extradata_size) {
+ const uint8_t *r1;
+
+ while (!*(r++));
+ r1 = ff_avc_find_startcode(r, c->extradata + c->extradata_size);
+ if (p != (psets + strlen(pset_string))) {
+ *p = ',';
+ p++;
+ }
+ if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
+ av_log(c, AV_LOG_ERROR, "Cannot BASE64 encode %d %d!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
+ av_free(psets);
+
+ return NULL;
+ }
+ p += strlen(p);
+ r = r1;
+ }
+
+ return psets;
+}
+
+static void digit_to_char(char *dst, uint8_t src)
+{
+ if (src < 10) {
+ *dst = '0' + src;
+ } else {
+ *dst = 'A' + src - 10;
+ }
+}
+
+static char *data_to_hex(char *buff, const uint8_t *src, int s)
+{
+ int i;
+
+ for(i = 0; i < s; i++) {
+ digit_to_char(buff + 2 * i, src[i] >> 4);
+ digit_to_char(buff + 2 * i + 1, src[i] & 0xF);
+ }
+
+ return buff;
+}
+
+static char *extradata2config(AVCodecContext *c)
+{
+ char *config;
+
+ if (c->extradata_size > MAX_EXTRADATA_SIZE) {
+ av_log(c, AV_LOG_ERROR, "Too many extra data!\n");
+
+ return NULL;
+ }
+ config = av_malloc(10 + c->extradata_size * 2);
+ if (config == NULL) {
+ av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info\n");
+ return NULL;
+ }
+ memcpy(config, "; config=", 9);
+ data_to_hex(config + 9, c->extradata, c->extradata_size);
+ config[9 + c->extradata_size * 2] = 0;
+
+ return config;
+}
+
+static char *sdp_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type)
+{
+ char *config = NULL;
+
+ switch (c->codec_id) {
+ case CODEC_ID_H264:
+ if (c->extradata_size) {
+ config = extradata2psets(c);
+ }
+ av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
+ "a=fmtp:%d packetization-mode=1%s\r\n",
+ payload_type,
+ payload_type, config ? config : "");
+ break;
+ case CODEC_ID_MPEG4:
+ if (c->extradata_size) {
+ config = extradata2config(c);
+ }
+ av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
+ "a=fmtp:%d profile-level-id=1%s\r\n",
+ payload_type,
+ payload_type, config ? config : "");
+ break;
+ case CODEC_ID_AAC:
+ if (c->extradata_size) {
+ config = extradata2config(c);
+ } else {
+ /* FIXME: maybe we can forge config information based on the
+ * codec parameters...
+ */
+ av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported\n");
+ return NULL;
+ }
+ if (config == NULL) {
+ return NULL;
+ }
+ av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
+ "a=fmtp:%d profile-level-id=1;"
+ "mode=AAC-hbr;sizelength=13;indexlength=3;"
+ "indexdeltalength=3%s\r\n",
+ payload_type, c->sample_rate, c->channels,
+ payload_type, config);
+ break;
+ case CODEC_ID_PCM_S16BE:
+ if (payload_type >= 96)
+ av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
+ payload_type,
+ c->sample_rate, c->channels);
+ break;
+ case CODEC_ID_PCM_MULAW:
+ if (payload_type >= 96)
+ av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
+ payload_type,
+ c->sample_rate, c->channels);
+ break;
+ case CODEC_ID_PCM_ALAW:
+ if (payload_type >= 96)
+ av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
+ payload_type,
+ c->sample_rate, c->channels);
+ break;
+ default:
+ /* Nothing special to do, here... */
+ break;
+ }
+
+ av_free(config);
+
+ return buff;
+}
+
+static void sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, int port, int ttl)
+{
+ const char *type;
+ int payload_type;
+
+ payload_type = rtp_get_payload_type(c);
+ if (payload_type < 0) {
+ payload_type = 96; /* FIXME: how to assign a private pt? rtp.c is broken too */
+ }
+
+ switch (c->codec_type) {
+ case CODEC_TYPE_VIDEO : type = "video" ; break;
+ case CODEC_TYPE_AUDIO : type = "audio" ; break;
+ case CODEC_TYPE_SUBTITLE: type = "text" ; break;
+ default : type = "application"; break;
+ }
+
+ av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type);
+ dest_write(buff, size, dest_addr, ttl);
+
+ sdp_media_attributes(buff, size, c, payload_type);
+}
+
+int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
+{
+ struct sdp_session_level s;
+ int i, j, port, ttl;
+ char dst[32];
+
+ memset(buff, 0, size);
+ memset(&s, 0, sizeof(struct sdp_session_level));
+ s.user = "-";
+ s.src_addr = "127.0.0.1"; /* FIXME: Properly set this */
+ s.name = ac[0]->title;
+
+ port = 0;
+ ttl = 0;
+ if (n_files == 1) {
+ port = get_address(dst, sizeof(dst), &ttl, ac[0]->filename);
+ if (port > 0) {
+ s.dst_addr = dst;
+ s.ttl = ttl;
+ }
+ }
+ sdp_write_header(buff, size, &s);
+
+ dst[0] = 0;
+ for (i = 0; i < n_files; i++) {
+ if (n_files != 1) {
+ port = get_address(dst, sizeof(dst), &ttl, ac[i]->filename);
+ }
+ for (j = 0; j < ac[i]->nb_streams; j++) {
+ sdp_write_media(buff, size,
+ ac[i]->streams[j]->codec, dst[0] ? dst : NULL,
+ (port > 0) ? port + j * 2 : 0, ttl);
+ if (port <= 0) {
+ av_strlcatf(buff, size,
+ "a=control:streamid=%d\r\n", i + j);
+ }
+ }
+ }
+
+ return 0;
+}
+#else
+int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
+{
+ return AVERROR(ENOSYS);
+}
+#endif
diff --git a/contrib/ffmpeg/libavformat/segafilm.c b/contrib/ffmpeg/libavformat/segafilm.c
index b5375ccf7..5b149a7ca 100644
--- a/contrib/ffmpeg/libavformat/segafilm.c
+++ b/contrib/ffmpeg/libavformat/segafilm.c
@@ -66,9 +66,6 @@ typedef struct FilmDemuxContext {
static int film_probe(AVProbeData *p)
{
- if (p->buf_size < 4)
- return 0;
-
if (AV_RB32(&p->buf[0]) != FILM_TAG)
return 0;
@@ -78,8 +75,8 @@ static int film_probe(AVProbeData *p)
static int film_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ FilmDemuxContext *film = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVStream *st;
unsigned char scratch[256];
int i;
@@ -92,7 +89,7 @@ static int film_read_header(AVFormatContext *s,
/* load the main FILM header */
if (get_buffer(pb, scratch, 16) != 16)
- return AVERROR_IO;
+ return AVERROR(EIO);
data_offset = AV_RB32(&scratch[4]);
film->version = AV_RB32(&scratch[8]);
@@ -100,7 +97,7 @@ static int film_read_header(AVFormatContext *s,
if (film->version == 0) {
/* special case for Lemmings .film files; 20-byte header */
if (get_buffer(pb, scratch, 20) != 20)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* make some assumptions about the audio parameters */
film->audio_type = CODEC_ID_PCM_S8;
film->audio_samplerate = 22050;
@@ -109,8 +106,8 @@ static int film_read_header(AVFormatContext *s,
} else {
/* normal Saturn .cpk files; 32-byte header */
if (get_buffer(pb, scratch, 32) != 32)
- return AVERROR_IO;
- film->audio_samplerate = AV_RB16(&scratch[24]);;
+ return AVERROR(EIO);
+ film->audio_samplerate = AV_RB16(&scratch[24]);
film->audio_channels = scratch[21];
film->audio_bits = scratch[22];
if (film->audio_bits == 8)
@@ -133,7 +130,7 @@ static int film_read_header(AVFormatContext *s,
if (film->video_type) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
film->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = film->video_type;
@@ -145,7 +142,7 @@ static int film_read_header(AVFormatContext *s,
if (film->audio_type) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
film->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = film->audio_type;
@@ -161,7 +158,7 @@ static int film_read_header(AVFormatContext *s,
/* load the sample table */
if (get_buffer(pb, scratch, 16) != 16)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (AV_RB32(&scratch[0]) != STAB_TAG)
return AVERROR_INVALIDDATA;
film->base_clock = AV_RB32(&scratch[8]);
@@ -178,7 +175,7 @@ static int film_read_header(AVFormatContext *s,
/* load the next sample record and transfer it to an internal struct */
if (get_buffer(pb, scratch, 16) != 16) {
av_free(film->sample_table);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
film->sample_table[i].sample_offset =
data_offset + AV_RB32(&scratch[0]);
@@ -206,15 +203,15 @@ static int film_read_header(AVFormatContext *s,
static int film_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ FilmDemuxContext *film = s->priv_data;
+ ByteIOContext *pb = s->pb;
film_sample_t *sample;
int ret = 0;
int i;
int left, right;
if (film->current_sample >= film->sample_count)
- return AVERROR_IO;
+ return AVERROR(EIO);
sample = &film->sample_table[film->current_sample];
@@ -226,14 +223,14 @@ static int film_read_packet(AVFormatContext *s,
(film->video_type == CODEC_ID_CINEPAK)) {
pkt->pos= url_ftell(pb);
if (av_new_packet(pkt, sample->sample_size))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
get_buffer(pb, pkt->data, sample->sample_size);
} else if ((sample->stream == film->audio_stream_index) &&
(film->audio_channels == 2)) {
/* stereo PCM needs to be interleaved */
if (av_new_packet(pkt, sample->sample_size))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
/* make sure the interleave buffer is large enough */
if (sample->sample_size > film->stereo_buffer_size) {
@@ -245,7 +242,7 @@ static int film_read_packet(AVFormatContext *s,
pkt->pos= url_ftell(pb);
ret = get_buffer(pb, film->stereo_buffer, sample->sample_size);
if (ret != sample->sample_size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
left = 0;
right = sample->sample_size / 2;
@@ -263,7 +260,7 @@ static int film_read_packet(AVFormatContext *s,
} else {
ret= av_get_packet(pb, pkt, sample->sample_size);
if (ret != sample->sample_size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
}
pkt->stream_index = sample->stream;
@@ -276,7 +273,7 @@ static int film_read_packet(AVFormatContext *s,
static int film_read_close(AVFormatContext *s)
{
- FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
+ FilmDemuxContext *film = s->priv_data;
av_free(film->sample_table);
av_free(film->stereo_buffer);
diff --git a/contrib/ffmpeg/libavformat/sierravmd.c b/contrib/ffmpeg/libavformat/sierravmd.c
index 3e1c8597d..5e68a81c4 100644
--- a/contrib/ffmpeg/libavformat/sierravmd.c
+++ b/contrib/ffmpeg/libavformat/sierravmd.c
@@ -59,9 +59,6 @@ typedef struct VmdDemuxContext {
static int vmd_probe(AVProbeData *p)
{
- if (p->buf_size < 2)
- return 0;
-
/* check if the first 2 bytes of the file contain the appropriate size
* of a VMD header chunk */
if (AV_RL16(&p->buf[0]) != VMD_HEADER_SIZE - 2)
@@ -74,9 +71,9 @@ static int vmd_probe(AVProbeData *p)
static int vmd_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
- AVStream *st, *vst;
+ VmdDemuxContext *vmd = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVStream *st = NULL, *vst;
unsigned int toc_offset;
unsigned char *raw_frame_table;
int raw_frame_table_size;
@@ -92,12 +89,12 @@ static int vmd_read_header(AVFormatContext *s,
/* fetch the main header, including the 2 header length bytes */
url_fseek(pb, 0, SEEK_SET);
if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* start up the decoders */
vst = av_new_stream(s, 0);
if (!vst)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(vst, 33, 1, 10);
vmd->video_stream_index = vst->index;
vst->codec->codec_type = CODEC_TYPE_VIDEO;
@@ -114,7 +111,7 @@ static int vmd_read_header(AVFormatContext *s,
if (vmd->sample_rate) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
vmd->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_VMDAUDIO;
@@ -158,13 +155,13 @@ static int vmd_read_header(AVFormatContext *s,
if (!raw_frame_table || !vmd->frame_table) {
av_free(raw_frame_table);
av_free(vmd->frame_table);
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
if (get_buffer(pb, raw_frame_table, raw_frame_table_size) !=
raw_frame_table_size) {
av_free(raw_frame_table);
av_free(vmd->frame_table);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
total_frames = 0;
@@ -184,6 +181,7 @@ static int vmd_read_header(AVFormatContext *s,
continue;
switch(type) {
case 1: /* Audio Chunk */
+ if (!st) break;
/* first audio chunk contains several audio buffers */
if(current_audio_pts){
vmd->frame_table[total_frames].frame_offset = current_offset;
@@ -247,20 +245,20 @@ static int vmd_read_header(AVFormatContext *s,
static int vmd_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ VmdDemuxContext *vmd = s->priv_data;
+ ByteIOContext *pb = s->pb;
int ret = 0;
vmd_frame_t *frame;
if (vmd->current_frame >= vmd->frame_count)
- return AVERROR_IO;
+ return AVERROR(EIO);
frame = &vmd->frame_table[vmd->current_frame];
/* position the stream (will probably be there already) */
url_fseek(pb, frame->frame_offset, SEEK_SET);
if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
pkt->pos= url_ftell(pb);
memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD,
@@ -268,11 +266,11 @@ static int vmd_read_packet(AVFormatContext *s,
if (ret != frame->frame_size) {
av_free_packet(pkt);
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
}
pkt->stream_index = frame->stream_index;
pkt->pts = frame->pts;
- av_log(NULL, AV_LOG_INFO, " dispatching %s frame with %d bytes and pts %"PRId64"\n",
+ av_log(NULL, AV_LOG_DEBUG, " dispatching %s frame with %d bytes and pts %"PRId64"\n",
(frame->frame_record[0] == 0x02) ? "video" : "audio",
frame->frame_size + BYTES_PER_FRAME_RECORD,
pkt->pts);
@@ -284,7 +282,7 @@ static int vmd_read_packet(AVFormatContext *s,
static int vmd_read_close(AVFormatContext *s)
{
- VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
+ VmdDemuxContext *vmd = s->priv_data;
av_free(vmd->frame_table);
diff --git a/contrib/ffmpeg/libavformat/siff.c b/contrib/ffmpeg/libavformat/siff.c
new file mode 100644
index 000000000..00b4eaa9d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/siff.c
@@ -0,0 +1,237 @@
+/*
+ * Beam Software SIFF demuxer
+ * Copyright (c) 2007 Konstantin Shishkov.
+ *
+ * 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 "avformat.h"
+#include "riff.h"
+
+enum SIFFTags{
+ TAG_SIFF = MKTAG('S', 'I', 'F', 'F'),
+ TAG_BODY = MKTAG('B', 'O', 'D', 'Y'),
+ TAG_VBHD = MKTAG('V', 'B', 'H', 'D'),
+ TAG_SHDR = MKTAG('S', 'H', 'D', 'R'),
+ TAG_VBV1 = MKTAG('V', 'B', 'V', '1'),
+ TAG_SOUN = MKTAG('S', 'O', 'U', 'N'),
+};
+
+enum VBFlags{
+ VB_HAS_GMC = 0x01,
+ VB_HAS_AUDIO = 0x04,
+ VB_HAS_VIDEO = 0x08,
+ VB_HAS_PALETTE = 0x10,
+ VB_HAS_LENGTH = 0x20
+};
+
+typedef struct SIFFContext{
+ int frames;
+ int cur_frame;
+ int rate;
+ int bits;
+ int block_align;
+
+ int has_video;
+ int has_audio;
+
+ int curstrm;
+ int pktsize;
+ int gmcsize;
+ int sndsize;
+
+ int flags;
+ uint8_t gmc[4];
+}SIFFContext;
+
+static int siff_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (AV_RL32(p->buf) == TAG_SIFF)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int create_audio_stream(AVFormatContext *s, SIFFContext *c)
+{
+ AVStream *ast;
+ ast = av_new_stream(s, 0);
+ if (!ast)
+ return -1;
+ ast->codec->codec_type = CODEC_TYPE_AUDIO;
+ ast->codec->codec_id = CODEC_ID_PCM_U8;
+ ast->codec->channels = 1;
+ ast->codec->bits_per_sample = c->bits;
+ ast->codec->sample_rate = c->rate;
+ ast->codec->frame_size = c->block_align;
+ av_set_pts_info(ast, 16, 1, c->rate);
+ return 0;
+}
+
+static int siff_parse_vbv1(AVFormatContext *s, SIFFContext *c, ByteIOContext *pb)
+{
+ AVStream *st;
+ int width, height;
+
+ if (get_le32(pb) != TAG_VBHD){
+ av_log(s, AV_LOG_ERROR, "Header chunk is missing\n");
+ return -1;
+ }
+ if(get_be32(pb) != 32){
+ av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n");
+ return -1;
+ }
+ if(get_le16(pb) != 1){
+ av_log(s, AV_LOG_ERROR, "Incorrect header version\n");
+ return -1;
+ }
+ width = get_le16(pb);
+ height = get_le16(pb);
+ url_fskip(pb, 4);
+ c->frames = get_le16(pb);
+ if(!c->frames){
+ av_log(s, AV_LOG_ERROR, "File contains no frames ???\n");
+ return -1;
+ }
+ c->bits = get_le16(pb);
+ c->rate = get_le16(pb);
+ c->block_align = c->rate * (c->bits >> 3);
+
+ url_fskip(pb, 16); //zeroes
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_VB;
+ st->codec->codec_tag = MKTAG('V', 'B', 'V', '1');
+ st->codec->width = width;
+ st->codec->height = height;
+ st->codec->pix_fmt = PIX_FMT_PAL8;
+ av_set_pts_info(st, 16, 1, 12);
+
+ c->cur_frame = 0;
+ c->has_video = 1;
+ c->has_audio = !!c->rate;
+ c->curstrm = -1;
+ if (c->has_audio && create_audio_stream(s, c) < 0)
+ return -1;
+ return 0;
+}
+
+static int siff_parse_soun(AVFormatContext *s, SIFFContext *c, ByteIOContext *pb)
+{
+ if (get_le32(pb) != TAG_SHDR){
+ av_log(s, AV_LOG_ERROR, "Header chunk is missing\n");
+ return -1;
+ }
+ if(get_be32(pb) != 8){
+ av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n");
+ return -1;
+ }
+ url_fskip(pb, 4); //unknown value
+ c->rate = get_le16(pb);
+ c->bits = get_le16(pb);
+ c->block_align = c->rate * (c->bits >> 3);
+ return create_audio_stream(s, c);
+}
+
+static int siff_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ByteIOContext *pb = s->pb;
+ SIFFContext *c = s->priv_data;
+ uint32_t tag;
+
+ if (get_le32(pb) != TAG_SIFF)
+ return -1;
+ url_fskip(pb, 4); //ignore size
+ tag = get_le32(pb);
+
+ if (tag != TAG_VBV1 && tag != TAG_SOUN){
+ av_log(s, AV_LOG_ERROR, "Not a VBV file\n");
+ return -1;
+ }
+
+ if (tag == TAG_VBV1 && siff_parse_vbv1(s, c, pb) < 0)
+ return -1;
+ if (tag == TAG_SOUN && siff_parse_soun(s, c, pb) < 0)
+ return -1;
+ if (get_le32(pb) != MKTAG('B', 'O', 'D', 'Y')){
+ av_log(s, AV_LOG_ERROR, "'BODY' chunk is missing\n");
+ return -1;
+ }
+ url_fskip(pb, 4); //ignore size
+
+ return 0;
+}
+
+static int siff_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ SIFFContext *c = s->priv_data;
+ int size;
+
+ if (c->has_video){
+ if (c->cur_frame >= c->frames)
+ return AVERROR(EIO);
+ if (c->curstrm == -1){
+ c->pktsize = get_le32(s->pb) - 4;
+ c->flags = get_le16(s->pb);
+ c->gmcsize = (c->flags & VB_HAS_GMC) ? 4 : 0;
+ if (c->gmcsize)
+ get_buffer(s->pb, c->gmc, c->gmcsize);
+ c->sndsize = (c->flags & VB_HAS_AUDIO) ? get_le32(s->pb): 0;
+ c->curstrm = !!(c->flags & VB_HAS_AUDIO);
+ }
+
+ if (!c->curstrm){
+ size = c->pktsize - c->sndsize;
+ if (av_new_packet(pkt, size) < 0)
+ return AVERROR(ENOMEM);
+ AV_WL16(pkt->data, c->flags);
+ if (c->gmcsize)
+ memcpy(pkt->data + 2, c->gmc, c->gmcsize);
+ get_buffer(s->pb, pkt->data + 2 + c->gmcsize, size - c->gmcsize - 2);
+ pkt->stream_index = 0;
+ c->curstrm = -1;
+ }else{
+ if (av_get_packet(s->pb, pkt, c->sndsize - 4) < 0)
+ return AVERROR(EIO);
+ pkt->stream_index = 1;
+ c->curstrm = 0;
+ }
+ if(!c->cur_frame || c->curstrm)
+ pkt->flags |= PKT_FLAG_KEY;
+ if (c->curstrm == -1)
+ c->cur_frame++;
+ }else{
+ size = av_get_packet(s->pb, pkt, c->block_align);
+ if(size <= 0)
+ return AVERROR(EIO);
+ }
+ return pkt->size;
+}
+
+AVInputFormat siff_demuxer = {
+ "siff",
+ "Beam Software SIFF",
+ sizeof(SIFFContext),
+ siff_probe,
+ siff_read_header,
+ siff_read_packet,
+ .extensions = "vb,son"
+};
diff --git a/contrib/ffmpeg/libavformat/smacker.c b/contrib/ffmpeg/libavformat/smacker.c
index 04fde3d03..562a41616 100644
--- a/contrib/ffmpeg/libavformat/smacker.c
+++ b/contrib/ffmpeg/libavformat/smacker.c
@@ -28,6 +28,7 @@
#include "bswap.h"
#define SMACKER_PAL 0x01
+#define SMACKER_FLAG_RING_FRAME 0x01
enum SAudFlags {
SMK_AUD_PACKED = 0x80000000,
@@ -88,8 +89,6 @@ static const uint8_t smk_pal[64] = {
static int smacker_probe(AVProbeData *p)
{
- if (p->buf_size < 4)
- return 0;
if(p->buf[0] == 'S' && p->buf[1] == 'M' && p->buf[2] == 'K'
&& (p->buf[3] == '2' || p->buf[3] == '4'))
return AVPROBE_SCORE_MAX;
@@ -99,8 +98,8 @@ static int smacker_probe(AVProbeData *p)
static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
- SmackerContext *smk = (SmackerContext *)s->priv_data;
+ ByteIOContext *pb = s->pb;
+ SmackerContext *smk = s->priv_data;
AVStream *st, *ast[7];
int i, ret;
int tbase;
@@ -114,6 +113,8 @@ static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
smk->frames = get_le32(pb);
smk->pts_inc = (int32_t)get_le32(pb);
smk->flags = get_le32(pb);
+ if(smk->flags & SMACKER_FLAG_RING_FRAME)
+ smk->frames++;
for(i = 0; i < 7; i++)
smk->audio[i] = get_le32(pb);
smk->treesize = get_le32(pb);
@@ -201,7 +202,7 @@ static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
if(ret != st->codec->extradata_size - 16){
av_free(smk->frm_size);
av_free(smk->frm_flags);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size);
((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size);
@@ -217,7 +218,7 @@ static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- SmackerContext *smk = (SmackerContext *)s->priv_data;
+ SmackerContext *smk = s->priv_data;
int flags;
int ret;
int i;
@@ -225,35 +226,35 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
int palchange = 0;
int pos;
- if (url_feof(&s->pb) || smk->cur_frame >= smk->frames)
+ if (url_feof(s->pb) || smk->cur_frame >= smk->frames)
return AVERROR(EIO);
/* if we demuxed all streams, pass another frame */
if(smk->curstream < 0) {
- url_fseek(&s->pb, smk->nextpos, 0);
+ url_fseek(s->pb, smk->nextpos, 0);
frame_size = smk->frm_size[smk->cur_frame] & (~3);
flags = smk->frm_flags[smk->cur_frame];
/* handle palette change event */
- pos = url_ftell(&s->pb);
+ pos = url_ftell(s->pb);
if(flags & SMACKER_PAL){
int size, sz, t, off, j, pos;
uint8_t *pal = smk->pal;
uint8_t oldpal[768];
memcpy(oldpal, pal, 768);
- size = get_byte(&s->pb);
+ size = get_byte(s->pb);
size = size * 4 - 1;
frame_size -= size;
frame_size--;
sz = 0;
- pos = url_ftell(&s->pb) + size;
+ pos = url_ftell(s->pb) + size;
while(sz < 256){
- t = get_byte(&s->pb);
+ t = get_byte(s->pb);
if(t & 0x80){ /* skip palette entries */
sz += (t & 0x7F) + 1;
pal += ((t & 0x7F) + 1) * 3;
} else if(t & 0x40){ /* copy with offset */
- off = get_byte(&s->pb) * 3;
+ off = get_byte(s->pb) * 3;
j = (t & 0x3F) + 1;
while(j-- && sz < 256) {
*pal++ = oldpal[off + 0];
@@ -264,12 +265,12 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
}
} else { /* new entries */
*pal++ = smk_pal[t];
- *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
- *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
+ *pal++ = smk_pal[get_byte(s->pb) & 0x3F];
+ *pal++ = smk_pal[get_byte(s->pb) & 0x3F];
sz++;
}
}
- url_fseek(&s->pb, pos, 0);
+ url_fseek(s->pb, pos, 0);
palchange |= 1;
}
flags >>= 1;
@@ -278,35 +279,35 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
for(i = 0; i < 7; i++) {
if(flags & 1) {
int size;
- size = get_le32(&s->pb) - 4;
+ size = get_le32(s->pb) - 4;
frame_size -= size;
frame_size -= 4;
smk->curstream++;
smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size);
smk->buf_sizes[smk->curstream] = size;
- ret = get_buffer(&s->pb, smk->bufs[smk->curstream], size);
+ ret = get_buffer(s->pb, smk->bufs[smk->curstream], size);
if(ret != size)
- return AVERROR_IO;
+ return AVERROR(EIO);
smk->stream_id[smk->curstream] = smk->indexes[i];
}
flags >>= 1;
}
if (av_new_packet(pkt, frame_size + 768))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
if(smk->frm_size[smk->cur_frame] & 1)
palchange |= 2;
pkt->data[0] = palchange;
memcpy(pkt->data + 1, smk->pal, 768);
- ret = get_buffer(&s->pb, pkt->data + 769, frame_size);
+ ret = get_buffer(s->pb, pkt->data + 769, frame_size);
if(ret != frame_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = smk->videoindex;
pkt->size = ret + 769;
smk->cur_frame++;
- smk->nextpos = url_ftell(&s->pb);
+ smk->nextpos = url_ftell(s->pb);
} else {
if (av_new_packet(pkt, smk->buf_sizes[smk->curstream]))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]);
pkt->size = smk->buf_sizes[smk->curstream];
pkt->stream_index = smk->stream_id[smk->curstream];
@@ -320,7 +321,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
static int smacker_read_close(AVFormatContext *s)
{
- SmackerContext *smk = (SmackerContext *)s->priv_data;
+ SmackerContext *smk = s->priv_data;
int i;
for(i = 0; i < 7; i++)
diff --git a/contrib/ffmpeg/libavformat/sol.c b/contrib/ffmpeg/libavformat/sol.c
index 951ec6eb9..97ebfdb5e 100644
--- a/contrib/ffmpeg/libavformat/sol.c
+++ b/contrib/ffmpeg/libavformat/sol.c
@@ -24,7 +24,7 @@
*/
#include "avformat.h"
-#include "allformats.h"
+#include "raw.h"
#include "riff.h"
#include "bswap.h"
@@ -35,8 +35,6 @@ static int sol_probe(AVProbeData *p)
{
/* check file header */
uint16_t magic;
- if (p->buf_size <= 14)
- return 0;
magic=le2me_16(*((uint16_t*)p->buf));
if ((magic == 0x0B8D || magic == 0x0C0D || magic == 0x0C8D) &&
p->buf[2] == 'S' && p->buf[3] == 'O' &&
@@ -90,7 +88,7 @@ static int sol_read_header(AVFormatContext *s,
{
int size;
unsigned int magic,tag;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
unsigned int id, codec, channels, rate, type;
AVStream *st;
@@ -132,9 +130,9 @@ static int sol_read_packet(AVFormatContext *s,
{
int ret;
- if (url_feof(&s->pb))
+ if (url_feof(s->pb))
return AVERROR(EIO);
- ret= av_get_packet(&s->pb, pkt, MAX_SIZE);
+ ret= av_get_packet(s->pb, pkt, MAX_SIZE);
pkt->stream_index = 0;
/* note: we need to modify the packet size here to handle the last
diff --git a/contrib/ffmpeg/libavformat/swf.c b/contrib/ffmpeg/libavformat/swf.c
index 7d889af7d..387a96c5f 100644
--- a/contrib/ffmpeg/libavformat/swf.c
+++ b/contrib/ffmpeg/libavformat/swf.c
@@ -40,6 +40,7 @@
#define TAG_STREAMHEAD2 45
#define TAG_VIDEOSTREAM 60
#define TAG_VIDEOFRAME 61
+#define TAG_FILEATTRIBUTES 69
#define TAG_LONG 0x100
@@ -96,7 +97,7 @@ static const AVCodecTag swf_audio_codec_tags[] = {
static void put_swf_tag(AVFormatContext *s, int tag)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
swf->tag_pos = url_ftell(pb);
swf->tag = tag;
@@ -112,7 +113,7 @@ static void put_swf_tag(AVFormatContext *s, int tag)
static void put_swf_end_tag(AVFormatContext *s)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t pos;
int tag_len, tag;
@@ -187,17 +188,17 @@ static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
mask = (1 << nbits) - 1;
put_bits(pb, 4, nbits - 2); /* 16 bits precision */
if (dx == 0) {
- put_bits(pb, 1, 0);
- put_bits(pb, 1, 1);
- put_bits(pb, nbits, dy & mask);
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dy & mask);
} else if (dy == 0) {
- put_bits(pb, 1, 0);
- put_bits(pb, 1, 0);
- put_bits(pb, nbits, dx & mask);
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 0);
+ put_bits(pb, nbits, dx & mask);
} else {
- put_bits(pb, 1, 1);
- put_bits(pb, nbits, dx & mask);
- put_bits(pb, nbits, dy & mask);
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dx & mask);
+ put_bits(pb, nbits, dy & mask);
}
}
@@ -244,11 +245,12 @@ static void put_swf_matrix(ByteIOContext *pb,
static int swf_write_header(AVFormatContext *s)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc, *audio_enc, *video_enc;
PutBitContext p;
uint8_t buf1[256];
int i, width, height, rate, rate_base;
+ int is_avm2;
swf->audio_in_pos = 0;
swf->sound_samples = 0;
@@ -271,9 +273,9 @@ static int swf_write_header(AVFormatContext *s)
return -1;
}
} else {
- if ( enc->codec_id == CODEC_ID_VP6F ||
- enc->codec_id == CODEC_ID_FLV1 ||
- enc->codec_id == CODEC_ID_MJPEG ) {
+ if (enc->codec_id == CODEC_ID_VP6F ||
+ enc->codec_id == CODEC_ID_FLV1 ||
+ enc->codec_id == CODEC_ID_MJPEG) {
video_enc = enc;
} else {
av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
@@ -283,7 +285,7 @@ static int swf_write_header(AVFormatContext *s)
}
if (!video_enc) {
- /* currenty, cannot work correctly if audio only */
+ /* currently, cannot work correctly if audio only */
swf->video_type = 0;
width = 320;
height = 200;
@@ -297,18 +299,22 @@ static int swf_write_header(AVFormatContext *s)
rate_base = video_enc->time_base.num;
}
- if (!audio_enc ) {
+ if (!audio_enc) {
swf->audio_type = 0;
- swf->samples_per_frame = ( 44100. * rate_base ) / rate;
+ swf->samples_per_frame = (44100. * rate_base) / rate;
} else {
swf->audio_type = audio_enc->codec_id;
- swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
+ swf->samples_per_frame = (audio_enc->sample_rate * rate_base) / rate;
}
+ is_avm2 = !strcmp("avm2", s->oformat->name);
+
put_tag(pb, "FWS");
- if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
+ if (is_avm2) {
+ put_byte(pb, 9);
+ } else if (video_enc && video_enc->codec_id == CODEC_ID_VP6F) {
put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
- } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
+ } else if (video_enc && video_enc->codec_id == CODEC_ID_FLV1) {
put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
} else {
put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
@@ -321,10 +327,17 @@ static int swf_write_header(AVFormatContext *s)
swf->duration_pos = url_ftell(pb);
put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
+ /* avm2/swf v9 (also v8?) files require a file attribute tag */
+ if (is_avm2) {
+ put_swf_tag(s, TAG_FILEATTRIBUTES);
+ put_le32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */
+ put_swf_end_tag(s);
+ }
+
/* define a shape with the jpeg inside */
- if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
- video_enc->codec_id == CODEC_ID_FLV1 )) {
- } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
+ if (video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
+ video_enc->codec_id == CODEC_ID_FLV1)) {
+ } else if (video_enc && video_enc->codec_id == CODEC_ID_MJPEG) {
put_swf_tag(s, TAG_DEFINESHAPE);
put_le16(pb, SHAPE_ID); /* ID of shape */
@@ -336,7 +349,7 @@ static int swf_write_header(AVFormatContext *s)
put_le16(pb, BITMAP_ID); /* bitmap ID */
/* position of the bitmap */
put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
- 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
+ 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
put_byte(pb, 0); /* no line style */
/* shape drawing */
@@ -367,7 +380,7 @@ static int swf_write_header(AVFormatContext *s)
put_swf_end_tag(s);
}
- if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
+ if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3) {
int v;
/* start sound */
@@ -386,22 +399,22 @@ static int swf_write_header(AVFormatContext *s)
break;
default:
/* not supported */
- av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
+ av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
return -1;
}
v |= 0x02; /* 16 bit playback */
if (audio_enc->channels == 2)
v |= 0x01; /* stereo playback */
- put_byte(&s->pb, v);
+ put_byte(s->pb, v);
v |= 0x20; /* mp3 compressed */
- put_byte(&s->pb, v);
- put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
- put_le16(&s->pb, 0);
+ put_byte(s->pb, v);
+ put_le16(s->pb, swf->samples_per_frame); /* avg samples per frame */
+ put_le16(s->pb, 0);
put_swf_end_tag(s);
}
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
}
@@ -409,95 +422,95 @@ static int swf_write_video(AVFormatContext *s,
AVCodecContext *enc, const uint8_t *buf, int size)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
/* Flash Player limit */
- if ( swf->swf_frame_number == 16000 ) {
+ if (swf->swf_frame_number == 16000) {
av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
}
- if ( swf->video_type == CODEC_ID_VP6F ||
- swf->video_type == CODEC_ID_FLV1 ) {
- if ( swf->video_frame_number == 0 ) {
- /* create a new video object */
- put_swf_tag(s, TAG_VIDEOSTREAM);
- put_le16(pb, VIDEO_ID);
- put_le16(pb, 15000 ); /* hard flash player limit */
- put_le16(pb, enc->width);
- put_le16(pb, enc->height);
- put_byte(pb, 0);
- put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
- put_swf_end_tag(s);
-
- /* place the video object for the first time */
- put_swf_tag(s, TAG_PLACEOBJECT2);
- put_byte(pb, 0x36);
- put_le16(pb, 1);
- put_le16(pb, VIDEO_ID);
- put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
- put_le16(pb, swf->video_frame_number );
- put_byte(pb, 'v');
- put_byte(pb, 'i');
- put_byte(pb, 'd');
- put_byte(pb, 'e');
- put_byte(pb, 'o');
- put_byte(pb, 0x00);
- put_swf_end_tag(s);
- } else {
- /* mark the character for update */
- put_swf_tag(s, TAG_PLACEOBJECT2);
- put_byte(pb, 0x11);
- put_le16(pb, 1);
- put_le16(pb, swf->video_frame_number );
- put_swf_end_tag(s);
- }
+ if (swf->video_type == CODEC_ID_VP6F ||
+ swf->video_type == CODEC_ID_FLV1) {
+ if (swf->video_frame_number == 0) {
+ /* create a new video object */
+ put_swf_tag(s, TAG_VIDEOSTREAM);
+ put_le16(pb, VIDEO_ID);
+ put_le16(pb, 15000); /* hard flash player limit */
+ put_le16(pb, enc->width);
+ put_le16(pb, enc->height);
+ put_byte(pb, 0);
+ put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
+ put_swf_end_tag(s);
+
+ /* place the video object for the first time */
+ put_swf_tag(s, TAG_PLACEOBJECT2);
+ put_byte(pb, 0x36);
+ put_le16(pb, 1);
+ put_le16(pb, VIDEO_ID);
+ put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
+ put_le16(pb, swf->video_frame_number);
+ put_byte(pb, 'v');
+ put_byte(pb, 'i');
+ put_byte(pb, 'd');
+ put_byte(pb, 'e');
+ put_byte(pb, 'o');
+ put_byte(pb, 0x00);
+ put_swf_end_tag(s);
+ } else {
+ /* mark the character for update */
+ put_swf_tag(s, TAG_PLACEOBJECT2);
+ put_byte(pb, 0x11);
+ put_le16(pb, 1);
+ put_le16(pb, swf->video_frame_number);
+ put_swf_end_tag(s);
+ }
- /* set video frame data */
- put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
- put_le16(pb, VIDEO_ID);
- put_le16(pb, swf->video_frame_number++ );
- put_buffer(pb, buf, size);
- put_swf_end_tag(s);
- } else if ( swf->video_type == CODEC_ID_MJPEG ) {
- if (swf->swf_frame_number > 0) {
- /* remove the shape */
- put_swf_tag(s, TAG_REMOVEOBJECT);
- put_le16(pb, SHAPE_ID); /* shape ID */
- put_le16(pb, 1); /* depth */
- put_swf_end_tag(s);
-
- /* free the bitmap */
- put_swf_tag(s, TAG_FREECHARACTER);
- put_le16(pb, BITMAP_ID);
- put_swf_end_tag(s);
- }
+ /* set video frame data */
+ put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
+ put_le16(pb, VIDEO_ID);
+ put_le16(pb, swf->video_frame_number++);
+ put_buffer(pb, buf, size);
+ put_swf_end_tag(s);
+ } else if (swf->video_type == CODEC_ID_MJPEG) {
+ if (swf->swf_frame_number > 0) {
+ /* remove the shape */
+ put_swf_tag(s, TAG_REMOVEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_end_tag(s);
+
+ /* free the bitmap */
+ put_swf_tag(s, TAG_FREECHARACTER);
+ put_le16(pb, BITMAP_ID);
+ put_swf_end_tag(s);
+ }
- put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
+ put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
- put_le16(pb, BITMAP_ID); /* ID of the image */
+ put_le16(pb, BITMAP_ID); /* ID of the image */
- /* a dummy jpeg header seems to be required */
- put_byte(pb, 0xff);
- put_byte(pb, 0xd8);
- put_byte(pb, 0xff);
- put_byte(pb, 0xd9);
- /* write the jpeg image */
- put_buffer(pb, buf, size);
+ /* a dummy jpeg header seems to be required */
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd8);
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd9);
+ /* write the jpeg image */
+ put_buffer(pb, buf, size);
- put_swf_end_tag(s);
+ put_swf_end_tag(s);
- /* draw the shape */
+ /* draw the shape */
- put_swf_tag(s, TAG_PLACEOBJECT);
- put_le16(pb, SHAPE_ID); /* shape ID */
- put_le16(pb, 1); /* depth */
- put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
- put_swf_end_tag(s);
- } else {
- /* invalid codec */
- }
+ put_swf_tag(s, TAG_PLACEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
+ put_swf_end_tag(s);
+ } else {
+ /* invalid codec */
+ }
- swf->swf_frame_number ++;
+ swf->swf_frame_number ++;
/* streaming sound always should be placed just before showframe tags */
if (swf->audio_type && swf->audio_in_pos) {
@@ -516,7 +529,7 @@ static int swf_write_video(AVFormatContext *s,
put_swf_tag(s, TAG_SHOWFRAME);
put_swf_end_tag(s);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
return 0;
}
@@ -527,7 +540,7 @@ static int swf_write_audio(AVFormatContext *s,
SWFContext *swf = s->priv_data;
/* Flash Player limit */
- if ( swf->swf_frame_number == 16000 ) {
+ if (swf->swf_frame_number == 16000) {
av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
}
@@ -541,7 +554,7 @@ static int swf_write_audio(AVFormatContext *s,
swf->sound_samples += enc->frame_size;
/* if audio only stream make sure we add swf frames */
- if ( swf->video_type == 0 ) {
+ if (swf->video_type == 0) {
swf_write_video(s, enc, 0, 0);
}
@@ -560,7 +573,7 @@ static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
static int swf_write_trailer(AVFormatContext *s)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *enc, *video_enc;
int file_size, i;
@@ -574,10 +587,10 @@ static int swf_write_trailer(AVFormatContext *s)
put_swf_tag(s, TAG_END);
put_swf_end_tag(s);
- put_flush_packet(&s->pb);
+ put_flush_packet(s->pb);
/* patch file size and number of frames if not streamed */
- if (!url_is_streamed(&s->pb) && video_enc) {
+ if (!url_is_streamed(s->pb) && video_enc) {
file_size = url_ftell(pb);
url_fseek(pb, 4, SEEK_SET);
put_le32(pb, file_size);
@@ -618,8 +631,6 @@ static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
static int swf_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size <= 16)
- return 0;
if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
p->buf[2] == 'S')
return AVPROBE_SCORE_MAX;
@@ -630,21 +641,17 @@ static int swf_probe(AVProbeData *p)
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
- int nbits, len, tag, v;
- offset_t frame_offset = -1;
- AVStream *ast = 0;
- AVStream *vst = 0;
+ ByteIOContext *pb = s->pb;
+ int nbits, len, tag;
tag = get_be32(pb) & 0xffffff00;
- if (tag == MKBETAG('C', 'W', 'S', 0))
- {
+ if (tag == MKBETAG('C', 'W', 'S', 0)) {
av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
- return AVERROR_IO;
+ return AVERROR(EIO);
}
if (tag != MKBETAG('F', 'W', 'S', 0))
- return AVERROR_IO;
+ return AVERROR(EIO);
get_le32(pb);
/* skip rectangle size */
nbits = get_byte(pb) >> 3;
@@ -654,15 +661,22 @@ static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_le16(pb); /* frame count */
swf->samples_per_frame = 0;
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ return 0;
+}
+
+static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ AVStream *vst = NULL, *ast = NULL, *st = 0;
+ int tag, len, i, frame, v;
for(;;) {
- offset_t tag_offset = url_ftell(pb);
tag = get_swf_tag(pb, &len);
- if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
- url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
- break;
- }
- if ( tag == TAG_VIDEOSTREAM && !vst) {
+ if (tag < 0)
+ return AVERROR(EIO);
+ if (tag == TAG_VIDEOSTREAM && !vst) {
int ch_id = get_le16(pb);
get_le16(pb);
get_le16(pb);
@@ -670,58 +684,37 @@ static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_byte(pb);
/* Check for FLV1 */
vst = av_new_stream(s, ch_id);
+ if (!vst)
+ return -1;
vst->codec->codec_type = CODEC_TYPE_VIDEO;
vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
- } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
+ av_set_pts_info(vst, 64, 256, swf->frame_rate);
+ vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
+ len -= 10;
+ } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
/* streaming found */
int sample_rate_code;
get_byte(pb);
v = get_byte(pb);
swf->samples_per_frame = get_le16(pb);
ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
+ if (!ast)
+ return -1;
swf->audio_stream_index = ast->index;
ast->codec->channels = 1 + (v&1);
ast->codec->codec_type = CODEC_TYPE_AUDIO;
ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
- ast->need_parsing = 1;
+ ast->need_parsing = AVSTREAM_PARSE_FULL;
sample_rate_code= (v>>2) & 3;
if (!sample_rate_code)
- return AVERROR_IO;
+ return AVERROR(EIO);
ast->codec->sample_rate = 11025 << (sample_rate_code-1);
av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
- if (len > 4)
- url_fskip(pb,len-4);
-
- } else if (tag == TAG_JPEG2 && !vst) {
- vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
- vst->codec->codec_type = CODEC_TYPE_VIDEO;
- vst->codec->codec_id = CODEC_ID_MJPEG;
- url_fskip(pb, len);
- frame_offset = tag_offset;
- } else {
- url_fskip(pb, len);
- }
- }
- if (vst)
- av_set_pts_info(vst, 64, 256, swf->frame_rate);
- return 0;
-}
-
-static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
-{
- SWFContext *swf = s->priv_data;
- ByteIOContext *pb = &s->pb;
- AVStream *st = 0;
- int tag, len, i, frame;
-
- for(;;) {
- tag = get_swf_tag(pb, &len);
- if (tag < 0)
- return AVERROR_IO;
- if (tag == TAG_VIDEOFRAME) {
+ len -= 4;
+ } else if (tag == TAG_VIDEOFRAME) {
int ch_id = get_le16(pb);
len -= 2;
- 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 == CODEC_TYPE_VIDEO && st->id == ch_id) {
frame = get_le16(pb);
@@ -744,21 +737,33 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
} else if (tag == TAG_JPEG2) {
for (i=0; i<s->nb_streams; i++) {
st = s->streams[i];
- if (st->id == -2) {
- get_le16(pb); /* BITMAP_ID */
- av_new_packet(pkt, len-2);
- get_buffer(pb, pkt->data, 4);
- if (AV_RB32(pkt->data) == 0xffd8ffd9) {
- /* old SWF files containing SOI/EOI as data start */
- pkt->size -= 4;
- get_buffer(pb, pkt->data, pkt->size);
- } else {
- get_buffer(pb, pkt->data + 4, pkt->size - 4);
- }
- pkt->stream_index = st->index;
- return pkt->size;
- }
+ if (st->id == -2)
+ break;
}
+ if (i == s->nb_streams) {
+ vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
+ if (!vst)
+ return -1;
+ vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ vst->codec->codec_id = CODEC_ID_MJPEG;
+ av_set_pts_info(vst, 64, 256, swf->frame_rate);
+ vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
+ st = vst;
+ }
+ get_le16(pb); /* BITMAP_ID */
+ av_new_packet(pkt, len-2);
+ get_buffer(pb, pkt->data, 4);
+ 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;
+ get_buffer(pb, pkt->data, pkt->size);
+ } else {
+ get_buffer(pb, pkt->data + 4, pkt->size - 4);
+ }
+ pkt->stream_index = st->index;
+ return pkt->size;
}
url_fskip(pb, len);
}
@@ -767,7 +772,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
static int swf_read_close(AVFormatContext *s)
{
- return 0;
+ return 0;
}
#ifdef CONFIG_SWF_DEMUXER
@@ -795,3 +800,17 @@ AVOutputFormat swf_muxer = {
swf_write_trailer,
};
#endif
+#ifdef CONFIG_AVM2_MUXER
+AVOutputFormat avm2_muxer = {
+ "avm2",
+ "Flash 9 (AVM2) format",
+ "application/x-shockwave-flash",
+ NULL,
+ sizeof(SWFContext),
+ CODEC_ID_MP3,
+ CODEC_ID_FLV1,
+ swf_write_header,
+ swf_write_packet,
+ swf_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/tcp.c b/contrib/ffmpeg/libavformat/tcp.c
index a5539be4c..bea0fb909 100644
--- a/contrib/ffmpeg/libavformat/tcp.c
+++ b/contrib/ffmpeg/libavformat/tcp.c
@@ -21,27 +21,13 @@
#include "avformat.h"
#include <unistd.h>
#include "network.h"
+#include "os_support.h"
#include <sys/time.h>
-#include <fcntl.h>
typedef struct TCPContext {
int fd;
} TCPContext;
-/* resolve host with also IP address parsing */
-int resolve_host(struct in_addr *sin_addr, const char *hostname)
-{
- struct hostent *hp;
-
- if ((inet_aton(hostname, sin_addr)) == 0) {
- hp = gethostbyname(hostname);
- if (!hp)
- return -1;
- memcpy (sin_addr, hp->h_addr, sizeof(struct in_addr));
- }
- return 0;
-}
-
/* return non zero if error */
static int tcp_open(URLContext *h, const char *uri, int flags)
{
@@ -68,6 +54,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
if (port <= 0 || port >= 65536)
goto fail;
+ if(!ff_network_init())
+ return AVERROR(EIO);
+
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
if (resolve_host(&dest_addr.sin_addr, hostname) < 0)
@@ -76,15 +65,16 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
goto fail;
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ ff_socket_nonblock(fd, 1);
redo:
ret = connect(fd, (struct sockaddr *)&dest_addr,
sizeof(dest_addr));
if (ret < 0) {
- if (errno == EINTR)
+ if (ff_neterrno() == FF_NETERROR(EINTR))
goto redo;
- if (errno != EINPROGRESS)
+ if (ff_neterrno() != FF_NETERROR(EINPROGRESS) &&
+ ff_neterrno() != FF_NETERROR(EAGAIN))
goto fail;
/* wait until we are connected or until abort */
@@ -113,7 +103,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
return 0;
fail:
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
fail1:
if (fd >= 0)
closesocket(fd);
@@ -140,7 +130,8 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size)
if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
len = recv(s->fd, buf, size, 0);
if (len < 0) {
- if (errno != EINTR && errno != EAGAIN)
+ if (ff_neterrno() != FF_NETERROR(EINTR) &&
+ ff_neterrno() != FF_NETERROR(EAGAIN))
return AVERROR(errno);
} else return len;
} else if (ret < 0) {
@@ -169,7 +160,8 @@ static int tcp_write(URLContext *h, uint8_t *buf, int size)
if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
len = send(s->fd, buf, size, 0);
if (len < 0) {
- if (errno != EINTR && errno != EAGAIN)
+ if (ff_neterrno() != FF_NETERROR(EINTR) &&
+ ff_neterrno() != FF_NETERROR(EAGAIN))
return AVERROR(errno);
continue;
}
@@ -186,6 +178,7 @@ static int tcp_close(URLContext *h)
{
TCPContext *s = h->priv_data;
closesocket(s->fd);
+ ff_network_close();
av_free(s);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/thp.c b/contrib/ffmpeg/libavformat/thp.c
index d0d80428c..a0747ecad 100644
--- a/contrib/ffmpeg/libavformat/thp.c
+++ b/contrib/ffmpeg/libavformat/thp.c
@@ -21,7 +21,6 @@
#include "avformat.h"
-#include "allformats.h"
typedef struct ThpDemuxContext {
int version;
@@ -35,19 +34,18 @@ typedef struct ThpDemuxContext {
int next_frame;
int next_framesz;
int video_stream_index;
+ int audio_stream_index;
int compcount;
unsigned char components[16];
AVStream* vst;
int has_audio;
+ int audiosize;
} ThpDemuxContext;
static int thp_probe(AVProbeData *p)
{
/* check file header */
- if (p->buf_size < 4)
- return 0;
-
if (AV_RL32(p->buf) == MKTAG('T', 'H', 'P', '\0'))
return AVPROBE_SCORE_MAX;
else
@@ -57,106 +55,135 @@ static int thp_probe(AVProbeData *p)
static int thp_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ThpDemuxContext *thp = s->priv_data;
- AVStream *st;
- ByteIOContext *pb = &s->pb;
- int i;
-
- /* Read the file header. */
-
- get_be32(pb); /* Skip Magic. */
- thp->version = get_be32(pb);
-
- get_be32(pb); /* Max buf size. */
- get_be32(pb); /* Max samples. */
-
- thp->fps = av_d2q(av_int2flt(get_be32(pb)), INT_MAX);
- thp->framecnt = get_be32(pb);
- thp->first_framesz = get_be32(pb);
- get_be32(pb); /* Data size. */
-
- thp->compoff = get_be32(pb);
- get_be32(pb); /* offsetDataOffset. */
- thp->first_frame = get_be32(pb);
- thp->last_frame = get_be32(pb);
-
- thp->next_framesz = thp->first_framesz;
- thp->next_frame = thp->first_frame;
-
- /* Read the component structure. */
- url_fseek (pb, thp->compoff, SEEK_SET);
- thp->compcount = get_be32(pb);
-
- /* Read the list of component types. */
- get_buffer(pb, thp->components, 16);
-
- for (i = 0; i < thp->compcount; i++) {
- if (thp->components[i] == 0) {
- if (thp->vst != 0)
- break;
-
- /* Video component. */
- st = av_new_stream(s, 0);
- if (!st)
- return AVERROR_NOMEM;
-
- /* The denominator and numerator are switched because 1/fps
- is required. */
- av_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = CODEC_ID_THP;
- st->codec->codec_tag = 0; /* no fourcc */
- st->codec->width = get_be32(pb);
- st->codec->height = get_be32(pb);
- st->codec->sample_rate = av_q2d(thp->fps);
- thp->vst = st;
- thp->video_stream_index = st->index;
-
- if (thp->version == 0x11000)
- get_be32(pb); /* Unknown. */
+ ThpDemuxContext *thp = s->priv_data;
+ AVStream *st;
+ ByteIOContext *pb = s->pb;
+ int i;
+
+ /* Read the file header. */
+ get_be32(pb); /* Skip Magic. */
+ thp->version = get_be32(pb);
+
+ get_be32(pb); /* Max buf size. */
+ get_be32(pb); /* Max samples. */
+
+ thp->fps = av_d2q(av_int2flt(get_be32(pb)), INT_MAX);
+ thp->framecnt = get_be32(pb);
+ thp->first_framesz = get_be32(pb);
+ get_be32(pb); /* Data size. */
+
+ thp->compoff = get_be32(pb);
+ get_be32(pb); /* offsetDataOffset. */
+ thp->first_frame = get_be32(pb);
+ thp->last_frame = get_be32(pb);
+
+ thp->next_framesz = thp->first_framesz;
+ thp->next_frame = thp->first_frame;
+
+ /* Read the component structure. */
+ url_fseek (pb, thp->compoff, SEEK_SET);
+ thp->compcount = get_be32(pb);
+
+ /* Read the list of component types. */
+ get_buffer(pb, thp->components, 16);
+
+ for (i = 0; i < thp->compcount; i++) {
+ if (thp->components[i] == 0) {
+ if (thp->vst != 0)
+ break;
+
+ /* Video component. */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ /* The denominator and numerator are switched because 1/fps
+ is required. */
+ av_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_THP;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = get_be32(pb);
+ st->codec->height = get_be32(pb);
+ st->codec->sample_rate = av_q2d(thp->fps);
+ thp->vst = st;
+ thp->video_stream_index = st->index;
+
+ if (thp->version == 0x11000)
+ get_be32(pb); /* Unknown. */
+ } else if (thp->components[i] == 1) {
+ if (thp->has_audio != 0)
+ break;
+
+ /* Audio component. */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ADPCM_THP;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->channels = get_be32(pb); /* numChannels. */
+ st->codec->sample_rate = get_be32(pb); /* Frequency. */
+
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+
+ thp->audio_stream_index = st->index;
+ thp->has_audio = 1;
}
- else if (thp->components[i] == 1) {
- /* XXX: Required for audio playback. */
- thp->has_audio = 1;
- }
}
- return 0;
+ return 0;
}
static int thp_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
ThpDemuxContext *thp = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int size;
int ret;
- /* Terminate when last frame is reached. */
- if (thp->frame >= thp->framecnt)
- return AVERROR_IO;
+ if (thp->audiosize == 0) {
+ /* Terminate when last frame is reached. */
+ if (thp->frame >= thp->framecnt)
+ return AVERROR(EIO);
- url_fseek(pb, thp->next_frame, SEEK_SET);
+ url_fseek(pb, thp->next_frame, SEEK_SET);
- /* Locate the next frame and read out its size. */
- thp->next_frame += thp->next_framesz;
- thp->next_framesz = get_be32(pb);
+ /* Locate the next frame and read out its size. */
+ thp->next_frame += thp->next_framesz;
+ thp->next_framesz = get_be32(pb);
get_be32(pb); /* Previous total size. */
- size = get_be32(pb); /* Total size of this frame. */
+ size = get_be32(pb); /* Total size of this frame. */
+
+ /* Store the audiosize so the next time this function is called,
+ the audio can be read. */
+ if (thp->has_audio)
+ thp->audiosize = get_be32(pb); /* Audio size. */
+ else
+ thp->frame++;
+
+ ret = av_get_packet(pb, pkt, size);
+ if (ret != size) {
+ av_free_packet(pkt);
+ return AVERROR(EIO);
+ }
- if (thp->has_audio)
- get_be32(pb); /* Audio size. */
+ pkt->stream_index = thp->video_stream_index;
+ } else {
+ ret = av_get_packet(pb, pkt, thp->audiosize);
+ if (ret != thp->audiosize) {
+ av_free_packet(pkt);
+ return AVERROR(EIO);
+ }
- ret = av_get_packet(pb, pkt, size);
- if (ret != size) {
- av_free_packet(pkt);
- return AVERROR_IO;
+ pkt->stream_index = thp->audio_stream_index;
+ thp->audiosize = 0;
+ thp->frame++;
}
- pkt->stream_index = thp->video_stream_index;
- thp->frame++;
-
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/tiertexseq.c b/contrib/ffmpeg/libavformat/tiertexseq.c
index 8f565824a..457185b63 100644
--- a/contrib/ffmpeg/libavformat/tiertexseq.c
+++ b/contrib/ffmpeg/libavformat/tiertexseq.c
@@ -95,7 +95,7 @@ static int seq_init_frame_buffers(SeqDemuxContext *seq, ByteIOContext *pb)
seq_buffer->data_size = sz;
seq_buffer->data = av_malloc(sz);
if (!seq_buffer->data)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
}
seq->frame_buffers_count = i;
@@ -115,7 +115,7 @@ static int seq_fill_buffer(SeqDemuxContext *seq, ByteIOContext *pb, int buffer_n
url_fseek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
if (get_buffer(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
seq_buffer->fill_size += data_size;
return 0;
@@ -183,8 +183,8 @@ static int seq_parse_frame_data(SeqDemuxContext *seq, ByteIOContext *pb)
static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
int i, rc;
- SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ SeqDemuxContext *seq = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVStream *st;
/* init internal buffers */
@@ -208,7 +208,7 @@ static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* initialize the video decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
seq->video_stream_index = st->index;
@@ -221,7 +221,7 @@ static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
/* initialize the audio decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
seq->audio_stream_index = st->index;
@@ -240,8 +240,8 @@ static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int rc;
- SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ SeqDemuxContext *seq = s->priv_data;
+ ByteIOContext *pb = s->pb;
if (!seq->audio_buffer_full) {
rc = seq_parse_frame_data(seq, pb);
@@ -251,14 +251,14 @@ static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
/* video packet */
if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size))
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
pkt->data[0] = 0;
if (seq->current_pal_data_size != 0) {
pkt->data[0] |= 1;
url_fseek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
if (get_buffer(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
}
if (seq->current_video_data_size != 0) {
pkt->data[0] |= 2;
@@ -277,7 +277,7 @@ static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
/* audio packet */
if (seq->current_audio_data_offs == 0) /* end of data reached */
- return AVERROR_IO;
+ return AVERROR(EIO);
url_fseek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
@@ -294,7 +294,7 @@ static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
static int seq_read_close(AVFormatContext *s)
{
int i;
- SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
+ SeqDemuxContext *seq = s->priv_data;
for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
av_free(seq->frame_buffers[i].data);
diff --git a/contrib/ffmpeg/libavformat/tta.c b/contrib/ffmpeg/libavformat/tta.c
index a3709437e..2cd0101f1 100644
--- a/contrib/ffmpeg/libavformat/tta.c
+++ b/contrib/ffmpeg/libavformat/tta.c
@@ -16,21 +16,18 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "bitstream.h"
typedef struct {
int totalframes, currentframe;
- uint32_t *seektable;
} TTAContext;
static int tta_probe(AVProbeData *p)
{
const uint8_t *d = p->buf;
- if (p->buf_size < 4)
- return 0;
if (d[0] == 'T' && d[1] == 'T' && d[2] == 'A' && d[3] == '1')
return 80;
return 0;
@@ -41,26 +38,27 @@ static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap)
TTAContext *c = s->priv_data;
AVStream *st;
int i, channels, bps, samplerate, datalen, framelen;
+ uint64_t framepos;
- if (get_le32(&s->pb) != ff_get_fourcc("TTA1"))
+ if (get_le32(s->pb) != ff_get_fourcc("TTA1"))
return -1; // not tta file
- url_fskip(&s->pb, 2); // FIXME: flags
- channels = get_le16(&s->pb);
- bps = get_le16(&s->pb);
- samplerate = get_le32(&s->pb);
+ url_fskip(s->pb, 2); // FIXME: flags
+ channels = get_le16(s->pb);
+ bps = get_le16(s->pb);
+ samplerate = get_le32(s->pb);
if(samplerate <= 0 || samplerate > 1000000){
av_log(s, AV_LOG_ERROR, "nonsense samplerate\n");
return -1;
}
- datalen = get_le32(&s->pb);
+ datalen = get_le32(s->pb);
if(datalen < 0){
av_log(s, AV_LOG_ERROR, "nonsense datalen\n");
return -1;
}
- url_fskip(&s->pb, 4); // header crc
+ url_fskip(s->pb, 4); // header crc
framelen = samplerate*256/245;
c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0);
@@ -70,33 +68,39 @@ static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_log(s, AV_LOG_ERROR, "totalframes too large\n");
return -1;
}
- c->seektable = av_mallocz(sizeof(uint32_t)*c->totalframes);
- if (!c->seektable)
- return AVERROR_NOMEM;
-
- for (i = 0; i < c->totalframes; i++)
- c->seektable[i] = get_le32(&s->pb);
- url_fskip(&s->pb, 4); // seektable crc
st = av_new_stream(s, 0);
-// av_set_pts_info(st, 32, 1, 1000);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
+
+ av_set_pts_info(st, 64, 1, samplerate);
+ st->start_time = 0;
+ st->duration = datalen;
+
+ framepos = url_ftell(s->pb) + 4*c->totalframes + 4;
+
+ for (i = 0; i < c->totalframes; i++) {
+ uint32_t size = get_le32(s->pb);
+ av_add_index_entry(st, framepos, i*framelen, size, 0, AVINDEX_KEYFRAME);
+ framepos += size;
+ }
+ url_fskip(s->pb, 4); // seektable crc
+
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_TTA;
st->codec->channels = channels;
st->codec->sample_rate = samplerate;
st->codec->bits_per_sample = bps;
- st->codec->extradata_size = url_ftell(&s->pb);
+ st->codec->extradata_size = url_ftell(s->pb);
if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
//this check is redundant as get_buffer should fail
av_log(s, AV_LOG_ERROR, "extradata_size too large\n");
return -1;
}
st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE);
- url_fseek(&s->pb, 0, SEEK_SET);
- get_buffer(&s->pb, st->codec->extradata, st->codec->extradata_size);
+ url_fseek(s->pb, 0, SEEK_SET);
+ get_buffer(s->pb, st->codec->extradata, st->codec->extradata_size);
return 0;
}
@@ -104,37 +108,31 @@ static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int tta_read_packet(AVFormatContext *s, AVPacket *pkt)
{
TTAContext *c = s->priv_data;
- int ret, size;
+ AVStream *st = s->streams[0];
+ int size, ret;
// FIXME!
if (c->currentframe > c->totalframes)
- size = 0;
- else
- size = c->seektable[c->currentframe];
-
- c->currentframe++;
+ return -1;
- if (av_new_packet(pkt, size) < 0)
- return AVERROR_IO;
+ size = st->index_entries[c->currentframe].size;
- pkt->pos = url_ftell(&s->pb);
- pkt->stream_index = 0;
- ret = get_buffer(&s->pb, pkt->data, size);
- if (ret <= 0) {
- av_free_packet(pkt);
- return AVERROR_IO;
- }
- pkt->size = ret;
-// av_log(s, AV_LOG_INFO, "TTA packet #%d desired size: %d read size: %d at pos %d\n",
-// c->currentframe, size, ret, pkt->pos);
- return 0; //ret;
+ ret = av_get_packet(s->pb, pkt, size);
+ pkt->dts = st->index_entries[c->currentframe++].timestamp;
+ return ret;
}
-static int tta_read_close(AVFormatContext *s)
+static int tta_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{
TTAContext *c = s->priv_data;
- if (c->seektable)
- av_free(c->seektable);
+ AVStream *st = s->streams[stream_index];
+ int index = av_index_search_timestamp(st, timestamp, flags);
+ if (index < 0)
+ return -1;
+
+ c->currentframe = index;
+ url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
+
return 0;
}
@@ -145,6 +143,7 @@ AVInputFormat tta_demuxer = {
tta_probe,
tta_read_header,
tta_read_packet,
- tta_read_close,
+ NULL,
+ tta_read_seek,
.extensions = "tta",
};
diff --git a/contrib/ffmpeg/libavformat/txd.c b/contrib/ffmpeg/libavformat/txd.c
new file mode 100644
index 000000000..8092a41a4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/txd.c
@@ -0,0 +1,103 @@
+/*
+ * Renderware TeXture Dictionary (.txd) demuxer
+ * Copyright (c) 2007 Ivo van Poorten
+ *
+ * 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 "avformat.h"
+
+#define TXD_FILE 0x16
+#define TXD_INFO 0x01
+#define TXD_EXTRA 0x03
+#define TXD_TEXTURE 0x15
+#define TXD_TEXTURE_DATA 0x01
+#define TXD_MARKER 0x1803ffff
+#define TXD_MARKER2 0x1003ffff
+
+static int txd_probe(AVProbeData * pd) {
+ if (AV_RL32(pd->buf ) == TXD_FILE &&
+ (AV_RL32(pd->buf+8) == TXD_MARKER || AV_RL32(pd->buf+8) == TXD_MARKER2))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+static int txd_read_header(AVFormatContext *s, AVFormatParameters *ap) {
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_TXD;
+ st->codec->time_base.den = 5;
+ st->codec->time_base.num = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+static int txd_read_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = s->pb;
+ unsigned int id, chunk_size, marker;
+ int ret;
+
+next_chunk:
+ id = get_le32(pb);
+ chunk_size = get_le32(pb);
+ marker = get_le32(pb);
+
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
+ if (marker != TXD_MARKER && marker != TXD_MARKER2) {
+ av_log(NULL, AV_LOG_ERROR, "marker does not match\n");
+ return AVERROR(EIO);
+ }
+
+ switch (id) {
+ case TXD_INFO:
+ if (chunk_size > 100)
+ break;
+ case TXD_EXTRA:
+ url_fskip(s->pb, chunk_size);
+ case TXD_FILE:
+ case TXD_TEXTURE:
+ goto next_chunk;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "unknown chunk id %i\n", id);
+ return AVERROR(EIO);
+ }
+
+ ret = av_get_packet(s->pb, pkt, chunk_size);
+ pkt->stream_index = 0;
+
+ return ret <= 0 ? AVERROR(EIO) : ret;
+}
+
+static int txd_read_close(AVFormatContext *s) {
+ return 0;
+}
+
+AVInputFormat txd_demuxer =
+{
+ "txd",
+ "txd format",
+ 0,
+ txd_probe,
+ txd_read_header,
+ txd_read_packet,
+ txd_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/udp.c b/contrib/ffmpeg/libavformat/udp.c
index bbf8ca2ec..da3e25382 100644
--- a/contrib/ffmpeg/libavformat/udp.c
+++ b/contrib/ffmpeg/libavformat/udp.c
@@ -21,6 +21,7 @@
#include "avformat.h"
#include <unistd.h>
#include "network.h"
+#include "os_support.h"
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -34,91 +35,98 @@ typedef struct {
int local_port;
int reuse_socket;
#ifndef CONFIG_IPV6
- struct ip_mreq mreq;
struct sockaddr_in dest_addr;
#else
struct sockaddr_storage dest_addr;
- size_t dest_addr_len;
#endif
+ size_t dest_addr_len;
} UDPContext;
#define UDP_TX_BUF_SIZE 32768
+#define UDP_MAX_PKT_SIZE 65536
-#ifdef CONFIG_IPV6
-
-static int udp_ipv6_is_multicast_address(const struct sockaddr *addr) {
- if (addr->sa_family == AF_INET)
- return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
- if (addr->sa_family == AF_INET6)
- return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
- return -1;
-}
-
-static int udp_ipv6_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) {
+static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) {
+#ifdef IP_MULTICAST_TTL
if (addr->sa_family == AF_INET) {
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
- perror("setsockopt(IP_MULTICAST_TTL)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL): %s\n", strerror(errno));
return -1;
}
}
+#endif
+#ifdef CONFIG_IPV6
if (addr->sa_family == AF_INET6) {
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
- perror("setsockopt(IPV6_MULTICAST_HOPS)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS): %s\n", strerror(errno));
return -1;
}
}
+#endif
return 0;
}
-static int udp_ipv6_join_multicast_group(int sockfd, struct sockaddr *addr) {
- struct ip_mreq mreq;
- struct ipv6_mreq mreq6;
+static int udp_join_multicast_group(int sockfd, struct sockaddr *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 (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
- perror("setsockopt(IP_ADD_MEMBERSHIP)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP): %s\n", strerror(errno));
return -1;
}
}
+#endif
+#ifdef CONFIG_IPV6
if (addr->sa_family == AF_INET6) {
+ struct ipv6_mreq mreq6;
+
memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
mreq6.ipv6mr_interface= 0;
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
- perror("setsockopt(IPV6_ADD_MEMBERSHIP)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP): %s\n", strerror(errno));
return -1;
}
}
+#endif
return 0;
}
-static int udp_ipv6_leave_multicast_group(int sockfd, struct sockaddr *addr) {
- struct ip_mreq mreq;
- struct ipv6_mreq mreq6;
+static int udp_leave_multicast_group(int sockfd, struct sockaddr *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 (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
- perror("setsockopt(IP_DROP_MEMBERSHIP)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP): %s\n", strerror(errno));
return -1;
}
}
+#endif
+#ifdef CONFIG_IPV6
if (addr->sa_family == AF_INET6) {
+ struct ipv6_mreq mreq6;
+
memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
mreq6.ipv6mr_interface= 0;
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
- perror("setsockopt(IPV6_DROP_MEMBERSHIP)");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP): %s\n", strerror(errno));
return -1;
}
}
+#endif
return 0;
}
+#ifdef CONFIG_IPV6
static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, int type, int family, int flags) {
struct addrinfo hints, *res = 0;
int error;
char sport[16];
- const char *node = 0, *service = 0;
+ const char *node = 0, *service = "0";
if (port > 0) {
snprintf(sport, sizeof(sport), "%d", port);
@@ -127,80 +135,54 @@ static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, in
if ((hostname) && (hostname[0] != '\0') && (hostname[0] != '?')) {
node = hostname;
}
- if ((node) || (service)) {
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = type;
- hints.ai_family = family;
- hints.ai_flags = flags;
- if ((error = getaddrinfo(node, service, &hints, &res))) {
- av_log(NULL, AV_LOG_ERROR, "udp_ipv6_resolve_host: %s\n", gai_strerror(error));
- }
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = type;
+ hints.ai_family = family;
+ hints.ai_flags = flags;
+ if ((error = getaddrinfo(node, service, &hints, &res))) {
+ av_log(NULL, AV_LOG_ERROR, "udp_ipv6_resolve_host: %s\n", gai_strerror(error));
}
+
return res;
}
-static int udp_ipv6_set_remote_url(URLContext *h, const char *uri) {
- UDPContext *s = h->priv_data;
- char hostname[256];
- int port;
+static int udp_set_url(struct sockaddr_storage *addr, const char *hostname, int port) {
struct addrinfo *res0;
- url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
+ int addr_len;
+
res0 = udp_ipv6_resolve_host(hostname, port, SOCK_DGRAM, AF_UNSPEC, 0);
- if (res0 == 0) return AVERROR_IO;
- memcpy(&s->dest_addr, res0->ai_addr, res0->ai_addrlen);
- s->dest_addr_len = res0->ai_addrlen;
+ if (res0 == 0) return AVERROR(EIO);
+ memcpy(addr, res0->ai_addr, res0->ai_addrlen);
+ addr_len = res0->ai_addrlen;
freeaddrinfo(res0);
- return 0;
+
+ return addr_len;
}
-static int udp_ipv6_set_local(URLContext *h) {
- UDPContext *s = h->priv_data;
+static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, int *addr_len)
+{
int udp_fd = -1;
- struct sockaddr_storage clientaddr;
- socklen_t addrlen;
- char sbuf[NI_MAXSERV];
- char hbuf[NI_MAXHOST];
struct addrinfo *res0 = NULL, *res = NULL;
+ int family = AF_UNSPEC;
- if (s->local_port != 0) {
- res0 = udp_ipv6_resolve_host(0, s->local_port, SOCK_DGRAM, AF_UNSPEC, AI_PASSIVE);
- if (res0 == 0)
- goto fail;
- for (res = res0; res; res=res->ai_next) {
- udp_fd = socket(res->ai_family, SOCK_DGRAM, 0);
- if (udp_fd > 0) break;
- perror("socket");
- }
- } else {
- udp_fd = socket(s->dest_addr.ss_family, SOCK_DGRAM, 0);
- if (udp_fd < 0)
- perror("socket");
- }
-
- if (udp_fd < 0)
+ if (((struct sockaddr *) &s->dest_addr)->sa_family)
+ family = ((struct sockaddr *) &s->dest_addr)->sa_family;
+ res0 = udp_ipv6_resolve_host(0, s->local_port, SOCK_DGRAM, family, AI_PASSIVE);
+ if (res0 == 0)
goto fail;
-
- if (s->local_port != 0) {
- if (bind(udp_fd, res0->ai_addr, res0->ai_addrlen) < 0) {
- perror("bind");
- goto fail;
- }
- freeaddrinfo(res0);
- res0 = NULL;
+ for (res = res0; res; res=res->ai_next) {
+ udp_fd = socket(res->ai_family, SOCK_DGRAM, 0);
+ if (udp_fd > 0) break;
+ av_log(NULL, AV_LOG_ERROR, "socket: %s\n", strerror(errno));
}
- addrlen = sizeof(clientaddr);
- if (getsockname(udp_fd, (struct sockaddr *)&clientaddr, &addrlen) < 0) {
- perror("getsockname");
+ if (udp_fd < 0)
goto fail;
- }
- if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
- perror("getnameinfo");
- goto fail;
- }
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ *addr_len = res->ai_addrlen;
- s->local_port = strtol(sbuf, NULL, 10);
+ freeaddrinfo(res0);
return udp_fd;
@@ -212,7 +194,52 @@ static int udp_ipv6_set_local(URLContext *h) {
return -1;
}
-#endif
+static int udp_port(struct sockaddr_storage *addr, int addr_len)
+{
+ char sbuf[sizeof(int)*3+1];
+
+ if (getnameinfo((struct sockaddr *)addr, addr_len, NULL, 0, sbuf, sizeof(sbuf), NI_NUMERICSERV) != 0) {
+ av_log(NULL, AV_LOG_ERROR, "getnameinfo: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return strtol(sbuf, NULL, 10);
+}
+
+#else
+
+static int udp_set_url(struct sockaddr_in *addr, const char *hostname, int port)
+{
+ /* set the destination address */
+ if (resolve_host(&addr->sin_addr, hostname) < 0)
+ return AVERROR(EIO);
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(port);
+
+ return sizeof(struct sockaddr_in);
+}
+
+static int udp_socket_create(UDPContext *s, struct sockaddr_in *addr, int *addr_len)
+{
+ int fd;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return -1;
+
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = htonl (INADDR_ANY);
+ addr->sin_port = htons(s->local_port);
+ *addr_len = sizeof(struct sockaddr_in);
+
+ return fd;
+}
+
+static int udp_port(struct sockaddr_in *addr, int len)
+{
+ return ntohs(addr->sin_port);
+}
+#endif /* CONFIG_IPV6 */
/**
@@ -233,9 +260,6 @@ static int udp_ipv6_set_local(URLContext *h) {
*/
int udp_set_remote_url(URLContext *h, const char *uri)
{
-#ifdef CONFIG_IPV6
- return udp_ipv6_set_remote_url(h, uri);
-#else
UDPContext *s = h->priv_data;
char hostname[256];
int port;
@@ -243,12 +267,12 @@ int udp_set_remote_url(URLContext *h, const char *uri)
url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
/* set the destination address */
- if (resolve_host(&s->dest_addr.sin_addr, hostname) < 0)
- return AVERROR_IO;
- s->dest_addr.sin_family = AF_INET;
- s->dest_addr.sin_port = htons(port);
+ s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port);
+ if (s->dest_addr_len < 0) {
+ return AVERROR(EIO);
+ }
+
return 0;
-#endif
}
/**
@@ -284,24 +308,23 @@ static int udp_open(URLContext *h, const char *uri, int flags)
const char *p;
char buf[256];
#ifndef CONFIG_IPV6
- struct sockaddr_in my_addr, my_addr1;
- int len;
+ struct sockaddr_in my_addr;
+#else
+ struct sockaddr_storage my_addr;
#endif
+ int len;
h->is_streamed = 1;
h->max_packet_size = 1472;
is_output = (flags & URL_WRONLY);
- s = av_malloc(sizeof(UDPContext));
+ s = av_mallocz(sizeof(UDPContext));
if (!s)
return AVERROR(ENOMEM);
h->priv_data = s;
s->ttl = 16;
- s->is_multicast = 0;
- s->local_port = 0;
- s->reuse_socket = 0;
p = strchr(uri, '?');
if (p) {
s->is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
@@ -329,78 +352,51 @@ static int udp_open(URLContext *h, const char *uri, int flags)
udp_set_remote_url(h, uri);
}
-#ifndef CONFIG_IPV6
- udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if(!ff_network_init())
+ return AVERROR(EIO);
+
+ if (s->is_multicast && !(h->flags & URL_WRONLY))
+ s->local_port = port;
+ udp_fd = udp_socket_create(s, &my_addr, &len);
if (udp_fd < 0)
goto fail;
- my_addr.sin_family = AF_INET;
- my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
- if (s->is_multicast && !(h->flags & URL_WRONLY)) {
- /* special case: the bind must be done on the multicast address port */
- my_addr.sin_port = s->dest_addr.sin_port;
- } else {
- my_addr.sin_port = htons(s->local_port);
- }
-
if (s->reuse_socket)
if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
goto fail;
/* the bind is needed to give a port to the socket now */
- if (bind(udp_fd,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ if (bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0)
goto fail;
- len = sizeof(my_addr1);
- getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len);
- s->local_port = ntohs(my_addr1.sin_port);
+ len = sizeof(my_addr);
+ getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
+ s->local_port = udp_port(&my_addr, len);
-#ifdef IP_MULTICAST_TTL
if (s->is_multicast) {
if (h->flags & URL_WRONLY) {
/* output */
- if (setsockopt(udp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
- &s->ttl, sizeof(s->ttl)) < 0) {
- perror("IP_MULTICAST_TTL");
+ if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
goto fail;
- }
} else {
/* input */
- memset(&s->mreq, 0, sizeof(s->mreq));
- s->mreq.imr_multiaddr = s->dest_addr.sin_addr;
- s->mreq.imr_interface.s_addr = htonl (INADDR_ANY);
- if (setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &s->mreq, sizeof(s->mreq)) < 0) {
- perror("rtp: IP_ADD_MEMBERSHIP");
+ if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
goto fail;
- }
}
}
-#endif
-#else
- if (s->is_multicast && !(h->flags & URL_WRONLY))
- s->local_port = port;
- udp_fd = udp_ipv6_set_local(h);
- if (udp_fd < 0)
- goto fail;
- if (s->is_multicast) {
- if (h->flags & URL_WRONLY) {
- if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
- goto fail;
- } else {
- if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
- goto fail;
- }
- }
-#endif
if (is_output) {
/* limit the tx buf size to limit latency */
tmp = UDP_TX_BUF_SIZE;
if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
- perror("setsockopt sndbuf");
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno));
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. */
+ tmp = UDP_MAX_PKT_SIZE;
+ setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp));
}
s->udp_fd = udp_fd;
@@ -409,27 +405,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (udp_fd >= 0)
closesocket(udp_fd);
av_free(s);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
static int udp_read(URLContext *h, uint8_t *buf, int size)
{
UDPContext *s = h->priv_data;
-#ifndef CONFIG_IPV6
- struct sockaddr_in from;
-#else
- struct sockaddr_storage from;
-#endif
- socklen_t from_len;
int len;
for(;;) {
- from_len = sizeof(from);
- len = recvfrom (s->udp_fd, buf, size, 0,
- (struct sockaddr *)&from, &from_len);
+ len = recv(s->udp_fd, buf, size, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR)
- return AVERROR_IO;
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR))
+ return AVERROR(EIO);
} else {
break;
}
@@ -445,14 +434,11 @@ static int udp_write(URLContext *h, uint8_t *buf, int size)
for(;;) {
ret = sendto (s->udp_fd, buf, size, 0,
(struct sockaddr *) &s->dest_addr,
-#ifndef CONFIG_IPV6
- sizeof (s->dest_addr));
-#else
s->dest_addr_len);
-#endif
if (ret < 0) {
- if (errno != EINTR && errno != EAGAIN)
- return AVERROR_IO;
+ if (ff_neterrno() != FF_NETERROR(EINTR) &&
+ ff_neterrno() != FF_NETERROR(EAGAIN))
+ return AVERROR(EIO);
} else {
break;
}
@@ -464,20 +450,10 @@ static int udp_close(URLContext *h)
{
UDPContext *s = h->priv_data;
-#ifndef CONFIG_IPV6
-#ifdef IP_DROP_MEMBERSHIP
- if (s->is_multicast && !(h->flags & URL_WRONLY)) {
- if (setsockopt(s->udp_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- &s->mreq, sizeof(s->mreq)) < 0) {
- perror("IP_DROP_MEMBERSHIP");
- }
- }
-#endif
-#else
if (s->is_multicast && !(h->flags & URL_WRONLY))
- udp_ipv6_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
-#endif
+ udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
closesocket(s->udp_fd);
+ ff_network_close();
av_free(s);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/utils.c b/contrib/ffmpeg/libavformat/utils.c
index 36cb269b5..caf8df4eb 100644
--- a/contrib/ffmpeg/libavformat/utils.c
+++ b/contrib/ffmpeg/libavformat/utils.c
@@ -1,5 +1,5 @@
/*
- * Various utilities for ffmpeg system
+ * various utility functions for use within FFmpeg
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
@@ -19,25 +19,40 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "allformats.h"
#include "opt.h"
+#include "avstring.h"
+#include "riff.h"
+#include <sys/time.h>
+#include <time.h>
#undef NDEBUG
#include <assert.h>
/**
* @file libavformat/utils.c
- * Various utility functions for using ffmpeg library.
+ * various utility functions for use within FFmpeg
*/
static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den);
static void av_frac_add(AVFrac *f, int64_t incr);
-/** head of registered input format linked list. */
+/** head of registered input format linked list */
AVInputFormat *first_iformat = NULL;
-/** head of registered output format linked list. */
+/** head of registered output format linked list */
AVOutputFormat *first_oformat = NULL;
+AVInputFormat *av_iformat_next(AVInputFormat *f)
+{
+ if(f) return f->next;
+ else return first_iformat;
+}
+
+AVOutputFormat *av_oformat_next(AVOutputFormat *f)
+{
+ if(f) return f->next;
+ else return first_oformat;
+}
+
void av_register_input_format(AVInputFormat *format)
{
AVInputFormat **p;
@@ -97,7 +112,7 @@ AVOutputFormat *guess_format(const char *short_name, const char *filename,
return guess_format("image2", NULL, NULL);
}
#endif
- /* find the proper file type */
+ /* Find the proper file type. */
fmt_found = NULL;
score_max = 0;
fmt = first_oformat;
@@ -176,14 +191,25 @@ void av_destruct_packet(AVPacket *pkt)
pkt->data = NULL; pkt->size = 0;
}
+void av_init_packet(AVPacket *pkt)
+{
+ pkt->pts = AV_NOPTS_VALUE;
+ pkt->dts = AV_NOPTS_VALUE;
+ pkt->pos = -1;
+ pkt->duration = 0;
+ pkt->flags = 0;
+ pkt->stream_index = 0;
+ pkt->destruct= av_destruct_packet_nofree;
+}
+
int av_new_packet(AVPacket *pkt, int size)
{
uint8_t *data;
if((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!data)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
av_init_packet(pkt);
@@ -215,13 +241,12 @@ int av_dup_packet(AVPacket *pkt)
{
if (pkt->destruct != av_destruct_packet) {
uint8_t *data;
- /* we duplicate the packet and don't forget to put the padding
- again */
+ /* We duplicate the packet and don't forget to add the padding again. */
if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!data) {
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
memcpy(data, pkt->data, pkt->size);
memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
@@ -282,7 +307,7 @@ static const char* format_to_name(void* ptr)
}
#define OFFSET(x) offsetof(AVFormatContext,x)
-#define DEFAULT 0 //should be NAN but it doesnt work as its not a constant in glibc as required by ANSI/ISO C
+#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C
//these names are too long to be readable
#define E AV_OPT_FLAG_ENCODING_PARAM
#define D AV_OPT_FLAG_DECODING_PARAM
@@ -296,7 +321,9 @@ static const AVOption options[]={
{"genpts", "generate pts", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_GENPTS, INT_MIN, INT_MAX, D, "fflags"},
{"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E},
{"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E},
-{"analyzeduration", NULL, OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D},
+{"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D},
+{"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, 0, 0, 0, D},
+{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), FF_OPT_TYPE_INT, 1<<20, 0, INT_MAX, D},
{NULL},
};
@@ -343,21 +370,20 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
else
ic = *ic_ptr;
if (!ic) {
- err = AVERROR_NOMEM;
+ err = AVERROR(ENOMEM);
goto fail;
}
ic->iformat = fmt;
- if (pb)
- ic->pb = *pb;
+ ic->pb = pb;
ic->duration = AV_NOPTS_VALUE;
ic->start_time = AV_NOPTS_VALUE;
- pstrcpy(ic->filename, sizeof(ic->filename), filename);
+ av_strlcpy(ic->filename, filename, sizeof(ic->filename));
/* allocate private data */
if (fmt->priv_data_size > 0) {
ic->priv_data = av_mallocz(fmt->priv_data_size);
if (!ic->priv_data) {
- err = AVERROR_NOMEM;
+ err = AVERROR(ENOMEM);
goto fail;
}
} else {
@@ -369,7 +395,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
goto fail;
if (pb && !ic->data_offset)
- ic->data_offset = url_ftell(&ic->pb);
+ ic->data_offset = url_ftell(ic->pb);
*ic_ptr = ic;
return 0;
@@ -382,7 +408,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
return err;
}
-/** Size of probe buffer, for guessing file type from file contents. */
+/** size of probe buffer, for guessing file type from file contents */
#define PROBE_BUF_MIN 2048
#define PROBE_BUF_MAX (1<<20)
@@ -391,11 +417,10 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
int buf_size,
AVFormatParameters *ap)
{
- int err, must_open_file, file_opened, probe_size;
+ int err, probe_size;
AVProbeData probe_data, *pd = &probe_data;
- ByteIOContext pb1, *pb = &pb1;
+ ByteIOContext *pb = NULL;
- file_opened = 0;
pd->filename = "";
if (filename)
pd->filename = filename;
@@ -403,25 +428,17 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
pd->buf_size = 0;
if (!fmt) {
- /* guess format if no file can be opened */
+ /* guess format if no file can be opened */
fmt = av_probe_input_format(pd, 0);
}
- /* do not open file if the format does not need it. XXX: specific
+ /* Do not open file if the format does not need it. XXX: specific
hack needed to handle RTSP/TCP */
- must_open_file = 1;
- if (fmt && (fmt->flags & AVFMT_NOFILE)) {
- must_open_file = 0;
- pb= NULL; //FIXME this or memset(pb, 0, sizeof(ByteIOContext)); otherwise its uninitalized
- }
-
- if (!fmt || must_open_file) {
+ if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
/* if no file needed do not try to open one */
- if (url_fopen(pb, filename, URL_RDONLY) < 0) {
- err = AVERROR_IO;
+ if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) {
goto fail;
}
- file_opened = 1;
if (buf_size > 0) {
url_setbufsize(pb, buf_size);
}
@@ -429,13 +446,14 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){
int score= probe_size < PROBE_BUF_MAX ? AVPROBE_SCORE_MAX/4 : 0;
/* read probe data */
- pd->buf= av_realloc(pd->buf, probe_size);
+ pd->buf= av_realloc(pd->buf, probe_size + AVPROBE_PADDING_SIZE);
pd->buf_size = get_buffer(pb, pd->buf, probe_size);
+ memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
if (url_fseek(pb, 0, SEEK_SET) < 0) {
url_fclose(pb);
- if (url_fopen(pb, filename, URL_RDONLY) < 0) {
- file_opened = 0;
- err = AVERROR_IO;
+ if (url_fopen(&pb, filename, URL_RDONLY) < 0) {
+ pb = NULL;
+ err = AVERROR(EIO);
goto fail;
}
}
@@ -451,16 +469,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
goto fail;
}
- /* XXX: suppress this hack for redirectors */
-#ifdef CONFIG_NETWORK
- if (fmt == &redir_demuxer) {
- err = redir_open(ic_ptr, pb);
- url_fclose(pb);
- return err;
- }
-#endif
-
- /* check filename in case of an image number is expected */
+ /* check filename in case an image number is expected */
if (fmt->flags & AVFMT_NEEDNUMBER) {
if (!av_filename_number_test(filename)) {
err = AVERROR_NUMEXPECTED;
@@ -473,7 +482,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
return 0;
fail:
av_freep(&pd->buf);
- if (file_opened)
+ if (pb)
url_fclose(pb);
*ic_ptr = NULL;
return err;
@@ -484,13 +493,33 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
int av_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- return s->iformat->read_packet(s, pkt);
+ int ret;
+ AVStream *st;
+ av_init_packet(pkt);
+ ret= s->iformat->read_packet(s, pkt);
+ if (ret < 0)
+ return ret;
+ st= s->streams[pkt->stream_index];
+
+ switch(st->codec->codec_type){
+ case CODEC_TYPE_VIDEO:
+ if(s->video_codec_id) st->codec->codec_id= s->video_codec_id;
+ break;
+ case CODEC_TYPE_AUDIO:
+ if(s->audio_codec_id) st->codec->codec_id= s->audio_codec_id;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ if(s->subtitle_codec_id)st->codec->codec_id= s->subtitle_codec_id;
+ break;
+ }
+
+ return ret;
}
/**********************************************************/
/**
- * Get the number of samples of an audio frame. Return (-1) if error.
+ * Get the number of samples of an audio frame. Return -1 on error.
*/
static int get_audio_frame_size(AVCodecContext *enc, int size)
{
@@ -517,7 +546,7 @@ static int get_audio_frame_size(AVCodecContext *enc, int size)
/**
- * Return the frame duration in seconds, return 0 if not available.
+ * Return the frame duration in seconds. Return 0 if not available.
*/
static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt)
@@ -574,35 +603,87 @@ static int is_intra_only(AVCodecContext *enc){
return 0;
}
-static int64_t lsb2full(int64_t lsb, int64_t last_ts, int lsb_bits){
- int64_t mask = lsb_bits < 64 ? (1LL<<lsb_bits)-1 : -1LL;
- int64_t delta= last_ts - mask/2;
- return ((lsb - delta)&mask) + delta;
+static void update_initial_timestamps(AVFormatContext *s, int stream_index,
+ int64_t dts, int64_t pts)
+{
+ AVStream *st= s->streams[stream_index];
+ AVPacketList *pktl= s->packet_buffer;
+
+ if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)
+ return;
+
+ st->first_dts= dts - st->cur_dts;
+ st->cur_dts= dts;
+
+ for(; pktl; pktl= pktl->next){
+ if(pktl->pkt.stream_index != stream_index)
+ continue;
+ //FIXME think more about this check
+ if(pktl->pkt.pts != AV_NOPTS_VALUE && pktl->pkt.pts == pktl->pkt.dts)
+ pktl->pkt.pts += st->first_dts;
+
+ if(pktl->pkt.dts != AV_NOPTS_VALUE)
+ pktl->pkt.dts += st->first_dts;
+
+ 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)
+ st->start_time = pts;
+}
+
+static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket *pkt)
+{
+ AVPacketList *pktl= s->packet_buffer;
+
+ assert(pkt->duration && !st->cur_dts);
+
+ for(; pktl; pktl= pktl->next){
+ if(pktl->pkt.stream_index != pkt->stream_index)
+ continue;
+ if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE
+ && !pktl->pkt.duration){
+ pktl->pkt.pts= pktl->pkt.dts= st->cur_dts;
+ st->cur_dts += pkt->duration;
+ pktl->pkt.duration= pkt->duration;
+ }else
+ break;
+ }
}
static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt)
{
int num, den, presentation_delayed, delay, i;
- /* handle wrapping */
- if(st->cur_dts != AV_NOPTS_VALUE){
- if(pkt->pts != AV_NOPTS_VALUE)
- pkt->pts= lsb2full(pkt->pts, st->cur_dts, st->pts_wrap_bits);
- if(pkt->dts != AV_NOPTS_VALUE)
- pkt->dts= lsb2full(pkt->dts, st->cur_dts, st->pts_wrap_bits);
+ int64_t offset;
+
+ if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63
+ /*&& pkt->dts-(1LL<<st->pts_wrap_bits) < pkt->pts*/){
+ pkt->dts -= 1LL<<st->pts_wrap_bits;
}
if (pkt->duration == 0) {
compute_frame_duration(&num, &den, st, pc, pkt);
if (den && num) {
pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
+
+ if(st->cur_dts == 0)
+ update_initial_durations(s, st, pkt);
}
}
- if(is_intra_only(st->codec))
- pkt->flags |= PKT_FLAG_KEY;
+ /* 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)
+ pkt->pts += offset;
+ if(pkt->dts != AV_NOPTS_VALUE)
+ pkt->dts += offset;
+ }
- /* do we have a video B frame ? */
+ /* do we have a video B-frame ? */
delay= st->codec->has_b_frames;
presentation_delayed = 0;
/* XXX: need has_b_frame, but cannot get it if the codec is
@@ -610,34 +691,35 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
if (delay &&
pc && pc->pict_type != FF_B_TYPE)
presentation_delayed = 1;
- /* this may be redundant, but it shouldnt hurt */
+ /* This may be redundant, but it should not hurt. */
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)
presentation_delayed = 1;
if(st->cur_dts == AV_NOPTS_VALUE){
- st->cur_dts = -delay * pkt->duration;
+ st->cur_dts = 0; //FIXME maybe set it to 0 during init
}
// av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc);
/* interpolate PTS and DTS if they are not present */
if(delay <=1){
if (presentation_delayed) {
- /* DTS = decompression time stamp */
- /* PTS = presentation time stamp */
+ /* DTS = decompression timestamp */
+ /* PTS = presentation timestamp */
if (pkt->dts == AV_NOPTS_VALUE)
pkt->dts = st->last_IP_pts;
+ update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts);
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 */
+ 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;
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 futur */
+ by knowing the future */
} else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){
if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){
int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts);
@@ -651,6 +733,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
/* presentation is not delayed : PTS and DTS are the same */
if(pkt->pts == AV_NOPTS_VALUE)
pkt->pts = pkt->dts;
+ update_initial_timestamps(s, pkt->stream_index, pkt->pts, pkt->pts);
if(pkt->pts == AV_NOPTS_VALUE)
pkt->pts = st->cur_dts;
pkt->dts = pkt->pts;
@@ -666,6 +749,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
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(delay>1){
+ update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); // this should happen on the first packet
+ }
if(pkt->dts > st->cur_dts)
st->cur_dts = pkt->dts;
}
@@ -673,9 +759,11 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
// av_log(NULL, AV_LOG_ERROR, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts);
/* update flags */
- if (pc) {
+ if(is_intra_only(st->codec))
+ pkt->flags |= PKT_FLAG_KEY;
+ else if (pc) {
pkt->flags = 0;
- /* key frame computation */
+ /* keyframe computation */
if (pc->pict_type == FF_I_TYPE)
pkt->flags |= PKT_FLAG_KEY;
}
@@ -691,6 +779,8 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
AVStream *st;
int len, ret, i;
+ av_init_packet(pkt);
+
for(;;) {
/* select current input stream component */
st = s->cur_st;
@@ -715,6 +805,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
/* return packet if any */
if (pkt->size) {
got_packet:
+ pkt->pos = s->cur_pkt.pos; // Isn't quite accurate but close.
pkt->duration = 0;
pkt->stream_index = st->index;
pkt->pts = st->parser->pts;
@@ -723,6 +814,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
compute_pkt_fields(s, st, st->parser, pkt);
if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & PKT_FLAG_KEY){
+ ff_reduce_index(s, st->index);
av_add_index_entry(st, st->parser->frame_offset, pkt->dts,
0, 0, AVINDEX_KEYFRAME);
}
@@ -752,7 +844,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
goto got_packet;
}
}
- /* no more packets: really terminates parsing */
+ /* no more packets: really terminate parsing */
return ret;
}
@@ -770,9 +862,9 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
if (st->need_parsing && !st->parser) {
st->parser = av_parser_init(st->codec->codec_id);
if (!st->parser) {
- /* no parser available : just output the raw packets */
- st->need_parsing = 0;
- }else if(st->need_parsing == 2){
+ /* no parser available: just output the raw packets */
+ st->need_parsing = AVSTREAM_PARSE_NONE;
+ }else if(st->need_parsing == AVSTREAM_PARSE_HEADERS){
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
}
if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){
@@ -792,6 +884,22 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
return 0;
}
+static AVPacket *add_to_pktbuf(AVFormatContext *s, AVPacket *pkt){
+ AVPacketList *pktl= s->packet_buffer;
+ AVPacketList **plast_pktl= &s->packet_buffer;
+
+ while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
+
+ pktl = av_mallocz(sizeof(AVPacketList));
+ if (!pktl)
+ return NULL;
+
+ /* add the packet in the buffered packet list */
+ *plast_pktl = pktl;
+ pktl->pkt= *pkt;
+ return &pktl->pkt;
+}
+
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
AVPacketList *pktl;
@@ -827,7 +935,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
}
}
if(genpts){
- AVPacketList **plast_pktl= &s->packet_buffer;
int ret= av_read_frame_internal(s, pkt);
if(ret<0){
if(pktl && ret != AVERROR(EAGAIN)){
@@ -837,19 +944,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
return ret;
}
- /* duplicate the packet */
- if (av_dup_packet(pkt) < 0)
- return AVERROR_NOMEM;
-
- while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
-
- pktl = av_mallocz(sizeof(AVPacketList));
- if (!pktl)
- return AVERROR_NOMEM;
-
- /* add the packet in the buffered packet list */
- *plast_pktl = pktl;
- pktl->pkt= *pkt;
+ if(av_dup_packet(add_to_pktbuf(s, pkt)) < 0)
+ return AVERROR(ENOMEM);
}else{
assert(!s->packet_buffer);
return av_read_frame_internal(s, pkt);
@@ -936,6 +1032,19 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
}
}
+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);
+
+ 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;
+ }
+}
+
int av_add_index_entry(AVStream *st,
int64_t pos, int64_t timestamp, int size, int distance, int flags)
{
@@ -967,7 +1076,7 @@ int av_add_index_entry(AVStream *st,
return -1;
memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(st->nb_index_entries - index));
st->nb_index_entries++;
- }else if(ie->pos == pos && distance < ie->min_distance) //dont reduce the distance
+ }else if(ie->pos == pos && distance < ie->min_distance) //do not reduce the distance
distance= ie->min_distance;
}
@@ -980,49 +1089,6 @@ int av_add_index_entry(AVStream *st,
return index;
}
-/**
- * build an index for raw streams using a parser.
- */
-static void av_build_index_raw(AVFormatContext *s)
-{
- AVPacket pkt1, *pkt = &pkt1;
- int ret;
- AVStream *st;
-
- st = s->streams[0];
- av_read_frame_flush(s);
- url_fseek(&s->pb, s->data_offset, SEEK_SET);
-
- for(;;) {
- ret = av_read_frame(s, pkt);
- if (ret < 0)
- break;
- if (pkt->stream_index == 0 && st->parser &&
- (pkt->flags & PKT_FLAG_KEY)) {
- av_add_index_entry(st, st->parser->frame_offset, pkt->dts,
- 0, 0, AVINDEX_KEYFRAME);
- }
- av_free_packet(pkt);
- }
-}
-
-/**
- * Returns TRUE if we deal with a raw stream.
- *
- * Raw codec data and parsing needed.
- */
-static int is_raw_stream(AVFormatContext *s)
-{
- AVStream *st;
-
- if (s->nb_streams != 1)
- return 0;
- st = s->streams[0];
- if (!st->need_parsing)
- return 0;
- return 1;
-}
-
int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp,
int flags)
{
@@ -1073,13 +1139,13 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
ts_max=
ts_min= AV_NOPTS_VALUE;
- pos_limit= -1; //gcc falsely says it may be uninitalized
+ pos_limit= -1; //gcc falsely says it may be uninitialized
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= 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];
@@ -1114,7 +1180,7 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
return -1;
/* do the seek */
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
av_update_cur_dts(s, st, ts);
@@ -1139,7 +1205,7 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
if(ts_max == AV_NOPTS_VALUE){
int step= 1024;
- filesize = url_fsize(&s->pb);
+ filesize = url_fsize(s->pb);
pos_max = filesize - 1;
do{
pos_max -= step;
@@ -1186,7 +1252,8 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
// bisection, if interpolation failed to change min or 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 keframes between min/max
+ /* linear search if bisection failed, can only happen if there
+ are very few or no keyframes between min/max */
pos=pos_min;
}
if(pos <= pos_min)
@@ -1203,6 +1270,10 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
#ifdef DEBUG_SEEK
av_log(s, AV_LOG_DEBUG, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change);
#endif
+ 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;
@@ -1241,12 +1312,12 @@ static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos,
#endif
pos_min = s->data_offset;
- pos_max = url_fsize(&s->pb) - 1;
+ pos_max = url_fsize(s->pb) - 1;
if (pos < pos_min) pos= pos_min;
else if(pos > pos_max) pos= pos_max;
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
#if 0
av_update_cur_dts(s, st, ts);
@@ -1265,16 +1336,16 @@ static int av_seek_frame_generic(AVFormatContext *s,
index = av_index_search_timestamp(st, timestamp, flags);
- if(index < 0){
+ if(index < 0 || index==st->nb_index_entries-1){
int i;
AVPacket pkt;
if(st->index_entries && st->nb_index_entries){
ie= &st->index_entries[st->nb_index_entries-1];
- url_fseek(&s->pb, ie->pos, SEEK_SET);
+ url_fseek(s->pb, ie->pos, SEEK_SET);
av_update_cur_dts(s, st, ie->timestamp);
}else
- url_fseek(&s->pb, 0, SEEK_SET);
+ url_fseek(s->pb, 0, SEEK_SET);
for(i=0;; i++) {
int ret = av_read_frame(s, &pkt);
@@ -1297,7 +1368,7 @@ static int av_seek_frame_generic(AVFormatContext *s,
return 0;
}
ie = &st->index_entries[index];
- url_fseek(&s->pb, ie->pos, SEEK_SET);
+ url_fseek(s->pb, ie->pos, SEEK_SET);
av_update_cur_dts(s, st, ie->timestamp);
@@ -1343,19 +1414,18 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f
/*******************************************************/
/**
- * Returns TRUE if the stream has accurate timings in any stream.
+ * Returns TRUE if the stream has accurate duration in any stream.
*
- * @return TRUE if the stream has accurate timings for at least one component.
+ * @return TRUE if the stream has accurate duration for at least one component.
*/
-static int av_has_timings(AVFormatContext *ic)
+static int av_has_duration(AVFormatContext *ic)
{
int i;
AVStream *st;
for(i = 0;i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (st->start_time != AV_NOPTS_VALUE &&
- st->duration != AV_NOPTS_VALUE)
+ if (st->duration != AV_NOPTS_VALUE)
return 1;
}
return 0;
@@ -1369,14 +1439,16 @@ static int av_has_timings(AVFormatContext *ic)
static void av_update_stream_timings(AVFormatContext *ic)
{
int64_t start_time, start_time1, end_time, end_time1;
+ int64_t duration, duration1;
int i;
AVStream *st;
start_time = INT64_MAX;
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) {
+ 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);
if (start_time1 < start_time)
start_time = start_time1;
@@ -1387,19 +1459,27 @@ static void av_update_stream_timings(AVFormatContext *ic)
end_time = end_time1;
}
}
+ if (st->duration != AV_NOPTS_VALUE) {
+ duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
+ if (duration1 > duration)
+ duration = duration1;
+ }
}
if (start_time != INT64_MAX) {
ic->start_time = start_time;
if (end_time != INT64_MIN) {
- ic->duration = end_time - start_time;
- if (ic->file_size > 0) {
- /* compute the bit rate */
- ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /
- (double)ic->duration;
- }
+ if (end_time - start_time > duration)
+ duration = end_time - start_time;
+ }
+ }
+ if (duration != INT64_MIN) {
+ ic->duration = duration;
+ if (ic->file_size > 0) {
+ /* compute the bitrate */
+ ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /
+ (double)ic->duration;
}
}
-
}
static void fill_all_stream_timings(AVFormatContext *ic)
@@ -1444,11 +1524,8 @@ static void av_estimate_timings_from_bit_rate(AVFormatContext *ic)
for(i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num);
- if (st->start_time == AV_NOPTS_VALUE ||
- st->duration == AV_NOPTS_VALUE) {
- st->start_time = 0;
+ if (st->duration == AV_NOPTS_VALUE)
st->duration = duration;
- }
}
}
}
@@ -1465,11 +1542,25 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse
int64_t end_time;
int64_t filesize, offset, duration;
- av_read_frame_flush(ic);
+ /* free previous packet */
+ if (ic->cur_st && ic->cur_st->parser)
+ av_free_packet(&ic->cur_pkt);
+ ic->cur_st = NULL;
+
+ /* flush packet queue */
+ flush_packet_queue(ic);
+
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (st->parser) {
+ av_parser_close(st->parser);
+ st->parser= NULL;
+ }
+ }
/* we read the first packets to get the first PTS (not fully
accurate, but it is enough now) */
- url_fseek(&ic->pb, 0, SEEK_SET);
+ url_fseek(ic->pb, 0, SEEK_SET);
read_size = 0;
for(;;) {
if (read_size >= DURATION_MAX_READ_SIZE)
@@ -1502,26 +1593,19 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse
if (offset < 0)
offset = 0;
- url_fseek(&ic->pb, offset, SEEK_SET);
+ url_fseek(ic->pb, offset, SEEK_SET);
read_size = 0;
for(;;) {
if (read_size >= DURATION_MAX_READ_SIZE)
break;
- /* if all info is available, we can stop */
- for(i = 0;i < ic->nb_streams; i++) {
- st = ic->streams[i];
- if (st->duration == AV_NOPTS_VALUE)
- break;
- }
- if (i == ic->nb_streams)
- break;
ret = av_read_packet(ic, pkt);
if (ret != 0)
break;
read_size += pkt->size;
st = ic->streams[pkt->stream_index];
- if (pkt->pts != AV_NOPTS_VALUE) {
+ if (pkt->pts != AV_NOPTS_VALUE &&
+ st->start_time != AV_NOPTS_VALUE) {
end_time = pkt->pts;
duration = end_time - st->start_time;
if (duration > 0) {
@@ -1535,7 +1619,12 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse
fill_all_stream_timings(ic);
- url_fseek(&ic->pb, old_offset, SEEK_SET);
+ url_fseek(ic->pb, old_offset, SEEK_SET);
+ for(i=0; i<ic->nb_streams; i++){
+ st= ic->streams[i];
+ st->cur_dts= st->first_dts;
+ st->last_IP_pts = AV_NOPTS_VALUE;
+ }
}
static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset)
@@ -1546,7 +1635,7 @@ static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset)
if (ic->iformat->flags & AVFMT_NOFILE) {
file_size = 0;
} else {
- file_size = url_fsize(&ic->pb);
+ file_size = url_fsize(ic->pb);
if (file_size < 0)
file_size = 0;
}
@@ -1554,15 +1643,15 @@ static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset)
if ((!strcmp(ic->iformat->name, "mpeg") ||
!strcmp(ic->iformat->name, "mpegts")) &&
- file_size && !ic->pb.is_streamed) {
+ file_size && !url_is_streamed(ic->pb)) {
/* get accurate estimate from the PTSes */
av_estimate_timings_from_pts(ic, old_offset);
- } else if (av_has_timings(ic)) {
- /* at least one components has timings - we use them for all
+ } else if (av_has_duration(ic)) {
+ /* at least one component has timings - we use them for all
the components */
fill_all_stream_timings(ic);
} else {
- /* less precise: use bit rate info */
+ /* less precise: use bitrate info */
av_estimate_timings_from_bit_rate(ic);
}
av_update_stream_timings(ic);
@@ -1599,7 +1688,7 @@ static int has_codec_parameters(AVCodecContext *enc)
val = 1;
break;
}
- return (val != 0);
+ return (enc->codec_id != CODEC_ID_NONE && val != 0);
}
static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
@@ -1622,7 +1711,7 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
switch(st->codec->codec_type) {
case CODEC_TYPE_VIDEO:
ret = avcodec_decode_video(st->codec, &picture,
- &got_picture, (uint8_t *)data, size);
+ &got_picture, data, size);
break;
case CODEC_TYPE_AUDIO:
data_size = FFMAX(size, AVCODEC_MAX_AUDIO_FRAME_SIZE);
@@ -1630,7 +1719,7 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
if (!samples)
goto fail;
ret = avcodec_decode_audio2(st->codec, samples,
- &data_size, (uint8_t *)data, size);
+ &data_size, data, size);
av_free(samples);
break;
default:
@@ -1641,6 +1730,67 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
return ret;
}
+static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score)
+{
+ AVInputFormat *fmt;
+ fmt = av_probe_input_format2(pd, 1, &score);
+
+ if (fmt) {
+ if (strncmp(fmt->name, "mp3", 3) == 0)
+ st->codec->codec_id = CODEC_ID_MP3;
+ else if (strncmp(fmt->name, "ac3", 3) == 0)
+ st->codec->codec_id = CODEC_ID_AC3;
+ }
+ return !!fmt;
+}
+
+unsigned int codec_get_tag(const AVCodecTag *tags, int id)
+{
+ while (tags->id != CODEC_ID_NONE) {
+ if (tags->id == id)
+ return tags->tag;
+ tags++;
+ }
+ return 0;
+}
+
+enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag)
+{
+ int i;
+ for(i=0; tags[i].id != CODEC_ID_NONE;i++) {
+ if(tag == tags[i].tag)
+ return tags[i].id;
+ }
+ for(i=0; tags[i].id != CODEC_ID_NONE; i++) {
+ if( toupper((tag >> 0)&0xFF) == toupper((tags[i].tag >> 0)&0xFF)
+ && toupper((tag >> 8)&0xFF) == toupper((tags[i].tag >> 8)&0xFF)
+ && toupper((tag >>16)&0xFF) == toupper((tags[i].tag >>16)&0xFF)
+ && toupper((tag >>24)&0xFF) == toupper((tags[i].tag >>24)&0xFF))
+ return tags[i].id;
+ }
+ return CODEC_ID_NONE;
+}
+
+unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id)
+{
+ int i;
+ for(i=0; tags && tags[i]; i++){
+ int tag= codec_get_tag(tags[i], id);
+ if(tag) return tag;
+ }
+ return 0;
+}
+
+enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag)
+{
+ int i;
+ for(i=0; tags && tags[i]; i++){
+ enum CodecID id= codec_get_id(tags[i], tag);
+ if(id!=CODEC_ID_NONE) return id;
+ }
+ return CODEC_ID_NONE;
+}
+
/* absolute maximum size we read until we abort */
#define MAX_READ_SIZE 5000000
@@ -1650,21 +1800,40 @@ static int get_std_framerate(int i){
else return ((int[]){24,30,60,12,15})[i-60*12]*1000*12;
}
+/*
+ * 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 == ff_get_fourcc("DIVX")
+ || c->codec_tag == ff_get_fourcc("XVID")*/
+ || c->codec_id == CODEC_ID_MPEG2VIDEO)
+ return 1;
+ return 0;
+}
+
int av_find_stream_info(AVFormatContext *ic)
{
int i, count, ret, read_size, j;
AVStream *st;
AVPacket pkt1, *pkt;
- AVPacketList *pktl=NULL, **ppktl;
int64_t last_dts[MAX_STREAMS];
int duration_count[MAX_STREAMS]={0};
double (*duration_error)[MAX_STD_TIMEBASES];
- offset_t old_offset = url_ftell(&ic->pb);
+ offset_t old_offset = url_ftell(ic->pb);
int64_t codec_info_duration[MAX_STREAMS]={0};
int codec_info_nb_frames[MAX_STREAMS]={0};
+ AVProbeData probe_data[MAX_STREAMS];
+ int codec_identified[MAX_STREAMS]={0};
duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));
- if (!duration_error) return AVERROR_NOMEM;
+ if (!duration_error) return AVERROR(ENOMEM);
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
@@ -1677,7 +1846,7 @@ int av_find_stream_info(AVFormatContext *ic)
//only for the split stuff
if (!st->parser) {
st->parser = av_parser_init(st->codec->codec_id);
- if(st->need_parsing == 2 && st->parser){
+ if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
}
}
@@ -1687,9 +1856,9 @@ int av_find_stream_info(AVFormatContext *ic)
last_dts[i]= AV_NOPTS_VALUE;
}
+ memset(probe_data, 0, sizeof(probe_data));
count = 0;
read_size = 0;
- ppktl = &ic->packet_buffer;
for(;;) {
/* check if one codec still needs to be handled */
for(i=0;i<ic->nb_streams;i++) {
@@ -1697,11 +1866,13 @@ int av_find_stream_info(AVFormatContext *ic)
if (!has_codec_parameters(st->codec))
break;
/* variable fps and no guess at the real fps */
- if( (st->codec->time_base.den >= 101LL*st->codec->time_base.num || st->codec->codec_id == CODEC_ID_MPEG2VIDEO)
+ if( tb_unreliable(st->codec)
&& duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
break;
if(st->parser && st->parser->parser->split && !st->codec->extradata)
break;
+ if(st->first_dts == AV_NOPTS_VALUE)
+ break;
}
if (i == ic->nb_streams) {
/* NOTE: if the format has no header, then we need to read
@@ -1738,24 +1909,9 @@ int av_find_stream_info(AVFormatContext *ic)
break;
}
- pktl = av_mallocz(sizeof(AVPacketList));
- if (!pktl) {
- ret = AVERROR_NOMEM;
- break;
- }
-
- /* add the packet in the buffered packet list */
- *ppktl = pktl;
- ppktl = &pktl->next;
-
- pkt = &pktl->pkt;
- *pkt = pkt1;
-
- /* duplicate the packet */
- if (av_dup_packet(pkt) < 0) {
- ret = AVERROR_NOMEM;
- break;
- }
+ pkt= add_to_pktbuf(ic, &pkt1);
+ if(av_dup_packet(pkt) < 0)
+ return AVERROR(ENOMEM);
read_size += pkt->size;
@@ -1787,6 +1943,14 @@ int av_find_stream_info(AVFormatContext *ic)
}
if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
last_dts[pkt->stream_index]= pkt->dts;
+
+ if (st->codec->codec_id == CODEC_ID_NONE) {
+ AVProbeData *pd = &(probe_data[st->index]);
+ pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_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);
+ }
}
if(st->parser && st->parser->parser->split && !st->codec->extradata){
int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
@@ -1800,8 +1964,8 @@ int av_find_stream_info(AVFormatContext *ic)
/* 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 MPEG4, we need to
- decompress for Quicktime. */
+ it takes longer and uses more memory. For MPEG-4, we need to
+ decompress for QuickTime. */
if (!has_codec_parameters(st->codec) /*&&
(st->codec->codec_id == CODEC_ID_FLV1 ||
st->codec->codec_id == CODEC_ID_H264 ||
@@ -1819,7 +1983,7 @@ int av_find_stream_info(AVFormatContext *ic)
(st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/)
try_decode_frame(st, pkt->data, pkt->size);
- if (av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
+ if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
break;
}
count++;
@@ -1838,8 +2002,8 @@ int av_find_stream_info(AVFormatContext *ic)
st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
if(duration_count[i]
- && (st->codec->time_base.num*101LL <= st->codec->time_base.den || st->codec->codec_id == CODEC_ID_MPEG2VIDEO) /*&&
- //FIXME we should not special case mpeg2, but this needs testing with non mpeg2 ...
+ && tb_unreliable(st->codec) /*&&
+ //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ...
st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){
double best_error= 2*av_q2d(st->time_base);
best_error= best_error*best_error*duration_count[i]*1000*12*30;
@@ -1866,14 +2030,39 @@ int av_find_stream_info(AVFormatContext *ic)
}
}
}else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) {
+ codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1);
+ if (codec_identified[st->index]) {
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ }
+ }
if(!st->codec->bits_per_sample)
st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);
}
}
av_estimate_timings(ic, old_offset);
+
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (codec_identified[st->index])
+ break;
+ }
+ //FIXME this is a mess
+ if(i!=ic->nb_streams){
+ av_read_frame_flush(ic);
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (codec_identified[st->index]) {
+ av_seek_frame(ic, st->index, 0.0, 0);
+ }
+ st->cur_dts= st->first_dts;
+ }
+ url_fseek(ic->pb, ic->data_offset, SEEK_SET);
+ }
+
#if 0
- /* correct DTS for b frame streams with no timestamps */
+ /* correct DTS for B-frame streams with no timestamps */
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
@@ -1898,6 +2087,9 @@ int av_find_stream_info(AVFormatContext *ic)
#endif
av_free(duration_error);
+ for(i=0;i<MAX_STREAMS;i++){
+ av_freep(&(probe_data[i].buf));
+ }
return ret;
}
@@ -1906,21 +2098,25 @@ int av_find_stream_info(AVFormatContext *ic)
int av_read_play(AVFormatContext *s)
{
- if (!s->iformat->read_play)
- return AVERROR_NOTSUPP;
- return s->iformat->read_play(s);
+ if (s->iformat->read_play)
+ return s->iformat->read_play(s);
+ if (s->pb)
+ return av_url_read_fpause(s->pb, 0);
+ return AVERROR(ENOSYS);
}
int av_read_pause(AVFormatContext *s)
{
- if (!s->iformat->read_pause)
- return AVERROR_NOTSUPP;
- return s->iformat->read_pause(s);
+ if (s->iformat->read_pause)
+ return s->iformat->read_pause(s);
+ if (s->pb)
+ return av_url_read_fpause(s->pb, 1);
+ return AVERROR(ENOSYS);
}
-void av_close_input_file(AVFormatContext *s)
+void av_close_input_stream(AVFormatContext *s)
{
- int i, must_open_file;
+ int i;
AVStream *st;
/* free previous packet */
@@ -1938,20 +2134,28 @@ void av_close_input_file(AVFormatContext *s)
av_free(st->index_entries);
av_free(st->codec->extradata);
av_free(st->codec);
+ av_free(st->filename);
av_free(st);
}
- flush_packet_queue(s);
- must_open_file = 1;
- if (s->iformat->flags & AVFMT_NOFILE) {
- must_open_file = 0;
- }
- if (must_open_file) {
- url_fclose(&s->pb);
+ for(i=s->nb_programs-1; i>=0; i--) {
+ av_freep(&s->programs[i]->provider_name);
+ av_freep(&s->programs[i]->name);
+ av_freep(&s->programs[i]->stream_index);
+ av_freep(&s->programs[i]);
}
+ flush_packet_queue(s);
av_freep(&s->priv_data);
av_free(s);
}
+void av_close_input_file(AVFormatContext *s)
+{
+ ByteIOContext *pb = s->iformat->flags & AVFMT_NOFILE ? NULL : s->pb;
+ av_close_input_stream(s);
+ if (pb)
+ url_fclose(pb);
+}
+
AVStream *av_new_stream(AVFormatContext *s, int id)
{
AVStream *st;
@@ -1974,8 +2178,9 @@ AVStream *av_new_stream(AVFormatContext *s, int id)
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
st->cur_dts = AV_NOPTS_VALUE;
+ st->first_dts = AV_NOPTS_VALUE;
- /* default pts settings is MPEG like */
+ /* default pts setting is MPEG-like */
av_set_pts_info(st, 33, 1, 90000);
st->last_IP_pts = AV_NOPTS_VALUE;
for(i=0; i<MAX_REORDER_DELAY+1; i++)
@@ -1985,6 +2190,43 @@ AVStream *av_new_stream(AVFormatContext *s, int id)
return st;
}
+AVProgram *av_new_program(AVFormatContext *ac, int id)
+{
+ AVProgram *program=NULL;
+ int i;
+
+#ifdef DEBUG_SI
+ av_log(ac, AV_LOG_DEBUG, "new_program: id=0x%04x\n", id);
+#endif
+
+ for(i=0; i<ac->nb_programs; i++)
+ if(ac->programs[i]->id == id)
+ program = ac->programs[i];
+
+ if(!program){
+ program = av_mallocz(sizeof(AVProgram));
+ if (!program)
+ return NULL;
+ dynarray_add(&ac->programs, &ac->nb_programs, program);
+ program->discard = AVDISCARD_NONE;
+ }
+ program->id = id;
+
+ return program;
+}
+
+void av_set_program_name(AVProgram *program, char *provider_name, char *name)
+{
+ assert(!provider_name == !name);
+ if(name){
+ av_free(program->provider_name);
+ av_free(program-> name);
+ program->provider_name = av_strdup(provider_name);
+ program-> name = av_strdup( name);
+ }
+}
+
+
/************************************************************/
/* output media file */
@@ -1995,7 +2237,7 @@ int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
} else
s->priv_data = NULL;
@@ -2039,7 +2281,7 @@ int av_write_header(AVFormatContext *s)
if(st->codec->codec_tag){
//FIXME
//check that tag + id is in the table
- //if neither is in the table -> ok
+ //if neither is in the table -> OK
//if tag is in the table with another id -> FAIL
//if id is in the table with another tag -> FAIL unless strict < ?
}else
@@ -2050,7 +2292,7 @@ int av_write_header(AVFormatContext *s)
if (!s->priv_data && s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
}
if(s->oformat->write_header){
@@ -2120,12 +2362,11 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){
}
if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){
- av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64" st:%d\n", st->cur_dts, pkt->dts, st->index);
+ av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts);
return -1;
}
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){
- av_log(NULL, AV_LOG_ERROR, "error, pts < dts (%"PRId64" < %"PRId64")\n",
- pkt->pts, pkt->dts);
+ av_log(NULL, AV_LOG_ERROR, "error, pts < dts\n");
return -1;
}
@@ -2138,8 +2379,9 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){
case CODEC_TYPE_AUDIO:
frame_size = get_audio_frame_size(st->codec, pkt->size);
- /* 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 had the real timestamps from the encoder */
+ /* 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
+ had the real timestamps from the encoder */
if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) {
av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
}
@@ -2157,7 +2399,7 @@ static void truncate_ts(AVStream *st, AVPacket *pkt){
int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1;
// if(pkt->dts < 0)
-// pkt->dts= 0; //this happens for low_delay=0 and b frames, FIXME, needs further invstigation about what we should do here
+// pkt->dts= 0; //this happens for low_delay=0 and B-frames, FIXME, needs further investigation about what we should do here
if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts &= pts_mask;
@@ -2177,7 +2419,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
ret= s->oformat->write_packet(s, pkt);
if(!ret)
- ret= url_ferror(&s->pb);
+ ret= url_ferror(s->pb);
return ret;
}
@@ -2194,7 +2436,7 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk
this_pktl = av_mallocz(sizeof(AVPacketList));
this_pktl->pkt= *pkt;
if(pkt->destruct == av_destruct_packet)
- pkt->destruct= NULL; // non shared -> must keep original from being freed
+ pkt->destruct= NULL; // not shared -> must keep original from being freed
else
av_dup_packet(&this_pktl->pkt); //shared -> must dup
@@ -2235,7 +2477,7 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk
}
/**
- * Interleaves a AVPacket correctly so it can be muxed.
+ * Interleaves an AVPacket correctly so it can be muxed.
* @param out the interleaved packet will be output here
* @param in the input packet
* @param flush 1 if no further packets are available as input and all
@@ -2278,8 +2520,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
if(ret<0)
return ret;
- if(url_ferror(&s->pb))
- return url_ferror(&s->pb);
+ if(url_ferror(s->pb))
+ return url_ferror(s->pb);
}
}
@@ -2302,7 +2544,7 @@ int av_write_trailer(AVFormatContext *s)
if(ret<0)
goto fail;
- if(url_ferror(&s->pb))
+ if(url_ferror(s->pb))
goto fail;
}
@@ -2310,22 +2552,70 @@ int av_write_trailer(AVFormatContext *s)
ret = s->oformat->write_trailer(s);
fail:
if(ret == 0)
- ret=url_ferror(&s->pb);
+ ret=url_ferror(s->pb);
for(i=0;i<s->nb_streams;i++)
av_freep(&s->streams[i]->priv_data);
av_freep(&s->priv_data);
return ret;
}
+void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx)
+{
+ int i, j;
+ AVProgram *program=NULL;
+ void *tmp;
+
+ 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)
+ return;
+
+ tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1));
+ if(!tmp)
+ return;
+ program->stream_index = tmp;
+ program->stream_index[program->nb_stream_indexes++] = idx;
+ return;
+ }
+}
+
/* "user interface" functions */
+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);
+ AVStream *st = ic->streams[i];
+ int g = ff_gcd(st->time_base.num, st->time_base.den);
+ avcodec_string(buf, sizeof(buf), st->codec, is_output);
+ av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i);
+ /* the pid is an important information, so we display it */
+ /* XXX: add a generic system */
+ if (flags & AVFMT_SHOW_IDS)
+ av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
+ if (strlen(st->language) > 0)
+ av_log(NULL, AV_LOG_INFO, "(%s)", st->language);
+ av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
+ av_log(NULL, AV_LOG_INFO, ": %s", buf);
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+ if(st->r_frame_rate.den && st->r_frame_rate.num)
+ av_log(NULL, AV_LOG_INFO, ", %5.2f tb(r)", av_q2d(st->r_frame_rate));
+/* else if(st->time_base.den && st->time_base.num)
+ av_log(NULL, AV_LOG_INFO, ", %5.2f tb(m)", 1/av_q2d(st->time_base));*/
+ else
+ av_log(NULL, AV_LOG_INFO, ", %5.2f tb(c)", 1/av_q2d(st->codec->time_base));
+ }
+ av_log(NULL, AV_LOG_INFO, "\n");
+}
void dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output)
{
- int i, flags;
- char buf[256];
+ int i;
av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
is_output ? "Output" : "Input",
@@ -2363,124 +2653,43 @@ void dump_format(AVFormatContext *ic,
}
av_log(NULL, AV_LOG_INFO, "\n");
}
- for(i=0;i<ic->nb_streams;i++) {
- AVStream *st = ic->streams[i];
- int g= ff_gcd(st->time_base.num, st->time_base.den);
- avcodec_string(buf, sizeof(buf), st->codec, is_output);
- av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i);
- /* the pid is an important information, so we display it */
- /* XXX: add a generic system */
- if (is_output)
- flags = ic->oformat->flags;
- else
- flags = ic->iformat->flags;
- if (flags & AVFMT_SHOW_IDS) {
- av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
- }
- if (strlen(st->language) > 0) {
- av_log(NULL, AV_LOG_INFO, "(%s)", st->language);
- }
- av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
- av_log(NULL, AV_LOG_INFO, ": %s", buf);
- if(st->codec->codec_type == CODEC_TYPE_VIDEO){
- if(st->r_frame_rate.den && st->r_frame_rate.num)
- av_log(NULL, AV_LOG_INFO, ", %5.2f fps(r)", av_q2d(st->r_frame_rate));
-/* else if(st->time_base.den && st->time_base.num)
- av_log(NULL, AV_LOG_INFO, ", %5.2f fps(m)", 1/av_q2d(st->time_base));*/
- else
- av_log(NULL, AV_LOG_INFO, ", %5.2f fps(c)", 1/av_q2d(st->codec->time_base));
- }
- av_log(NULL, AV_LOG_INFO, "\n");
- }
+ if(ic->nb_programs) {
+ int j, k;
+ for(j=0; j<ic->nb_programs; j++) {
+ av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id,
+ ic->programs[j]->name ? ic->programs[j]->name : "");
+ for(k=0; k<ic->programs[j]->nb_stream_indexes; k++)
+ dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
+ }
+ } else
+ for(i=0;i<ic->nb_streams;i++)
+ dump_stream_format(ic, i, index, is_output);
}
-typedef struct {
- const char *abv;
- int width, height;
- int frame_rate, frame_rate_base;
-} AbvEntry;
-
-static AbvEntry frame_abvs[] = {
- { "ntsc", 720, 480, 30000, 1001 },
- { "pal", 720, 576, 25, 1 },
- { "qntsc", 352, 240, 30000, 1001 }, /* VCD compliant ntsc */
- { "qpal", 352, 288, 25, 1 }, /* VCD compliant pal */
- { "sntsc", 640, 480, 30000, 1001 }, /* square pixel ntsc */
- { "spal", 768, 576, 25, 1 }, /* square pixel pal */
- { "film", 352, 240, 24, 1 },
- { "ntsc-film", 352, 240, 24000, 1001 },
- { "sqcif", 128, 96, 0, 0 },
- { "qcif", 176, 144, 0, 0 },
- { "cif", 352, 288, 0, 0 },
- { "4cif", 704, 576, 0, 0 },
-};
-
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
{
- int i;
- int n = sizeof(frame_abvs) / sizeof(AbvEntry);
- const char *p;
- int frame_width = 0, frame_height = 0;
-
- for(i=0;i<n;i++) {
- if (!strcmp(frame_abvs[i].abv, str)) {
- frame_width = frame_abvs[i].width;
- frame_height = frame_abvs[i].height;
- break;
- }
- }
- if (i == n) {
- p = str;
- frame_width = strtol(p, (char **)&p, 10);
- if (*p)
- p++;
- frame_height = strtol(p, (char **)&p, 10);
- }
- if (frame_width <= 0 || frame_height <= 0)
- return -1;
- *width_ptr = frame_width;
- *height_ptr = frame_height;
- return 0;
+ return av_parse_video_frame_size(width_ptr, height_ptr, str);
}
-int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg)
+int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg)
{
- int i;
- char* cp;
-
- /* First, we check our abbreviation table */
- for (i = 0; i < sizeof(frame_abvs)/sizeof(*frame_abvs); ++i)
- if (!strcmp(frame_abvs[i].abv, arg)) {
- *frame_rate = frame_abvs[i].frame_rate;
- *frame_rate_base = frame_abvs[i].frame_rate_base;
- return 0;
- }
+ AVRational frame_rate;
+ int ret = av_parse_video_frame_rate(&frame_rate, arg);
+ *frame_rate_num= frame_rate.num;
+ *frame_rate_den= frame_rate.den;
+ return ret;
+}
- /* Then, we try to parse it as fraction */
- cp = strchr(arg, '/');
- if (!cp)
- cp = strchr(arg, ':');
- if (cp) {
- char* cpp;
- *frame_rate = strtol(arg, &cpp, 10);
- if (cpp != arg || cpp == cp)
- *frame_rate_base = strtol(cp+1, &cpp, 10);
- else
- *frame_rate = 0;
- }
- else {
- /* Finally we give up and parse it as double */
- AVRational time_base = av_d2q(strtod(arg, 0), DEFAULT_FRAME_RATE_BASE);
- *frame_rate_base = time_base.den;
- *frame_rate = time_base.num;
- }
- if (!*frame_rate || !*frame_rate_base)
- return -1;
- else
- return 0;
+/**
+ * Gets the current time in microseconds.
+ */
+int64_t av_gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
-#ifndef CONFIG_WINCE
int64_t parse_date(const char *datestr, int duration)
{
const char *p;
@@ -2515,6 +2724,7 @@ int64_t parse_date(const char *datestr, int duration)
p = datestr;
q = NULL;
if (!duration) {
+ /* parse the year-month-day part */
for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
q = small_strptime(p, date_fmt[i], &dt);
if (q) {
@@ -2522,6 +2732,8 @@ int64_t parse_date(const char *datestr, int duration)
}
}
+ /* if the year-month-day part is missing, then take the
+ * current year-month-day time */
if (!q) {
if (is_utc) {
dt = *gmtime(&now);
@@ -2536,6 +2748,7 @@ int64_t parse_date(const char *datestr, int duration)
if (*p == 'T' || *p == 't' || *p == ' ')
p++;
+ /* parse the hour-minute-second part */
for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
q = small_strptime(p, time_fmt[i], &dt);
if (q) {
@@ -2543,13 +2756,19 @@ int64_t parse_date(const char *datestr, int duration)
}
}
} else {
+ /* parse datestr as a duration */
if (p[0] == '-') {
negative = 1;
++p;
}
+ /* parse datestr as HH:MM:SS */
q = small_strptime(p, time_fmt[0], &dt);
if (!q) {
+ /* parse datestr as S+ */
dt.tm_sec = strtol(p, (char **)&q, 10);
+ if (q == p)
+ /* the parsing didn't succeed */
+ return INT64_MIN;
dt.tm_min = 0;
dt.tm_hour = 0;
}
@@ -2557,10 +2776,7 @@ int64_t parse_date(const char *datestr, int duration)
/* Now we have all the fields that we can get */
if (!q) {
- if (duration)
- return 0;
- else
- return now * INT64_C(1000000);
+ return INT64_MIN;
}
if (duration) {
@@ -2576,6 +2792,7 @@ int64_t parse_date(const char *datestr, int duration)
t *= 1000000;
+ /* parse the .m... part */
if (*q == '.') {
int val, n;
q++;
@@ -2588,7 +2805,6 @@ int64_t parse_date(const char *datestr, int duration)
}
return negative ? -t : t;
}
-#endif /* CONFIG_WINCE */
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
{
@@ -2735,7 +2951,7 @@ static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int
PRINT("N/A");
else
PRINT("%0.3f", (double)pkt->dts / AV_TIME_BASE);
- /* PTS may be not known if B frames are present */
+ /* PTS may not be known if B-frames are present. */
PRINT(" pts=");
if (pkt->pts == AV_NOPTS_VALUE)
PRINT("N/A");
@@ -2765,68 +2981,58 @@ void url_split(char *proto, int proto_size,
char *path, int path_size,
const char *url)
{
- const char *p;
- char *q;
- int port;
+ const char *p, *ls, *at, *col, *brk;
- port = -1;
+ 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;
- p = url;
- q = proto;
- while (*p != ':' && *p != '\0') {
- if ((q - proto) < proto_size - 1)
- *q++ = *p;
- p++;
- }
- if (proto_size > 0)
- *q = '\0';
- if (authorization_size > 0)
- authorization[0] = '\0';
- if (*p == '\0') {
- if (proto_size > 0)
- proto[0] = '\0';
- if (hostname_size > 0)
- hostname[0] = '\0';
- p = url;
+ /* parse protocol */
+ if ((p = strchr(url, ':'))) {
+ av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
+ p++; /* skip ':' */
+ if (*p == '/') p++;
+ if (*p == '/') p++;
} else {
- char *at,*slash; // PETR: position of '@' character and '/' character
+ /* no protocol means plain filename */
+ av_strlcpy(path, url, path_size);
+ return;
+ }
- p++;
- if (*p == '/')
- p++;
- if (*p == '/')
- p++;
- at = strchr(p,'@'); // PETR: get the position of '@'
- slash = strchr(p,'/'); // PETR: get position of '/' - end of hostname
- if (at && slash && at > slash) at = NULL; // PETR: not interested in '@' behind '/'
-
- q = at ? authorization : hostname; // PETR: if '@' exists starting with auth.
-
- while ((at || *p != ':') && *p != '/' && *p != '?' && *p != '\0') { // PETR:
- if (*p == '@') { // PETR: passed '@'
- if (authorization_size > 0)
- *q = '\0';
- q = hostname;
- at = NULL;
- } else if (!at) { // PETR: hostname
- if ((q - hostname) < hostname_size - 1)
- *q++ = *p;
- } else {
- if ((q - authorization) < authorization_size - 1)
- *q++ = *p;
- }
- p++;
- }
- if (hostname_size > 0)
- *q = '\0';
- if (*p == ':') {
- p++;
- port = strtoul(p, (char **)&p, 10);
+ /* separate path from hostname */
+ ls = strchr(p, '/');
+ if(!ls)
+ ls = strchr(p, '?');
+ if(ls)
+ av_strlcpy(path, ls, path_size);
+ else
+ ls = &p[strlen(p)]; // XXX
+
+ /* the rest is hostname, use that to parse auth/port */
+ if (ls != p) {
+ /* authorization (user[:pass]@hostname) */
+ if ((at = strchr(p, '@')) && at < ls) {
+ av_strlcpy(authorization, p,
+ FFMIN(authorization_size, at + 1 - p));
+ p = at + 1; /* skip '@' */
}
+
+ if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
+ /* [host]:port */
+ av_strlcpy(hostname, p + 1,
+ FFMIN(hostname_size, brk - p));
+ if (brk[1] == ':' && port_ptr)
+ *port_ptr = atoi(brk + 2);
+ } 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);
+ } else
+ av_strlcpy(hostname, p,
+ FFMIN(ls + 1 - p, hostname_size));
}
- if (port_ptr)
- *port_ptr = port;
- pstrcpy(path, path_size, p);
}
void av_set_pts_info(AVStream *s, int pts_wrap_bits,
@@ -2862,7 +3068,7 @@ static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
}
/**
- * Fractionnal addition to f: f = f + (incr / f->den).
+ * Fractional addition to f: f = f + (incr / f->den).
*
* @param f fractional number
* @param incr increment, can be positive or negative
diff --git a/contrib/ffmpeg/libavformat/v4l2.c b/contrib/ffmpeg/libavformat/v4l2.c
deleted file mode 100644
index aeaac3347..000000000
--- a/contrib/ffmpeg/libavformat/v4l2.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Video4Linux2 grab interface
- * Copyright (c) 2000,2001 Fabrice Bellard.
- * Copyright (c) 2006 Luca Abeni.
- *
- * Part of this file is based on the V4L2 video capture example
- * (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
- *
- * Thanks to Michael Niedermayer for providing the mapping between
- * V4L2_PIX_FMT_* and PIX_FMT_*
- *
- *
- * 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 "avformat.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <asm/types.h>
-#include <linux/videodev2.h>
-#include <time.h>
-
-static const int desired_video_buffers = 256;
-
-enum io_method {
- io_read,
- io_mmap,
- io_userptr
-};
-
-struct video_data {
- int fd;
- int frame_format; /* V4L2_PIX_FMT_* */
- enum io_method io_method;
- int width, height;
- int frame_rate;
- int frame_rate_base;
- int frame_size;
- int top_field_first;
-
- int buffers;
- void **buf_start;
- unsigned int *buf_len;
-};
-
-struct buff_data {
- int index;
- int fd;
-};
-
-struct fmt_map {
- enum PixelFormat ff_fmt;
- int32_t v4l2_fmt;
-};
-
-static struct fmt_map fmt_conversion_table[] = {
- {
- .ff_fmt = PIX_FMT_YUV420P,
- .v4l2_fmt = V4L2_PIX_FMT_YUV420,
- },
- {
- .ff_fmt = PIX_FMT_YUV422P,
- .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
- },
- {
- .ff_fmt = PIX_FMT_YUYV422,
- .v4l2_fmt = V4L2_PIX_FMT_YUYV,
- },
- {
- .ff_fmt = PIX_FMT_UYVY422,
- .v4l2_fmt = V4L2_PIX_FMT_UYVY,
- },
- {
- .ff_fmt = PIX_FMT_YUV411P,
- .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
- },
- {
- .ff_fmt = PIX_FMT_YUV410P,
- .v4l2_fmt = V4L2_PIX_FMT_YUV410,
- },
- {
- .ff_fmt = PIX_FMT_BGR24,
- .v4l2_fmt = V4L2_PIX_FMT_BGR24,
- },
- {
- .ff_fmt = PIX_FMT_RGB24,
- .v4l2_fmt = V4L2_PIX_FMT_RGB24,
- },
- /*
- {
- .ff_fmt = PIX_FMT_RGB32,
- .v4l2_fmt = V4L2_PIX_FMT_BGR32,
- },
- */
- {
- .ff_fmt = PIX_FMT_GRAY8,
- .v4l2_fmt = V4L2_PIX_FMT_GREY,
- },
-};
-
-static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
-{
- struct v4l2_capability cap;
- int fd;
- int res;
-
- fd = open(ctx->filename, O_RDWR /*| O_NONBLOCK*/, 0);
- if (fd < 0) {
- av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
- ctx->filename, strerror(errno));
-
- return -1;
- }
-
- res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
- // ENOIOCTLCMD definition only availble on __KERNEL__
- if (res < 0 && errno == 515)
- {
- av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
- close(fd);
-
- return -1;
- }
- if (res < 0) {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
- strerror(errno));
- close(fd);
-
- return -1;
- }
- if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
- av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
- close(fd);
-
- return -1;
- }
- *capabilities = cap.capabilities;
-
- return fd;
-}
-
-static int device_init(AVFormatContext *ctx, int *width, int *height, int pix_fmt)
-{
- struct video_data *s = ctx->priv_data;
- int fd = s->fd;
- struct v4l2_format fmt;
- int res;
-
- memset(&fmt, 0, sizeof(struct v4l2_format));
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = *width;
- fmt.fmt.pix.height = *height;
- fmt.fmt.pix.pixelformat = pix_fmt;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- res = ioctl(fd, VIDIOC_S_FMT, &fmt);
- if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
- av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height);
- *width = fmt.fmt.pix.width;
- *height = fmt.fmt.pix.height;
- }
-
- return res;
-}
-
-static int first_field(int fd)
-{
- int res;
- v4l2_std_id std;
-
- res = ioctl(fd, VIDIOC_G_STD, &std);
- if (res < 0) {
- return 0;
- }
- if (std & V4L2_STD_NTSC) {
- return 0;
- }
-
- return 1;
-}
-
-static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt)
-{
- int i;
-
- for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
- if (fmt_conversion_table[i].ff_fmt == pix_fmt) {
- return fmt_conversion_table[i].v4l2_fmt;
- }
- }
-
- return 0;
-}
-
-static enum PixelFormat fmt_v4l2ff(uint32_t pix_fmt)
-{
- int i;
-
- for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
- if (fmt_conversion_table[i].v4l2_fmt == pix_fmt) {
- return fmt_conversion_table[i].ff_fmt;
- }
- }
-
- return -1;
-}
-
-static int mmap_init(AVFormatContext *ctx)
-{
- struct video_data *s = ctx->priv_data;
- struct v4l2_requestbuffers req;
- int i, res;
-
- memset(&req, 0, sizeof(struct v4l2_requestbuffers));
- req.count = desired_video_buffers;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
- if (res < 0) {
- if (errno == EINVAL) {
- av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
- } else {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
- }
-
- return -1;
- }
-
- if (req.count < 2) {
- av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
-
- return -1;
- }
- s->buffers = req.count;
- s->buf_start = av_malloc(sizeof(void *) * s->buffers);
- if (s->buf_start == NULL) {
- av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
-
- return -1;
- }
- s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
- if (s->buf_len == NULL) {
- av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
- av_free(s->buf_start);
-
- return -1;
- }
-
- for (i = 0; i < req.count; i++) {
- struct v4l2_buffer buf;
-
- memset(&buf, 0, sizeof(struct v4l2_buffer));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
- res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
- if (res < 0) {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
-
- return -1;
- }
-
- s->buf_len[i] = buf.length;
- if (s->buf_len[i] < s->frame_size) {
- av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
-
- return -1;
- }
- s->buf_start[i] = mmap (NULL, buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
- if (s->buf_start[i] == MAP_FAILED) {
- av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
-
- return -1;
- }
- }
-
- return 0;
-}
-
-static int read_init(AVFormatContext *ctx)
-{
- return -1;
-}
-
-static void mmap_release_buffer(AVPacket *pkt)
-{
- struct v4l2_buffer buf;
- int res, fd;
- struct buff_data *buf_descriptor = pkt->priv;
-
- memset(&buf, 0, sizeof(struct v4l2_buffer));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = buf_descriptor->index;
- fd = buf_descriptor->fd;
- av_free(buf_descriptor);
-
- res = ioctl (fd, VIDIOC_QBUF, &buf);
- if (res < 0) {
- av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
- }
- pkt->data = NULL;
- pkt->size = 0;
-}
-
-static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
-{
- struct video_data *s = ctx->priv_data;
- struct v4l2_buffer buf;
- struct buff_data *buf_descriptor;
- int res;
-
- memset(&buf, 0, sizeof(struct v4l2_buffer));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
-
- /* FIXME: Some special treatment might be needed in case of loss of signal... */
- while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 &&
- ((errno == EAGAIN) || (errno == EINTR)));
- if (res < 0) {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
-
- return -1;
- }
- assert (buf.index < s->buffers);
- if (buf.bytesused != s->frame_size) {
- av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
-
- return -1;
- }
-
- /* Image is at s->buff_start[buf.index] */
- pkt->data= s->buf_start[buf.index];
- pkt->size = buf.bytesused;
- pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
- pkt->destruct = mmap_release_buffer;
- buf_descriptor = av_malloc(sizeof(struct buff_data));
- if (buf_descriptor == NULL) {
- /* Something went wrong... Since av_malloc() failed, we cannot even
- * allocate a buffer for memcopying into it
- */
- av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
- res = ioctl (s->fd, VIDIOC_QBUF, &buf);
-
- return -1;
- }
- buf_descriptor->fd = s->fd;
- buf_descriptor->index = buf.index;
- pkt->priv = buf_descriptor;
-
- return s->buf_len[buf.index];
-}
-
-static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
-{
- return -1;
-}
-
-static int mmap_start(AVFormatContext *ctx)
-{
- struct video_data *s = ctx->priv_data;
- enum v4l2_buf_type type;
- int i, res;
-
- for (i = 0; i < s->buffers; i++) {
- struct v4l2_buffer buf;
-
- memset(&buf, 0, sizeof(struct v4l2_buffer));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
-
- res = ioctl (s->fd, VIDIOC_QBUF, &buf);
- if (res < 0) {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
-
- return -1;
- }
- }
-
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- res = ioctl (s->fd, VIDIOC_STREAMON, &type);
- if (res < 0) {
- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
-
- return -1;
- }
-
- return 0;
-}
-
-static void mmap_close(struct video_data *s)
-{
- enum v4l2_buf_type type;
- int i;
-
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- /* We do not check for the result, because we could
- * not do anything about it anyway...
- */
- ioctl(s->fd, VIDIOC_STREAMOFF, &type);
- for (i = 0; i < s->buffers; i++) {
- munmap(s->buf_start[i], s->buf_len[i]);
- }
- av_free(s->buf_start);
- av_free(s->buf_len);
-}
-
-static int v4l2_set_parameters( AVFormatContext *s1, AVFormatParameters *ap )
-{
- struct video_data *s = s1->priv_data;
- struct v4l2_input input;
- struct v4l2_standard standard;
- int i;
-
- /* set tv video input */
- memset (&input, 0, sizeof (input));
- input.index = ap->channel;
- if(ioctl (s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
- av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
- return AVERROR_IO;
- }
-
- av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
- ap->channel, input.name);
- if(ioctl (s->fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
- av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
- ap->channel);
- return AVERROR_IO;
- }
-
- av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
- ap->standard );
- /* set tv standard */
- memset (&standard, 0, sizeof (standard));
- for(i=0;;i++) {
- standard.index = i;
- if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
- av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
- ap->standard);
- return AVERROR_IO;
- }
-
- if(!strcasecmp(standard.name, ap->standard)) {
- break;
- }
- }
-
- av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
- ap->standard, standard.id);
- if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
- av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
- ap->standard);
- return AVERROR_IO;
- }
-
- return 0;
-}
-
-static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- struct video_data *s = s1->priv_data;
- AVStream *st;
- int width, height;
- int res, frame_rate, frame_rate_base;
- uint32_t desired_format, capabilities;
-
- if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
- av_log(s1, AV_LOG_ERROR, "Missing/Wrong parameters\n");
-
- return -1;
- }
-
- width = ap->width;
- height = ap->height;
- frame_rate = ap->time_base.den;
- frame_rate_base = ap->time_base.num;
-
- if((unsigned)width > 32767 || (unsigned)height > 32767) {
- av_log(s1, AV_LOG_ERROR, "Wrong size %dx%d\n", width, height);
-
- return -1;
- }
-
- st = av_new_stream(s1, 0);
- if (!st) {
- return AVERROR(ENOMEM);
- }
- av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
-
- s->width = width;
- s->height = height;
- s->frame_rate = frame_rate;
- s->frame_rate_base = frame_rate_base;
-
- capabilities = 0;
- s->fd = device_open(s1, &capabilities);
- if (s->fd < 0) {
- av_free(st);
-
- return AVERROR_IO;
- }
- av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
-
- desired_format = fmt_ff2v4l(ap->pix_fmt);
- if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {
- int i, done;
-
- done = 0; i = 0;
- while (!done) {
- desired_format = fmt_conversion_table[i].v4l2_fmt;
- if (device_init(s1, &width, &height, desired_format) < 0) {
- desired_format = 0;
- i++;
- } else {
- done = 1;
- }
- if (i == sizeof(fmt_conversion_table) / sizeof(struct fmt_map)) {
- done = 1;
- }
- }
- }
- if (desired_format == 0) {
- av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");
- close(s->fd);
- av_free(st);
-
- return AVERROR_IO;
- }
- s->frame_format = desired_format;
-
- if( v4l2_set_parameters( s1, ap ) < 0 )
- return AVERROR_IO;
-
- st->codec->pix_fmt = fmt_v4l2ff(desired_format);
- s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);
- if (capabilities & V4L2_CAP_STREAMING) {
- s->io_method = io_mmap;
- res = mmap_init(s1);
- if (res == 0) {
- res = mmap_start(s1);
- }
- } else {
- s->io_method = io_read;
- res = read_init(s1);
- }
- if (res < 0) {
- close(s->fd);
- av_free(st);
-
- return AVERROR_IO;
- }
- s->top_field_first = first_field(s->fd);
-
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = CODEC_ID_RAWVIDEO;
- st->codec->width = width;
- st->codec->height = height;
- st->codec->time_base.den = frame_rate;
- st->codec->time_base.num = frame_rate_base;
- st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
-
- return 0;
-}
-
-static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- struct video_data *s = s1->priv_data;
- int res;
-
- if (s->io_method == io_mmap) {
- av_init_packet(pkt);
- res = mmap_read_frame(s1, pkt);
- } else if (s->io_method == io_read) {
- if (av_new_packet(pkt, s->frame_size) < 0)
- return AVERROR_IO;
-
- res = read_frame(s1, pkt);
- } else {
- return AVERROR_IO;
- }
- if (res < 0) {
- return AVERROR_IO;
- }
-
- if (s1->streams[0]->codec->coded_frame) {
- s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
- s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
- }
-
- return s->frame_size;
-}
-
-static int v4l2_read_close(AVFormatContext *s1)
-{
- struct video_data *s = s1->priv_data;
-
- if (s->io_method == io_mmap) {
- mmap_close(s);
- }
-
- close(s->fd);
- return 0;
-}
-
-AVInputFormat v4l2_demuxer = {
- "video4linux2",
- "video grab",
- sizeof(struct video_data),
- NULL,
- v4l2_read_header,
- v4l2_read_packet,
- v4l2_read_close,
- .flags = AVFMT_NOFILE,
-};
diff --git a/contrib/ffmpeg/libavformat/vc1test.c b/contrib/ffmpeg/libavformat/vc1test.c
new file mode 100644
index 000000000..c8340179c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/vc1test.c
@@ -0,0 +1,112 @@
+/*
+ * VC1 Test Bitstreams Format Demuxer
+ * Copyright (c) 2006, 2008 Konstantin Shishkov
+ *
+ * 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 vc1test.c
+ * VC1 test bitstream file demuxer
+ * by Konstantin Shishkov
+ * Format specified in SMPTE standard 421 Annex L
+ */
+
+#include "avformat.h"
+
+#define VC1_EXTRADATA_SIZE 4
+
+static int vc1t_probe(AVProbeData *p)
+{
+ if (p->buf[3] != 0xC5 && AV_RL32(&p->buf[4]) != 4)
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int vc1t_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = s->pb;
+ AVStream *st;
+ int fps, frames;
+
+ frames = get_le24(pb);
+ if(get_byte(pb) != 0xC5 || get_le32(pb) != 4)
+ return -1;
+
+ /* init video codec */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_WMV3;
+
+ st->codec->extradata = av_malloc(VC1_EXTRADATA_SIZE);
+ st->codec->extradata_size = VC1_EXTRADATA_SIZE;
+ get_buffer(pb, st->codec->extradata, VC1_EXTRADATA_SIZE);
+ st->codec->height = get_le32(pb);
+ st->codec->width = get_le32(pb);
+ if(get_le32(pb) != 0xC)
+ return -1;
+ url_fskip(pb, 8);
+ fps = get_le32(pb);
+ if(fps == -1)
+ av_set_pts_info(st, 32, 1, 1000);
+ else{
+ av_set_pts_info(st, 24, 1, fps);
+ st->duration = frames;
+ }
+
+ return 0;
+}
+
+static int vc1t_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ ByteIOContext *pb = s->pb;
+ int frame_size;
+ int keyframe = 0;
+ uint32_t pts;
+
+ if(url_feof(pb))
+ return AVERROR(EIO);
+
+ frame_size = get_le24(pb);
+ if(get_byte(pb) & 0x80)
+ keyframe = 1;
+ pts = get_le32(pb);
+ if(av_get_packet(pb, pkt, frame_size) < 0)
+ return AVERROR(EIO);
+ if(s->streams[0]->time_base.den == 1000)
+ pkt->pts = pts;
+ pkt->flags |= keyframe ? PKT_FLAG_KEY : 0;
+ pkt->pos -= 8;
+
+ return pkt->size;
+}
+
+AVInputFormat vc1t_demuxer = {
+ "vc1test",
+ "VC1 test bitstream format",
+ 0,
+ vc1t_probe,
+ vc1t_read_header,
+ vc1t_read_packet,
+ .flags = AVFMT_GENERIC_INDEX,
+};
diff --git a/contrib/ffmpeg/libavformat/voc.c b/contrib/ffmpeg/libavformat/voc.c
index 97b73d163..750f78d15 100644
--- a/contrib/ffmpeg/libavformat/voc.c
+++ b/contrib/ffmpeg/libavformat/voc.c
@@ -16,7 +16,7 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "voc.h"
diff --git a/contrib/ffmpeg/libavformat/voc.h b/contrib/ffmpeg/libavformat/voc.h
index 9b2bb8cce..606f2152e 100644
--- a/contrib/ffmpeg/libavformat/voc.h
+++ b/contrib/ffmpeg/libavformat/voc.h
@@ -16,11 +16,11 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef VOC_H
-#define VOC_H
+#ifndef FFMPEG_VOC_H
+#define FFMPEG_VOC_H
#include "avformat.h"
#include "riff.h" /* for CodecTag */
@@ -48,4 +48,4 @@ extern const AVCodecTag voc_codec_tags[];
int voc_get_packet(AVFormatContext *s, AVPacket *pkt,
AVStream *st, int max_size);
-#endif
+#endif /* FFMPEG_VOC_H */
diff --git a/contrib/ffmpeg/libavformat/vocdec.c b/contrib/ffmpeg/libavformat/vocdec.c
index 85d304dff..7c50fa588 100644
--- a/contrib/ffmpeg/libavformat/vocdec.c
+++ b/contrib/ffmpeg/libavformat/vocdec.c
@@ -16,24 +16,20 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "voc.h"
-
-
static int voc_probe(AVProbeData *p)
{
int version, check;
- if (p->buf_size < 26)
- return 0;
if (memcmp(p->buf, voc_magic, sizeof(voc_magic) - 1))
return 0;
- version = p->buf[22] | (p->buf[23] << 8);
- check = p->buf[24] | (p->buf[25] << 8);
+ version = AV_RL16(p->buf + 22);
+ check = AV_RL16(p->buf + 24);
if (~version + 0x1234 != check)
return 10;
@@ -43,7 +39,7 @@ static int voc_probe(AVProbeData *p)
static int voc_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
voc_dec_context_t *voc = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int header_size;
AVStream *st;
@@ -51,12 +47,12 @@ static int voc_read_header(AVFormatContext *s, AVFormatParameters *ap)
header_size = get_le16(pb) - 22;
if (header_size != 4) {
av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size);
- return AVERROR_NOTSUPP;
+ return AVERROR(ENOSYS);
}
url_fskip(pb, header_size);
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
voc->remaining_size = 0;
@@ -68,7 +64,7 @@ voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
{
voc_dec_context_t *voc = s->priv_data;
AVCodecContext *dec = st->codec;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
voc_type_t type;
int size;
int sample_rate = 0;
@@ -77,7 +73,7 @@ voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
while (!voc->remaining_size) {
type = get_byte(pb);
if (type == VOC_TYPE_EOF)
- return AVERROR_IO;
+ return AVERROR(EIO);
voc->remaining_size = get_le24(pb);
max_size -= 4;
@@ -138,11 +134,6 @@ static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
return voc_get_packet(s, pkt, s->streams[0], 0);
}
-static int voc_read_close(AVFormatContext *s)
-{
- return 0;
-}
-
AVInputFormat voc_demuxer = {
"voc",
"Creative Voice File format",
@@ -150,6 +141,5 @@ AVInputFormat voc_demuxer = {
voc_probe,
voc_read_header,
voc_read_packet,
- voc_read_close,
.codec_tag=(const AVCodecTag*[]){voc_codec_tags, 0},
};
diff --git a/contrib/ffmpeg/libavformat/vocenc.c b/contrib/ffmpeg/libavformat/vocenc.c
index 6a07c92dd..d967fae09 100644
--- a/contrib/ffmpeg/libavformat/vocenc.c
+++ b/contrib/ffmpeg/libavformat/vocenc.c
@@ -16,7 +16,7 @@
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "voc.h"
@@ -28,13 +28,13 @@ typedef struct voc_enc_context {
static int voc_write_header(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
const int header_size = 26;
const int version = 0x0114;
if (s->nb_streams != 1
|| s->streams[0]->codec->codec_type != CODEC_TYPE_AUDIO)
- return AVERROR_NOTSUPP;
+ return AVERROR_PATCHWELCOME;
put_buffer(pb, voc_magic, sizeof(voc_magic) - 1);
put_le16(pb, header_size);
@@ -48,7 +48,7 @@ static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
{
voc_enc_context_t *voc = s->priv_data;
AVCodecContext *enc = s->streams[0]->codec;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
if (!voc->param_written) {
if (enc->codec_tag > 0xFF) {
@@ -84,7 +84,7 @@ static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
static int voc_write_trailer(AVFormatContext *s)
{
- put_byte(&s->pb, 0);
+ put_byte(s->pb, 0);
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/wav.c b/contrib/ffmpeg/libavformat/wav.c
index 0699bec70..5053d1500 100644
--- a/contrib/ffmpeg/libavformat/wav.c
+++ b/contrib/ffmpeg/libavformat/wav.c
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
-#include "allformats.h"
+#include "raw.h"
#include "riff.h"
typedef struct {
@@ -34,7 +34,7 @@ typedef struct {
static int wav_write_header(AVFormatContext *s)
{
WAVContext *wav = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t fmt, fact;
put_tag(pb, "RIFF");
@@ -50,7 +50,7 @@ static int wav_write_header(AVFormatContext *s)
end_tag(pb, fmt);
if(s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
- && !url_is_streamed(&s->pb)) {
+ && !url_is_streamed(s->pb)) {
fact = start_tag(pb, "fact");
put_le32(pb, 0);
end_tag(pb, fact);
@@ -70,7 +70,7 @@ static int wav_write_header(AVFormatContext *s)
static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
WAVContext *wav = s->priv_data;
put_buffer(pb, pkt->data, pkt->size);
if(pkt->pts != AV_NOPTS_VALUE) {
@@ -84,11 +84,11 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
static int wav_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
WAVContext *wav = s->priv_data;
offset_t file_size;
- if (!url_is_streamed(&s->pb)) {
+ if (!url_is_streamed(s->pb)) {
end_tag(pb, wav->data);
/* update file size */
@@ -156,7 +156,7 @@ static int wav_read_header(AVFormatContext *s,
{
int size;
unsigned int tag;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
WAVContext *wav = s->priv_data;
@@ -176,10 +176,10 @@ static int wav_read_header(AVFormatContext *s,
return -1;
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
get_wav_header(pb, st->codec, size);
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
av_set_pts_info(st, 64, 1, st->codec->sample_rate);
@@ -199,17 +199,17 @@ static int wav_read_packet(AVFormatContext *s,
AVStream *st;
WAVContext *wav = s->priv_data;
- if (url_feof(&s->pb))
- return AVERROR_IO;
+ if (url_feof(s->pb))
+ return AVERROR(EIO);
st = s->streams[0];
- left= wav->data_end - url_ftell(&s->pb);
+ left= wav->data_end - url_ftell(s->pb);
if(left <= 0){
- left = find_tag(&(s->pb), MKTAG('d', 'a', 't', 'a'));
+ left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
if (left < 0) {
- return AVERROR_IO;
+ return AVERROR(EIO);
}
- wav->data_end= url_ftell(&s->pb) + left;
+ wav->data_end= url_ftell(s->pb) + left;
}
size = MAX_SIZE;
@@ -219,9 +219,9 @@ static int wav_read_packet(AVFormatContext *s,
size = (size / st->codec->block_align) * st->codec->block_align;
}
size= FFMIN(size, left);
- ret= av_get_packet(&s->pb, pkt, size);
+ ret= av_get_packet(s->pb, pkt, size);
if (ret <= 0)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = 0;
/* note: we need to modify the packet size here to handle the last
diff --git a/contrib/ffmpeg/libavformat/wc3movie.c b/contrib/ffmpeg/libavformat/wc3movie.c
index 3e58a1bba..00efb02ca 100644
--- a/contrib/ffmpeg/libavformat/wc3movie.c
+++ b/contrib/ffmpeg/libavformat/wc3movie.c
@@ -33,7 +33,7 @@
#define FORM_TAG MKTAG('F', 'O', 'R', 'M')
#define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
-#define _PC__TAG MKTAG('_', 'P', 'C', '_')
+#define PC__TAG MKTAG('_', 'P', 'C', '_')
#define SOND_TAG MKTAG('S', 'O', 'N', 'D')
#define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
#define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
@@ -125,8 +125,8 @@ static int wc3_probe(AVProbeData *p)
static int wc3_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ Wc3DemuxContext *wc3 = s->priv_data;
+ ByteIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size;
AVStream *st;
@@ -152,7 +152,7 @@ static int wc3_read_header(AVFormatContext *s,
* the first BRCH tag */
if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
WC3_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
fourcc_tag = AV_RL32(&preamble[0]);
size = (AV_RB32(&preamble[4]) + 1) & (~1);
@@ -165,11 +165,11 @@ static int wc3_read_header(AVFormatContext *s,
url_fseek(pb, size, SEEK_CUR);
break;
- case _PC__TAG:
+ case PC__TAG:
/* need the number of palettes */
url_fseek(pb, 8, SEEK_CUR);
if ((ret = get_buffer(pb, preamble, 4)) != 4)
- return AVERROR_IO;
+ return AVERROR(EIO);
wc3->palette_count = AV_RL32(&preamble[0]);
if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
wc3->palette_count= 0;
@@ -185,14 +185,14 @@ static int wc3_read_header(AVFormatContext *s,
else
bytes_to_read = 512;
if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
- return AVERROR_IO;
+ return AVERROR(EIO);
break;
case SIZE_TAG:
/* video resolution override */
if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
WC3_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
wc3->width = AV_RL32(&preamble[0]);
wc3->height = AV_RL32(&preamble[4]);
break;
@@ -204,7 +204,7 @@ static int wc3_read_header(AVFormatContext *s,
if ((ret = get_buffer(pb,
&wc3->palettes[current_palette * PALETTE_SIZE],
PALETTE_SIZE)) != PALETTE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* transform the current palette in place */
for (i = current_palette * PALETTE_SIZE;
@@ -228,7 +228,7 @@ static int wc3_read_header(AVFormatContext *s,
if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
WC3_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
fourcc_tag = AV_RL32(&preamble[0]);
/* chunk sizes are 16-bit aligned */
size = (AV_RB32(&preamble[4]) + 1) & (~1);
@@ -238,7 +238,7 @@ static int wc3_read_header(AVFormatContext *s,
/* initialize the decoder streams */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, 90000);
wc3->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
@@ -252,7 +252,7 @@ static int wc3_read_header(AVFormatContext *s,
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, 90000);
wc3->audio_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_AUDIO;
@@ -271,8 +271,8 @@ static int wc3_read_header(AVFormatContext *s,
static int wc3_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ Wc3DemuxContext *wc3 = s->priv_data;
+ ByteIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size;
int packet_read = 0;
@@ -289,7 +289,7 @@ static int wc3_read_packet(AVFormatContext *s,
/* get the next chunk preamble */
if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
WC3_PREAMBLE_SIZE)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
fourcc_tag = AV_RL32(&preamble[0]);
/* chunk sizes are 16-bit aligned */
@@ -304,7 +304,7 @@ static int wc3_read_packet(AVFormatContext *s,
case SHOT_TAG:
/* load up new palette */
if ((ret = get_buffer(pb, preamble, 4)) != 4)
- return AVERROR_IO;
+ return AVERROR(EIO);
palette_number = AV_RL32(&preamble[0]);
if (palette_number >= wc3->palette_count)
return AVERROR_INVALIDDATA;
@@ -324,7 +324,7 @@ static int wc3_read_packet(AVFormatContext *s,
pkt->stream_index = wc3->video_stream_index;
pkt->pts = wc3->pts;
if (ret != size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
packet_read = 1;
break;
@@ -334,7 +334,7 @@ static int wc3_read_packet(AVFormatContext *s,
url_fseek(pb, size, SEEK_CUR);
#else
if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
else {
int i = 0;
av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
@@ -353,7 +353,7 @@ static int wc3_read_packet(AVFormatContext *s,
pkt->stream_index = wc3->audio_stream_index;
pkt->pts = wc3->pts;
if (ret != size)
- ret = AVERROR_IO;
+ ret = AVERROR(EIO);
/* time to advance pts */
wc3->pts += WC3_FRAME_PTS_INC;
@@ -376,7 +376,7 @@ static int wc3_read_packet(AVFormatContext *s,
static int wc3_read_close(AVFormatContext *s)
{
- Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
+ Wc3DemuxContext *wc3 = s->priv_data;
av_free(wc3->palettes);
diff --git a/contrib/ffmpeg/libavformat/westwood.c b/contrib/ffmpeg/libavformat/westwood.c
index bed2f0d14..268f2e71e 100644
--- a/contrib/ffmpeg/libavformat/westwood.c
+++ b/contrib/ffmpeg/libavformat/westwood.c
@@ -117,13 +117,13 @@ static int wsaud_probe(AVProbeData *p)
static int wsaud_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ WsAudDemuxContext *wsaud = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVStream *st;
unsigned char header[AUD_HEADER_SIZE];
if (get_buffer(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
wsaud->audio_samplerate = AV_RL16(&header[0]);
if (header[11] == 99)
wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS;
@@ -138,7 +138,7 @@ static int wsaud_read_header(AVFormatContext *s,
/* initialize the audio decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, wsaud->audio_samplerate);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = wsaud->audio_type;
@@ -159,15 +159,15 @@ static int wsaud_read_header(AVFormatContext *s,
static int wsaud_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ WsAudDemuxContext *wsaud = s->priv_data;
+ ByteIOContext *pb = s->pb;
unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE];
unsigned int chunk_size;
int ret = 0;
if (get_buffer(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) !=
AUD_CHUNK_PREAMBLE_SIZE)
- return AVERROR_IO;
+ return AVERROR(EIO);
/* validate the chunk */
if (AV_RL32(&preamble[4]) != AUD_CHUNK_SIGNATURE)
@@ -176,7 +176,7 @@ static int wsaud_read_packet(AVFormatContext *s,
chunk_size = AV_RL16(&preamble[0]);
ret= av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
- return AVERROR_IO;
+ return AVERROR(EIO);
pkt->stream_index = wsaud->audio_stream_index;
pkt->pts = wsaud->audio_frame_counter;
pkt->pts /= wsaud->audio_samplerate;
@@ -189,7 +189,7 @@ static int wsaud_read_packet(AVFormatContext *s,
static int wsaud_read_close(AVFormatContext *s)
{
-// WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
+// WsAudDemuxContext *wsaud = s->priv_data;
return 0;
}
@@ -212,8 +212,8 @@ static int wsvqa_probe(AVProbeData *p)
static int wsvqa_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ WsVqaDemuxContext *wsvqa = s->priv_data;
+ ByteIOContext *pb = s->pb;
AVStream *st;
unsigned char *header;
unsigned char scratch[VQA_PREAMBLE_SIZE];
@@ -223,7 +223,7 @@ static int wsvqa_read_header(AVFormatContext *s,
/* initialize the video decoder stream */
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, VQA_FRAMERATE);
wsvqa->video_stream_index = st->index;
st->codec->codec_type = CODEC_TYPE_VIDEO;
@@ -240,7 +240,7 @@ static int wsvqa_read_header(AVFormatContext *s,
if (get_buffer(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
VQA_HEADER_SIZE) {
av_free(st->codec->extradata);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
st->codec->width = AV_RL16(&header[6]);
st->codec->height = AV_RL16(&header[8]);
@@ -249,7 +249,7 @@ static int wsvqa_read_header(AVFormatContext *s,
if (AV_RL16(&header[24]) || (AV_RL16(&header[0]) == 1 && AV_RL16(&header[2]) == 1)) {
st = av_new_stream(s, 0);
if (!st)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, VQA_FRAMERATE);
st->codec->codec_type = CODEC_TYPE_AUDIO;
if (AV_RL16(&header[0]) == 1)
@@ -279,7 +279,7 @@ static int wsvqa_read_header(AVFormatContext *s,
do {
if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
av_free(st->codec->extradata);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
chunk_tag = AV_RB32(&scratch[0]);
chunk_size = AV_RB32(&scratch[4]);
@@ -314,8 +314,8 @@ static int wsvqa_read_header(AVFormatContext *s,
static int wsvqa_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
- ByteIOContext *pb = &s->pb;
+ WsVqaDemuxContext *wsvqa = s->priv_data;
+ ByteIOContext *pb = s->pb;
int ret = -1;
unsigned char preamble[VQA_PREAMBLE_SIZE];
unsigned int chunk_type;
@@ -330,11 +330,11 @@ static int wsvqa_read_packet(AVFormatContext *s,
if ((chunk_type == SND1_TAG) || (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
if (av_new_packet(pkt, chunk_size))
- return AVERROR_IO;
+ return AVERROR(EIO);
ret = get_buffer(pb, pkt->data, chunk_size);
if (ret != chunk_size) {
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
if (chunk_type == SND2_TAG) {
@@ -371,7 +371,7 @@ static int wsvqa_read_packet(AVFormatContext *s,
static int wsvqa_read_close(AVFormatContext *s)
{
-// WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
+// WsVqaDemuxContext *wsvqa = s->priv_data;
return 0;
}
diff --git a/contrib/ffmpeg/libavformat/wv.c b/contrib/ffmpeg/libavformat/wv.c
index ed1eefeea..2240dfde2 100644
--- a/contrib/ffmpeg/libavformat/wv.c
+++ b/contrib/ffmpeg/libavformat/wv.c
@@ -20,7 +20,6 @@
*/
#include "avformat.h"
-#include "allformats.h"
#include "bswap.h"
// specs say that maximum block size is 1Mb
@@ -86,7 +85,7 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb)
}
wc->blksize = size;
ver = get_le16(pb);
- if(ver < 0x402 || ver > 0x40F){
+ if(ver < 0x402 || ver > 0x410){
av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
return -1;
}
@@ -105,10 +104,6 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb)
av_log(ctx, AV_LOG_ERROR, "Hybrid coding mode is not supported\n");
return -1;
}
- if(wc->flags & WV_INT32){
- av_log(ctx, AV_LOG_ERROR, "Integer point data is not supported\n");
- return -1;
- }
bpp = ((wc->flags & 3) + 1) << 3;
chan = 1 + !(wc->flags & WV_MONO);
@@ -140,7 +135,7 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb)
static int wv_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
WVContext *wc = s->priv_data;
AVStream *st;
@@ -169,20 +164,20 @@ static int wv_read_packet(AVFormatContext *s,
WVContext *wc = s->priv_data;
int ret;
- if (url_feof(&s->pb))
+ if (url_feof(s->pb))
return AVERROR(EIO);
if(wc->block_parsed){
- if(wv_read_block_header(s, &s->pb) < 0)
+ if(wv_read_block_header(s, s->pb) < 0)
return -1;
}
if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE) < 0)
- return AVERROR_NOMEM;
+ return AVERROR(ENOMEM);
memcpy(pkt->data, wc->extra, WV_EXTRA_SIZE);
- ret = get_buffer(&s->pb, pkt->data + WV_EXTRA_SIZE, wc->blksize);
+ ret = get_buffer(s->pb, pkt->data + WV_EXTRA_SIZE, wc->blksize);
if(ret != wc->blksize){
av_free_packet(pkt);
- return AVERROR_IO;
+ return AVERROR(EIO);
}
pkt->stream_index = 0;
wc->block_parsed = 1;
@@ -209,18 +204,18 @@ static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp,
/* if found, seek there */
if (index >= 0){
wc->block_parsed = 1;
- url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
+ url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
return 0;
}
/* if timestamp is out of bounds, return error */
if(timestamp < 0 || timestamp >= s->duration)
return -1;
- pos = url_ftell(&s->pb);
+ pos = url_ftell(s->pb);
do{
ret = av_read_frame(s, pkt);
if (ret < 0){
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
return -1;
}
pts = pkt->pts;
diff --git a/contrib/ffmpeg/libavformat/x11grab.c b/contrib/ffmpeg/libavformat/x11grab.c
deleted file mode 100644
index 8916d799a..000000000
--- a/contrib/ffmpeg/libavformat/x11grab.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * X11 video grab interface
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg integration:
- * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org>
- * Edouard Gomez <ed.gomez@free.fr>
- *
- * This file contains code from grab.c:
- * Copyright (c) 2000-2001 Fabrice Bellard
- *
- * This file contains code from the xvidcap project:
- * Copyright (C) 1997-1998 Rasca, Berlin
- * 2003-2004 Karl H. Beckers, Frankfurt
- *
- * FFmpeg is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU 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 x11grab.c
- * X11 frame device demuxer by Clemens Fruhwirth <clemens@endorphin.org>
- * and Edouard Gomez <ed.gomez@free.fr>.
- */
-
-#include "avformat.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#define _LINUX_TIME_H 1
-#include <time.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xlibint.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-
-/**
- * X11 Device Demuxer context
- */
-typedef struct x11_grab_s
-{
- int frame_size; /**< Size in bytes of a grabbed frame */
- AVRational time_base; /**< Time base */
- int64_t time_frame; /**< Current time */
-
- int height; /**< Height of the grab frame */
- int width; /**< Width of the grab frame */
- int x_off; /**< Horizontal top-left corner coordinate */
- int y_off; /**< Vertical top-left corner coordinate */
-
- Display *dpy; /**< X11 display from which x11grab grabs frames */
- XImage *image; /**< X11 image holding the grab */
- int use_shm; /**< !0 when using XShm extension */
- XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */
- int mouse_warning_shown;
-} x11_grab_t;
-
-/**
- * Initializes the x11 grab device demuxer (public device demuxer API).
- *
- * @param s1 Context from avformat core
- * @param ap Parameters from avformat core
- * @return <ul>
- * <li>ENOMEM no memory left</li>
- * <li>AVERROR_IO other failure case</li>
- * <li>0 success</li>
- * </ul>
- */
-static int
-x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
-{
- x11_grab_t *x11grab = s1->priv_data;
- Display *dpy;
- AVStream *st = NULL;
- int input_pixfmt;
- XImage *image;
- int x_off = 0;
- int y_off = 0;
- int use_shm;
- char *param, *offset;
-
- param = av_strdup(s1->filename);
- offset = strchr(param, '+');
- if (offset) {
- sscanf(offset, "%d,%d", &x_off, &y_off);
- *offset= 0;
- }
-
- av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, param, x_off, y_off, ap->width, ap->height);
-
- dpy = XOpenDisplay(param);
- if(!dpy) {
- av_log(s1, AV_LOG_ERROR, "Could not open X display.\n");
- return AVERROR_IO;
- }
-
- if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
- av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n");
- return AVERROR_IO;
- }
-
- st = av_new_stream(s1, 0);
- if (!st) {
- return AVERROR(ENOMEM);
- }
- av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
-
- use_shm = XShmQueryExtension(dpy);
- av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ? "" : "not");
-
- if(use_shm) {
- int scr = XDefaultScreen(dpy);
- image = XShmCreateImage(dpy,
- DefaultVisual(dpy, scr),
- DefaultDepth(dpy, scr),
- ZPixmap,
- NULL,
- &x11grab->shminfo,
- ap->width, ap->height);
- x11grab->shminfo.shmid = shmget(IPC_PRIVATE,
- image->bytes_per_line * image->height,
- IPC_CREAT|0777);
- if (x11grab->shminfo.shmid == -1) {
- av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n");
- return AVERROR(ENOMEM);
- }
- x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0);
- x11grab->shminfo.readOnly = False;
-
- if (!XShmAttach(dpy, &x11grab->shminfo)) {
- av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n");
- /* needs some better error subroutine :) */
- return AVERROR_IO;
- }
- } else {
- image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)),
- x_off,y_off,
- ap->width,ap->height,
- AllPlanes, ZPixmap);
- }
-
- switch (image->bits_per_pixel) {
- case 8:
- av_log (s1, AV_LOG_DEBUG, "8 bit palette\n");
- input_pixfmt = PIX_FMT_PAL8;
- break;
- case 16:
- if ( image->red_mask == 0xf800 &&
- image->green_mask == 0x07e0 &&
- image->blue_mask == 0x001f ) {
- av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n");
- input_pixfmt = PIX_FMT_RGB565;
- } else if (image->red_mask == 0x7c00 &&
- image->green_mask == 0x03e0 &&
- image->blue_mask == 0x001f ) {
- av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n");
- input_pixfmt = PIX_FMT_RGB555;
- } else {
- av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
- av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
- return AVERROR_IO;
- }
- break;
- case 24:
- if ( image->red_mask == 0xff0000 &&
- image->green_mask == 0x00ff00 &&
- image->blue_mask == 0x0000ff ) {
- input_pixfmt = PIX_FMT_BGR24;
- } else if ( image->red_mask == 0x0000ff &&
- image->green_mask == 0x00ff00 &&
- image->blue_mask == 0xff0000 ) {
- input_pixfmt = PIX_FMT_RGB24;
- } else {
- av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
- av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
- return AVERROR_IO;
- }
- break;
- case 32:
-#if 0
- GetColorInfo (image, &c_info);
- if ( c_info.alpha_mask == 0xff000000 && image->green_mask == 0x0000ff00) {
- /* byte order is relevant here, not endianness
- * endianness is handled by avcodec, but atm no such thing
- * as having ABGR, instead of ARGB in a word. Since we
- * need this for Solaris/SPARC, but need to do the conversion
- * for every frame we do it outside of this loop, cf. below
- * this matches both ARGB32 and ABGR32 */
- input_pixfmt = PIX_FMT_ARGB32;
- } else {
- av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel);
- return AVERROR_IO;
- }
-#endif
- input_pixfmt = PIX_FMT_RGB32;
- break;
- default:
- av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel);
- return -1;
- }
-
- x11grab->frame_size = ap->width * ap->height * image->bits_per_pixel/8;
- x11grab->dpy = dpy;
- x11grab->width = ap->width;
- x11grab->height = ap->height;
- x11grab->time_base = ap->time_base;
- x11grab->time_frame = av_gettime() / av_q2d(ap->time_base);
- x11grab->x_off = x_off;
- x11grab->y_off = y_off;
- x11grab->image = image;
- x11grab->use_shm = use_shm;
- x11grab->mouse_warning_shown = 0;
-
- st->codec->codec_type = CODEC_TYPE_VIDEO;
- st->codec->codec_id = CODEC_ID_RAWVIDEO;
- st->codec->width = ap->width;
- st->codec->height = ap->height;
- st->codec->pix_fmt = input_pixfmt;
- st->codec->time_base = ap->time_base;
- st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(ap->time_base) * 8;
-
- return 0;
-}
-
-/**
- * Get pointer coordinates from X11.
- *
- * @param x Integer where horizontal coordinate will be returned
- * @param y Integer where vertical coordinate will be returned
- * @param dpy X11 display from where pointer coordinates are retrieved
- * @param s1 Context used for logging errors if necessary
- */
-static void
-get_pointer_coordinates(int *x, int *y, Display *dpy, AVFormatContext *s1)
-{
- Window mrootwindow, childwindow;
- int dummy;
-
- mrootwindow = DefaultRootWindow(dpy);
-
- if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow,
- x, y, &dummy, &dummy, (unsigned int*)&dummy)) {
- } else {
- x11_grab_t *s = s1->priv_data;
- if (!s->mouse_warning_shown) {
- av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n");
- s->mouse_warning_shown = 1;
- }
- *x = -1;
- *y = -1;
- }
-}
-
-/**
- * Mouse painting helper function that applies an 'and' and 'or' mask pair to
- * '*dst' pixel. It actually draws a mouse pointer pixel to grabbed frame.
- *
- * @param dst Destination pixel
- * @param and Part of the mask that must be applied using a bitwise 'and'
- * operator
- * @param or Part of the mask that must be applied using a bitwise 'or'
- * operator
- * @param bits_per_pixel Bits per pixel used in the grabbed image
- */
-static void inline
-apply_masks(uint8_t *dst, int and, int or, int bits_per_pixel)
-{
- switch (bits_per_pixel) {
- case 32:
- *(uint32_t*)dst = (*(uint32_t*)dst & and) | or;
- break;
- case 16:
- *(uint16_t*)dst = (*(uint16_t*)dst & and) | or;
- break;
- case 8:
- *dst = !!or;
- break;
- }
-}
-
-/**
- * Paints a mouse pointer in an X11 image.
- *
- * @param image Image where to paint the mouse pointer
- * @param s context used to retrieve original grabbing rectangle
- * coordinates
- * @param x Mouse pointer coordinate
- * @param y Mouse pointer coordinate
- */
-static void
-paint_mouse_pointer(XImage *image, x11_grab_t *s, int x, int y)
-{
- /* 16x20x1bpp bitmap for the black channel of the mouse pointer */
- static const uint16_t const mousePointerBlack[] =
- {
- 0x0000, 0x0003, 0x0005, 0x0009, 0x0011,
- 0x0021, 0x0041, 0x0081, 0x0101, 0x0201,
- 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120,
- 0x0120, 0x0240, 0x0240, 0x0380, 0x0000
- };
-
- /* 16x20x1bpp bitmap for the white channel of the mouse pointer */
- static const uint16_t const mousePointerWhite[] =
- {
- 0x0000, 0x0000, 0x0002, 0x0006, 0x000e,
- 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe,
- 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0,
- 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000
- };
-
- int x_off = s->x_off;
- int y_off = s->y_off;
- int width = s->width;
- int height = s->height;
-
- if ( x - x_off >= 0 && x < width + x_off
- && y - y_off >= 0 && y < height + y_off) {
- uint8_t *im_data = (uint8_t*)image->data;
- int bytes_per_pixel;
- int line;
- int masks;
-
- /* Select correct masks and pixel size */
- if (image->bits_per_pixel == 8) {
- masks = 1;
- } else {
- masks = (image->red_mask|image->green_mask|image->blue_mask);
- }
- bytes_per_pixel = image->bits_per_pixel>>3;
-
- /* Shift to right line */
- im_data += image->bytes_per_line * (y - y_off);
- /* Shift to right pixel in the line */
- im_data += bytes_per_pixel * (x - x_off);
-
- /* Draw the cursor - proper loop */
- for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) {
- uint8_t *cursor = im_data;
- int column;
- uint16_t bm_b;
- uint16_t bm_w;
-
- bm_b = mousePointerBlack[line];
- bm_w = mousePointerWhite[line];
-
- for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) {
- apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1),
- image->bits_per_pixel);
- cursor += bytes_per_pixel;
- bm_b >>= 1;
- bm_w >>= 1;
- }
- im_data += image->bytes_per_line;
- }
- }
-}
-
-
-/**
- * Reads new data in the image structure.
- *
- * @param dpy X11 display to grab from
- * @param d
- * @param image Image where the grab will be put
- * @param x Top-Left grabbing rectangle horizontal coordinate
- * @param y Top-Left grabbing rectangle vertical coordinate
- * @return 0 if error, !0 if successful
- */
-static int
-xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
-{
- xGetImageReply rep;
- xGetImageReq *req;
- long nbytes;
-
- if (!image) {
- return 0;
- }
-
- LockDisplay(dpy);
- GetReq(GetImage, req);
-
- /* First set up the standard stuff in the request */
- req->drawable = d;
- req->x = x;
- req->y = y;
- req->width = image->width;
- req->height = image->height;
- req->planeMask = (unsigned int)AllPlanes;
- req->format = ZPixmap;
-
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
- UnlockDisplay(dpy);
- SyncHandle();
- return 0;
- }
-
- nbytes = (long)rep.length << 2;
- _XReadPad(dpy, image->data, nbytes);
-
- UnlockDisplay(dpy);
- SyncHandle();
- return 1;
-}
-
-/**
- * Grabs a frame from x11 (public device demuxer API).
- *
- * @param s1 Context from avformat core
- * @param pkt Packet holding the brabbed frame
- * @return frame size in bytes
- */
-static int
-x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
- x11_grab_t *s = s1->priv_data;
- Display *dpy = s->dpy;
- XImage *image = s->image;
- int x_off = s->x_off;
- int y_off = s->y_off;
-
- int64_t curtime, delay;
- struct timespec ts;
-
- /* Calculate the time of the next frame */
- s->time_frame += INT64_C(1000000);
-
- /* wait based on the frame rate */
- for(;;) {
- curtime = av_gettime();
- delay = s->time_frame * av_q2d(s->time_base) - curtime;
- if (delay <= 0) {
- if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) {
- s->time_frame += INT64_C(1000000);
- }
- break;
- }
- ts.tv_sec = delay / 1000000;
- ts.tv_nsec = (delay % 1000000) * 1000;
- nanosleep(&ts, NULL);
- }
-
- if (av_new_packet(pkt, s->frame_size) < 0) {
- return AVERROR_IO;
- }
-
- pkt->pts = curtime;
-
- if(s->use_shm) {
- if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) {
- av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n");
- }
- } else {
- if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) {
- av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n");
- }
- }
-
- {
- int pointer_x, pointer_y;
- get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1);
- paint_mouse_pointer(image, s, pointer_x, pointer_y);
- }
-
-
- /* XXX: avoid memcpy */
- memcpy(pkt->data, image->data, s->frame_size);
- return s->frame_size;
-}
-
-/**
- * Closes x11 frame grabber (public device demuxer API).
- *
- * @param s1 Context from avformat core
- * @return 0 success, !0 failure
- */
-static int
-x11grab_read_close(AVFormatContext *s1)
-{
- x11_grab_t *x11grab = s1->priv_data;
-
- /* Detach cleanly from shared mem */
- if (x11grab->use_shm) {
- XShmDetach(x11grab->dpy, &x11grab->shminfo);
- shmdt(x11grab->shminfo.shmaddr);
- shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL);
- }
-
- /* Destroy X11 image */
- if (x11grab->image) {
- XDestroyImage(x11grab->image);
- x11grab->image = NULL;
- }
-
- /* Free X11 display */
- XCloseDisplay(x11grab->dpy);
- return 0;
-}
-
-/** x11 grabber device demuxer declaration */
-AVInputFormat x11_grab_device_demuxer =
-{
- "x11grab",
- "X11grab",
- sizeof(x11_grab_t),
- NULL,
- x11grab_read_header,
- x11grab_read_packet,
- x11grab_read_close,
- .flags = AVFMT_NOFILE,
-};
diff --git a/contrib/ffmpeg/libavformat/yuv4mpeg.c b/contrib/ffmpeg/libavformat/yuv4mpeg.c
index 70214ae00..7913e417a 100644
--- a/contrib/ffmpeg/libavformat/yuv4mpeg.c
+++ b/contrib/ffmpeg/libavformat/yuv4mpeg.c
@@ -87,7 +87,7 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf)
static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVStream *st = s->streams[pkt->stream_index];
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVPicture *picture;
int* first_pkt = s->priv_data;
int width, height, h_chroma_shift, v_chroma_shift;
@@ -103,7 +103,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
*first_pkt = 0;
if (yuv4_generate_header(s, buf2) < 0) {
av_log(s, AV_LOG_ERROR, "Error. YUV4MPEG stream header write failed.\n");
- return AVERROR_IO;
+ return AVERROR(EIO);
} else {
put_buffer(pb, buf2, strlen(buf2));
}
@@ -149,7 +149,7 @@ static int yuv4_write_header(AVFormatContext *s)
int* first_pkt = s->priv_data;
if (s->nb_streams != 1)
- return AVERROR_IO;
+ return AVERROR(EIO);
if (s->streams[0]->codec->pix_fmt == PIX_FMT_YUV411P) {
av_log(s, AV_LOG_ERROR, "Warning: generating rarely used 4:1:1 YUV stream, some mjpegtools might not work.\n");
@@ -159,18 +159,13 @@ static int yuv4_write_header(AVFormatContext *s)
(s->streams[0]->codec->pix_fmt != PIX_FMT_GRAY8) &&
(s->streams[0]->codec->pix_fmt != PIX_FMT_YUV444P)) {
av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg only handles yuv444p, yuv422p, yuv420p, yuv411p and gray pixel formats. Use -pix_fmt to select one.\n");
- return AVERROR_IO;
+ return AVERROR(EIO);
}
*first_pkt = 1;
return 0;
}
-static int yuv4_write_trailer(AVFormatContext *s)
-{
- return 0;
-}
-
#ifdef CONFIG_YUV4MPEGPIPE_MUXER
AVOutputFormat yuv4mpegpipe_muxer = {
"yuv4mpegpipe",
@@ -182,7 +177,6 @@ AVOutputFormat yuv4mpegpipe_muxer = {
CODEC_ID_RAWVIDEO,
yuv4_write_header,
yuv4_write_packet,
- yuv4_write_trailer,
.flags = AVFMT_RAWPICTURE,
};
#endif
@@ -196,7 +190,7 @@ static int yuv4_read_header(AVFormatContext *s, AVFormatParameters *ap)
char header[MAX_YUV4_HEADER+10]; // Include headroom for the longest option
char *tokstart,*tokend,*header_end;
int i;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int width=-1, height=-1, raten=0, rated=0, aspectn=0, aspectd=0;
enum PixelFormat pix_fmt=PIX_FMT_NONE,alt_pix_fmt=PIX_FMT_NONE;
AVStream *st;
@@ -350,7 +344,7 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
struct frame_attributes *s1 = s->priv_data;
for (i=0; i<MAX_FRAME_HEADER; i++) {
- header[i] = get_byte(&s->pb);
+ header[i] = get_byte(s->pb);
if (header[i] == '\n') {
header[i+1] = 0;
break;
@@ -366,8 +360,8 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
if (packet_size < 0)
return -1;
- if (av_get_packet(&s->pb, pkt, packet_size) != packet_size)
- return AVERROR_IO;
+ if (av_get_packet(s->pb, pkt, packet_size) != packet_size)
+ return AVERROR(EIO);
if (s->streams[0]->codec->coded_frame) {
s->streams[0]->codec->coded_frame->interlaced_frame = s1->interlaced_frame;
@@ -386,8 +380,6 @@ static int yuv4_read_close(AVFormatContext *s)
static int yuv4_probe(AVProbeData *pd)
{
/* check file header */
- if (pd->buf_size <= sizeof(Y4M_MAGIC))
- return 0;
if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC)-1)==0)
return AVPROBE_SCORE_MAX;
else