early-access version 1432

This commit is contained in:
pineappleEA
2021-02-09 04:25:58 +01:00
parent de64eab4b4
commit 3d5a9d908a
7336 changed files with 1773492 additions and 111 deletions

3
externals/ffmpeg/libavformat/.gitignore vendored Executable file
View File

@@ -0,0 +1,3 @@
/protocol_list.c
/muxer_list.c
/demuxer_list.c

168
externals/ffmpeg/libavformat/3dostr.c vendored Executable file
View File

@@ -0,0 +1,168 @@
/*
* 3DO STR demuxer
* Copyright (c) 2015 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "internal.h"
static int threedostr_probe(const AVProbeData *p)
{
if (memcmp(p->buf, "CTRL", 4) &&
memcmp(p->buf, "SHDR", 4) &&
memcmp(p->buf, "SNDS", 4))
return 0;
return AVPROBE_SCORE_MAX / 3 * 2;
}
static int threedostr_read_header(AVFormatContext *s)
{
unsigned chunk, codec = 0, size, ctrl_size = -1, found_shdr = 0;
AVStream *st;
while (!avio_feof(s->pb) && !found_shdr) {
chunk = avio_rl32(s->pb);
size = avio_rb32(s->pb);
if (size < 8)
return AVERROR_INVALIDDATA;
size -= 8;
switch (chunk) {
case MKTAG('C','T','R','L'):
ctrl_size = size;
break;
case MKTAG('S','N','D','S'):
if (size < 56)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 8);
if (avio_rl32(s->pb) != MKTAG('S','H','D','R'))
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 24);
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->sample_rate = avio_rb32(s->pb);
st->codecpar->channels = avio_rb32(s->pb);
if (st->codecpar->channels <= 0)
return AVERROR_INVALIDDATA;
codec = avio_rl32(s->pb);
avio_skip(s->pb, 4);
if (ctrl_size == 20 || ctrl_size == 3 || ctrl_size == -1)
st->duration = (avio_rb32(s->pb) - 1) / st->codecpar->channels;
else
st->duration = avio_rb32(s->pb) * 16 / st->codecpar->channels;
size -= 56;
found_shdr = 1;
break;
case MKTAG('S','H','D','R'):
if (size > 0x78) {
avio_skip(s->pb, 0x74);
size -= 0x78;
if (avio_rl32(s->pb) == MKTAG('C','T','R','L') && size > 4) {
ctrl_size = avio_rb32(s->pb);
size -= 4;
}
}
break;
default:
av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk);
break;
}
avio_skip(s->pb, size);
}
switch (codec) {
case MKTAG('S','D','X','2'):
st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM;
st->codecpar->block_align = 1 * st->codecpar->channels;
break;
default:
avpriv_request_sample(s, "codec %X", codec);
return AVERROR_PATCHWELCOME;
}
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int threedostr_read_packet(AVFormatContext *s, AVPacket *pkt)
{
unsigned chunk, size, found_ssmp = 0;
AVStream *st = s->streams[0];
int64_t pos;
int ret = 0;
while (!found_ssmp) {
if (avio_feof(s->pb))
return AVERROR_EOF;
pos = avio_tell(s->pb);
chunk = avio_rl32(s->pb);
size = avio_rb32(s->pb);
if (!size)
continue;
if (size < 8)
return AVERROR_INVALIDDATA;
size -= 8;
switch (chunk) {
case MKTAG('S','N','D','S'):
if (size <= 16)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 8);
if (avio_rl32(s->pb) != MKTAG('S','S','M','P'))
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 4);
size -= 16;
ret = av_get_packet(s->pb, pkt, size);
pkt->pos = pos;
pkt->stream_index = 0;
pkt->duration = size / st->codecpar->channels;
size = 0;
found_ssmp = 1;
break;
default:
av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk);
break;
}
avio_skip(s->pb, size);
}
return ret;
}
AVInputFormat ff_threedostr_demuxer = {
.name = "3dostr",
.long_name = NULL_IF_CONFIG_SMALL("3DO STR"),
.read_probe = threedostr_probe,
.read_header = threedostr_read_header,
.read_packet = threedostr_read_packet,
.extensions = "str",
.flags = AVFMT_GENERIC_INDEX,
};

404
externals/ffmpeg/libavformat/4xm.c vendored Executable file
View File

@@ -0,0 +1,404 @@
/*
* 4X Technologies .4xm File Demuxer (no muxer)
* Copyright (c) 2003 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
* 4X Technologies file demuxer
* by Mike Melanson (melanson@pcisys.net)
* for more information on the .4xm file format, visit:
* http://www.pcisys.net/~melanson/codecs/
*/
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "libavcodec/internal.h"
#include "avformat.h"
#include "internal.h"
#define RIFF_TAG MKTAG('R', 'I', 'F', 'F')
#define FOURXMV_TAG MKTAG('4', 'X', 'M', 'V')
#define LIST_TAG MKTAG('L', 'I', 'S', 'T')
#define HEAD_TAG MKTAG('H', 'E', 'A', 'D')
#define TRK__TAG MKTAG('T', 'R', 'K', '_')
#define MOVI_TAG MKTAG('M', 'O', 'V', 'I')
#define VTRK_TAG MKTAG('V', 'T', 'R', 'K')
#define STRK_TAG MKTAG('S', 'T', 'R', 'K')
#define std__TAG MKTAG('s', 't', 'd', '_')
#define name_TAG MKTAG('n', 'a', 'm', 'e')
#define vtrk_TAG MKTAG('v', 't', 'r', 'k')
#define strk_TAG MKTAG('s', 't', 'r', 'k')
#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
#define strk_SIZE 0x28
#define GET_LIST_HEADER() \
fourcc_tag = avio_rl32(pb); \
size = avio_rl32(pb); \
if (fourcc_tag != LIST_TAG) { \
ret = AVERROR_INVALIDDATA; \
goto fail; \
} \
fourcc_tag = avio_rl32(pb);
typedef struct AudioTrack {
int sample_rate;
int bits;
int channels;
int stream_index;
int adpcm;
int64_t audio_pts;
} AudioTrack;
typedef struct FourxmDemuxContext {
int video_stream_index;
int track_count;
AudioTrack *tracks;
int64_t video_pts;
AVRational fps;
} FourxmDemuxContext;
static int fourxm_probe(const AVProbeData *p)
{
if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
(AV_RL32(&p->buf[8]) != FOURXMV_TAG))
return 0;
return AVPROBE_SCORE_MAX;
}
static int parse_vtrk(AVFormatContext *s,
FourxmDemuxContext *fourxm, uint8_t *buf, int size,
int left)
{
AVStream *st;
/* check that there is enough data */
if (size != vtrk_SIZE || left < size + 8) {
return AVERROR_INVALIDDATA;
}
/* allocate a new AVStream */
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 60, fourxm->fps.den, fourxm->fps.num);
fourxm->video_stream_index = st->index;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_4XM;
st->codecpar->extradata = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE);
if (!st->codecpar->extradata)
return AVERROR(ENOMEM);
st->codecpar->extradata_size = 4;
AV_WL32(st->codecpar->extradata, AV_RL32(buf + 16));
st->codecpar->width = AV_RL32(buf + 36);
st->codecpar->height = AV_RL32(buf + 40);
return 0;
}
static int parse_strk(AVFormatContext *s,
FourxmDemuxContext *fourxm, uint8_t *buf, int size,
int left)
{
AVStream *st;
int track;
/* check that there is enough data */
if (size != strk_SIZE || left < size + 8)
return AVERROR_INVALIDDATA;
track = AV_RL32(buf + 8);
if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
av_log(s, AV_LOG_ERROR, "current_track too large\n");
return AVERROR_INVALIDDATA;
}
if (track + 1 > fourxm->track_count) {
if (av_reallocp_array(&fourxm->tracks, track + 1, sizeof(AudioTrack)))
return AVERROR(ENOMEM);
memset(&fourxm->tracks[fourxm->track_count], 0,
sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
fourxm->track_count = track + 1;
}
fourxm->tracks[track].adpcm = AV_RL32(buf + 12);
fourxm->tracks[track].channels = AV_RL32(buf + 36);
fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
fourxm->tracks[track].bits = AV_RL32(buf + 44);
fourxm->tracks[track].audio_pts = 0;
if (fourxm->tracks[track].channels <= 0 ||
fourxm->tracks[track].channels > FF_SANE_NB_CHANNELS ||
fourxm->tracks[track].sample_rate <= 0 ||
fourxm->tracks[track].bits <= 0 ||
fourxm->tracks[track].bits > INT_MAX / FF_SANE_NB_CHANNELS) {
av_log(s, AV_LOG_ERROR, "audio header invalid\n");
return AVERROR_INVALIDDATA;
}
if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) {
av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
return AVERROR_INVALIDDATA;
}
if (fourxm->tracks[track].sample_rate > INT64_MAX / fourxm->tracks[track].bits / fourxm->tracks[track].channels) {
av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %d * %d * %d\n",
fourxm->tracks[track].sample_rate, fourxm->tracks[track].bits, fourxm->tracks[track].channels);
return AVERROR_INVALIDDATA;
}
/* allocate a new AVStream */
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->id = track;
avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
fourxm->tracks[track].stream_index = st->index;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0;
st->codecpar->channels = fourxm->tracks[track].channels;
st->codecpar->sample_rate = fourxm->tracks[track].sample_rate;
st->codecpar->bits_per_coded_sample = fourxm->tracks[track].bits;
st->codecpar->bit_rate = (int64_t)st->codecpar->channels *
st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
st->codecpar->block_align = st->codecpar->channels *
st->codecpar->bits_per_coded_sample;
if (fourxm->tracks[track].adpcm){
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_4XM;
} else if (st->codecpar->bits_per_coded_sample == 8) {
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
} else
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
return 0;
}
static int fourxm_read_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size;
int header_size;
FourxmDemuxContext *fourxm = s->priv_data;
unsigned char *header = NULL;
int i, ret;
fourxm->track_count = 0;
fourxm->tracks = NULL;
fourxm->fps = (AVRational){1,1};
fourxm->video_stream_index = -1;
/* skip the first 3 32-bit numbers */
avio_skip(pb, 12);
/* check for LIST-HEAD */
GET_LIST_HEADER();
header_size = size - 4;
if (fourcc_tag != HEAD_TAG || header_size < 0)
return AVERROR_INVALIDDATA;
/* allocate space for the header and load the whole thing */
header = av_malloc(header_size);
if (!header)
return AVERROR(ENOMEM);
if (avio_read(pb, header, header_size) != header_size) {
av_free(header);
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++) {
fourcc_tag = AV_RL32(&header[i]);
size = AV_RL32(&header[i + 4]);
if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) {
av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8);
ret = AVERROR_INVALIDDATA;
goto fail;
}
if (fourcc_tag == std__TAG) {
if (header_size - i < 16) {
av_log(s, AV_LOG_ERROR, "std TAG truncated\n");
ret = AVERROR_INVALIDDATA;
goto fail;
}
fourxm->fps = av_d2q(av_int2float(AV_RL32(&header[i + 12])), 10000);
} else if (fourcc_tag == vtrk_TAG) {
if ((ret = parse_vtrk(s, fourxm, header + i, size,
header_size - i)) < 0)
goto fail;
i += 8 + size;
} else if (fourcc_tag == strk_TAG) {
if ((ret = parse_strk(s, fourxm, header + i, size,
header_size - i)) < 0)
goto fail;
i += 8 + size;
}
}
/* skip over the LIST-MOVI chunk (which is where the stream should be */
GET_LIST_HEADER();
if (fourcc_tag != MOVI_TAG) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
av_free(header);
/* initialize context members */
fourxm->video_pts = -1; /* first frame will push to 0 */
return 0;
fail:
av_freep(&fourxm->tracks);
av_free(header);
return ret;
}
static int fourxm_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
FourxmDemuxContext *fourxm = s->priv_data;
AVIOContext *pb = s->pb;
unsigned int fourcc_tag;
unsigned int size;
int ret = 0;
unsigned int track_number;
int packet_read = 0;
unsigned char header[8];
int audio_frame_count;
while (!packet_read) {
if ((ret = avio_read(s->pb, header, 8)) < 0)
return ret;
fourcc_tag = AV_RL32(&header[0]);
size = AV_RL32(&header[4]);
if (avio_feof(pb))
return AVERROR(EIO);
switch (fourcc_tag) {
case LIST_TAG:
/* this is a good time to bump the video pts */
fourxm->video_pts++;
/* skip the LIST-* tag and move on to the next fourcc */
avio_rl32(pb);
break;
case ifrm_TAG:
case pfrm_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 > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - 8)
return AVERROR_INVALIDDATA;
if (fourxm->video_stream_index < 0)
return AVERROR_INVALIDDATA;
if ((ret = av_new_packet(pkt, size + 8)) < 0)
return ret;
pkt->stream_index = fourxm->video_stream_index;
pkt->pts = fourxm->video_pts;
pkt->pos = avio_tell(s->pb);
memcpy(pkt->data, header, 8);
ret = avio_read(s->pb, &pkt->data[8], size);
if (ret < 0) {
av_packet_unref(pkt);
} else {
packet_read = 1;
av_shrink_packet(pkt, ret + 8);
}
break;
case snd__TAG:
track_number = avio_rl32(pb);
avio_skip(pb, 4);
size -= 8;
if (track_number < fourxm->track_count &&
fourxm->tracks[track_number].channels > 0) {
ret = av_get_packet(s->pb, pkt, size);
if (ret < 0)
return ret;
pkt->stream_index =
fourxm->tracks[track_number].stream_index;
pkt->pts = fourxm->tracks[track_number].audio_pts;
packet_read = 1;
/* pts accounting */
audio_frame_count = size;
if (fourxm->tracks[track_number].adpcm)
audio_frame_count -= 2 * (fourxm->tracks[track_number].channels);
audio_frame_count /= fourxm->tracks[track_number].channels;
if (fourxm->tracks[track_number].adpcm) {
audio_frame_count *= 2;
} else
audio_frame_count /=
(fourxm->tracks[track_number].bits / 8);
fourxm->tracks[track_number].audio_pts += audio_frame_count;
} else {
avio_skip(pb, size);
}
break;
default:
avio_skip(pb, size);
break;
}
}
return ret;
}
static int fourxm_read_close(AVFormatContext *s)
{
FourxmDemuxContext *fourxm = s->priv_data;
av_freep(&fourxm->tracks);
return 0;
}
AVInputFormat ff_fourxm_demuxer = {
.name = "4xm",
.long_name = NULL_IF_CONFIG_SMALL("4X Technologies"),
.priv_data_size = sizeof(FourxmDemuxContext),
.read_probe = fourxm_probe,
.read_header = fourxm_read_header,
.read_packet = fourxm_read_packet,
.read_close = fourxm_read_close,
};

673
externals/ffmpeg/libavformat/Makefile vendored Executable file
View File

@@ -0,0 +1,673 @@
NAME = avformat
DESC = FFmpeg container format library
HEADERS = avformat.h \
avio.h \
version.h \
OBJS = allformats.o \
avio.o \
aviobuf.o \
cutils.o \
dump.o \
format.o \
id3v1.o \
id3v2.o \
metadata.o \
mux.o \
options.o \
os_support.o \
qtpalette.o \
protocols.o \
riff.o \
sdp.o \
url.o \
utils.o \
OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o
# subsystems
OBJS-$(CONFIG_ISO_MEDIA) += isom.o
OBJS-$(CONFIG_NETWORK) += network.o
OBJS-$(CONFIG_RIFFDEC) += riffdec.o
OBJS-$(CONFIG_RIFFENC) += riffenc.o
OBJS-$(CONFIG_RTPDEC) += rdt.o \
rtp.o \
rtpdec.o \
rtpdec_ac3.o \
rtpdec_amr.o \
rtpdec_asf.o \
rtpdec_dv.o \
rtpdec_g726.o \
rtpdec_h261.o \
rtpdec_h263.o \
rtpdec_h263_rfc2190.o \
rtpdec_h264.o \
rtpdec_hevc.o \
rtpdec_ilbc.o \
rtpdec_jpeg.o \
rtpdec_latm.o \
rtpdec_mpa_robust.o \
rtpdec_mpeg12.o \
rtpdec_mpeg4.o \
rtpdec_mpegts.o \
rtpdec_qcelp.o \
rtpdec_qdm2.o \
rtpdec_qt.o \
rtpdec_rfc4175.o \
rtpdec_svq3.o \
rtpdec_vc2hq.o \
rtpdec_vp8.o \
rtpdec_vp9.o \
rtpdec_xiph.o
OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o
OBJS-$(CONFIG_SHARED) += log2_tab.o golomb_tab.o
OBJS-$(CONFIG_SRTP) += srtp.o
# muxers/demuxers
OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o
OBJS-$(CONFIG_AA_DEMUXER) += aadec.o
OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o apetag.o img2.o rawdec.o
OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o
OBJS-$(CONFIG_AC3_MUXER) += rawenc.o
OBJS-$(CONFIG_ACM_DEMUXER) += acm.o rawdec.o
OBJS-$(CONFIG_ACT_DEMUXER) += act.o
OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o
OBJS-$(CONFIG_ADP_DEMUXER) += adp.o
OBJS-$(CONFIG_ADS_DEMUXER) += ads.o
OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o apetag.o img2.o \
id3v2enc.o
OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o
OBJS-$(CONFIG_ADX_MUXER) += rawenc.o
OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o
OBJS-$(CONFIG_AFC_DEMUXER) += afc.o
OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o pcm.o isom.o \
mov_chan.o replaygain.o
OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o id3v2enc.o
OBJS-$(CONFIG_AIX_DEMUXER) += aixdec.o
OBJS-$(CONFIG_ALP_DEMUXER) += alp.o
OBJS-$(CONFIG_AMR_DEMUXER) += amr.o
OBJS-$(CONFIG_AMR_MUXER) += amr.o rawenc.o
OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o
OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o
OBJS-$(CONFIG_ANM_DEMUXER) += anm.o
OBJS-$(CONFIG_APC_DEMUXER) += apc.o
OBJS-$(CONFIG_APE_DEMUXER) += ape.o apetag.o img2.o
OBJS-$(CONFIG_APM_DEMUXER) += apm.o riffdec.o
OBJS-$(CONFIG_APNG_DEMUXER) += apngdec.o
OBJS-$(CONFIG_APNG_MUXER) += apngenc.o
OBJS-$(CONFIG_APTX_DEMUXER) += aptxdec.o rawdec.o
OBJS-$(CONFIG_APTX_MUXER) += rawenc.o
OBJS-$(CONFIG_APTX_HD_DEMUXER) += aptxdec.o rawdec.o
OBJS-$(CONFIG_APTX_HD_MUXER) += rawenc.o
OBJS-$(CONFIG_AQTITLE_DEMUXER) += aqtitledec.o subtitles.o
OBJS-$(CONFIG_ARGO_ASF_DEMUXER) += argo_asf.o
OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \
avlanguage.o
OBJS-$(CONFIG_ASF_O_DEMUXER) += asfdec_o.o asf.o asfcrypt.o \
avlanguage.o
OBJS-$(CONFIG_ASF_MUXER) += asfenc.o asf.o avlanguage.o
OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o subtitles.o
OBJS-$(CONFIG_ASS_MUXER) += assenc.o
OBJS-$(CONFIG_AST_DEMUXER) += ast.o astdec.o
OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o
OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o
OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o
OBJS-$(CONFIG_AVI_MUXER) += avienc.o mpegtsenc.o avlanguage.o rawutils.o
OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o
OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o
OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o
OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o
OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o
OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o
OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o
OBJS-$(CONFIG_BINK_DEMUXER) += bink.o
OBJS-$(CONFIG_BINTEXT_DEMUXER) += bintext.o sauce.o
OBJS-$(CONFIG_BIT_DEMUXER) += bit.o
OBJS-$(CONFIG_BIT_MUXER) += bit.o
OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o
OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o
OBJS-$(CONFIG_BFSTM_DEMUXER) += brstm.o
OBJS-$(CONFIG_BRSTM_DEMUXER) += brstm.o
OBJS-$(CONFIG_C93_DEMUXER) += c93.o voc_packet.o vocdec.o voc.o
OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov_chan.o mov_esds.o
OBJS-$(CONFIG_CAF_MUXER) += cafenc.o caf.o riff.o
OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o
OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o
OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o
OBJS-$(CONFIG_CINE_DEMUXER) += cinedec.o
OBJS-$(CONFIG_CODEC2_DEMUXER) += codec2.o rawdec.o pcm.o
OBJS-$(CONFIG_CODEC2_MUXER) += codec2.o rawenc.o
OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2.o rawdec.o pcm.o
OBJS-$(CONFIG_CODEC2RAW_MUXER) += rawenc.o
OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o
OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o
OBJS-$(CONFIG_DATA_MUXER) += rawenc.o
OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o hlsplaylist.o
OBJS-$(CONFIG_DASH_DEMUXER) += dash.o dashdec.o
OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o
OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o
OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o
OBJS-$(CONFIG_DERF_DEMUXER) += derf.o pcm.o
OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o
OBJS-$(CONFIG_DHAV_DEMUXER) += dhav.o
OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o
OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o
OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddec.o rawdec.o
OBJS-$(CONFIG_DNXHD_MUXER) += rawenc.o
OBJS-$(CONFIG_DSF_DEMUXER) += dsfdec.o
OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o
OBJS-$(CONFIG_DSS_DEMUXER) += dss.o
OBJS-$(CONFIG_DTSHD_DEMUXER) += dtshddec.o
OBJS-$(CONFIG_DTS_DEMUXER) += dtsdec.o rawdec.o
OBJS-$(CONFIG_DTS_MUXER) += rawenc.o
OBJS-$(CONFIG_DV_DEMUXER) += dv.o
OBJS-$(CONFIG_DV_MUXER) += dvenc.o
OBJS-$(CONFIG_DVBSUB_DEMUXER) += dvbsub.o rawdec.o
OBJS-$(CONFIG_DVBTXT_DEMUXER) += dvbtxt.o rawdec.o
OBJS-$(CONFIG_DXA_DEMUXER) += dxa.o
OBJS-$(CONFIG_EA_CDATA_DEMUXER) += eacdata.o
OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o
OBJS-$(CONFIG_EAC3_DEMUXER) += ac3dec.o rawdec.o
OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o
OBJS-$(CONFIG_EPAF_DEMUXER) += epafdec.o pcm.o
OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o
OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o
OBJS-$(CONFIG_FIFO_MUXER) += fifo.o
OBJS-$(CONFIG_FIFO_TEST_MUXER) += fifo_test.o
OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o
OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o rawenc.o
OBJS-$(CONFIG_FITS_DEMUXER) += fitsdec.o
OBJS-$(CONFIG_FITS_MUXER) += fitsenc.o
OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \
flac_picture.o \
oggparsevorbis.o \
replaygain.o \
vorbiscomment.o
OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \
vorbiscomment.o
OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o
OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o
OBJS-$(CONFIG_LIVE_FLV_DEMUXER) += flvdec.o
OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o
OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o
OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o
OBJS-$(CONFIG_FRAMEHASH_MUXER) += hashenc.o framehash.o
OBJS-$(CONFIG_FRAMEMD5_MUXER) += hashenc.o framehash.o
OBJS-$(CONFIG_FRM_DEMUXER) += frmdec.o
OBJS-$(CONFIG_FSB_DEMUXER) += fsb.o
OBJS-$(CONFIG_FWSE_DEMUXER) += fwse.o pcm.o
OBJS-$(CONFIG_GIF_MUXER) += gif.o
OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o
OBJS-$(CONFIG_GSM_DEMUXER) += gsmdec.o
OBJS-$(CONFIG_GSM_MUXER) += rawenc.o
OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o
OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o
OBJS-$(CONFIG_G722_DEMUXER) += g722.o rawdec.o
OBJS-$(CONFIG_G722_MUXER) += rawenc.o
OBJS-$(CONFIG_G723_1_DEMUXER) += g723_1.o
OBJS-$(CONFIG_G723_1_MUXER) += rawenc.o
OBJS-$(CONFIG_G726_DEMUXER) += g726.o
OBJS-$(CONFIG_G726_MUXER) += rawenc.o
OBJS-$(CONFIG_G726LE_DEMUXER) += g726.o
OBJS-$(CONFIG_G726LE_MUXER) += rawenc.o
OBJS-$(CONFIG_G729_DEMUXER) += g729dec.o
OBJS-$(CONFIG_GDV_DEMUXER) += gdv.o
OBJS-$(CONFIG_GENH_DEMUXER) += genh.o
OBJS-$(CONFIG_H261_DEMUXER) += h261dec.o rawdec.o
OBJS-$(CONFIG_H261_MUXER) += rawenc.o
OBJS-$(CONFIG_H263_DEMUXER) += h263dec.o rawdec.o
OBJS-$(CONFIG_H263_MUXER) += rawenc.o
OBJS-$(CONFIG_H264_DEMUXER) += h264dec.o rawdec.o
OBJS-$(CONFIG_H264_MUXER) += rawenc.o
OBJS-$(CONFIG_HASH_MUXER) += hashenc.o
OBJS-$(CONFIG_HCA_DEMUXER) += hca.o
OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o pcm.o
OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o
OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o
OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o
OBJS-$(CONFIG_HLS_DEMUXER) += hls.o
OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o
OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o
OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o
OBJS-$(CONFIG_ICO_MUXER) += icoenc.o
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o sauce.o
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o
OBJS-$(CONFIG_IFV_DEMUXER) += ifv.o
OBJS-$(CONFIG_ILBC_DEMUXER) += ilbc.o
OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o rawenc.o
OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2enc.o img2.o
OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER) += img2_alias_pix.o
OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o
OBJS-$(CONFIG_IMAGE_BMP_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_DDS_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_GIF_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PGM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PPM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PSD_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_QDRAW_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_SVG_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_TIFF_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_WEBP_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_XPM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_XWD_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o
OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o
OBJS-$(CONFIG_IRCAM_DEMUXER) += ircamdec.o ircam.o pcm.o
OBJS-$(CONFIG_IRCAM_MUXER) += ircamenc.o ircam.o rawenc.o
OBJS-$(CONFIG_ISS_DEMUXER) += iss.o
OBJS-$(CONFIG_IV8_DEMUXER) += iv8.o
OBJS-$(CONFIG_IVF_DEMUXER) += ivfdec.o
OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o
OBJS-$(CONFIG_IVR_DEMUXER) += rmdec.o rm.o rmsipr.o
OBJS-$(CONFIG_JACOSUB_DEMUXER) += jacosubdec.o subtitles.o
OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o
OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o
OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o
OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o
OBJS-$(CONFIG_KVAG_MUXER) += kvag.o rawenc.o
OBJS-$(CONFIG_LATM_MUXER) += latmenc.o rawenc.o
OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o
OBJS-$(CONFIG_LOAS_DEMUXER) += loasdec.o rawdec.o
OBJS-$(CONFIG_LRC_DEMUXER) += lrcdec.o lrc.o subtitles.o
OBJS-$(CONFIG_LRC_MUXER) += lrcenc.o lrc.o
OBJS-$(CONFIG_LVF_DEMUXER) += lvfdec.o
OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o
OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o
OBJS-$(CONFIG_M4V_MUXER) += rawenc.o
OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \
rmsipr.o flac_picture.o \
oggparsevorbis.o vorbiscomment.o \
replaygain.o
OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \
av1.o avc.o hevc.o \
flacenc_header.o avlanguage.o \
vorbiscomment.o wv.o
OBJS-$(CONFIG_MD5_MUXER) += hashenc.o
OBJS-$(CONFIG_MGSTS_DEMUXER) += mgsts.o
OBJS-$(CONFIG_MICRODVD_DEMUXER) += microdvddec.o subtitles.o
OBJS-$(CONFIG_MICRODVD_MUXER) += microdvdenc.o
OBJS-$(CONFIG_MJPEG_2000_DEMUXER) += rawdec.o mj2kdec.o
OBJS-$(CONFIG_MJPEG_DEMUXER) += rawdec.o
OBJS-$(CONFIG_MJPEG_MUXER) += rawenc.o
OBJS-$(CONFIG_MLP_DEMUXER) += rawdec.o mlpdec.o
OBJS-$(CONFIG_MLP_MUXER) += rawenc.o
OBJS-$(CONFIG_MLV_DEMUXER) += mlvdec.o riffdec.o
OBJS-$(CONFIG_MM_DEMUXER) += mm.o
OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o
OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o
OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o replaygain.o
OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \
movenchint.o mov_chan.o rtp.o \
movenccenc.o rawutils.o
OBJS-$(CONFIG_MP2_MUXER) += rawenc.o
OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o
OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o
OBJS-$(CONFIG_MPC_DEMUXER) += mpc.o apetag.o img2.o
OBJS-$(CONFIG_MPC8_DEMUXER) += mpc8.o apetag.o img2.o
OBJS-$(CONFIG_MPEG1SYSTEM_MUXER) += mpegenc.o
OBJS-$(CONFIG_MPEG1VCD_MUXER) += mpegenc.o
OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_MPEG2DVD_MUXER) += mpegenc.o
OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpegenc.o
OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpegenc.o
OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o
OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += mpegvideodec.o rawdec.o
OBJS-$(CONFIG_MPJPEG_DEMUXER) += mpjpegdec.o
OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
OBJS-$(CONFIG_MPL2_DEMUXER) += mpl2dec.o subtitles.o
OBJS-$(CONFIG_MSF_DEMUXER) += msf.o
OBJS-$(CONFIG_MPSUB_DEMUXER) += mpsubdec.o subtitles.o
OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o
OBJS-$(CONFIG_MTAF_DEMUXER) += mtaf.o
OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o
OBJS-$(CONFIG_MUSX_DEMUXER) += musx.o
OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o
OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o
OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o
OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o avc.o
OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o
OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o
OBJS-$(CONFIG_NISTSPHERE_DEMUXER) += nistspheredec.o pcm.o
OBJS-$(CONFIG_NSP_DEMUXER) += nspdec.o pcm.o
OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o
OBJS-$(CONFIG_NULL_MUXER) += nullenc.o
OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o isom.o
OBJS-$(CONFIG_NUT_MUXER) += nutenc.o nut.o
OBJS-$(CONFIG_NUV_DEMUXER) += nuv.o
OBJS-$(CONFIG_AV1_DEMUXER) += av1dec.o
OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \
oggparsecelt.o \
oggparsedirac.o \
oggparseflac.o \
oggparseogm.o \
oggparseopus.o \
oggparseskeleton.o \
oggparsespeex.o \
oggparsetheora.o \
oggparsevorbis.o \
oggparsevp8.o \
replaygain.o \
vorbiscomment.o \
flac_picture.o
OBJS-$(CONFIG_OGA_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_OGG_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_OGV_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_OMA_DEMUXER) += omadec.o pcm.o oma.o
OBJS-$(CONFIG_OMA_MUXER) += omaenc.o rawenc.o oma.o id3v2enc.o
OBJS-$(CONFIG_OPUS_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_PAF_DEMUXER) += paf.o
OBJS-$(CONFIG_PCM_ALAW_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_ALAW_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_F32BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_F32BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_F32LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_F32LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_F64BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_F64BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_F64LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_F64LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_MULAW_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_MULAW_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S16BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S16BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S16LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S16LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S24BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S24BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S24LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S24LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S32BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S32BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S32LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S32LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_S8_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_S8_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U16BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U16BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U16LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U16LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U24BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U24BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U24LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U24LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U32BE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U32BE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U32LE_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U32LE_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_U8_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_U8_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PCM_VIDC_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_VIDC_MUXER) += pcmenc.o rawenc.o
OBJS-$(CONFIG_PJS_DEMUXER) += pjsdec.o subtitles.o
OBJS-$(CONFIG_PMP_DEMUXER) += pmpdec.o
OBJS-$(CONFIG_PP_BNK_DEMUXER) += pp_bnk.o
OBJS-$(CONFIG_PVA_DEMUXER) += pva.o
OBJS-$(CONFIG_PVF_DEMUXER) += pvfdec.o pcm.o
OBJS-$(CONFIG_QCP_DEMUXER) += qcp.o
OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
OBJS-$(CONFIG_RL2_DEMUXER) += rl2.o
OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o rm.o rmsipr.o
OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o
OBJS-$(CONFIG_ROQ_DEMUXER) += idroqdec.o
OBJS-$(CONFIG_ROQ_MUXER) += idroqenc.o rawenc.o
OBJS-$(CONFIG_RSD_DEMUXER) += rsd.o
OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o
OBJS-$(CONFIG_RSO_DEMUXER) += rsodec.o rso.o pcm.o
OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o rawenc.o
OBJS-$(CONFIG_RTP_MPEGTS_MUXER) += rtpenc_mpegts.o
OBJS-$(CONFIG_RTP_MUXER) += rtp.o \
rtpenc_aac.o \
rtpenc_latm.o \
rtpenc_amr.o \
rtpenc_h261.o \
rtpenc_h263.o \
rtpenc_h263_rfc2190.o \
rtpenc_h264_hevc.o \
rtpenc_jpeg.o \
rtpenc_mpv.o \
rtpenc.o \
rtpenc_vc2hq.o \
rtpenc_vp8.o \
rtpenc_vp9.o \
rtpenc_xiph.o \
avc.o hevc.o
OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o \
urldecode.o
OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o \
urldecode.o
OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o spdif.o
OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o
OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o
OBJS-$(CONFIG_SAP_MUXER) += sapenc.o
OBJS-$(CONFIG_SBC_DEMUXER) += sbcdec.o rawdec.o
OBJS-$(CONFIG_SBC_MUXER) += rawenc.o
OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o
OBJS-$(CONFIG_SCC_DEMUXER) += sccdec.o subtitles.o
OBJS-$(CONFIG_SCC_MUXER) += sccenc.o subtitles.o
OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o
OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o
OBJS-$(CONFIG_SDS_DEMUXER) += sdsdec.o
OBJS-$(CONFIG_SDX_DEMUXER) += sdxdec.o pcm.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
OBJS-$(CONFIG_SEGAFILM_MUXER) += segafilmenc.o
OBJS-$(CONFIG_SEGMENT_MUXER) += segment.o
OBJS-$(CONFIG_SER_DEMUXER) += serdec.o
OBJS-$(CONFIG_SHORTEN_DEMUXER) += shortendec.o rawdec.o
OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o
OBJS-$(CONFIG_SINGLEJPEG_MUXER) += rawenc.o
OBJS-$(CONFIG_SLN_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o
OBJS-$(CONFIG_SMJPEG_DEMUXER) += smjpegdec.o smjpeg.o
OBJS-$(CONFIG_SMJPEG_MUXER) += smjpegenc.o smjpeg.o
OBJS-$(CONFIG_SMOOTHSTREAMING_MUXER) += smoothstreamingenc.o
OBJS-$(CONFIG_SMUSH_DEMUXER) += smush.o
OBJS-$(CONFIG_SOL_DEMUXER) += sol.o pcm.o
OBJS-$(CONFIG_SOX_DEMUXER) += soxdec.o pcm.o
OBJS-$(CONFIG_SOX_MUXER) += soxenc.o rawenc.o
OBJS-$(CONFIG_SPDIF_DEMUXER) += spdif.o spdifdec.o
OBJS-$(CONFIG_SPDIF_MUXER) += spdif.o spdifenc.o
OBJS-$(CONFIG_SPEEX_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_SRT_DEMUXER) += srtdec.o subtitles.o
OBJS-$(CONFIG_SRT_MUXER) += srtenc.o
OBJS-$(CONFIG_STL_DEMUXER) += stldec.o subtitles.o
OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o
OBJS-$(CONFIG_STREAMHASH_MUXER) += hashenc.o
OBJS-$(CONFIG_STREAM_SEGMENT_MUXER) += segment.o
OBJS-$(CONFIG_SUBVIEWER1_DEMUXER) += subviewer1dec.o subtitles.o
OBJS-$(CONFIG_SUBVIEWER_DEMUXER) += subviewerdec.o subtitles.o
OBJS-$(CONFIG_SUP_DEMUXER) += supdec.o
OBJS-$(CONFIG_SUP_MUXER) += supenc.o
OBJS-$(CONFIG_SVAG_DEMUXER) += svag.o
OBJS-$(CONFIG_SWF_DEMUXER) += swfdec.o swf.o
OBJS-$(CONFIG_SWF_MUXER) += swfenc.o swf.o
OBJS-$(CONFIG_TAK_DEMUXER) += takdec.o apetag.o img2.o rawdec.o
OBJS-$(CONFIG_TEDCAPTIONS_DEMUXER) += tedcaptionsdec.o subtitles.o
OBJS-$(CONFIG_TEE_MUXER) += tee.o tee_common.o
OBJS-$(CONFIG_THP_DEMUXER) += thp.o
OBJS-$(CONFIG_THREEDOSTR_DEMUXER) += 3dostr.o
OBJS-$(CONFIG_TIERTEXSEQ_DEMUXER) += tiertexseq.o
OBJS-$(CONFIG_MKVTIMESTAMP_V2_MUXER) += mkvtimestamp_v2.o
OBJS-$(CONFIG_TMV_DEMUXER) += tmv.o
OBJS-$(CONFIG_TRUEHD_DEMUXER) += rawdec.o mlpdec.o
OBJS-$(CONFIG_TRUEHD_MUXER) += rawenc.o
OBJS-$(CONFIG_TTA_DEMUXER) += tta.o apetag.o img2.o
OBJS-$(CONFIG_TTA_MUXER) += ttaenc.o apetag.o img2.o
OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o
OBJS-$(CONFIG_TY_DEMUXER) += ty.o
OBJS-$(CONFIG_TXD_DEMUXER) += txd.o
OBJS-$(CONFIG_UNCODEDFRAMECRC_MUXER) += uncodedframecrcenc.o framehash.o
OBJS-$(CONFIG_V210_DEMUXER) += v210.o
OBJS-$(CONFIG_V210X_DEMUXER) += v210.o
OBJS-$(CONFIG_VAG_DEMUXER) += vag.o
OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o vc1dec.o
OBJS-$(CONFIG_VC1_MUXER) += rawenc.o
OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o
OBJS-$(CONFIG_VC1T_MUXER) += vc1testenc.o
OBJS-$(CONFIG_VIVIDAS_DEMUXER) += vividas.o
OBJS-$(CONFIG_VIVO_DEMUXER) += vivo.o
OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o
OBJS-$(CONFIG_VOBSUB_DEMUXER) += subtitles.o # mpeg demuxer is in the dependencies
OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc_packet.o voc.o
OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o
OBJS-$(CONFIG_VPK_DEMUXER) += vpk.o
OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o subtitles.o
OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o
OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o
OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o
OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o
OBJS-$(CONFIG_WAV_MUXER) += wavenc.o
OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o
OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \
av1.o avc.o hevc.o \
flacenc_header.o avlanguage.o \
wv.o vorbiscomment.o
OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o
OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o
OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o
OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o
OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o
OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o
OBJS-$(CONFIG_WSD_DEMUXER) += wsddec.o rawdec.o
OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o
OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv_common.o \
asf.o
OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv_common.o \
asf.o
OBJS-$(CONFIG_WV_DEMUXER) += wvdec.o wv.o apetag.o img2.o
OBJS-$(CONFIG_WVE_DEMUXER) += wvedec.o pcm.o
OBJS-$(CONFIG_WV_MUXER) += wvenc.o wv.o apetag.o img2.o
OBJS-$(CONFIG_XA_DEMUXER) += xa.o
OBJS-$(CONFIG_XBIN_DEMUXER) += bintext.o sauce.o
OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o
OBJS-$(CONFIG_XVAG_DEMUXER) += xvag.o
OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o
OBJS-$(CONFIG_YOP_DEMUXER) += yop.o
OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpegdec.o
OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpegenc.o
# external library muxers/demuxers
OBJS-$(CONFIG_AVISYNTH_DEMUXER) += avisynth.o
OBJS-$(CONFIG_CHROMAPRINT_MUXER) += chromaprint.o
OBJS-$(CONFIG_LIBGME_DEMUXER) += libgme.o
OBJS-$(CONFIG_LIBMODPLUG_DEMUXER) += libmodplug.o
OBJS-$(CONFIG_LIBOPENMPT_DEMUXER) += libopenmpt.o
OBJS-$(CONFIG_VAPOURSYNTH_DEMUXER) += vapoursynth.o
# protocols I/O
OBJS-$(CONFIG_ASYNC_PROTOCOL) += async.o
OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o
OBJS-$(CONFIG_BLURAY_PROTOCOL) += bluray.o
OBJS-$(CONFIG_CACHE_PROTOCOL) += cache.o
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o
OBJS-$(CONFIG_DATA_PROTOCOL) += data_uri.o
OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdigest.o rtmpdh.o
OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o
OBJS-$(CONFIG_FILE_PROTOCOL) += file.o
OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o urldecode.o
OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o
OBJS-$(CONFIG_HLS_PROTOCOL) += hlsproto.o
OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o
OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o
OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o urldecode.o
OBJS-$(CONFIG_ICECAST_PROTOCOL) += icecast.o
OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o
OBJS-$(CONFIG_MMSH_PROTOCOL) += mmsh.o mms.o asf.o
OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o
OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o
OBJS-$(CONFIG_PROMPEG_PROTOCOL) += prompeg.o
OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o ip.o
OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o
OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o
OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o
OBJS-$(CONFIG_TEE_PROTOCOL) += teeproto.o tee_common.o
OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o
TLS-OBJS-$(CONFIG_GNUTLS) += tls_gnutls.o
TLS-OBJS-$(CONFIG_LIBTLS) += tls_libtls.o
TLS-OBJS-$(CONFIG_MBEDTLS) += tls_mbedtls.o
TLS-OBJS-$(CONFIG_OPENSSL) += tls_openssl.o
TLS-OBJS-$(CONFIG_SECURETRANSPORT) += tls_securetransport.o
TLS-OBJS-$(CONFIG_SCHANNEL) += tls_schannel.o
OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o $(TLS-OBJS-yes)
OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o ip.o
OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o ip.o
OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o
# external library protocols
OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o
OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o
OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o
OBJS-$(CONFIG_LIBRTMPS_PROTOCOL) += librtmp.o
OBJS-$(CONFIG_LIBRTMPT_PROTOCOL) += librtmp.o
OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL) += librtmp.o
OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL) += libsmbclient.o
OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o
OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o
OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o
# libavdevice dependencies
OBJS-$(CONFIG_IEC61883_INDEV) += dv.o
# Windows resource file
SLIBOBJS-$(HAVE_GNU_WINDRES) += avformatres.o
SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h
TESTPROGS = seek \
url \
# async \
FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK) += fifo_muxer
TESTPROGS-$(CONFIG_FIFO_MUXER) += $(FIFO-MUXER-TESTPROGS-yes)
TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh
TESTPROGS-$(CONFIG_MOV_MUXER) += movenc
TESTPROGS-$(CONFIG_NETWORK) += noproxy
TESTPROGS-$(CONFIG_SRTP) += srtp
TOOLS = aviocat \
ismindex \
pktdumper \
probetest \
seek_print \
sidxindex \
venc_data_dump

68
externals/ffmpeg/libavformat/a64.c vendored Executable file
View File

@@ -0,0 +1,68 @@
/*
* a64 muxer
* Copyright (c) 2009 Tobias Bindhammer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavcodec/avcodec.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "rawenc.h"
static int a64_write_header(AVFormatContext *s)
{
AVCodecParameters *par = s->streams[0]->codecpar;
uint8_t header[5] = {
0x00, //load
0x40, //address
0x00, //mode
0x00, //charset_lifetime (multi only)
0x00 //fps in 50/fps;
};
if (par->extradata_size < 4) {
av_log(s, AV_LOG_ERROR, "Missing extradata\n");
return AVERROR_INVALIDDATA;
}
switch (par->codec_id) {
case AV_CODEC_ID_A64_MULTI:
header[2] = 0x00;
header[3] = AV_RB32(par->extradata+0);
header[4] = 2;
break;
case AV_CODEC_ID_A64_MULTI5:
header[2] = 0x01;
header[3] = AV_RB32(par->extradata+0);
header[4] = 3;
break;
default:
return AVERROR_INVALIDDATA;
}
avio_write(s->pb, header, 2);
return 0;
}
AVOutputFormat ff_a64_muxer = {
.name = "a64",
.long_name = NULL_IF_CONFIG_SMALL("a64 - video for Commodore 64"),
.extensions = "a64, A64",
.video_codec = AV_CODEC_ID_A64_MULTI,
.write_header = a64_write_header,
.write_packet = ff_raw_write_packet,
};

219
externals/ffmpeg/libavformat/aacdec.c vendored Executable file
View File

@@ -0,0 +1,219 @@
/*
* raw ADTS AAC demuxer
* Copyright (c) 2008 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2009 Robert Swain ( rob opendot cl )
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avassert.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
#include "id3v1.h"
#include "id3v2.h"
#include "apetag.h"
#define ADTS_HEADER_SIZE 7
static int adts_aac_probe(const AVProbeData *p)
{
int max_frames = 0, first_frames = 0;
int fsize, frames;
const uint8_t *buf0 = p->buf;
const uint8_t *buf2;
const uint8_t *buf;
const uint8_t *end = buf0 + p->buf_size - 7;
buf = buf0;
for (; buf < end; buf = buf2 + 1) {
buf2 = buf;
for (frames = 0; buf2 < end; frames++) {
uint32_t header = AV_RB16(buf2);
if ((header & 0xFFF6) != 0xFFF0) {
if (buf != buf0) {
// Found something that isn't an ADTS header, starting
// from a position other than the start of the buffer.
// Discard the count we've accumulated so far since it
// probably was a false positive.
frames = 0;
}
break;
}
fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF;
if (fsize < 7)
break;
fsize = FFMIN(fsize, end - buf2);
buf2 += fsize;
}
max_frames = FFMAX(max_frames, frames);
if (buf == buf0)
first_frames = frames;
}
if (first_frames >= 3)
return AVPROBE_SCORE_EXTENSION + 1;
else if (max_frames > 100)
return AVPROBE_SCORE_EXTENSION;
else if (max_frames >= 3)
return AVPROBE_SCORE_EXTENSION / 2;
else if (first_frames >= 1)
return 1;
else
return 0;
}
static int adts_aac_resync(AVFormatContext *s)
{
uint16_t state;
// skip data until an ADTS frame is found
state = avio_r8(s->pb);
while (!avio_feof(s->pb) && avio_tell(s->pb) < s->probesize) {
state = (state << 8) | avio_r8(s->pb);
if ((state >> 4) != 0xFFF)
continue;
avio_seek(s->pb, -2, SEEK_CUR);
break;
}
if (s->pb->eof_reached)
return AVERROR_EOF;
if ((state >> 4) != 0xFFF)
return AVERROR_INVALIDDATA;
return 0;
}
static int adts_aac_read_header(AVFormatContext *s)
{
AVStream *st;
int ret;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = s->iformat->raw_codec_id;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
ff_id3v1_read(s);
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
int64_t cur = avio_tell(s->pb);
ff_ape_parse_tag(s);
avio_seek(s->pb, cur, SEEK_SET);
}
ret = adts_aac_resync(s);
if (ret < 0)
return ret;
// LCM of all possible ADTS sample rates
avpriv_set_pts_info(st, 64, 1, 28224000);
return 0;
}
static int handle_id3(AVFormatContext *s, AVPacket *pkt)
{
AVDictionary *metadata = NULL;
AVIOContext ioctx;
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
int ret;
ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size);
if (ret < 0) {
return ret;
}
ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL);
ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
if ((ret = ff_id3v2_parse_priv_dict(&metadata, id3v2_extra_meta)) < 0)
goto error;
if (metadata) {
if ((ret = av_dict_copy(&s->metadata, metadata, 0)) < 0)
goto error;
s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
}
error:
av_packet_unref(pkt);
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
av_dict_free(&metadata);
return ret;
}
static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, fsize;
retry:
ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE);
if (ret < 0)
return ret;
if (ret < ADTS_HEADER_SIZE) {
return AVERROR(EIO);
}
if ((AV_RB16(pkt->data) >> 4) != 0xfff) {
// Parse all the ID3 headers between frames
int append = ID3v2_HEADER_SIZE - ADTS_HEADER_SIZE;
av_assert2(append > 0);
ret = av_append_packet(s->pb, pkt, append);
if (ret != append) {
return AVERROR(EIO);
}
if (!ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) {
av_packet_unref(pkt);
ret = adts_aac_resync(s);
} else
ret = handle_id3(s, pkt);
if (ret < 0)
return ret;
goto retry;
}
fsize = (AV_RB32(pkt->data + 3) >> 13) & 0x1FFF;
if (fsize < ADTS_HEADER_SIZE) {
return AVERROR_INVALIDDATA;
}
ret = av_append_packet(s->pb, pkt, fsize - pkt->size);
return ret;
}
AVInputFormat ff_aac_demuxer = {
.name = "aac",
.long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"),
.read_probe = adts_aac_probe,
.read_header = adts_aac_read_header,
.read_packet = adts_aac_read_packet,
.flags = AVFMT_GENERIC_INDEX,
.extensions = "aac",
.mime_type = "audio/aac,audio/aacp,audio/x-aac",
.raw_codec_id = AV_CODEC_ID_AAC,
};

416
externals/ffmpeg/libavformat/aadec.c vendored Executable file
View File

@@ -0,0 +1,416 @@
/*
* Audible AA demuxer
* Copyright (c) 2015 Vesselin Bontchev
*
* Header parsing is borrowed from https://github.com/jteeuwen/audible project.
* Copyright (c) 2001-2014, Jim Teeuwen
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "avformat.h"
#include "internal.h"
#include "libavutil/dict.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/tea.h"
#include "libavutil/opt.h"
#define AA_MAGIC 1469084982 /* this identifies an audible .aa file */
#define MAX_CODEC_SECOND_SIZE 3982
#define MAX_TOC_ENTRIES 16
#define MAX_DICTIONARY_ENTRIES 128
#define TEA_BLOCK_SIZE 8
#define CHAPTER_HEADER_SIZE 8
#define TIMEPREC 1000
#define MP3_FRAME_SIZE 104
typedef struct AADemuxContext {
AVClass *class;
uint8_t *aa_fixed_key;
int aa_fixed_key_len;
int codec_second_size;
int current_codec_second_size;
int chapter_idx;
struct AVTEA *tea_ctx;
uint8_t file_key[16];
int64_t current_chapter_size;
int64_t content_start;
int64_t content_end;
int seek_offset;
} AADemuxContext;
static int get_second_size(char *codec_name)
{
int result = -1;
if (!strcmp(codec_name, "mp332")) {
result = 3982;
} else if (!strcmp(codec_name, "acelp16")) {
result = 2000;
} else if (!strcmp(codec_name, "acelp85")) {
result = 1045;
}
return result;
}
static int aa_read_header(AVFormatContext *s)
{
int i, j, idx, largest_idx = -1;
uint32_t nkey, nval, toc_size, npairs, header_seed = 0, start;
char key[128], val[128], codec_name[64] = {0};
uint8_t output[24], dst[8], src[8];
int64_t largest_size = -1, current_size = -1, chapter_pos;
struct toc_entry {
uint32_t offset;
uint32_t size;
} TOC[MAX_TOC_ENTRIES];
uint32_t header_key_part[4];
uint8_t header_key[16] = {0};
AADemuxContext *c = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int ret;
/* parse .aa header */
avio_skip(pb, 4); // file size
avio_skip(pb, 4); // magic string
toc_size = avio_rb32(pb); // TOC size
avio_skip(pb, 4); // unidentified integer
if (toc_size > MAX_TOC_ENTRIES || toc_size < 2)
return AVERROR_INVALIDDATA;
for (i = 0; i < toc_size; i++) { // read TOC
avio_skip(pb, 4); // TOC entry index
TOC[i].offset = avio_rb32(pb); // block offset
TOC[i].size = avio_rb32(pb); // block size
}
avio_skip(pb, 24); // header termination block (ignored)
npairs = avio_rb32(pb); // read dictionary entries
if (npairs > MAX_DICTIONARY_ENTRIES)
return AVERROR_INVALIDDATA;
for (i = 0; i < npairs; i++) {
memset(val, 0, sizeof(val));
memset(key, 0, sizeof(key));
avio_skip(pb, 1); // unidentified integer
nkey = avio_rb32(pb); // key string length
nval = avio_rb32(pb); // value string length
avio_get_str(pb, nkey, key, sizeof(key));
avio_get_str(pb, nval, val, sizeof(val));
if (!strcmp(key, "codec")) {
av_log(s, AV_LOG_DEBUG, "Codec is <%s>\n", val);
strncpy(codec_name, val, sizeof(codec_name) - 1);
} else if (!strcmp(key, "HeaderSeed")) {
av_log(s, AV_LOG_DEBUG, "HeaderSeed is <%s>\n", val);
header_seed = atoi(val);
} else if (!strcmp(key, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890"
av_log(s, AV_LOG_DEBUG, "HeaderKey is <%s>\n", val);
ret = sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32,
&header_key_part[0], &header_key_part[1], &header_key_part[2], &header_key_part[3]);
if (ret != 4)
return AVERROR_INVALIDDATA;
for (idx = 0; idx < 4; idx++) {
AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE!
}
av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is ");
for (i = 0; i < 16; i++)
av_log(s, AV_LOG_DEBUG, "%02x", header_key[i]);
av_log(s, AV_LOG_DEBUG, "\n");
} else {
av_dict_set(&s->metadata, key, val, 0);
}
}
/* verify fixed key */
if (c->aa_fixed_key_len != 16) {
av_log(s, AV_LOG_ERROR, "aa_fixed_key value needs to be 16 bytes!\n");
return AVERROR(EINVAL);
}
/* verify codec */
if ((c->codec_second_size = get_second_size(codec_name)) == -1) {
av_log(s, AV_LOG_ERROR, "unknown codec <%s>!\n", codec_name);
return AVERROR(EINVAL);
}
/* decryption key derivation */
c->tea_ctx = av_tea_alloc();
if (!c->tea_ctx)
return AVERROR(ENOMEM);
av_tea_init(c->tea_ctx, c->aa_fixed_key, 16);
output[0] = output[1] = 0; // purely for padding purposes
memcpy(output + 2, header_key, 16);
idx = 0;
for (i = 0; i < 3; i++) { // TEA CBC with weird mixed endianness
AV_WB32(src, header_seed);
AV_WB32(src + 4, header_seed + 1);
header_seed += 2;
av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 0); // TEA ECB encrypt
for (j = 0; j < TEA_BLOCK_SIZE && idx < 18; j+=1, idx+=1) {
output[idx] = output[idx] ^ dst[j];
}
}
memcpy(c->file_key, output + 2, 16); // skip first 2 bytes of output
av_log(s, AV_LOG_DEBUG, "File key is ");
for (i = 0; i < 16; i++)
av_log(s, AV_LOG_DEBUG, "%02x", c->file_key[i]);
av_log(s, AV_LOG_DEBUG, "\n");
/* decoder setup */
st = avformat_new_stream(s, NULL);
if (!st) {
av_freep(&c->tea_ctx);
return AVERROR(ENOMEM);
}
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
if (!strcmp(codec_name, "mp332")) {
st->codecpar->codec_id = AV_CODEC_ID_MP3;
st->codecpar->sample_rate = 22050;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
avpriv_set_pts_info(st, 64, 8, 32000 * TIMEPREC);
// encoded audio frame is MP3_FRAME_SIZE bytes (+1 with padding, unlikely)
} else if (!strcmp(codec_name, "acelp85")) {
st->codecpar->codec_id = AV_CODEC_ID_SIPR;
st->codecpar->block_align = 19;
st->codecpar->channels = 1;
st->codecpar->sample_rate = 8500;
st->codecpar->bit_rate = 8500;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
avpriv_set_pts_info(st, 64, 8, 8500 * TIMEPREC);
} else if (!strcmp(codec_name, "acelp16")) {
st->codecpar->codec_id = AV_CODEC_ID_SIPR;
st->codecpar->block_align = 20;
st->codecpar->channels = 1;
st->codecpar->sample_rate = 16000;
st->codecpar->bit_rate = 16000;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
avpriv_set_pts_info(st, 64, 8, 16000 * TIMEPREC);
}
/* determine, and jump to audio start offset */
for (i = 1; i < toc_size; i++) { // skip the first entry!
current_size = TOC[i].size;
if (current_size > largest_size) {
largest_idx = i;
largest_size = current_size;
}
}
start = TOC[largest_idx].offset;
avio_seek(pb, start, SEEK_SET);
// extract chapter positions. since all formats have constant bit rate, use it
// as time base in bytes/s, for easy stream position <-> timestamp conversion
st->start_time = 0;
c->content_start = start;
c->content_end = start + largest_size;
while ((chapter_pos = avio_tell(pb)) >= 0 && chapter_pos < c->content_end) {
int chapter_idx = s->nb_chapters;
uint32_t chapter_size = avio_rb32(pb);
if (chapter_size == 0) break;
chapter_pos -= start + CHAPTER_HEADER_SIZE * chapter_idx;
avio_skip(pb, 4 + chapter_size);
if (!avpriv_new_chapter(s, chapter_idx, st->time_base,
chapter_pos * TIMEPREC, (chapter_pos + chapter_size) * TIMEPREC, NULL))
return AVERROR(ENOMEM);
}
st->duration = (largest_size - CHAPTER_HEADER_SIZE * s->nb_chapters) * TIMEPREC;
ff_update_cur_dts(s, st, 0);
avio_seek(pb, start, SEEK_SET);
c->current_chapter_size = 0;
c->seek_offset = 0;
return 0;
}
static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
{
uint8_t dst[TEA_BLOCK_SIZE];
uint8_t src[TEA_BLOCK_SIZE];
int i;
int trailing_bytes;
int blocks;
uint8_t buf[MAX_CODEC_SECOND_SIZE * 2];
int written = 0;
int ret;
AADemuxContext *c = s->priv_data;
uint64_t pos = avio_tell(s->pb);
// are we at the end of the audio content?
if (pos >= c->content_end) {
return AVERROR_EOF;
}
// are we at the start of a chapter?
if (c->current_chapter_size == 0) {
c->current_chapter_size = avio_rb32(s->pb);
if (c->current_chapter_size == 0) {
return AVERROR_EOF;
}
av_log(s, AV_LOG_DEBUG, "Chapter %d (%" PRId64 " bytes)\n", c->chapter_idx, c->current_chapter_size);
c->chapter_idx = c->chapter_idx + 1;
avio_skip(s->pb, 4); // data start offset
pos += 8;
c->current_codec_second_size = c->codec_second_size;
}
// is this the last block in this chapter?
if (c->current_chapter_size / c->current_codec_second_size == 0) {
c->current_codec_second_size = c->current_chapter_size % c->current_codec_second_size;
}
// decrypt c->current_codec_second_size bytes
blocks = c->current_codec_second_size / TEA_BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
ret = avio_read(s->pb, src, TEA_BLOCK_SIZE);
if (ret != TEA_BLOCK_SIZE)
return (ret < 0) ? ret : AVERROR_EOF;
av_tea_init(c->tea_ctx, c->file_key, 16);
av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1);
memcpy(buf + written, dst, TEA_BLOCK_SIZE);
written = written + TEA_BLOCK_SIZE;
}
trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE;
if (trailing_bytes != 0) { // trailing bytes are left unencrypted!
ret = avio_read(s->pb, src, trailing_bytes);
if (ret != trailing_bytes)
return (ret < 0) ? ret : AVERROR_EOF;
memcpy(buf + written, src, trailing_bytes);
written = written + trailing_bytes;
}
// update state
c->current_chapter_size = c->current_chapter_size - c->current_codec_second_size;
if (c->current_chapter_size <= 0)
c->current_chapter_size = 0;
if (c->seek_offset > written)
c->seek_offset = 0; // ignore wrong estimate
ret = av_new_packet(pkt, written - c->seek_offset);
if (ret < 0)
return ret;
memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset);
pkt->pos = pos;
c->seek_offset = 0;
return 0;
}
static int aa_read_seek(AVFormatContext *s,
int stream_index, int64_t timestamp, int flags)
{
AADemuxContext *c = s->priv_data;
AVChapter *ch;
int64_t chapter_pos, chapter_start, chapter_size;
int chapter_idx = 0;
// find chapter containing seek timestamp
if (timestamp < 0)
timestamp = 0;
while (chapter_idx < s->nb_chapters && timestamp >= s->chapters[chapter_idx]->end) {
++chapter_idx;
}
if (chapter_idx >= s->nb_chapters) {
chapter_idx = s->nb_chapters - 1;
if (chapter_idx < 0) return -1; // there is no chapter.
timestamp = s->chapters[chapter_idx]->end;
}
ch = s->chapters[chapter_idx];
// sync by clamping timestamp to nearest valid block position in its chapter
chapter_size = ch->end / TIMEPREC - ch->start / TIMEPREC;
chapter_pos = av_rescale_rnd((timestamp - ch->start) / TIMEPREC,
1, c->codec_second_size,
(flags & AVSEEK_FLAG_BACKWARD) ? AV_ROUND_DOWN : AV_ROUND_UP)
* c->codec_second_size;
if (chapter_pos >= chapter_size)
chapter_pos = chapter_size;
chapter_start = c->content_start + (ch->start / TIMEPREC) + CHAPTER_HEADER_SIZE * (1 + chapter_idx);
// reinit read state
avio_seek(s->pb, chapter_start + chapter_pos, SEEK_SET);
c->current_codec_second_size = c->codec_second_size;
c->current_chapter_size = chapter_size - chapter_pos;
c->chapter_idx = 1 + chapter_idx;
// for unaligned frames, estimate offset of first frame in block (assume no padding)
if (s->streams[0]->codecpar->codec_id == AV_CODEC_ID_MP3) {
c->seek_offset = (MP3_FRAME_SIZE - chapter_pos % MP3_FRAME_SIZE) % MP3_FRAME_SIZE;
}
ff_update_cur_dts(s, s->streams[0], ch->start + (chapter_pos + c->seek_offset) * TIMEPREC);
return 1;
}
static int aa_probe(const AVProbeData *p)
{
uint8_t *buf = p->buf;
// first 4 bytes are file size, next 4 bytes are the magic
if (AV_RB32(buf+4) != AA_MAGIC)
return 0;
return AVPROBE_SCORE_MAX / 2;
}
static int aa_read_close(AVFormatContext *s)
{
AADemuxContext *c = s->priv_data;
av_freep(&c->tea_ctx);
return 0;
}
#define OFFSET(x) offsetof(AADemuxContext, x)
static const AVOption aa_options[] = {
{ "aa_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
"Fixed key used for handling Audible AA files", OFFSET(aa_fixed_key),
AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd2a51d673"},
.flags = AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
static const AVClass aa_class = {
.class_name = "aa",
.item_name = av_default_item_name,
.option = aa_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_aa_demuxer = {
.name = "aa",
.long_name = NULL_IF_CONFIG_SMALL("Audible AA format files"),
.priv_class = &aa_class,
.priv_data_size = sizeof(AADemuxContext),
.extensions = "aa",
.read_probe = aa_probe,
.read_header = aa_read_header,
.read_packet = aa_read_packet,
.read_seek = aa_read_seek,
.read_close = aa_read_close,
.flags = AVFMT_NO_BYTE_SEEK | AVFMT_NOGENSEARCH,
};

139
externals/ffmpeg/libavformat/ac3dec.c vendored Executable file
View File

@@ -0,0 +1,139 @@
/*
* RAW AC-3 and E-AC-3 demuxer
* Copyright (c) 2007 Justin Ruggles <justin.ruggles@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 "libavutil/avassert.h"
#include "libavutil/crc.h"
#include "libavcodec/ac3_parser.h"
#include "avformat.h"
#include "rawdec.h"
static int ac3_eac3_probe(const AVProbeData *p, enum AVCodecID expected_codec_id)
{
int max_frames, first_frames = 0, frames;
const uint8_t *buf, *buf2, *end;
enum AVCodecID codec_id = AV_CODEC_ID_AC3;
max_frames = 0;
buf = p->buf;
end = buf + p->buf_size;
for(; buf < end; buf++) {
if(buf > p->buf && !(buf[0] == 0x0B && buf[1] == 0x77)
&& !(buf[0] == 0x77 && buf[1] == 0x0B) )
continue;
buf2 = buf;
for(frames = 0; buf2 < end; frames++) {
uint8_t buf3[4096];
uint8_t bitstream_id;
uint16_t frame_size;
int i, ret;
if(!memcmp(buf2, "\x1\x10", 2)) {
if (buf2 + 16 > end)
break;
buf2+=16;
}
if (buf[0] == 0x77 && buf[1] == 0x0B) {
for(i=0; i<8; i+=2) {
buf3[i ] = buf2[i+1];
buf3[i+1] = buf2[i ];
}
ret = av_ac3_parse_header(buf3, 8, &bitstream_id,
&frame_size);
}else
ret = av_ac3_parse_header(buf2, end - buf2, &bitstream_id,
&frame_size);
if (ret < 0)
break;
if(buf2 + frame_size > end)
break;
if (buf[0] == 0x77 && buf[1] == 0x0B) {
av_assert0(frame_size <= sizeof(buf3));
for(i = 8; i < frame_size; i += 2) {
buf3[i ] = buf2[i+1];
buf3[i+1] = buf2[i ];
}
if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf3 + 2, frame_size - 2))
break;
} else {
if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf2 + 2, frame_size - 2))
break;
}
if (bitstream_id > 10)
codec_id = AV_CODEC_ID_EAC3;
buf2 += frame_size;
}
max_frames = FFMAX(max_frames, frames);
if(buf == p->buf)
first_frames = frames;
}
if(codec_id != expected_codec_id) return 0;
// keep this in sync with mp3 probe, both need to avoid
// issues with MPEG-files!
if (first_frames>=7) return AVPROBE_SCORE_EXTENSION + 1;
else if(max_frames>200)return AVPROBE_SCORE_EXTENSION;
else if(max_frames>=4) return AVPROBE_SCORE_EXTENSION/2;
else if(max_frames>=1) return 1;
else return 0;
}
#if CONFIG_AC3_DEMUXER
static int ac3_probe(const AVProbeData *p)
{
return ac3_eac3_probe(p, AV_CODEC_ID_AC3);
}
FF_RAW_DEMUXER_CLASS(ac3)
AVInputFormat ff_ac3_demuxer = {
.name = "ac3",
.long_name = NULL_IF_CONFIG_SMALL("raw AC-3"),
.read_probe = ac3_probe,
.read_header = ff_raw_audio_read_header,
.read_packet = ff_raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "ac3",
.raw_codec_id = AV_CODEC_ID_AC3,
.priv_data_size = sizeof(FFRawDemuxerContext),
.priv_class = &ac3_demuxer_class,
};
#endif
#if CONFIG_EAC3_DEMUXER
static int eac3_probe(const AVProbeData *p)
{
return ac3_eac3_probe(p, AV_CODEC_ID_EAC3);
}
FF_RAW_DEMUXER_CLASS(eac3)
AVInputFormat ff_eac3_demuxer = {
.name = "eac3",
.long_name = NULL_IF_CONFIG_SMALL("raw E-AC-3"),
.read_probe = eac3_probe,
.read_header = ff_raw_audio_read_header,
.read_packet = ff_raw_read_partial_packet,
.flags = AVFMT_GENERIC_INDEX,
.extensions = "eac3",
.raw_codec_id = AV_CODEC_ID_EAC3,
.priv_data_size = sizeof(FFRawDemuxerContext),
.priv_class = &eac3_demuxer_class,
};
#endif

75
externals/ffmpeg/libavformat/acm.c vendored Executable file
View File

@@ -0,0 +1,75 @@
/*
* ACM demuxer
* Copyright (c) 2015 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "rawdec.h"
#include "internal.h"
static int acm_probe(const AVProbeData *p)
{
if (AV_RB32(p->buf) != 0x97280301)
return 0;
return AVPROBE_SCORE_MAX / 3 * 2;
}
static int acm_read_header(AVFormatContext *s)
{
AVStream *st;
int ret;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_ACM;
ret = ff_get_extradata(s, st->codecpar, s->pb, 14);
if (ret < 0)
return ret;
st->codecpar->channels = AV_RL16(st->codecpar->extradata + 8);
st->codecpar->sample_rate = AV_RL16(st->codecpar->extradata + 10);
if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0)
return AVERROR_INVALIDDATA;
st->start_time = 0;
st->duration = AV_RL32(st->codecpar->extradata + 4) / st->codecpar->channels;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
FF_RAW_DEMUXER_CLASS(acm)
AVInputFormat ff_acm_demuxer = {
.name = "acm",
.long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"),
.read_probe = acm_probe,
.read_header = acm_read_header,
.read_packet = ff_raw_read_partial_packet,
.flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,
.extensions = "acm",
.raw_codec_id = AV_CODEC_ID_INTERPLAY_ACM,
.priv_data_size = sizeof(FFRawDemuxerContext),
.priv_class = &acm_demuxer_class,
};

207
externals/ffmpeg/libavformat/act.c vendored Executable file
View File

@@ -0,0 +1,207 @@
/*
* ACT file format demuxer
* Copyright (c) 2007-2008 Vladimir Voroshilov
*
* 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"
#include "internal.h"
#include "libavcodec/get_bits.h"
#define CHUNK_SIZE 512
#define RIFF_TAG MKTAG('R','I','F','F')
#define WAVE_TAG MKTAG('W','A','V','E')
typedef struct{
int bytes_left_in_chunk;
uint8_t audio_buffer[22];///< temporary buffer for ACT frame
char second_packet; ///< 1 - if temporary buffer contains valid (second) G.729 packet
} ACTContext;
static int probe(const AVProbeData *p)
{
int i;
if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
(AV_RL32(&p->buf[8]) != WAVE_TAG) ||
(AV_RL32(&p->buf[16]) != 16))
return 0;
//We can't be sure that this is ACT and not regular WAV
if (p->buf_size<512)
return 0;
for(i=44; i<256; i++)
if(p->buf[i])
return 0;
if(p->buf[256]!=0x84)
return 0;
for(i=264; i<512; i++)
if(p->buf[i])
return 0;
return AVPROBE_SCORE_MAX;
}
static int read_header(AVFormatContext *s)
{
ACTContext* ctx = s->priv_data;
AVIOContext *pb = s->pb;
int size;
AVStream* st;
int min,sec,msec;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
avio_skip(pb, 16);
size=avio_rl32(pb);
ff_get_wav_header(s, pb, st->codecpar, size, 0);
/*
8000Hz (Fine-rec) file format has 10 bytes long
packets with 10ms of sound data in them
*/
if (st->codecpar->sample_rate != 8000) {
av_log(s, AV_LOG_ERROR, "Sample rate %d is not supported.\n", st->codecpar->sample_rate);
return AVERROR_INVALIDDATA;
}
st->codecpar->frame_size=80;
st->codecpar->channels=1;
avpriv_set_pts_info(st, 64, 1, 100);
st->codecpar->codec_id=AV_CODEC_ID_G729;
avio_seek(pb, 257, SEEK_SET);
msec=avio_rl16(pb);
sec=avio_r8(pb);
min=avio_rl32(pb);
st->duration = av_rescale(1000*(min*60+sec)+msec, st->codecpar->sample_rate, 1000 * st->codecpar->frame_size);
ctx->bytes_left_in_chunk=CHUNK_SIZE;
avio_seek(pb, 512, SEEK_SET);
return 0;
}
static int read_packet(AVFormatContext *s,
AVPacket *pkt)
{
ACTContext *ctx = s->priv_data;
AVIOContext *pb = s->pb;
int ret;
int frame_size=s->streams[0]->codecpar->sample_rate==8000?10:22;
if(s->streams[0]->codecpar->sample_rate==8000)
ret=av_new_packet(pkt, 10);
else
ret=av_new_packet(pkt, 11);
if(ret)
return ret;
if(s->streams[0]->codecpar->sample_rate==4400 && !ctx->second_packet)
{
ret = avio_read(pb, ctx->audio_buffer, frame_size);
if(ret<0)
return ret;
if(ret!=frame_size)
return AVERROR(EIO);
pkt->data[0]=ctx->audio_buffer[11];
pkt->data[1]=ctx->audio_buffer[0];
pkt->data[2]=ctx->audio_buffer[12];
pkt->data[3]=ctx->audio_buffer[1];
pkt->data[4]=ctx->audio_buffer[13];
pkt->data[5]=ctx->audio_buffer[2];
pkt->data[6]=ctx->audio_buffer[14];
pkt->data[7]=ctx->audio_buffer[3];
pkt->data[8]=ctx->audio_buffer[15];
pkt->data[9]=ctx->audio_buffer[4];
pkt->data[10]=ctx->audio_buffer[16];
ctx->second_packet=1;
}
else if(s->streams[0]->codecpar->sample_rate==4400 && ctx->second_packet)
{
pkt->data[0]=ctx->audio_buffer[5];
pkt->data[1]=ctx->audio_buffer[17];
pkt->data[2]=ctx->audio_buffer[6];
pkt->data[3]=ctx->audio_buffer[18];
pkt->data[4]=ctx->audio_buffer[7];
pkt->data[5]=ctx->audio_buffer[19];
pkt->data[6]=ctx->audio_buffer[8];
pkt->data[7]=ctx->audio_buffer[20];
pkt->data[8]=ctx->audio_buffer[9];
pkt->data[9]=ctx->audio_buffer[21];
pkt->data[10]=ctx->audio_buffer[10];
ctx->second_packet=0;
}
else // 8000 Hz
{
ret = avio_read(pb, ctx->audio_buffer, frame_size);
if(ret<0)
return ret;
if(ret!=frame_size)
return AVERROR(EIO);
pkt->data[0]=ctx->audio_buffer[5];
pkt->data[1]=ctx->audio_buffer[0];
pkt->data[2]=ctx->audio_buffer[6];
pkt->data[3]=ctx->audio_buffer[1];
pkt->data[4]=ctx->audio_buffer[7];
pkt->data[5]=ctx->audio_buffer[2];
pkt->data[6]=ctx->audio_buffer[8];
pkt->data[7]=ctx->audio_buffer[3];
pkt->data[8]=ctx->audio_buffer[9];
pkt->data[9]=ctx->audio_buffer[4];
}
ctx->bytes_left_in_chunk -= frame_size;
if(ctx->bytes_left_in_chunk < frame_size)
{
avio_skip(pb, ctx->bytes_left_in_chunk);
ctx->bytes_left_in_chunk=CHUNK_SIZE;
}
pkt->duration=1;
return ret;
}
AVInputFormat ff_act_demuxer = {
.name = "act",
.long_name = "ACT Voice file format",
.priv_data_size = sizeof(ACTContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
};

97
externals/ffmpeg/libavformat/adp.c vendored Executable file
View File

@@ -0,0 +1,97 @@
/*
* ADP demuxer
* Copyright (c) 2013 James Almer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
static int adp_probe(const AVProbeData *p)
{
int i, changes = 0;
uint8_t last = 0;
if (p->buf_size < 32)
return 0;
for (i = 0; i < p->buf_size - 3; i+=32) {
if (p->buf[i] != p->buf[i+2] || p->buf[i+1] != p->buf[i+3])
return 0;
if (p->buf[i] != last)
changes++;
last = p->buf[i];
}
if (changes <= 1)
return 0;
return p->buf_size < 260 ? 1 : AVPROBE_SCORE_MAX / 4;
}
static int adp_read_header(AVFormatContext *s)
{
AVStream *st;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK;
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
st->codecpar->channels = 2;
st->codecpar->sample_rate = 48000;
st->start_time = 0;
if (s->pb->seekable & AVIO_SEEKABLE_NORMAL)
st->duration = av_get_audio_frame_duration2(st->codecpar, avio_size(s->pb));
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int adp_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, size = 1024;
if (avio_feof(s->pb))
return AVERROR_EOF;
ret = av_get_packet(s->pb, pkt, size);
if (ret != size) {
if (ret < 0) {
return ret;
}
av_shrink_packet(pkt, ret);
}
pkt->stream_index = 0;
return ret;
}
AVInputFormat ff_adp_demuxer = {
.name = "adp",
.long_name = NULL_IF_CONFIG_SMALL("ADP"),
.read_probe = adp_probe,
.read_header = adp_read_header,
.read_packet = adp_read_packet,
.extensions = "adp,dtk",
};

89
externals/ffmpeg/libavformat/ads.c vendored Executable file
View File

@@ -0,0 +1,89 @@
/*
* ADS/SS2 demuxer
* Copyright (c) 2015 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
static int ads_probe(const AVProbeData *p)
{
if (memcmp(p->buf, "SShd", 4) ||
memcmp(p->buf+32, "SSbd", 4))
return 0;
return AVPROBE_SCORE_MAX / 3 * 2;
}
static int ads_read_header(AVFormatContext *s)
{
int align, codec, size;
AVStream *st;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
avio_skip(s->pb, 8);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
codec = avio_rl32(s->pb);
st->codecpar->sample_rate = avio_rl32(s->pb);
if (st->codecpar->sample_rate <= 0)
return AVERROR_INVALIDDATA;
st->codecpar->channels = avio_rl32(s->pb);
if (st->codecpar->channels <= 0)
return AVERROR_INVALIDDATA;
align = avio_rl32(s->pb);
if (align <= 0 || align > INT_MAX / st->codecpar->channels)
return AVERROR_INVALIDDATA;
if (codec == 1)
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR;
else
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX;
st->codecpar->block_align = st->codecpar->channels * align;
avio_skip(s->pb, 12);
size = avio_rl32(s->pb);
if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_PSX)
st->duration = (size - 0x40) / 16 / st->codecpar->channels * 28;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int ads_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVCodecParameters *par = s->streams[0]->codecpar;
int ret;
ret = av_get_packet(s->pb, pkt, par->block_align);
pkt->stream_index = 0;
return ret;
}
AVInputFormat ff_ads_demuxer = {
.name = "ads",
.long_name = NULL_IF_CONFIG_SMALL("Sony PS2 ADS"),
.read_probe = ads_probe,
.read_header = ads_read_header,
.read_packet = ads_read_packet,
.extensions = "ads,ss2",
};

241
externals/ffmpeg/libavformat/adtsenc.c vendored Executable file
View File

@@ -0,0 +1,241 @@
/*
* ADTS muxer.
* Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
* Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavcodec/get_bits.h"
#include "libavcodec/put_bits.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/mpeg4audio.h"
#include "libavutil/opt.h"
#include "avformat.h"
#include "apetag.h"
#include "id3v2.h"
#define ADTS_HEADER_SIZE 7
typedef struct ADTSContext {
AVClass *class;
int write_adts;
int objecttype;
int sample_rate_index;
int channel_conf;
int pce_size;
int apetag;
int id3v2tag;
uint8_t pce_data[MAX_PCE_SIZE];
} ADTSContext;
#define ADTS_MAX_FRAME_BYTES ((1 << 13) - 1)
static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, const uint8_t *buf, int size)
{
GetBitContext gb;
PutBitContext pb;
MPEG4AudioConfig m4ac;
int off;
init_get_bits(&gb, buf, size * 8);
off = avpriv_mpeg4audio_get_config2(&m4ac, buf, size, 1, s);
if (off < 0)
return off;
skip_bits_long(&gb, off);
adts->objecttype = m4ac.object_type - 1;
adts->sample_rate_index = m4ac.sampling_index;
adts->channel_conf = m4ac.chan_config;
if (adts->objecttype > 3U) {
av_log(s, AV_LOG_ERROR, "MPEG-4 AOT %d is not allowed in ADTS\n", adts->objecttype+1);
return AVERROR_INVALIDDATA;
}
if (adts->sample_rate_index == 15) {
av_log(s, AV_LOG_ERROR, "Escape sample rate index illegal in ADTS\n");
return AVERROR_INVALIDDATA;
}
if (get_bits(&gb, 1)) {
av_log(s, AV_LOG_ERROR, "960/120 MDCT window is not allowed in ADTS\n");
return AVERROR_INVALIDDATA;
}
if (get_bits(&gb, 1)) {
av_log(s, AV_LOG_ERROR, "Scalable configurations are not allowed in ADTS\n");
return AVERROR_INVALIDDATA;
}
if (get_bits(&gb, 1)) {
av_log(s, AV_LOG_ERROR, "Extension flag is not allowed in ADTS\n");
return AVERROR_INVALIDDATA;
}
if (!adts->channel_conf) {
init_put_bits(&pb, adts->pce_data, MAX_PCE_SIZE);
put_bits(&pb, 3, 5); //ID_PCE
adts->pce_size = (ff_copy_pce_data(&pb, &gb) + 3) / 8;
flush_put_bits(&pb);
}
adts->write_adts = 1;
return 0;
}
static int adts_init(AVFormatContext *s)
{
ADTSContext *adts = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
if (par->codec_id != AV_CODEC_ID_AAC) {
av_log(s, AV_LOG_ERROR, "Only AAC streams can be muxed by the ADTS muxer\n");
return AVERROR(EINVAL);
}
if (par->extradata_size > 0)
return adts_decode_extradata(s, adts, par->extradata,
par->extradata_size);
return 0;
}
static int adts_write_header(AVFormatContext *s)
{
ADTSContext *adts = s->priv_data;
if (adts->id3v2tag)
ff_id3v2_write_simple(s, 4, ID3v2_DEFAULT_MAGIC);
return 0;
}
static int adts_write_frame_header(ADTSContext *ctx,
uint8_t *buf, int size, int pce_size)
{
PutBitContext pb;
unsigned full_frame_size = (unsigned)ADTS_HEADER_SIZE + size + pce_size;
if (full_frame_size > ADTS_MAX_FRAME_BYTES) {
av_log(NULL, AV_LOG_ERROR, "ADTS frame size too large: %u (max %d)\n",
full_frame_size, ADTS_MAX_FRAME_BYTES);
return AVERROR_INVALIDDATA;
}
init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
/* adts_fixed_header */
put_bits(&pb, 12, 0xfff); /* syncword */
put_bits(&pb, 1, 0); /* ID */
put_bits(&pb, 2, 0); /* layer */
put_bits(&pb, 1, 1); /* protection_absent */
put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
put_bits(&pb, 4, ctx->sample_rate_index);
put_bits(&pb, 1, 0); /* private_bit */
put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
put_bits(&pb, 1, 0); /* original_copy */
put_bits(&pb, 1, 0); /* home */
/* adts_variable_header */
put_bits(&pb, 1, 0); /* copyright_identification_bit */
put_bits(&pb, 1, 0); /* copyright_identification_start */
put_bits(&pb, 13, full_frame_size); /* aac_frame_length */
put_bits(&pb, 11, 0x7ff); /* adts_buffer_fullness */
put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
flush_put_bits(&pb);
return 0;
}
static int adts_write_packet(AVFormatContext *s, AVPacket *pkt)
{
ADTSContext *adts = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
AVIOContext *pb = s->pb;
uint8_t buf[ADTS_HEADER_SIZE];
if (!pkt->size)
return 0;
if (!par->extradata_size) {
uint8_t *side_data;
int side_data_size = 0, ret;
side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
&side_data_size);
if (side_data_size) {
ret = adts_decode_extradata(s, adts, side_data, side_data_size);
if (ret < 0)
return ret;
ret = ff_alloc_extradata(par, side_data_size);
if (ret < 0)
return ret;
memcpy(par->extradata, side_data, side_data_size);
}
}
if (adts->write_adts) {
int err = adts_write_frame_header(adts, buf, pkt->size,
adts->pce_size);
if (err < 0)
return err;
avio_write(pb, buf, ADTS_HEADER_SIZE);
if (adts->pce_size) {
avio_write(pb, adts->pce_data, adts->pce_size);
adts->pce_size = 0;
}
}
avio_write(pb, pkt->data, pkt->size);
return 0;
}
static int adts_write_trailer(AVFormatContext *s)
{
ADTSContext *adts = s->priv_data;
if (adts->apetag)
ff_ape_write_tag(s);
return 0;
}
#define ENC AV_OPT_FLAG_ENCODING_PARAM
#define OFFSET(obj) offsetof(ADTSContext, obj)
static const AVOption options[] = {
{ "write_id3v2", "Enable ID3v2 tag writing", OFFSET(id3v2tag), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC},
{ "write_apetag", "Enable APE tag writing", OFFSET(apetag), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC},
{ NULL },
};
static const AVClass adts_muxer_class = {
.class_name = "ADTS muxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVOutputFormat ff_adts_muxer = {
.name = "adts",
.long_name = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"),
.mime_type = "audio/aac",
.extensions = "aac,adts",
.priv_data_size = sizeof(ADTSContext),
.audio_codec = AV_CODEC_ID_AAC,
.video_codec = AV_CODEC_ID_NONE,
.init = adts_init,
.write_header = adts_write_header,
.write_packet = adts_write_packet,
.write_trailer = adts_write_trailer,
.priv_class = &adts_muxer_class,
.flags = AVFMT_NOTIMESTAMPS,
};

134
externals/ffmpeg/libavformat/adxdec.c vendored Executable file
View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2011 Justin Ruggles
*
* 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
* CRI ADX demuxer
*/
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
#define BLOCK_SIZE 18
#define BLOCK_SAMPLES 32
typedef struct ADXDemuxerContext {
int header_size;
} ADXDemuxerContext;
static int adx_probe(const AVProbeData *p)
{
int offset;
if (AV_RB16(p->buf) != 0x8000)
return 0;
offset = AV_RB16(&p->buf[2]);
if ( offset < 8
|| offset > p->buf_size - 4
|| memcmp(p->buf + offset - 2, "(c)CRI", 6))
return 0;
return AVPROBE_SCORE_MAX * 3 / 4;
}
static int adx_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ADXDemuxerContext *c = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
int ret, size;
if (par->channels <= 0) {
av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels);
return AVERROR_INVALIDDATA;
}
size = BLOCK_SIZE * par->channels;
pkt->pos = avio_tell(s->pb);
pkt->stream_index = 0;
ret = av_get_packet(s->pb, pkt, size);
if (ret != size) {
return ret < 0 ? ret : AVERROR(EIO);
}
if (AV_RB16(pkt->data) & 0x8000) {
return AVERROR_EOF;
}
pkt->size = size;
pkt->duration = 1;
pkt->pts = (pkt->pos - c->header_size) / size;
return 0;
}
static int adx_read_header(AVFormatContext *s)
{
ADXDemuxerContext *c = s->priv_data;
AVCodecParameters *par;
int ret;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
par = s->streams[0]->codecpar;
if (avio_rb16(s->pb) != 0x8000)
return AVERROR_INVALIDDATA;
c->header_size = avio_rb16(s->pb) + 4;
avio_seek(s->pb, -4, SEEK_CUR);
if ((ret = ff_get_extradata(s, par, s->pb, c->header_size)) < 0)
return ret;
if (par->extradata_size < 12) {
av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n");
return AVERROR_INVALIDDATA;
}
par->channels = AV_RB8 (par->extradata + 7);
par->sample_rate = AV_RB32(par->extradata + 8);
if (par->channels <= 0) {
av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels);
return AVERROR_INVALIDDATA;
}
if (par->sample_rate <= 0) {
av_log(s, AV_LOG_ERROR, "Invalid sample rate %d\n", par->sample_rate);
return AVERROR_INVALIDDATA;
}
par->codec_type = AVMEDIA_TYPE_AUDIO;
par->codec_id = s->iformat->raw_codec_id;
par->bit_rate = (int64_t)par->sample_rate * par->channels * BLOCK_SIZE * 8LL / BLOCK_SAMPLES;
avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, par->sample_rate);
return 0;
}
AVInputFormat ff_adx_demuxer = {
.name = "adx",
.long_name = NULL_IF_CONFIG_SMALL("CRI ADX"),
.read_probe = adx_probe,
.priv_data_size = sizeof(ADXDemuxerContext),
.read_header = adx_read_header,
.read_packet = adx_read_packet,
.extensions = "adx",
.raw_codec_id = AV_CODEC_ID_ADPCM_ADX,
.flags = AVFMT_GENERIC_INDEX,
};

110
externals/ffmpeg/libavformat/aea.c vendored Executable file
View File

@@ -0,0 +1,110 @@
/*
* MD STUDIO audio demuxer
*
* Copyright (c) 2009 Benjamin Larsson
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "pcm.h"
#define AT1_SU_SIZE 212
static int aea_read_probe(const AVProbeData *p)
{
if (p->buf_size <= 2048+212)
return 0;
/* Magic is '00 08 00 00' in little-endian*/
if (AV_RL32(p->buf)==0x800) {
int ch, i;
ch = p->buf[264];
if (ch != 1 && ch != 2)
return 0;
/* Check so that the redundant bsm bytes and info bytes are valid
* the block size mode bytes have to be the same
* the info bytes have to be the same
*/
for (i = 2048; i + 211 < p->buf_size; i+= 212) {
int bsm_s, bsm_e, inb_s, inb_e;
bsm_s = p->buf[0];
inb_s = p->buf[1];
inb_e = p->buf[210];
bsm_e = p->buf[211];
if (bsm_s != bsm_e || inb_s != inb_e)
return 0;
}
return AVPROBE_SCORE_MAX / 4 + 1;
}
return 0;
}
static int aea_read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
/* Parse the amount of channels and skip to pos 2048(0x800) */
avio_skip(s->pb, 264);
st->codecpar->channels = avio_r8(s->pb);
avio_skip(s->pb, 1783);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ATRAC1;
st->codecpar->sample_rate = 44100;
st->codecpar->bit_rate = 292000;
if (st->codecpar->channels != 1 && st->codecpar->channels != 2) {
av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", st->codecpar->channels);
return AVERROR_INVALIDDATA;
}
st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->channels;
return 0;
}
static int aea_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret = av_get_packet(s->pb, pkt, s->streams[0]->codecpar->block_align);
pkt->stream_index = 0;
if (ret <= 0)
return AVERROR(EIO);
return ret;
}
AVInputFormat ff_aea_demuxer = {
.name = "aea",
.long_name = NULL_IF_CONFIG_SMALL("MD STUDIO audio"),
.read_probe = aea_read_probe,
.read_header = aea_read_header,
.read_packet = aea_read_packet,
.read_seek = ff_pcm_read_seek,
.flags = AVFMT_GENERIC_INDEX,
.extensions = "aea",
};

80
externals/ffmpeg/libavformat/afc.c vendored Executable file
View File

@@ -0,0 +1,80 @@
/*
* AFC demuxer
* Copyright (c) 2012 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
typedef struct AFCDemuxContext {
int64_t data_end;
} AFCDemuxContext;
static int afc_read_header(AVFormatContext *s)
{
AFCDemuxContext *c = s->priv_data;
AVStream *st;
int ret;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AFC;
st->codecpar->channels = 2;
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
if ((ret = ff_alloc_extradata(st->codecpar, 1)) < 0)
return ret;
st->codecpar->extradata[0] = 8 * st->codecpar->channels;
c->data_end = avio_rb32(s->pb) + 32LL;
st->duration = avio_rb32(s->pb);
st->codecpar->sample_rate = avio_rb16(s->pb);
avio_skip(s->pb, 22);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int afc_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AFCDemuxContext *c = s->priv_data;
int64_t size;
int ret;
size = FFMIN(c->data_end - avio_tell(s->pb), 18 * 128);
if (size <= 0)
return AVERROR_EOF;
ret = av_get_packet(s->pb, pkt, size);
pkt->stream_index = 0;
return ret;
}
AVInputFormat ff_afc_demuxer = {
.name = "afc",
.long_name = NULL_IF_CONFIG_SMALL("AFC"),
.priv_data_size = sizeof(AFCDemuxContext),
.read_header = afc_read_header,
.read_packet = afc_read_packet,
.extensions = "afc",
.flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
};

61
externals/ffmpeg/libavformat/aiff.h vendored Executable file
View File

@@ -0,0 +1,61 @@
/*
* AIFF/AIFF-C muxer/demuxer common header
* Copyright (c) 2006 Patrick Guimond
*
* 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
* common header for AIFF muxer and demuxer
*/
#ifndef AVFORMAT_AIFF_H
#define AVFORMAT_AIFF_H
#include "avformat.h"
#include "internal.h"
static const AVCodecTag ff_codec_aiff_tags[] = {
{ AV_CODEC_ID_PCM_S16BE, MKTAG('N','O','N','E') },
{ AV_CODEC_ID_PCM_S8, MKTAG('N','O','N','E') },
{ AV_CODEC_ID_PCM_U8, MKTAG('r','a','w',' ') },
{ AV_CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') },
{ AV_CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') },
{ AV_CODEC_ID_PCM_F32BE, MKTAG('f','l','3','2') },
{ AV_CODEC_ID_PCM_F64BE, MKTAG('f','l','6','4') },
{ AV_CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') },
{ AV_CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') },
{ AV_CODEC_ID_PCM_S24BE, MKTAG('i','n','2','4') },
{ AV_CODEC_ID_PCM_S32BE, MKTAG('i','n','3','2') },
{ AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') },
{ AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') },
{ AV_CODEC_ID_GSM, MKTAG('G','S','M',' ') },
{ AV_CODEC_ID_ADPCM_G722, MKTAG('G','7','2','2') },
{ AV_CODEC_ID_ADPCM_G726LE, MKTAG('G','7','2','6') },
{ AV_CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') },
{ AV_CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') },
{ AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') },
{ AV_CODEC_ID_QDMC, MKTAG('Q','D','M','C') },
{ AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') },
{ AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') },
{ AV_CODEC_ID_SDX2_DPCM, MKTAG('S','D','X','2') },
{ AV_CODEC_ID_ADPCM_IMA_WS, MKTAG('A','D','P','4') },
{ AV_CODEC_ID_NONE, 0 },
};
#endif /* AVFORMAT_AIFF_H */

432
externals/ffmpeg/libavformat/aiffdec.c vendored Executable file
View File

@@ -0,0 +1,432 @@
/*
* AIFF/AIFF-C demuxer
* Copyright (c) 2006 Patrick Guimond
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/dict.h"
#include "avformat.h"
#include "internal.h"
#include "pcm.h"
#include "aiff.h"
#include "isom.h"
#include "id3v2.h"
#include "mov_chan.h"
#include "replaygain.h"
#define AIFF 0
#define AIFF_C_VERSION1 0xA2805140
typedef struct AIFFInputContext {
int64_t data_end;
int block_duration;
} AIFFInputContext;
static enum AVCodecID aiff_codec_get_id(int bps)
{
if (bps <= 8)
return AV_CODEC_ID_PCM_S8;
if (bps <= 16)
return AV_CODEC_ID_PCM_S16BE;
if (bps <= 24)
return AV_CODEC_ID_PCM_S24BE;
if (bps <= 32)
return AV_CODEC_ID_PCM_S32BE;
/* bigger than 32 isn't allowed */
return AV_CODEC_ID_NONE;
}
/* returns the size of the found tag */
static int get_tag(AVIOContext *pb, uint32_t * tag)
{
int size;
if (avio_feof(pb))
return AVERROR(EIO);
*tag = avio_rl32(pb);
size = avio_rb32(pb);
if (size < 0)
size = 0x7fffffff;
return size;
}
/* Metadata string read */
static void get_meta(AVFormatContext *s, const char *key, int size)
{
uint8_t *str = av_malloc(size+1);
if (str) {
int res = avio_read(s->pb, str, size);
if (res < 0){
av_free(str);
return;
}
size -= res;
str[res] = 0;
av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL);
}
avio_skip(s->pb, size);
}
/* Returns the number of sound data frames or negative on error */
static int get_aiff_header(AVFormatContext *s, int size,
unsigned version)
{
AVIOContext *pb = s->pb;
AVCodecParameters *par = s->streams[0]->codecpar;
AIFFInputContext *aiff = s->priv_data;
int exp;
uint64_t val;
int sample_rate;
unsigned int num_frames;
if (size & 1)
size++;
par->codec_type = AVMEDIA_TYPE_AUDIO;
par->channels = avio_rb16(pb);
num_frames = avio_rb32(pb);
par->bits_per_coded_sample = avio_rb16(pb);
exp = avio_rb16(pb) - 16383 - 63;
val = avio_rb64(pb);
if (exp <-63 || exp >63) {
av_log(s, AV_LOG_ERROR, "exp %d is out of range\n", exp);
return AVERROR_INVALIDDATA;
}
if (exp >= 0)
sample_rate = val << exp;
else
sample_rate = (val + (1ULL<<(-exp-1))) >> -exp;
par->sample_rate = sample_rate;
size -= 18;
/* get codec id for AIFF-C */
if (size < 4) {
version = AIFF;
} else if (version == AIFF_C_VERSION1) {
par->codec_tag = avio_rl32(pb);
par->codec_id = ff_codec_get_id(ff_codec_aiff_tags, par->codec_tag);
if (par->codec_id == AV_CODEC_ID_NONE)
avpriv_request_sample(s, "unknown or unsupported codec tag: %s",
av_fourcc2str(par->codec_tag));
size -= 4;
}
if (version != AIFF_C_VERSION1 || par->codec_id == AV_CODEC_ID_PCM_S16BE) {
par->codec_id = aiff_codec_get_id(par->bits_per_coded_sample);
par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
aiff->block_duration = 1;
} else {
switch (par->codec_id) {
case AV_CODEC_ID_PCM_F32BE:
case AV_CODEC_ID_PCM_F64BE:
case AV_CODEC_ID_PCM_S16LE:
case AV_CODEC_ID_PCM_ALAW:
case AV_CODEC_ID_PCM_MULAW:
aiff->block_duration = 1;
break;
case AV_CODEC_ID_ADPCM_IMA_QT:
par->block_align = 34 * par->channels;
break;
case AV_CODEC_ID_MACE3:
par->block_align = 2 * par->channels;
break;
case AV_CODEC_ID_ADPCM_G726LE:
par->bits_per_coded_sample = 5;
case AV_CODEC_ID_ADPCM_IMA_WS:
case AV_CODEC_ID_ADPCM_G722:
case AV_CODEC_ID_MACE6:
case AV_CODEC_ID_SDX2_DPCM:
par->block_align = 1 * par->channels;
break;
case AV_CODEC_ID_GSM:
par->block_align = 33;
break;
default:
aiff->block_duration = 1;
break;
}
if (par->block_align > 0)
aiff->block_duration = av_get_audio_frame_duration2(par,
par->block_align);
}
/* Block align needs to be computed in all cases, as the definition
* is specific to applications -> here we use the WAVE format definition */
if (!par->block_align)
par->block_align = (av_get_bits_per_sample(par->codec_id) * par->channels) >> 3;
if (aiff->block_duration) {
par->bit_rate = (int64_t)par->sample_rate * (par->block_align << 3) /
aiff->block_duration;
}
/* Chunk is over */
if (size)
avio_skip(pb, size);
return num_frames;
}
static int aiff_probe(const AVProbeData *p)
{
/* check file header */
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' &&
p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C'))
return AVPROBE_SCORE_MAX;
else
return 0;
}
/* aiff input */
static int aiff_read_header(AVFormatContext *s)
{
int ret, size, filesize;
int64_t offset = 0, position;
uint32_t tag;
unsigned version = AIFF_C_VERSION1;
AVIOContext *pb = s->pb;
AVStream * st;
AIFFInputContext *aiff = s->priv_data;
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
/* check FORM header */
filesize = get_tag(pb, &tag);
if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M'))
return AVERROR_INVALIDDATA;
/* AIFF data type */
tag = avio_rl32(pb);
if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */
version = AIFF;
else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */
return AVERROR_INVALIDDATA;
filesize -= 4;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
while (filesize > 0) {
/* parse different chunks */
size = get_tag(pb, &tag);
if (size == AVERROR_EOF && offset > 0 && st->codecpar->block_align) {
av_log(s, AV_LOG_WARNING, "header parser hit EOF\n");
goto got_sound;
}
if (size < 0)
return size;
if (size >= 0x7fffffff - 8)
filesize = 0;
else
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(s, size, version);
if (st->nb_frames < 0)
return st->nb_frames;
if (offset > 0) // COMM is after SSND
goto got_sound;
break;
case MKTAG('I', 'D', '3', ' '):
position = avio_tell(pb);
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size);
if (id3v2_extra_meta)
if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 ||
(ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) {
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
return ret;
}
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
if (position + size > avio_tell(pb))
avio_skip(pb, position + size - avio_tell(pb));
break;
case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
version = avio_rb32(pb);
break;
case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
get_meta(s, "title" , size);
break;
case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
get_meta(s, "author" , size);
break;
case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
get_meta(s, "copyright", size);
break;
case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
get_meta(s, "comment" , size);
break;
case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
aiff->data_end = avio_tell(pb) + size;
offset = avio_rb32(pb); /* Offset of sound data */
avio_rb32(pb); /* BlockSize... don't care */
offset += avio_tell(pb); /* Compute absolute data offset */
if (st->codecpar->block_align && !(pb->seekable & AVIO_SEEKABLE_NORMAL)) /* Assume COMM already parsed */
goto got_sound;
if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
av_log(s, AV_LOG_ERROR, "file is not seekable\n");
return -1;
}
avio_skip(pb, size - 8);
break;
case MKTAG('w', 'a', 'v', 'e'):
if ((uint64_t)size > (1<<30))
return -1;
if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0)
return ret;
if ( (st->codecpar->codec_id == AV_CODEC_ID_QDMC || st->codecpar->codec_id == AV_CODEC_ID_QDM2)
&& size>=12*4 && !st->codecpar->block_align) {
st->codecpar->block_align = AV_RB32(st->codecpar->extradata+11*4);
aiff->block_duration = AV_RB32(st->codecpar->extradata+9*4);
} else if (st->codecpar->codec_id == AV_CODEC_ID_QCELP) {
char rate = 0;
if (size >= 25)
rate = st->codecpar->extradata[24];
switch (rate) {
case 'H': // RATE_HALF
st->codecpar->block_align = 17;
break;
case 'F': // RATE_FULL
default:
st->codecpar->block_align = 35;
}
aiff->block_duration = 160;
st->codecpar->bit_rate = (int64_t)st->codecpar->sample_rate * (st->codecpar->block_align << 3) /
aiff->block_duration;
}
break;
case MKTAG('C','H','A','N'):
if ((ret = ff_mov_read_chan(s, pb, st, size)) < 0)
return ret;
break;
case MKTAG('A','P','C','M'): /* XA ADPCM compressed sound chunk */
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA;
aiff->data_end = avio_tell(pb) + size;
offset = avio_tell(pb) + 8;
/* This field is unknown and its data seems to be irrelevant */
avio_rb32(pb);
st->codecpar->block_align = avio_rb32(pb);
goto got_sound;
break;
case 0:
if (offset > 0 && st->codecpar->block_align) // COMM && SSND
goto got_sound;
default: /* Jump */
avio_skip(pb, size);
}
/* Skip required padding byte for odd-sized chunks. */
if (size & 1) {
filesize--;
avio_skip(pb, 1);
}
}
ret = ff_replaygain_export(st, s->metadata);
if (ret < 0)
return ret;
got_sound:
if (!st->codecpar->block_align && st->codecpar->codec_id == AV_CODEC_ID_QCELP) {
av_log(s, AV_LOG_WARNING, "qcelp without wave chunk, assuming full rate\n");
st->codecpar->block_align = 35;
} else if (!st->codecpar->block_align) {
av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n");
return -1;
}
/* Now positioned, get the sound data start and end */
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->start_time = 0;
st->duration = st->nb_frames * aiff->block_duration;
/* Position the stream at the first block */
avio_seek(pb, offset, SEEK_SET);
return 0;
}
#define MAX_SIZE 4096
static int aiff_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
AVStream *st = s->streams[0];
AIFFInputContext *aiff = s->priv_data;
int64_t max_size;
int res, size;
/* calculate size of remaining data */
max_size = aiff->data_end - avio_tell(s->pb);
if (max_size <= 0)
return AVERROR_EOF;
if (!st->codecpar->block_align) {
av_log(s, AV_LOG_ERROR, "block_align not set\n");
return AVERROR_INVALIDDATA;
}
/* Now for that packet */
switch (st->codecpar->codec_id) {
case AV_CODEC_ID_ADPCM_IMA_QT:
case AV_CODEC_ID_GSM:
case AV_CODEC_ID_QDM2:
case AV_CODEC_ID_QCELP:
size = st->codecpar->block_align;
break;
default:
size = st->codecpar->block_align ? (MAX_SIZE / st->codecpar->block_align) * st->codecpar->block_align : MAX_SIZE;
}
size = FFMIN(max_size, size);
res = av_get_packet(s->pb, pkt, size);
if (res < 0)
return res;
if (size >= st->codecpar->block_align)
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
/* Only one stream in an AIFF file */
pkt->stream_index = 0;
pkt->duration = (res / st->codecpar->block_align) * aiff->block_duration;
return 0;
}
AVInputFormat ff_aiff_demuxer = {
.name = "aiff",
.long_name = NULL_IF_CONFIG_SMALL("Audio IFF"),
.priv_data_size = sizeof(AIFFInputContext),
.read_probe = aiff_probe,
.read_header = aiff_read_header,
.read_packet = aiff_read_packet,
.read_seek = ff_pcm_read_seek,
.codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 },
};

309
externals/ffmpeg/libavformat/aiffenc.c vendored Executable file
View File

@@ -0,0 +1,309 @@
/*
* AIFF/AIFF-C muxer
* Copyright (c) 2006 Patrick Guimond
*
* 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 <stdint.h>
#include "libavutil/intfloat.h"
#include "libavutil/opt.h"
#include "avformat.h"
#include "internal.h"
#include "aiff.h"
#include "avio_internal.h"
#include "isom.h"
#include "id3v2.h"
typedef struct AIFFOutputContext {
const AVClass *class;
int64_t form;
int64_t frames;
int64_t ssnd;
int audio_stream_idx;
AVPacketList *pict_list, *pict_list_end;
int write_id3v2;
int id3v2_version;
} AIFFOutputContext;
static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff)
{
int ret;
uint64_t pos, end, size;
ID3v2EncContext id3v2 = { 0 };
AVIOContext *pb = s->pb;
AVPacketList *pict_list = aiff->pict_list;
if (!s->metadata && !s->nb_chapters && !aiff->pict_list)
return 0;
avio_wl32(pb, MKTAG('I', 'D', '3', ' '));
avio_wb32(pb, 0);
pos = avio_tell(pb);
ff_id3v2_start(&id3v2, pb, aiff->id3v2_version, ID3v2_DEFAULT_MAGIC);
ff_id3v2_write_metadata(s, &id3v2);
while (pict_list) {
if ((ret = ff_id3v2_write_apic(s, &id3v2, &pict_list->pkt)) < 0)
return ret;
pict_list = pict_list->next;
}
ff_id3v2_finish(&id3v2, pb, s->metadata_header_padding);
end = avio_tell(pb);
size = end - pos;
/* Update chunk size */
avio_seek(pb, pos - 4, SEEK_SET);
avio_wb32(pb, size);
avio_seek(pb, end, SEEK_SET);
if (size & 1)
avio_w8(pb, 0);
return 0;
}
static void put_meta(AVFormatContext *s, const char *key, uint32_t id)
{
AVDictionaryEntry *tag;
AVIOContext *pb = s->pb;
if (tag = av_dict_get(s->metadata, key, NULL, 0)) {
int size = strlen(tag->value);
avio_wl32(pb, id);
avio_wb32(pb, FFALIGN(size, 2));
avio_write(pb, tag->value, size);
if (size & 1)
avio_w8(pb, 0);
}
}
static int aiff_write_header(AVFormatContext *s)
{
AIFFOutputContext *aiff = s->priv_data;
AVIOContext *pb = s->pb;
AVCodecParameters *par;
uint64_t sample_rate;
int i, aifc = 0;
aiff->audio_stream_idx = -1;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
if (aiff->audio_stream_idx < 0 && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
aiff->audio_stream_idx = i;
} else if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
av_log(s, AV_LOG_ERROR, "AIFF allows only one audio stream and a picture.\n");
return AVERROR(EINVAL);
}
}
if (aiff->audio_stream_idx < 0) {
av_log(s, AV_LOG_ERROR, "No audio stream present.\n");
return AVERROR(EINVAL);
}
par = s->streams[aiff->audio_stream_idx]->codecpar;
/* First verify if format is ok */
if (!par->codec_tag)
return AVERROR(EINVAL);
if (par->codec_tag != MKTAG('N','O','N','E'))
aifc = 1;
/* FORM AIFF header */
ffio_wfourcc(pb, "FORM");
aiff->form = avio_tell(pb);
avio_wb32(pb, 0); /* file length */
ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF");
if (aifc) { // compressed audio
if (!par->block_align) {
av_log(s, AV_LOG_ERROR, "block align not set\n");
return AVERROR(EINVAL);
}
/* Version chunk */
ffio_wfourcc(pb, "FVER");
avio_wb32(pb, 4);
avio_wb32(pb, 0xA2805140);
}
if (par->channels > 2 && par->channel_layout) {
ffio_wfourcc(pb, "CHAN");
avio_wb32(pb, 12);
ff_mov_write_chan(pb, par->channel_layout);
}
put_meta(s, "title", MKTAG('N', 'A', 'M', 'E'));
put_meta(s, "author", MKTAG('A', 'U', 'T', 'H'));
put_meta(s, "copyright", MKTAG('(', 'c', ')', ' '));
put_meta(s, "comment", MKTAG('A', 'N', 'N', 'O'));
/* Common chunk */
ffio_wfourcc(pb, "COMM");
avio_wb32(pb, aifc ? 24 : 18); /* size */
avio_wb16(pb, par->channels); /* Number of channels */
aiff->frames = avio_tell(pb);
avio_wb32(pb, 0); /* Number of frames */
if (!par->bits_per_coded_sample)
par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
if (!par->bits_per_coded_sample) {
av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n");
return AVERROR(EINVAL);
}
if (!par->block_align)
par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */
sample_rate = av_double2int(par->sample_rate);
avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023));
avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11);
if (aifc) {
avio_wl32(pb, par->codec_tag);
avio_wb16(pb, 0);
}
if ( (par->codec_tag == MKTAG('Q','D','M','2')
|| par->codec_tag == MKTAG('Q','c','l','p')) && par->extradata_size) {
ffio_wfourcc(pb, "wave");
avio_wb32(pb, par->extradata_size);
avio_write(pb, par->extradata, par->extradata_size);
}
/* Sound data chunk */
ffio_wfourcc(pb, "SSND");
aiff->ssnd = avio_tell(pb); /* Sound chunk size */
avio_wb32(pb, 0); /* Sound samples data size */
avio_wb32(pb, 0); /* Data offset */
avio_wb32(pb, 0); /* Block-size (block align) */
avpriv_set_pts_info(s->streams[aiff->audio_stream_idx], 64, 1,
s->streams[aiff->audio_stream_idx]->codecpar->sample_rate);
return 0;
}
static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
{
AIFFOutputContext *aiff = s->priv_data;
AVIOContext *pb = s->pb;
if (pkt->stream_index == aiff->audio_stream_idx)
avio_write(pb, pkt->data, pkt->size);
else {
if (s->streams[pkt->stream_index]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
return 0;
/* warn only once for each stream */
if (s->streams[pkt->stream_index]->nb_frames == 1) {
av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
" ignoring.\n", pkt->stream_index);
}
if (s->streams[pkt->stream_index]->nb_frames >= 1)
return 0;
return ff_packet_list_put(&aiff->pict_list, &aiff->pict_list_end,
pkt, FF_PACKETLIST_FLAG_REF_PACKET);
}
return 0;
}
static int aiff_write_trailer(AVFormatContext *s)
{
int ret = 0;
AVIOContext *pb = s->pb;
AIFFOutputContext *aiff = s->priv_data;
AVCodecParameters *par = s->streams[aiff->audio_stream_idx]->codecpar;
/* Chunks sizes must be even */
int64_t file_size, end_size;
end_size = file_size = avio_tell(pb);
if (file_size & 1) {
avio_w8(pb, 0);
end_size++;
}
if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
/* Number of sample frames */
avio_seek(pb, aiff->frames, SEEK_SET);
avio_wb32(pb, (file_size - aiff->ssnd - 12) / par->block_align);
/* Sound Data chunk size */
avio_seek(pb, aiff->ssnd, SEEK_SET);
avio_wb32(pb, file_size - aiff->ssnd - 4);
/* return to the end */
avio_seek(pb, end_size, SEEK_SET);
/* Write ID3 tags */
if (aiff->write_id3v2)
if ((ret = put_id3v2_tags(s, aiff)) < 0)
return ret;
/* File length */
file_size = avio_tell(pb);
avio_seek(pb, aiff->form, SEEK_SET);
avio_wb32(pb, file_size - aiff->form - 4);
}
return ret;
}
static void aiff_deinit(AVFormatContext *s)
{
AIFFOutputContext *aiff = s->priv_data;
ff_packet_list_free(&aiff->pict_list, &aiff->pict_list_end);
}
#define OFFSET(x) offsetof(AIFFOutputContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "write_id3v2", "Enable ID3 tags writing.",
OFFSET(write_id3v2), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC },
{ "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.",
OFFSET(id3v2_version), AV_OPT_TYPE_INT, {.i64 = 4}, 3, 4, ENC },
{ NULL },
};
static const AVClass aiff_muxer_class = {
.class_name = "AIFF muxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVOutputFormat ff_aiff_muxer = {
.name = "aiff",
.long_name = NULL_IF_CONFIG_SMALL("Audio IFF"),
.mime_type = "audio/aiff",
.extensions = "aif,aiff,afc,aifc",
.priv_data_size = sizeof(AIFFOutputContext),
.audio_codec = AV_CODEC_ID_PCM_S16BE,
.video_codec = AV_CODEC_ID_PNG,
.write_header = aiff_write_header,
.write_packet = aiff_write_packet,
.write_trailer = aiff_write_trailer,
.deinit = aiff_deinit,
.codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 },
.priv_class = &aiff_muxer_class,
};

140
externals/ffmpeg/libavformat/aixdec.c vendored Executable file
View File

@@ -0,0 +1,140 @@
/*
* AIX demuxer
* Copyright (c) 2016 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
static int aix_probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) != MKTAG('A','I','X','F') ||
AV_RB32(p->buf + 8) != 0x01000014 ||
AV_RB32(p->buf + 12) != 0x00000800)
return 0;
return AVPROBE_SCORE_MAX;
}
static int aix_read_header(AVFormatContext *s)
{
unsigned nb_streams, first_offset, nb_segments;
unsigned stream_list_offset;
unsigned segment_list_offset = 0x20;
unsigned segment_list_entry_size = 0x10;
unsigned size;
int i;
avio_skip(s->pb, 4);
first_offset = avio_rb32(s->pb) + 8;
avio_skip(s->pb, 16);
nb_segments = avio_rb16(s->pb);
if (nb_segments == 0)
return AVERROR_INVALIDDATA;
stream_list_offset = segment_list_offset + segment_list_entry_size * nb_segments + 0x10;
if (stream_list_offset >= first_offset)
return AVERROR_INVALIDDATA;
avio_seek(s->pb, stream_list_offset, SEEK_SET);
nb_streams = avio_r8(s->pb);
if (nb_streams == 0)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 7);
for (i = 0; i < nb_streams; i++) {
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ADX;
st->codecpar->sample_rate = avio_rb32(s->pb);
st->codecpar->channels = avio_r8(s->pb);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
avio_skip(s->pb, 3);
}
avio_seek(s->pb, first_offset, SEEK_SET);
for (i = 0; i < nb_streams; i++) {
if (avio_rl32(s->pb) != MKTAG('A','I','X','P'))
return AVERROR_INVALIDDATA;
size = avio_rb32(s->pb);
if (size <= 8)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 8);
ff_get_extradata(s, s->streams[i]->codecpar, s->pb, size - 8);
}
return 0;
}
static int aix_read_packet(AVFormatContext *s, AVPacket *pkt)
{
unsigned size, index, duration, chunk;
int64_t pos;
int sequence, ret, i;
pos = avio_tell(s->pb);
if (avio_feof(s->pb))
return AVERROR_EOF;
chunk = avio_rl32(s->pb);
size = avio_rb32(s->pb);
if (chunk == MKTAG('A','I','X','E')) {
avio_skip(s->pb, size);
for (i = 0; i < s->nb_streams; i++) {
if (avio_feof(s->pb))
return AVERROR_EOF;
chunk = avio_rl32(s->pb);
size = avio_rb32(s->pb);
avio_skip(s->pb, size);
}
pos = avio_tell(s->pb);
chunk = avio_rl32(s->pb);
size = avio_rb32(s->pb);
}
if (chunk != MKTAG('A','I','X','P'))
return AVERROR_INVALIDDATA;
if (size <= 8)
return AVERROR_INVALIDDATA;
index = avio_r8(s->pb);
if (avio_r8(s->pb) != s->nb_streams || index >= s->nb_streams)
return AVERROR_INVALIDDATA;
duration = avio_rb16(s->pb);
sequence = avio_rb32(s->pb);
if (sequence < 0) {
avio_skip(s->pb, size - 8);
return 0;
}
ret = av_get_packet(s->pb, pkt, size - 8);
pkt->stream_index = index;
pkt->duration = duration;
pkt->pos = pos;
return ret;
}
AVInputFormat ff_aix_demuxer = {
.name = "aix",
.long_name = NULL_IF_CONFIG_SMALL("CRI AIX"),
.read_probe = aix_probe,
.read_header = aix_read_header,
.read_packet = aix_read_packet,
.extensions = "aix",
.flags = AVFMT_GENERIC_INDEX,
};

652
externals/ffmpeg/libavformat/allformats.c vendored Executable file
View File

@@ -0,0 +1,652 @@
/*
* 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
*/
#include "libavutil/thread.h"
#include "libavformat/internal.h"
#include "avformat.h"
#include "rtp.h"
#include "rdt.h"
#include "url.h"
#include "version.h"
/* (de)muxers */
extern AVOutputFormat ff_a64_muxer;
extern AVInputFormat ff_aa_demuxer;
extern AVInputFormat ff_aac_demuxer;
extern AVInputFormat ff_ac3_demuxer;
extern AVOutputFormat ff_ac3_muxer;
extern AVInputFormat ff_acm_demuxer;
extern AVInputFormat ff_act_demuxer;
extern AVInputFormat ff_adf_demuxer;
extern AVInputFormat ff_adp_demuxer;
extern AVInputFormat ff_ads_demuxer;
extern AVOutputFormat ff_adts_muxer;
extern AVInputFormat ff_adx_demuxer;
extern AVOutputFormat ff_adx_muxer;
extern AVInputFormat ff_aea_demuxer;
extern AVInputFormat ff_afc_demuxer;
extern AVInputFormat ff_aiff_demuxer;
extern AVOutputFormat ff_aiff_muxer;
extern AVInputFormat ff_aix_demuxer;
extern AVInputFormat ff_alp_demuxer;
extern AVInputFormat ff_amr_demuxer;
extern AVOutputFormat ff_amr_muxer;
extern AVInputFormat ff_amrnb_demuxer;
extern AVInputFormat ff_amrwb_demuxer;
extern AVInputFormat ff_anm_demuxer;
extern AVInputFormat ff_apc_demuxer;
extern AVInputFormat ff_ape_demuxer;
extern AVInputFormat ff_apm_demuxer;
extern AVInputFormat ff_apng_demuxer;
extern AVOutputFormat ff_apng_muxer;
extern AVInputFormat ff_aptx_demuxer;
extern AVOutputFormat ff_aptx_muxer;
extern AVInputFormat ff_aptx_hd_demuxer;
extern AVOutputFormat ff_aptx_hd_muxer;
extern AVInputFormat ff_aqtitle_demuxer;
extern AVInputFormat ff_argo_asf_demuxer;
extern AVInputFormat ff_asf_demuxer;
extern AVOutputFormat ff_asf_muxer;
extern AVInputFormat ff_asf_o_demuxer;
extern AVInputFormat ff_ass_demuxer;
extern AVOutputFormat ff_ass_muxer;
extern AVInputFormat ff_ast_demuxer;
extern AVOutputFormat ff_ast_muxer;
extern AVOutputFormat ff_asf_stream_muxer;
extern AVInputFormat ff_au_demuxer;
extern AVOutputFormat ff_au_muxer;
extern AVInputFormat ff_av1_demuxer;
extern AVInputFormat ff_avi_demuxer;
extern AVOutputFormat ff_avi_muxer;
extern AVInputFormat ff_avisynth_demuxer;
extern AVOutputFormat ff_avm2_muxer;
extern AVInputFormat ff_avr_demuxer;
extern AVInputFormat ff_avs_demuxer;
extern AVInputFormat ff_avs2_demuxer;
extern AVOutputFormat ff_avs2_muxer;
extern AVInputFormat ff_bethsoftvid_demuxer;
extern AVInputFormat ff_bfi_demuxer;
extern AVInputFormat ff_bintext_demuxer;
extern AVInputFormat ff_bink_demuxer;
extern AVInputFormat ff_bit_demuxer;
extern AVOutputFormat ff_bit_muxer;
extern AVInputFormat ff_bmv_demuxer;
extern AVInputFormat ff_bfstm_demuxer;
extern AVInputFormat ff_brstm_demuxer;
extern AVInputFormat ff_boa_demuxer;
extern AVInputFormat ff_c93_demuxer;
extern AVInputFormat ff_caf_demuxer;
extern AVOutputFormat ff_caf_muxer;
extern AVInputFormat ff_cavsvideo_demuxer;
extern AVOutputFormat ff_cavsvideo_muxer;
extern AVInputFormat ff_cdg_demuxer;
extern AVInputFormat ff_cdxl_demuxer;
extern AVInputFormat ff_cine_demuxer;
extern AVInputFormat ff_codec2_demuxer;
extern AVOutputFormat ff_codec2_muxer;
extern AVInputFormat ff_codec2raw_demuxer;
extern AVOutputFormat ff_codec2raw_muxer;
extern AVInputFormat ff_concat_demuxer;
extern AVOutputFormat ff_crc_muxer;
extern AVInputFormat ff_dash_demuxer;
extern AVOutputFormat ff_dash_muxer;
extern AVInputFormat ff_data_demuxer;
extern AVOutputFormat ff_data_muxer;
extern AVInputFormat ff_daud_demuxer;
extern AVOutputFormat ff_daud_muxer;
extern AVInputFormat ff_dcstr_demuxer;
extern AVInputFormat ff_derf_demuxer;
extern AVInputFormat ff_dfa_demuxer;
extern AVInputFormat ff_dhav_demuxer;
extern AVInputFormat ff_dirac_demuxer;
extern AVOutputFormat ff_dirac_muxer;
extern AVInputFormat ff_dnxhd_demuxer;
extern AVOutputFormat ff_dnxhd_muxer;
extern AVInputFormat ff_dsf_demuxer;
extern AVInputFormat ff_dsicin_demuxer;
extern AVInputFormat ff_dss_demuxer;
extern AVInputFormat ff_dts_demuxer;
extern AVOutputFormat ff_dts_muxer;
extern AVInputFormat ff_dtshd_demuxer;
extern AVInputFormat ff_dv_demuxer;
extern AVOutputFormat ff_dv_muxer;
extern AVInputFormat ff_dvbsub_demuxer;
extern AVInputFormat ff_dvbtxt_demuxer;
extern AVInputFormat ff_dxa_demuxer;
extern AVInputFormat ff_ea_demuxer;
extern AVInputFormat ff_ea_cdata_demuxer;
extern AVInputFormat ff_eac3_demuxer;
extern AVOutputFormat ff_eac3_muxer;
extern AVInputFormat ff_epaf_demuxer;
extern AVOutputFormat ff_f4v_muxer;
extern AVInputFormat ff_ffmetadata_demuxer;
extern AVOutputFormat ff_ffmetadata_muxer;
extern AVOutputFormat ff_fifo_muxer;
extern AVOutputFormat ff_fifo_test_muxer;
extern AVInputFormat ff_filmstrip_demuxer;
extern AVOutputFormat ff_filmstrip_muxer;
extern AVInputFormat ff_fits_demuxer;
extern AVOutputFormat ff_fits_muxer;
extern AVInputFormat ff_flac_demuxer;
extern AVOutputFormat ff_flac_muxer;
extern AVInputFormat ff_flic_demuxer;
extern AVInputFormat ff_flv_demuxer;
extern AVOutputFormat ff_flv_muxer;
extern AVInputFormat ff_live_flv_demuxer;
extern AVInputFormat ff_fourxm_demuxer;
extern AVOutputFormat ff_framecrc_muxer;
extern AVOutputFormat ff_framehash_muxer;
extern AVOutputFormat ff_framemd5_muxer;
extern AVInputFormat ff_frm_demuxer;
extern AVInputFormat ff_fsb_demuxer;
extern AVInputFormat ff_fwse_demuxer;
extern AVInputFormat ff_g722_demuxer;
extern AVOutputFormat ff_g722_muxer;
extern AVInputFormat ff_g723_1_demuxer;
extern AVOutputFormat ff_g723_1_muxer;
extern AVInputFormat ff_g726_demuxer;
extern AVOutputFormat ff_g726_muxer;
extern AVInputFormat ff_g726le_demuxer;
extern AVOutputFormat ff_g726le_muxer;
extern AVInputFormat ff_g729_demuxer;
extern AVInputFormat ff_gdv_demuxer;
extern AVInputFormat ff_genh_demuxer;
extern AVInputFormat ff_gif_demuxer;
extern AVOutputFormat ff_gif_muxer;
extern AVInputFormat ff_gsm_demuxer;
extern AVOutputFormat ff_gsm_muxer;
extern AVInputFormat ff_gxf_demuxer;
extern AVOutputFormat ff_gxf_muxer;
extern AVInputFormat ff_h261_demuxer;
extern AVOutputFormat ff_h261_muxer;
extern AVInputFormat ff_h263_demuxer;
extern AVOutputFormat ff_h263_muxer;
extern AVInputFormat ff_h264_demuxer;
extern AVOutputFormat ff_h264_muxer;
extern AVOutputFormat ff_hash_muxer;
extern AVInputFormat ff_hca_demuxer;
extern AVInputFormat ff_hcom_demuxer;
extern AVOutputFormat ff_hds_muxer;
extern AVInputFormat ff_hevc_demuxer;
extern AVOutputFormat ff_hevc_muxer;
extern AVInputFormat ff_hls_demuxer;
extern AVOutputFormat ff_hls_muxer;
extern AVInputFormat ff_hnm_demuxer;
extern AVInputFormat ff_ico_demuxer;
extern AVOutputFormat ff_ico_muxer;
extern AVInputFormat ff_idcin_demuxer;
extern AVInputFormat ff_idf_demuxer;
extern AVInputFormat ff_iff_demuxer;
extern AVInputFormat ff_ifv_demuxer;
extern AVInputFormat ff_ilbc_demuxer;
extern AVOutputFormat ff_ilbc_muxer;
extern AVInputFormat ff_image2_demuxer;
extern AVOutputFormat ff_image2_muxer;
extern AVInputFormat ff_image2pipe_demuxer;
extern AVOutputFormat ff_image2pipe_muxer;
extern AVInputFormat ff_image2_alias_pix_demuxer;
extern AVInputFormat ff_image2_brender_pix_demuxer;
extern AVInputFormat ff_ingenient_demuxer;
extern AVInputFormat ff_ipmovie_demuxer;
extern AVOutputFormat ff_ipod_muxer;
extern AVInputFormat ff_ircam_demuxer;
extern AVOutputFormat ff_ircam_muxer;
extern AVOutputFormat ff_ismv_muxer;
extern AVInputFormat ff_iss_demuxer;
extern AVInputFormat ff_iv8_demuxer;
extern AVInputFormat ff_ivf_demuxer;
extern AVOutputFormat ff_ivf_muxer;
extern AVInputFormat ff_ivr_demuxer;
extern AVInputFormat ff_jacosub_demuxer;
extern AVOutputFormat ff_jacosub_muxer;
extern AVInputFormat ff_jv_demuxer;
extern AVInputFormat ff_kux_demuxer;
extern AVInputFormat ff_kvag_demuxer;
extern AVOutputFormat ff_kvag_muxer;
extern AVOutputFormat ff_latm_muxer;
extern AVInputFormat ff_lmlm4_demuxer;
extern AVInputFormat ff_loas_demuxer;
extern AVInputFormat ff_lrc_demuxer;
extern AVOutputFormat ff_lrc_muxer;
extern AVInputFormat ff_lvf_demuxer;
extern AVInputFormat ff_lxf_demuxer;
extern AVInputFormat ff_m4v_demuxer;
extern AVOutputFormat ff_m4v_muxer;
extern AVOutputFormat ff_md5_muxer;
extern AVInputFormat ff_matroska_demuxer;
extern AVOutputFormat ff_matroska_muxer;
extern AVOutputFormat ff_matroska_audio_muxer;
extern AVInputFormat ff_mgsts_demuxer;
extern AVInputFormat ff_microdvd_demuxer;
extern AVOutputFormat ff_microdvd_muxer;
extern AVInputFormat ff_mjpeg_demuxer;
extern AVOutputFormat ff_mjpeg_muxer;
extern AVInputFormat ff_mjpeg_2000_demuxer;
extern AVInputFormat ff_mlp_demuxer;
extern AVOutputFormat ff_mlp_muxer;
extern AVInputFormat ff_mlv_demuxer;
extern AVInputFormat ff_mm_demuxer;
extern AVInputFormat ff_mmf_demuxer;
extern AVOutputFormat ff_mmf_muxer;
extern AVInputFormat ff_mov_demuxer;
extern AVOutputFormat ff_mov_muxer;
extern AVOutputFormat ff_mp2_muxer;
extern AVInputFormat ff_mp3_demuxer;
extern AVOutputFormat ff_mp3_muxer;
extern AVOutputFormat ff_mp4_muxer;
extern AVInputFormat ff_mpc_demuxer;
extern AVInputFormat ff_mpc8_demuxer;
extern AVOutputFormat ff_mpeg1system_muxer;
extern AVOutputFormat ff_mpeg1vcd_muxer;
extern AVOutputFormat ff_mpeg1video_muxer;
extern AVOutputFormat ff_mpeg2dvd_muxer;
extern AVOutputFormat ff_mpeg2svcd_muxer;
extern AVOutputFormat ff_mpeg2video_muxer;
extern AVOutputFormat ff_mpeg2vob_muxer;
extern AVInputFormat ff_mpegps_demuxer;
extern AVInputFormat ff_mpegts_demuxer;
extern AVOutputFormat ff_mpegts_muxer;
extern AVInputFormat ff_mpegtsraw_demuxer;
extern AVInputFormat ff_mpegvideo_demuxer;
extern AVInputFormat ff_mpjpeg_demuxer;
extern AVOutputFormat ff_mpjpeg_muxer;
extern AVInputFormat ff_mpl2_demuxer;
extern AVInputFormat ff_mpsub_demuxer;
extern AVInputFormat ff_msf_demuxer;
extern AVInputFormat ff_msnwc_tcp_demuxer;
extern AVInputFormat ff_mtaf_demuxer;
extern AVInputFormat ff_mtv_demuxer;
extern AVInputFormat ff_musx_demuxer;
extern AVInputFormat ff_mv_demuxer;
extern AVInputFormat ff_mvi_demuxer;
extern AVInputFormat ff_mxf_demuxer;
extern AVOutputFormat ff_mxf_muxer;
extern AVOutputFormat ff_mxf_d10_muxer;
extern AVOutputFormat ff_mxf_opatom_muxer;
extern AVInputFormat ff_mxg_demuxer;
extern AVInputFormat ff_nc_demuxer;
extern AVInputFormat ff_nistsphere_demuxer;
extern AVInputFormat ff_nsp_demuxer;
extern AVInputFormat ff_nsv_demuxer;
extern AVOutputFormat ff_null_muxer;
extern AVInputFormat ff_nut_demuxer;
extern AVOutputFormat ff_nut_muxer;
extern AVInputFormat ff_nuv_demuxer;
extern AVOutputFormat ff_oga_muxer;
extern AVInputFormat ff_ogg_demuxer;
extern AVOutputFormat ff_ogg_muxer;
extern AVOutputFormat ff_ogv_muxer;
extern AVInputFormat ff_oma_demuxer;
extern AVOutputFormat ff_oma_muxer;
extern AVOutputFormat ff_opus_muxer;
extern AVInputFormat ff_paf_demuxer;
extern AVInputFormat ff_pcm_alaw_demuxer;
extern AVOutputFormat ff_pcm_alaw_muxer;
extern AVInputFormat ff_pcm_mulaw_demuxer;
extern AVOutputFormat ff_pcm_mulaw_muxer;
extern AVInputFormat ff_pcm_vidc_demuxer;
extern AVOutputFormat ff_pcm_vidc_muxer;
extern AVInputFormat ff_pcm_f64be_demuxer;
extern AVOutputFormat ff_pcm_f64be_muxer;
extern AVInputFormat ff_pcm_f64le_demuxer;
extern AVOutputFormat ff_pcm_f64le_muxer;
extern AVInputFormat ff_pcm_f32be_demuxer;
extern AVOutputFormat ff_pcm_f32be_muxer;
extern AVInputFormat ff_pcm_f32le_demuxer;
extern AVOutputFormat ff_pcm_f32le_muxer;
extern AVInputFormat ff_pcm_s32be_demuxer;
extern AVOutputFormat ff_pcm_s32be_muxer;
extern AVInputFormat ff_pcm_s32le_demuxer;
extern AVOutputFormat ff_pcm_s32le_muxer;
extern AVInputFormat ff_pcm_s24be_demuxer;
extern AVOutputFormat ff_pcm_s24be_muxer;
extern AVInputFormat ff_pcm_s24le_demuxer;
extern AVOutputFormat ff_pcm_s24le_muxer;
extern AVInputFormat ff_pcm_s16be_demuxer;
extern AVOutputFormat ff_pcm_s16be_muxer;
extern AVInputFormat ff_pcm_s16le_demuxer;
extern AVOutputFormat ff_pcm_s16le_muxer;
extern AVInputFormat ff_pcm_s8_demuxer;
extern AVOutputFormat ff_pcm_s8_muxer;
extern AVInputFormat ff_pcm_u32be_demuxer;
extern AVOutputFormat ff_pcm_u32be_muxer;
extern AVInputFormat ff_pcm_u32le_demuxer;
extern AVOutputFormat ff_pcm_u32le_muxer;
extern AVInputFormat ff_pcm_u24be_demuxer;
extern AVOutputFormat ff_pcm_u24be_muxer;
extern AVInputFormat ff_pcm_u24le_demuxer;
extern AVOutputFormat ff_pcm_u24le_muxer;
extern AVInputFormat ff_pcm_u16be_demuxer;
extern AVOutputFormat ff_pcm_u16be_muxer;
extern AVInputFormat ff_pcm_u16le_demuxer;
extern AVOutputFormat ff_pcm_u16le_muxer;
extern AVInputFormat ff_pcm_u8_demuxer;
extern AVOutputFormat ff_pcm_u8_muxer;
extern AVInputFormat ff_pjs_demuxer;
extern AVInputFormat ff_pmp_demuxer;
extern AVInputFormat ff_pp_bnk_demuxer;
extern AVOutputFormat ff_psp_muxer;
extern AVInputFormat ff_pva_demuxer;
extern AVInputFormat ff_pvf_demuxer;
extern AVInputFormat ff_qcp_demuxer;
extern AVInputFormat ff_r3d_demuxer;
extern AVInputFormat ff_rawvideo_demuxer;
extern AVOutputFormat ff_rawvideo_muxer;
extern AVInputFormat ff_realtext_demuxer;
extern AVInputFormat ff_redspark_demuxer;
extern AVInputFormat ff_rl2_demuxer;
extern AVInputFormat ff_rm_demuxer;
extern AVOutputFormat ff_rm_muxer;
extern AVInputFormat ff_roq_demuxer;
extern AVOutputFormat ff_roq_muxer;
extern AVInputFormat ff_rpl_demuxer;
extern AVInputFormat ff_rsd_demuxer;
extern AVInputFormat ff_rso_demuxer;
extern AVOutputFormat ff_rso_muxer;
extern AVInputFormat ff_rtp_demuxer;
extern AVOutputFormat ff_rtp_muxer;
extern AVOutputFormat ff_rtp_mpegts_muxer;
extern AVInputFormat ff_rtsp_demuxer;
extern AVOutputFormat ff_rtsp_muxer;
extern AVInputFormat ff_s337m_demuxer;
extern AVInputFormat ff_sami_demuxer;
extern AVInputFormat ff_sap_demuxer;
extern AVOutputFormat ff_sap_muxer;
extern AVInputFormat ff_sbc_demuxer;
extern AVOutputFormat ff_sbc_muxer;
extern AVInputFormat ff_sbg_demuxer;
extern AVInputFormat ff_scc_demuxer;
extern AVOutputFormat ff_scc_muxer;
extern AVInputFormat ff_sdp_demuxer;
extern AVInputFormat ff_sdr2_demuxer;
extern AVInputFormat ff_sds_demuxer;
extern AVInputFormat ff_sdx_demuxer;
extern AVInputFormat ff_segafilm_demuxer;
extern AVOutputFormat ff_segafilm_muxer;
extern AVOutputFormat ff_segment_muxer;
extern AVOutputFormat ff_stream_segment_muxer;
extern AVInputFormat ff_ser_demuxer;
extern AVInputFormat ff_shorten_demuxer;
extern AVInputFormat ff_siff_demuxer;
extern AVOutputFormat ff_singlejpeg_muxer;
extern AVInputFormat ff_sln_demuxer;
extern AVInputFormat ff_smacker_demuxer;
extern AVInputFormat ff_smjpeg_demuxer;
extern AVOutputFormat ff_smjpeg_muxer;
extern AVOutputFormat ff_smoothstreaming_muxer;
extern AVInputFormat ff_smush_demuxer;
extern AVInputFormat ff_sol_demuxer;
extern AVInputFormat ff_sox_demuxer;
extern AVOutputFormat ff_sox_muxer;
extern AVOutputFormat ff_spx_muxer;
extern AVInputFormat ff_spdif_demuxer;
extern AVOutputFormat ff_spdif_muxer;
extern AVInputFormat ff_srt_demuxer;
extern AVOutputFormat ff_srt_muxer;
extern AVInputFormat ff_str_demuxer;
extern AVInputFormat ff_stl_demuxer;
extern AVOutputFormat ff_streamhash_muxer;
extern AVInputFormat ff_subviewer1_demuxer;
extern AVInputFormat ff_subviewer_demuxer;
extern AVInputFormat ff_sup_demuxer;
extern AVOutputFormat ff_sup_muxer;
extern AVInputFormat ff_svag_demuxer;
extern AVInputFormat ff_swf_demuxer;
extern AVOutputFormat ff_swf_muxer;
extern AVInputFormat ff_tak_demuxer;
extern AVOutputFormat ff_tee_muxer;
extern AVInputFormat ff_tedcaptions_demuxer;
extern AVOutputFormat ff_tg2_muxer;
extern AVOutputFormat ff_tgp_muxer;
extern AVInputFormat ff_thp_demuxer;
extern AVInputFormat ff_threedostr_demuxer;
extern AVInputFormat ff_tiertexseq_demuxer;
extern AVOutputFormat ff_mkvtimestamp_v2_muxer;
extern AVInputFormat ff_tmv_demuxer;
extern AVInputFormat ff_truehd_demuxer;
extern AVOutputFormat ff_truehd_muxer;
extern AVInputFormat ff_tta_demuxer;
extern AVOutputFormat ff_tta_muxer;
extern AVInputFormat ff_txd_demuxer;
extern AVInputFormat ff_tty_demuxer;
extern AVInputFormat ff_ty_demuxer;
extern AVOutputFormat ff_uncodedframecrc_muxer;
extern AVInputFormat ff_v210_demuxer;
extern AVInputFormat ff_v210x_demuxer;
extern AVInputFormat ff_vag_demuxer;
extern AVInputFormat ff_vc1_demuxer;
extern AVOutputFormat ff_vc1_muxer;
extern AVInputFormat ff_vc1t_demuxer;
extern AVOutputFormat ff_vc1t_muxer;
extern AVInputFormat ff_vividas_demuxer;
extern AVInputFormat ff_vivo_demuxer;
extern AVInputFormat ff_vmd_demuxer;
extern AVInputFormat ff_vobsub_demuxer;
extern AVInputFormat ff_voc_demuxer;
extern AVOutputFormat ff_voc_muxer;
extern AVInputFormat ff_vpk_demuxer;
extern AVInputFormat ff_vplayer_demuxer;
extern AVInputFormat ff_vqf_demuxer;
extern AVInputFormat ff_w64_demuxer;
extern AVOutputFormat ff_w64_muxer;
extern AVInputFormat ff_wav_demuxer;
extern AVOutputFormat ff_wav_muxer;
extern AVInputFormat ff_wc3_demuxer;
extern AVOutputFormat ff_webm_muxer;
extern AVInputFormat ff_webm_dash_manifest_demuxer;
extern AVOutputFormat ff_webm_dash_manifest_muxer;
extern AVOutputFormat ff_webm_chunk_muxer;
extern AVOutputFormat ff_webp_muxer;
extern AVInputFormat ff_webvtt_demuxer;
extern AVOutputFormat ff_webvtt_muxer;
extern AVInputFormat ff_wsaud_demuxer;
extern AVInputFormat ff_wsd_demuxer;
extern AVInputFormat ff_wsvqa_demuxer;
extern AVInputFormat ff_wtv_demuxer;
extern AVOutputFormat ff_wtv_muxer;
extern AVInputFormat ff_wve_demuxer;
extern AVInputFormat ff_wv_demuxer;
extern AVOutputFormat ff_wv_muxer;
extern AVInputFormat ff_xa_demuxer;
extern AVInputFormat ff_xbin_demuxer;
extern AVInputFormat ff_xmv_demuxer;
extern AVInputFormat ff_xvag_demuxer;
extern AVInputFormat ff_xwma_demuxer;
extern AVInputFormat ff_yop_demuxer;
extern AVInputFormat ff_yuv4mpegpipe_demuxer;
extern AVOutputFormat ff_yuv4mpegpipe_muxer;
/* image demuxers */
extern AVInputFormat ff_image_bmp_pipe_demuxer;
extern AVInputFormat ff_image_dds_pipe_demuxer;
extern AVInputFormat ff_image_dpx_pipe_demuxer;
extern AVInputFormat ff_image_exr_pipe_demuxer;
extern AVInputFormat ff_image_gif_pipe_demuxer;
extern AVInputFormat ff_image_j2k_pipe_demuxer;
extern AVInputFormat ff_image_jpeg_pipe_demuxer;
extern AVInputFormat ff_image_jpegls_pipe_demuxer;
extern AVInputFormat ff_image_pam_pipe_demuxer;
extern AVInputFormat ff_image_pbm_pipe_demuxer;
extern AVInputFormat ff_image_pcx_pipe_demuxer;
extern AVInputFormat ff_image_pgmyuv_pipe_demuxer;
extern AVInputFormat ff_image_pgm_pipe_demuxer;
extern AVInputFormat ff_image_pictor_pipe_demuxer;
extern AVInputFormat ff_image_png_pipe_demuxer;
extern AVInputFormat ff_image_ppm_pipe_demuxer;
extern AVInputFormat ff_image_psd_pipe_demuxer;
extern AVInputFormat ff_image_qdraw_pipe_demuxer;
extern AVInputFormat ff_image_sgi_pipe_demuxer;
extern AVInputFormat ff_image_svg_pipe_demuxer;
extern AVInputFormat ff_image_sunrast_pipe_demuxer;
extern AVInputFormat ff_image_tiff_pipe_demuxer;
extern AVInputFormat ff_image_webp_pipe_demuxer;
extern AVInputFormat ff_image_xpm_pipe_demuxer;
extern AVInputFormat ff_image_xwd_pipe_demuxer;
/* external libraries */
extern AVOutputFormat ff_chromaprint_muxer;
extern AVInputFormat ff_libgme_demuxer;
extern AVInputFormat ff_libmodplug_demuxer;
extern AVInputFormat ff_libopenmpt_demuxer;
extern AVInputFormat ff_vapoursynth_demuxer;
#include "libavformat/muxer_list.c"
#include "libavformat/demuxer_list.c"
static const AVInputFormat * const *indev_list = NULL;
static const AVOutputFormat * const *outdev_list = NULL;
const AVOutputFormat *av_muxer_iterate(void **opaque)
{
static const uintptr_t size = sizeof(muxer_list)/sizeof(muxer_list[0]) - 1;
uintptr_t i = (uintptr_t)*opaque;
const AVOutputFormat *f = NULL;
if (i < size) {
f = muxer_list[i];
} else if (indev_list) {
f = outdev_list[i - size];
}
if (f)
*opaque = (void*)(i + 1);
return f;
}
const AVInputFormat *av_demuxer_iterate(void **opaque)
{
static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;
uintptr_t i = (uintptr_t)*opaque;
const AVInputFormat *f = NULL;
if (i < size) {
f = demuxer_list[i];
} else if (outdev_list) {
f = indev_list[i - size];
}
if (f)
*opaque = (void*)(i + 1);
return f;
}
static AVMutex avpriv_register_devices_mutex = AV_MUTEX_INITIALIZER;
#if FF_API_NEXT
FF_DISABLE_DEPRECATION_WARNINGS
static AVOnce av_format_next_init = AV_ONCE_INIT;
static void av_format_init_next(void)
{
AVOutputFormat *prevout = NULL, *out;
AVInputFormat *previn = NULL, *in;
ff_mutex_lock(&avpriv_register_devices_mutex);
for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) {
if (prevout)
prevout->next = out;
prevout = out;
}
if (outdev_list) {
for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) {
if (prevout)
prevout->next = out;
prevout = out;
}
}
for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) {
if (previn)
previn->next = in;
previn = in;
}
if (indev_list) {
for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) {
if (previn)
previn->next = in;
previn = in;
}
}
ff_mutex_unlock(&avpriv_register_devices_mutex);
}
AVInputFormat *av_iformat_next(const AVInputFormat *f)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
if (f)
#if FF_API_AVIOFORMAT
return f->next;
#else
return (AVInputFormat *) f->next;
#endif
else {
void *opaque = NULL;
return (AVInputFormat *)av_demuxer_iterate(&opaque);
}
}
AVOutputFormat *av_oformat_next(const AVOutputFormat *f)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
if (f)
#if FF_API_AVIOFORMAT
return f->next;
#else
return (AVOutputFormat *) f->next;
#endif
else {
void *opaque = NULL;
return (AVOutputFormat *)av_muxer_iterate(&opaque);
}
}
void av_register_all(void)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
void av_register_input_format(AVInputFormat *format)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
void av_register_output_format(AVOutputFormat *format)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[])
{
ff_mutex_lock(&avpriv_register_devices_mutex);
outdev_list = o;
indev_list = i;
ff_mutex_unlock(&avpriv_register_devices_mutex);
#if FF_API_NEXT
av_format_init_next();
#endif
}

146
externals/ffmpeg/libavformat/alp.c vendored Executable file
View File

@@ -0,0 +1,146 @@
/*
* LEGO Racers ALP (.tun & .pcm) demuxer
*
* Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.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 "internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/internal.h"
#define ALP_TAG MKTAG('A', 'L', 'P', ' ')
#define ALP_MAX_READ_SIZE 4096
typedef struct ALPHeader {
uint32_t magic; /*< Magic Number, {'A', 'L', 'P', ' '} */
uint32_t header_size; /*< Header size (after this). */
char adpcm[6]; /*< "ADPCM" */
uint8_t unk1; /*< Unknown */
uint8_t num_channels; /*< Channel Count. */
uint32_t sample_rate; /*< Sample rate, only if header_size >= 12. */
} ALPHeader;
static int alp_probe(const AVProbeData *p)
{
uint32_t i;
if (AV_RL32(p->buf) != ALP_TAG)
return 0;
/* Only allowed header sizes are 8 and 12. */
i = AV_RL32(p->buf + 4);
if (i != 8 && i != 12)
return 0;
if (strncmp("ADPCM", p->buf + 8, 6) != 0)
return 0;
return AVPROBE_SCORE_MAX - 1;
}
static int alp_read_header(AVFormatContext *s)
{
int ret;
AVStream *st;
ALPHeader hdr;
AVCodecParameters *par;
if ((hdr.magic = avio_rl32(s->pb)) != ALP_TAG)
return AVERROR_INVALIDDATA;
hdr.header_size = avio_rl32(s->pb);
if (hdr.header_size != 8 && hdr.header_size != 12) {
return AVERROR_INVALIDDATA;
}
if ((ret = avio_read(s->pb, hdr.adpcm, sizeof(hdr.adpcm))) < 0)
return ret;
else if (ret != sizeof(hdr.adpcm))
return AVERROR(EIO);
if (strncmp("ADPCM", hdr.adpcm, sizeof(hdr.adpcm)) != 0)
return AVERROR_INVALIDDATA;
hdr.unk1 = avio_r8(s->pb);
hdr.num_channels = avio_r8(s->pb);
if (hdr.header_size == 8) {
/* .TUN music file */
hdr.sample_rate = 11025 * hdr.num_channels;
} else {
/* .PCM sound file */
hdr.sample_rate = avio_rl32(s->pb);
}
if (hdr.sample_rate > 44100) {
avpriv_request_sample(s, "Sample Rate > 44100");
return AVERROR_PATCHWELCOME;
}
if (!(st = avformat_new_stream(s, NULL)))
return AVERROR(ENOMEM);
par = st->codecpar;
par->codec_type = AVMEDIA_TYPE_AUDIO;
par->codec_id = AV_CODEC_ID_ADPCM_IMA_ALP;
par->format = AV_SAMPLE_FMT_S16;
par->sample_rate = hdr.sample_rate;
par->channels = hdr.num_channels;
if (hdr.num_channels == 1)
par->channel_layout = AV_CH_LAYOUT_MONO;
else if (hdr.num_channels == 2)
par->channel_layout = AV_CH_LAYOUT_STEREO;
else
return AVERROR_INVALIDDATA;
par->bits_per_coded_sample = 4;
par->bits_per_raw_sample = 16;
par->block_align = 1;
par->bit_rate = par->channels *
par->sample_rate *
par->bits_per_coded_sample;
avpriv_set_pts_info(st, 64, 1, par->sample_rate);
return 0;
}
static int alp_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret;
AVCodecParameters *par = s->streams[0]->codecpar;
if ((ret = av_get_packet(s->pb, pkt, ALP_MAX_READ_SIZE)) < 0)
return ret;
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
pkt->stream_index = 0;
pkt->duration = ret * 2 / par->channels;
return 0;
}
AVInputFormat ff_alp_demuxer = {
.name = "alp",
.long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"),
.read_probe = alp_probe,
.read_header = alp_read_header,
.read_packet = alp_read_packet
};

297
externals/ffmpeg/libavformat/amr.c vendored Executable file
View File

@@ -0,0 +1,297 @@
/*
* amr file format
* Copyright (c) 2001 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
*/
/*
Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
Only mono files are supported.
*/
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
#include "rawenc.h"
typedef struct {
uint64_t cumulated_size;
uint64_t block_count;
} AMRContext;
static const char AMR_header[] = "#!AMR\n";
static const char AMRWB_header[] = "#!AMR-WB\n";
static const uint8_t amrnb_packed_size[16] = {
13, 14, 16, 18, 20, 21, 27, 32, 6, 1, 1, 1, 1, 1, 1, 1
};
static const uint8_t amrwb_packed_size[16] = {
18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 1, 1, 1, 1, 1, 1
};
#if CONFIG_AMR_MUXER
static int amr_write_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AVCodecParameters *par = s->streams[0]->codecpar;
s->priv_data = NULL;
if (par->codec_id == AV_CODEC_ID_AMR_NB) {
avio_write(pb, AMR_header, sizeof(AMR_header) - 1); /* magic number */
} else if (par->codec_id == AV_CODEC_ID_AMR_WB) {
avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */
} else {
return -1;
}
return 0;
}
#endif /* CONFIG_AMR_MUXER */
static int amr_probe(const AVProbeData *p)
{
// Only check for "#!AMR" which could be amr-wb, amr-nb.
// This will also trigger multichannel files: "#!AMR_MC1.0\n" and
// "#!AMR-WB_MC1.0\n" (not supported)
if (!memcmp(p->buf, AMR_header, 5))
return AVPROBE_SCORE_MAX;
else
return 0;
}
/* amr input */
static int amr_read_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AVStream *st;
uint8_t header[9];
if (avio_read(pb, header, 6) != 6)
return AVERROR_INVALIDDATA;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
if (memcmp(header, AMR_header, 6)) {
if (avio_read(pb, header + 6, 3) != 3)
return AVERROR_INVALIDDATA;
if (memcmp(header, AMRWB_header, 9)) {
return -1;
}
st->codecpar->codec_tag = MKTAG('s', 'a', 'w', 'b');
st->codecpar->codec_id = AV_CODEC_ID_AMR_WB;
st->codecpar->sample_rate = 16000;
} else {
st->codecpar->codec_tag = MKTAG('s', 'a', 'm', 'r');
st->codecpar->codec_id = AV_CODEC_ID_AMR_NB;
st->codecpar->sample_rate = 8000;
}
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVCodecParameters *par = s->streams[0]->codecpar;
int read, size = 0, toc, mode;
int64_t pos = avio_tell(s->pb);
AMRContext *amr = s->priv_data;
if (avio_feof(s->pb)) {
return AVERROR_EOF;
}
// FIXME this is wrong, this should rather be in an AVParser
toc = avio_r8(s->pb);
mode = (toc >> 3) & 0x0F;
if (par->codec_id == AV_CODEC_ID_AMR_NB) {
size = amrnb_packed_size[mode];
} else if (par->codec_id == AV_CODEC_ID_AMR_WB) {
size = amrwb_packed_size[mode];
}
if (!size || av_new_packet(pkt, size))
return AVERROR(EIO);
if (amr->cumulated_size < UINT64_MAX - size) {
amr->cumulated_size += size;
/* Both AMR formats have 50 frames per second */
s->streams[0]->codecpar->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50;
}
pkt->stream_index = 0;
pkt->pos = pos;
pkt->data[0] = toc;
pkt->duration = par->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320;
read = avio_read(s->pb, pkt->data + 1, size - 1);
if (read != size - 1) {
if (read < 0)
return read;
return AVERROR(EIO);
}
return 0;
}
#if CONFIG_AMR_DEMUXER
AVInputFormat ff_amr_demuxer = {
.name = "amr",
.long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"),
.priv_data_size = sizeof(AMRContext),
.read_probe = amr_probe,
.read_header = amr_read_header,
.read_packet = amr_read_packet,
.flags = AVFMT_GENERIC_INDEX,
};
#endif
#if CONFIG_AMRNB_DEMUXER
static int amrnb_probe(const AVProbeData *p)
{
int mode, i = 0, valid = 0, invalid = 0;
const uint8_t *b = p->buf;
while (i < p->buf_size) {
mode = b[i] >> 3 & 0x0F;
if (mode < 9 && (b[i] & 0x4) == 0x4) {
int last = b[i];
int size = amrnb_packed_size[mode];
while (size--) {
if (b[++i] != last)
break;
}
if (size > 0) {
valid++;
i += size;
}
} else {
valid = 0;
invalid++;
i++;
}
}
if (valid > 100 && valid >> 4 > invalid)
return AVPROBE_SCORE_EXTENSION / 2 + 1;
return 0;
}
static int amrnb_read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_AMR_NB;
st->codecpar->sample_rate = 8000;
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avpriv_set_pts_info(st, 64, 1, 8000);
return 0;
}
AVInputFormat ff_amrnb_demuxer = {
.name = "amrnb",
.long_name = NULL_IF_CONFIG_SMALL("raw AMR-NB"),
.priv_data_size = sizeof(AMRContext),
.read_probe = amrnb_probe,
.read_header = amrnb_read_header,
.read_packet = amr_read_packet,
.flags = AVFMT_GENERIC_INDEX,
};
#endif
#if CONFIG_AMRWB_DEMUXER
static int amrwb_probe(const AVProbeData *p)
{
int mode, i = 0, valid = 0, invalid = 0;
const uint8_t *b = p->buf;
while (i < p->buf_size) {
mode = b[i] >> 3 & 0x0F;
if (mode < 10 && (b[i] & 0x4) == 0x4) {
int last = b[i];
int size = amrwb_packed_size[mode];
while (size--) {
if (b[++i] != last)
break;
}
if (size > 0) {
valid++;
i += size;
}
} else {
valid = 0;
invalid++;
i++;
}
}
if (valid > 100 && valid >> 4 > invalid)
return AVPROBE_SCORE_EXTENSION / 2 + 1;
return 0;
}
static int amrwb_read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_AMR_WB;
st->codecpar->sample_rate = 16000;
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avpriv_set_pts_info(st, 64, 1, 16000);
return 0;
}
AVInputFormat ff_amrwb_demuxer = {
.name = "amrwb",
.long_name = NULL_IF_CONFIG_SMALL("raw AMR-WB"),
.priv_data_size = sizeof(AMRContext),
.read_probe = amrwb_probe,
.read_header = amrwb_read_header,
.read_packet = amr_read_packet,
.flags = AVFMT_GENERIC_INDEX,
};
#endif
#if CONFIG_AMR_MUXER
AVOutputFormat ff_amr_muxer = {
.name = "amr",
.long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"),
.mime_type = "audio/amr",
.extensions = "amr",
.audio_codec = AV_CODEC_ID_AMR_NB,
.video_codec = AV_CODEC_ID_NONE,
.write_header = amr_write_header,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
};
#endif

224
externals/ffmpeg/libavformat/anm.c vendored Executable file
View File

@@ -0,0 +1,224 @@
/*
* Deluxe Paint Animation demuxer
* Copyright (c) 2009 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
* Deluxe Paint Animation demuxer
*/
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
typedef struct Page {
int base_record;
unsigned int nb_records;
int size;
} Page;
typedef struct AnmDemuxContext {
unsigned int nb_pages; /**< total pages in file */
unsigned int nb_records; /**< total records in file */
int page_table_offset;
#define MAX_PAGES 256 /**< Deluxe Paint hardcoded value */
Page pt[MAX_PAGES]; /**< page table */
int page; /**< current page (or AVERROR_xxx code) */
int record; /**< current record (with in page) */
} AnmDemuxContext;
#define LPF_TAG MKTAG('L','P','F',' ')
#define ANIM_TAG MKTAG('A','N','I','M')
static int probe(const AVProbeData *p)
{
/* verify tags and video dimensions */
if (AV_RL32(&p->buf[0]) == LPF_TAG &&
AV_RL32(&p->buf[16]) == ANIM_TAG &&
AV_RL16(&p->buf[20]) && AV_RL16(&p->buf[22]))
return AVPROBE_SCORE_MAX;
return 0;
}
/**
* @return page containing the requested record or AVERROR_XXX
*/
static int find_record(const AnmDemuxContext *anm, int record)
{
int i;
if (record >= anm->nb_records)
return AVERROR_EOF;
for (i = 0; i < MAX_PAGES; i++) {
const Page *p = &anm->pt[i];
if (p->nb_records > 0 && record >= p->base_record && record < p->base_record + p->nb_records)
return i;
}
return AVERROR_INVALIDDATA;
}
static int read_header(AVFormatContext *s)
{
AnmDemuxContext *anm = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int i, ret;
avio_skip(pb, 4); /* magic number */
if (avio_rl16(pb) != MAX_PAGES) {
avpriv_request_sample(s, "max_pages != " AV_STRINGIFY(MAX_PAGES));
return AVERROR_PATCHWELCOME;
}
anm->nb_pages = avio_rl16(pb);
anm->nb_records = avio_rl32(pb);
avio_skip(pb, 2); /* max records per page */
anm->page_table_offset = avio_rl16(pb);
if (avio_rl32(pb) != ANIM_TAG)
return AVERROR_INVALIDDATA;
/* video stream */
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_ANM;
st->codecpar->codec_tag = 0; /* no fourcc */
st->codecpar->width = avio_rl16(pb);
st->codecpar->height = avio_rl16(pb);
if (avio_r8(pb) != 0)
goto invalid;
avio_skip(pb, 1); /* frame rate multiplier info */
/* ignore last delta record (used for looping) */
if (avio_r8(pb)) /* has_last_delta */
anm->nb_records = FFMAX(anm->nb_records - 1, 0);
avio_skip(pb, 1); /* last_delta_valid */
if (avio_r8(pb) != 0)
goto invalid;
if (avio_r8(pb) != 1)
goto invalid;
avio_skip(pb, 1); /* other recs per frame */
if (avio_r8(pb) != 1)
goto invalid;
avio_skip(pb, 32); /* record_types */
st->nb_frames = avio_rl32(pb);
avpriv_set_pts_info(st, 64, 1, avio_rl16(pb));
avio_skip(pb, 58);
/* color cycling and palette data */
ret = ff_get_extradata(s, st->codecpar, s->pb, 16*8 + 4*256);
if (ret < 0)
return ret;
/* read page table */
ret = avio_seek(pb, anm->page_table_offset, SEEK_SET);
if (ret < 0)
return ret;
for (i = 0; i < MAX_PAGES; i++) {
Page *p = &anm->pt[i];
p->base_record = avio_rl16(pb);
p->nb_records = avio_rl16(pb);
p->size = avio_rl16(pb);
}
/* find page of first frame */
anm->page = find_record(anm, 0);
if (anm->page < 0) {
return anm->page;
}
anm->record = -1;
return 0;
invalid:
avpriv_request_sample(s, "Invalid header element");
return AVERROR_PATCHWELCOME;
}
static int read_packet(AVFormatContext *s,
AVPacket *pkt)
{
AnmDemuxContext *anm = s->priv_data;
AVIOContext *pb = s->pb;
Page *p;
int tmp, record_size;
if (avio_feof(s->pb))
return AVERROR(EIO);
if (anm->page < 0)
return anm->page;
repeat:
p = &anm->pt[anm->page];
/* parse page header */
if (anm->record < 0) {
avio_seek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16), SEEK_SET);
avio_skip(pb, 8 + 2*p->nb_records);
anm->record = 0;
}
/* if we have fetched all records in this page, then find the
next page and repeat */
if (anm->record >= p->nb_records) {
anm->page = find_record(anm, p->base_record + p->nb_records);
if (anm->page < 0)
return anm->page;
anm->record = -1;
goto repeat;
}
/* fetch record size */
tmp = avio_tell(pb);
avio_seek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16) +
8 + anm->record * 2, SEEK_SET);
record_size = avio_rl16(pb);
avio_seek(pb, tmp, SEEK_SET);
/* fetch record */
pkt->size = av_get_packet(s->pb, pkt, record_size);
if (pkt->size < 0)
return pkt->size;
if (p->base_record + anm->record == 0)
pkt->flags |= AV_PKT_FLAG_KEY;
anm->record++;
return 0;
}
AVInputFormat ff_anm_demuxer = {
.name = "anm",
.long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
.priv_data_size = sizeof(AnmDemuxContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
};

92
externals/ffmpeg/libavformat/apc.c vendored Executable file
View File

@@ -0,0 +1,92 @@
/*
* 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 <string.h>
#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
static int apc_probe(const AVProbeData *p)
{
if (!strncmp(p->buf, "CRYO_APC", 8))
return AVPROBE_SCORE_MAX;
return 0;
}
static int apc_read_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AVStream *st;
int ret;
avio_rl32(pb); /* CRYO */
avio_rl32(pb); /* _APC */
avio_rl32(pb); /* 1.20 */
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_APC;
avio_rl32(pb); /* number of samples */
st->codecpar->sample_rate = avio_rl32(pb);
/* initial predictor values for adpcm decoder */
if ((ret = ff_get_extradata(s, st->codecpar, pb, 2 * 4)) < 0)
return ret;
if (avio_rl32(pb)) {
st->codecpar->channels = 2;
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
} else {
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
}
st->codecpar->bits_per_coded_sample = 4;
st->codecpar->bit_rate = (int64_t)st->codecpar->bits_per_coded_sample * st->codecpar->channels
* st->codecpar->sample_rate;
st->codecpar->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 ff_apc_demuxer = {
.name = "apc",
.long_name = NULL_IF_CONFIG_SMALL("CRYO APC"),
.read_probe = apc_probe,
.read_header = apc_read_header,
.read_packet = apc_read_packet,
};

485
externals/ffmpeg/libavformat/ape.c vendored Executable file
View File

@@ -0,0 +1,485 @@
/*
* 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 "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
#include "apetag.h"
/* The earliest and latest file formats supported by this library */
#define APE_MIN_VERSION 3800
#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 APE_EXTRADATA_SIZE 6
typedef struct APEFrame {
int64_t pos;
int nblocks;
int size;
int skip;
int64_t pts;
} APEFrame;
typedef struct APEContext {
/* Derived fields */
uint32_t junklength;
uint32_t firstframe;
uint32_t totalsamples;
int currentframe;
APEFrame *frames;
/* Info from Descriptor Block */
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;
uint8_t *bittable;
} APEContext;
static int ape_read_close(AVFormatContext * s);
static int ape_probe(const AVProbeData * p)
{
int version = AV_RL16(p->buf+4);
if (AV_RL32(p->buf) != MKTAG('M', 'A', 'C', ' '))
return 0;
if (version < APE_MIN_VERSION || version > APE_MAX_VERSION)
return AVPROBE_SCORE_MAX/4;
return AVPROBE_SCORE_MAX;
}
static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx)
{
#ifdef DEBUG
int i;
av_log(s, AV_LOG_DEBUG, "Descriptor Block:\n\n");
av_log(s, AV_LOG_DEBUG, "fileversion = %"PRId16"\n", ape_ctx->fileversion);
av_log(s, AV_LOG_DEBUG, "descriptorlength = %"PRIu32"\n", ape_ctx->descriptorlength);
av_log(s, AV_LOG_DEBUG, "headerlength = %"PRIu32"\n", ape_ctx->headerlength);
av_log(s, AV_LOG_DEBUG, "seektablelength = %"PRIu32"\n", ape_ctx->seektablelength);
av_log(s, AV_LOG_DEBUG, "wavheaderlength = %"PRIu32"\n", ape_ctx->wavheaderlength);
av_log(s, AV_LOG_DEBUG, "audiodatalength = %"PRIu32"\n", ape_ctx->audiodatalength);
av_log(s, AV_LOG_DEBUG, "audiodatalength_high = %"PRIu32"\n", ape_ctx->audiodatalength_high);
av_log(s, AV_LOG_DEBUG, "wavtaillength = %"PRIu32"\n", ape_ctx->wavtaillength);
av_log(s, AV_LOG_DEBUG, "md5 = ");
for (i = 0; i < 16; i++)
av_log(s, AV_LOG_DEBUG, "%02x", ape_ctx->md5[i]);
av_log(s, AV_LOG_DEBUG, "\n");
av_log(s, AV_LOG_DEBUG, "\nHeader Block:\n\n");
av_log(s, AV_LOG_DEBUG, "compressiontype = %"PRIu16"\n", ape_ctx->compressiontype);
av_log(s, AV_LOG_DEBUG, "formatflags = %"PRIu16"\n", ape_ctx->formatflags);
av_log(s, AV_LOG_DEBUG, "blocksperframe = %"PRIu32"\n", ape_ctx->blocksperframe);
av_log(s, AV_LOG_DEBUG, "finalframeblocks = %"PRIu32"\n", ape_ctx->finalframeblocks);
av_log(s, AV_LOG_DEBUG, "totalframes = %"PRIu32"\n", ape_ctx->totalframes);
av_log(s, AV_LOG_DEBUG, "bps = %"PRIu16"\n", ape_ctx->bps);
av_log(s, AV_LOG_DEBUG, "channels = %"PRIu16"\n", ape_ctx->channels);
av_log(s, AV_LOG_DEBUG, "samplerate = %"PRIu32"\n", ape_ctx->samplerate);
av_log(s, AV_LOG_DEBUG, "\nSeektable\n\n");
if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes) {
av_log(s, 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(s, AV_LOG_DEBUG, "%8d %"PRIu32" (%"PRIu32" bytes)",
i, ape_ctx->seektable[i],
ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]);
if (ape_ctx->bittable)
av_log(s, AV_LOG_DEBUG, " + %2d bits\n",
ape_ctx->bittable[i]);
av_log(s, AV_LOG_DEBUG, "\n");
} else {
av_log(s, AV_LOG_DEBUG, "%8d %"PRIu32"\n", i, ape_ctx->seektable[i]);
}
}
}
av_log(s, AV_LOG_DEBUG, "\nFrames\n\n");
for (i = 0; i < ape_ctx->totalframes; i++)
av_log(s, AV_LOG_DEBUG, "%8d %8"PRId64" %8d (%d samples)\n", i,
ape_ctx->frames[i].pos, ape_ctx->frames[i].size,
ape_ctx->frames[i].nblocks);
av_log(s, AV_LOG_DEBUG, "\nCalculated information:\n\n");
av_log(s, AV_LOG_DEBUG, "junklength = %"PRIu32"\n", ape_ctx->junklength);
av_log(s, AV_LOG_DEBUG, "firstframe = %"PRIu32"\n", ape_ctx->firstframe);
av_log(s, AV_LOG_DEBUG, "totalsamples = %"PRIu32"\n", ape_ctx->totalsamples);
#endif
}
static int ape_read_header(AVFormatContext * s)
{
AVIOContext *pb = s->pb;
APEContext *ape = s->priv_data;
AVStream *st;
uint32_t tag;
int i, ret;
int total_blocks, final_size = 0;
int64_t pts, file_size;
/* Skip any leading junk such as id3v2 tags */
ape->junklength = avio_tell(pb);
tag = avio_rl32(pb);
if (tag != MKTAG('M', 'A', 'C', ' '))
return AVERROR_INVALIDDATA;
ape->fileversion = avio_rl16(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 AVERROR_PATCHWELCOME;
}
if (ape->fileversion >= 3980) {
ape->padding1 = avio_rl16(pb);
ape->descriptorlength = avio_rl32(pb);
ape->headerlength = avio_rl32(pb);
ape->seektablelength = avio_rl32(pb);
ape->wavheaderlength = avio_rl32(pb);
ape->audiodatalength = avio_rl32(pb);
ape->audiodatalength_high = avio_rl32(pb);
ape->wavtaillength = avio_rl32(pb);
avio_read(pb, ape->md5, 16);
/* Skip any unknown bytes at the end of the descriptor.
This is for future compatibility */
if (ape->descriptorlength > 52)
avio_skip(pb, ape->descriptorlength - 52);
/* Read header data */
ape->compressiontype = avio_rl16(pb);
ape->formatflags = avio_rl16(pb);
ape->blocksperframe = avio_rl32(pb);
ape->finalframeblocks = avio_rl32(pb);
ape->totalframes = avio_rl32(pb);
ape->bps = avio_rl16(pb);
ape->channels = avio_rl16(pb);
ape->samplerate = avio_rl32(pb);
} else {
ape->descriptorlength = 0;
ape->headerlength = 32;
ape->compressiontype = avio_rl16(pb);
ape->formatflags = avio_rl16(pb);
ape->channels = avio_rl16(pb);
ape->samplerate = avio_rl32(pb);
ape->wavheaderlength = avio_rl32(pb);
ape->wavtaillength = avio_rl32(pb);
ape->totalframes = avio_rl32(pb);
ape->finalframeblocks = avio_rl32(pb);
if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) {
avio_skip(pb, 4); /* Skip the peak level */
ape->headerlength += 4;
}
if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) {
ape->seektablelength = avio_rl32(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))
avio_skip(pb, ape->wavheaderlength);
}
if(!ape->totalframes){
av_log(s, AV_LOG_ERROR, "No frames in the file!\n");
return AVERROR(EINVAL);
}
if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){
av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n",
ape->totalframes);
return AVERROR_INVALIDDATA;
}
if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) {
av_log(s, AV_LOG_ERROR,
"Number of seek entries is less than number of frames: %"SIZE_SPECIFIER" vs. %"PRIu32"\n",
ape->seektablelength / sizeof(*ape->seektable), ape->totalframes);
return AVERROR_INVALIDDATA;
}
ape->frames = av_malloc_array(ape->totalframes, sizeof(APEFrame));
if(!ape->frames)
return AVERROR(ENOMEM);
ape->firstframe = ape->junklength + ape->descriptorlength + ape->headerlength + ape->seektablelength + ape->wavheaderlength;
if (ape->fileversion < 3810)
ape->firstframe += ape->totalframes;
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_mallocz(ape->seektablelength);
if (!ape->seektable) {
ret = AVERROR(ENOMEM);
goto fail;
}
for (i = 0; i < ape->seektablelength / sizeof(uint32_t) && !pb->eof_reached; i++)
ape->seektable[i] = avio_rl32(pb);
if (ape->fileversion < 3810) {
ape->bittable = av_mallocz(ape->totalframes);
if (!ape->bittable) {
ret = AVERROR(ENOMEM);
goto fail;
}
for (i = 0; i < ape->totalframes && !pb->eof_reached; i++)
ape->bittable[i] = avio_r8(pb);
}
if (pb->eof_reached)
av_log(s, AV_LOG_WARNING, "File truncated\n");
}
ape->frames[0].pos = ape->firstframe;
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->junklength;
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].nblocks = ape->finalframeblocks;
/* calculate final packet size from total file size, if available */
file_size = avio_size(pb);
if (file_size > 0) {
final_size = file_size - ape->frames[ape->totalframes - 1].pos -
ape->wavtaillength;
final_size -= final_size & 3;
}
if (file_size <= 0 || final_size <= 0)
final_size = ape->finalframeblocks * 8;
ape->frames[ape->totalframes - 1].size = final_size;
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;
}
if (ape->fileversion < 3810) {
for (i = 0; i < ape->totalframes; i++) {
if (i < ape->totalframes - 1 && ape->bittable[i + 1])
ape->frames[i].size += 4;
ape->frames[i].skip <<= 3;
ape->frames[i].skip += ape->bittable[i];
}
}
ape_dumpinfo(s, ape);
av_log(s, AV_LOG_VERBOSE, "Decoding file - v%d.%02d, compression level %"PRIu16"\n",
ape->fileversion / 1000, (ape->fileversion % 1000) / 10,
ape->compressiontype);
/* now we are ready: build format streams */
st = avformat_new_stream(s, NULL);
if (!st) {
ret = AVERROR(ENOMEM);
goto fail;
}
total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_APE;
st->codecpar->codec_tag = MKTAG('A', 'P', 'E', ' ');
st->codecpar->channels = ape->channels;
st->codecpar->sample_rate = ape->samplerate;
st->codecpar->bits_per_coded_sample = ape->bps;
st->nb_frames = ape->totalframes;
st->start_time = 0;
st->duration = total_blocks;
avpriv_set_pts_info(st, 64, 1, ape->samplerate);
if ((ret = ff_alloc_extradata(st->codecpar, APE_EXTRADATA_SIZE)) < 0)
goto fail;
AV_WL16(st->codecpar->extradata + 0, ape->fileversion);
AV_WL16(st->codecpar->extradata + 2, ape->compressiontype);
AV_WL16(st->codecpar->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;
}
/* try to read APE tags */
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
ff_ape_parse_tag(s);
avio_seek(pb, 0, SEEK_SET);
}
return 0;
fail:
ape_read_close(s);
return ret;
}
static int ape_read_packet(AVFormatContext * s, AVPacket * pkt)
{
int ret;
int nblocks;
APEContext *ape = s->priv_data;
uint32_t extra_size = 8;
int64_t ret64;
if (avio_feof(s->pb))
return AVERROR_EOF;
if (ape->currentframe >= ape->totalframes)
return AVERROR_EOF;
ret64 = avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET);
if (ret64 < 0)
return ret64;
/* Calculate how many blocks there are in this frame */
if (ape->currentframe == (ape->totalframes - 1))
nblocks = ape->finalframeblocks;
else
nblocks = ape->blocksperframe;
if (ape->frames[ape->currentframe].size <= 0 ||
ape->frames[ape->currentframe].size > INT_MAX - extra_size) {
av_log(s, AV_LOG_ERROR, "invalid packet size: %d\n",
ape->frames[ape->currentframe].size);
ape->currentframe++;
return AVERROR(EIO);
}
ret = av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size);
if (ret < 0)
return ret;
AV_WL32(pkt->data , nblocks);
AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip);
ret = avio_read(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size);
if (ret < 0) {
return ret;
}
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);
av_freep(&ape->bittable);
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);
int64_t ret;
if (index < 0)
return -1;
if ((ret = avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET)) < 0)
return ret;
ape->currentframe = index;
return 0;
}
AVInputFormat ff_ape_demuxer = {
.name = "ape",
.long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"),
.priv_data_size = sizeof(APEContext),
.read_probe = ape_probe,
.read_header = ape_read_header,
.read_packet = ape_read_packet,
.read_close = ape_read_close,
.read_seek = ape_read_seek,
.extensions = "ape,apl,mac",
};

245
externals/ffmpeg/libavformat/apetag.c vendored Executable file
View File

@@ -0,0 +1,245 @@
/*
* APE tag handling
* 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 <inttypes.h>
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "avformat.h"
#include "avio_internal.h"
#include "apetag.h"
#include "internal.h"
#define APE_TAG_FLAG_CONTAINS_HEADER (1U << 31)
#define APE_TAG_FLAG_LACKS_FOOTER (1 << 30)
#define APE_TAG_FLAG_IS_HEADER (1 << 29)
#define APE_TAG_FLAG_IS_BINARY (1 << 1)
static int ape_tag_read_field(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
uint8_t key[1024], *value;
int64_t size, flags;
int i, c;
size = avio_rl32(pb); /* field size */
flags = avio_rl32(pb); /* field flags */
for (i = 0; i < sizeof(key) - 1; i++) {
c = avio_r8(pb);
if (c < 0x20 || c > 0x7E)
break;
else
key[i] = c;
}
key[i] = 0;
if (c != 0) {
av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key);
return -1;
}
if (size > INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
av_log(s, AV_LOG_ERROR, "APE tag size too large.\n");
return AVERROR_INVALIDDATA;
}
if (flags & APE_TAG_FLAG_IS_BINARY) {
uint8_t filename[1024];
enum AVCodecID id;
int ret;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
ret = avio_get_str(pb, size, filename, sizeof(filename));
if (ret < 0)
return ret;
if (size <= ret) {
av_log(s, AV_LOG_WARNING, "Skipping binary tag '%s'.\n", key);
return 0;
}
size -= ret;
av_dict_set(&st->metadata, key, filename, 0);
if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {
AVPacket pkt;
int ret;
ret = av_get_packet(s->pb, &pkt, size);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");
return ret;
}
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = id;
st->attached_pic = pkt;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
} else {
if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
return ret;
st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
}
} else {
value = av_malloc(size+1);
if (!value)
return AVERROR(ENOMEM);
c = avio_read(pb, value, size);
if (c < 0) {
av_free(value);
return c;
}
value[c] = 0;
av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
}
return 0;
}
int64_t ff_ape_parse_tag(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
int64_t file_size = avio_size(pb);
uint32_t val, fields, tag_bytes;
uint8_t buf[8];
int64_t tag_start;
int i;
if (file_size < APE_TAG_FOOTER_BYTES)
return 0;
avio_seek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
avio_read(pb, buf, 8); /* APETAGEX */
if (strncmp(buf, APE_TAG_PREAMBLE, 8)) {
return 0;
}
val = avio_rl32(pb); /* APE tag version */
if (val > APE_TAG_VERSION) {
av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION);
return 0;
}
tag_bytes = avio_rl32(pb); /* tag size */
if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {
av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");
return 0;
}
if (tag_bytes > file_size - APE_TAG_FOOTER_BYTES) {
av_log(s, AV_LOG_ERROR, "Invalid tag size %"PRIu32".\n", tag_bytes);
return 0;
}
fields = avio_rl32(pb); /* number of fields */
if (fields > 65536) {
av_log(s, AV_LOG_ERROR, "Too many tag fields (%"PRIu32")\n", fields);
return 0;
}
val = avio_rl32(pb); /* flags */
if (val & APE_TAG_FLAG_IS_HEADER) {
av_log(s, AV_LOG_ERROR, "APE Tag is a header\n");
return 0;
}
avio_seek(pb, file_size - tag_bytes, SEEK_SET);
if (val & APE_TAG_FLAG_CONTAINS_HEADER)
tag_bytes += APE_TAG_HEADER_BYTES;
tag_start = file_size - tag_bytes;
for (i=0; i<fields; i++)
if (ape_tag_read_field(s) < 0) break;
return tag_start;
}
static int string_is_ascii(const uint8_t *str)
{
while (*str && *str >= 0x20 && *str <= 0x7e ) str++;
return !*str;
}
int ff_ape_write_tag(AVFormatContext *s)
{
AVDictionaryEntry *e = NULL;
int size, ret, count = 0;
AVIOContext *dyn_bc;
uint8_t *dyn_buf;
if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
return ret;
ff_standardize_creation_time(s);
while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
int val_len;
if (!string_is_ascii(e->key)) {
av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n");
continue;
}
val_len = strlen(e->value);
avio_wl32(dyn_bc, val_len); // value length
avio_wl32(dyn_bc, 0); // item flags
avio_put_str(dyn_bc, e->key); // key
avio_write(dyn_bc, e->value, val_len); // value
count++;
}
if (!count)
goto end;
size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
if (size <= 0)
goto end;
size += APE_TAG_FOOTER_BYTES;
// header
avio_write(s->pb, "APETAGEX", 8); // id
avio_wl32(s->pb, APE_TAG_VERSION); // version
avio_wl32(s->pb, size);
avio_wl32(s->pb, count);
// flags
avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_IS_HEADER);
ffio_fill(s->pb, 0, 8); // reserved
avio_write(s->pb, dyn_buf, size - APE_TAG_FOOTER_BYTES);
// footer
avio_write(s->pb, "APETAGEX", 8); // id
avio_wl32(s->pb, APE_TAG_VERSION); // version
avio_wl32(s->pb, size); // size
avio_wl32(s->pb, count); // tag count
// flags
avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER);
ffio_fill(s->pb, 0, 8); // reserved
end:
ffio_free_dyn_buf(&dyn_bc);
return ret;
}

45
externals/ffmpeg/libavformat/apetag.h vendored Executable file
View File

@@ -0,0 +1,45 @@
/*
* APE tag handling
* 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
*/
#ifndef AVFORMAT_APETAG_H
#define AVFORMAT_APETAG_H
#include "avformat.h"
#define APE_TAG_PREAMBLE "APETAGEX"
#define APE_TAG_VERSION 2000
#define APE_TAG_FOOTER_BYTES 32
#define APE_TAG_HEADER_BYTES 32
/**
* Read and parse an APE tag
*
* @return offset of the tag start in the file
*/
int64_t ff_ape_parse_tag(AVFormatContext *s);
/**
* Write an APE tag into a file.
*/
int ff_ape_write_tag(AVFormatContext *s);
#endif /* AVFORMAT_APETAG_H */

188
externals/ffmpeg/libavformat/apm.c vendored Executable file
View File

@@ -0,0 +1,188 @@
/*
* Rayman 2 APM Demuxer
*
* Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.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 "internal.h"
#include "riff.h"
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#define APM_FILE_HEADER_SIZE 20
#define APM_VS12_CHUNK_SIZE 76
#define APM_MAX_READ_SIZE 4096
#define APM_TAG_VS12 MKTAG('v', 's', '1', '2')
#define APM_TAG_DATA MKTAG('D', 'A', 'T', 'A')
typedef struct APMState {
int32_t has_saved;
int32_t predictor_r;
int32_t step_index_r;
int32_t saved_r;
int32_t predictor_l;
int32_t step_index_l;
int32_t saved_l;
} APMState;
typedef struct APMVS12Chunk {
uint32_t magic;
uint32_t file_size;
uint32_t data_size;
uint32_t unk1;
uint32_t unk2;
APMState state;
uint32_t pad[7];
} APMVS12Chunk;
static void apm_parse_vs12(APMVS12Chunk *vs12, const uint8_t *buf)
{
vs12->magic = AV_RL32(buf + 0);
vs12->file_size = AV_RL32(buf + 4);
vs12->data_size = AV_RL32(buf + 8);
vs12->unk1 = AV_RL32(buf + 12);
vs12->unk2 = AV_RL32(buf + 16);
vs12->state.has_saved = AV_RL32(buf + 20);
vs12->state.predictor_r = AV_RL32(buf + 24);
vs12->state.step_index_r = AV_RL32(buf + 28);
vs12->state.saved_r = AV_RL32(buf + 32);
vs12->state.predictor_l = AV_RL32(buf + 36);
vs12->state.step_index_l = AV_RL32(buf + 40);
vs12->state.saved_l = AV_RL32(buf + 44);
for (int i = 0; i < FF_ARRAY_ELEMS(vs12->pad); i++)
vs12->pad[i] = AV_RL32(buf + 48 + (i * 4));
}
static int apm_probe(const AVProbeData *p)
{
if (p->buf_size < 100)
return 0;
if (AV_RL32(p->buf + 20) != APM_TAG_VS12)
return 0;
if (AV_RL32(p->buf + 96) != APM_TAG_DATA)
return 0;
return AVPROBE_SCORE_MAX - 1;
}
static int apm_read_header(AVFormatContext *s)
{
int64_t ret;
AVStream *st;
APMVS12Chunk vs12;
uint8_t buf[APM_VS12_CHUNK_SIZE];
if (!(st = avformat_new_stream(s, NULL)))
return AVERROR(ENOMEM);
/* The header starts with a WAVEFORMATEX */
if ((ret = ff_get_wav_header(s, s->pb, st->codecpar, APM_FILE_HEADER_SIZE, 0)) < 0)
return ret;
if (st->codecpar->bits_per_coded_sample != 4)
return AVERROR_INVALIDDATA;
if (st->codecpar->codec_tag != 0x2000)
return AVERROR_INVALIDDATA;
/* ff_get_wav_header() does most of the work, but we need to fix a few things. */
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_APM;
st->codecpar->codec_tag = 0;
if (st->codecpar->channels == 2)
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
else if (st->codecpar->channels == 1)
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
else
return AVERROR_INVALIDDATA;
st->codecpar->format = AV_SAMPLE_FMT_S16;
st->codecpar->bits_per_raw_sample = 16;
st->codecpar->bit_rate = st->codecpar->channels *
st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
if ((ret = avio_read(s->pb, buf, APM_VS12_CHUNK_SIZE)) < 0)
return ret;
else if (ret != APM_VS12_CHUNK_SIZE)
return AVERROR(EIO);
apm_parse_vs12(&vs12, buf);
if (vs12.magic != APM_TAG_VS12) {
return AVERROR_INVALIDDATA;
}
if (vs12.state.has_saved) {
avpriv_request_sample(s, "Saved Samples");
return AVERROR_PATCHWELCOME;
}
if (avio_rl32(s->pb) != APM_TAG_DATA)
return AVERROR_INVALIDDATA;
if ((ret = ff_alloc_extradata(st->codecpar, 16)) < 0)
return ret;
AV_WL32(st->codecpar->extradata + 0, vs12.state.predictor_l);
AV_WL32(st->codecpar->extradata + 4, vs12.state.step_index_l);
AV_WL32(st->codecpar->extradata + 8, vs12.state.predictor_r);
AV_WL32(st->codecpar->extradata + 12, vs12.state.step_index_r);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->start_time = 0;
st->duration = vs12.data_size *
(8 / st->codecpar->bits_per_coded_sample) /
st->codecpar->channels;
return 0;
}
static int apm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret;
AVCodecParameters *par = s->streams[0]->codecpar;
/*
* For future reference: if files with the `has_saved` field set ever
* surface, `saved_l`, and `saved_r` will each contain 8 "saved" samples
* that should be sent to the decoder before the actual data.
*/
if ((ret = av_get_packet(s->pb, pkt, APM_MAX_READ_SIZE)) < 0)
return ret;
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
pkt->stream_index = 0;
pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->channels;
return 0;
}
AVInputFormat ff_apm_demuxer = {
.name = "apm",
.long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"),
.read_probe = apm_probe,
.read_header = apm_read_header,
.read_packet = apm_read_packet
};

441
externals/ffmpeg/libavformat/apngdec.c vendored Executable file
View File

@@ -0,0 +1,441 @@
/*
* APNG demuxer
* Copyright (c) 2014 Benoit Fouet
*
* 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
* APNG demuxer.
* @see https://wiki.mozilla.org/APNG_Specification
* @see http://www.w3.org/TR/PNG
*/
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavcodec/apng.h"
#include "libavcodec/png.h"
#include "libavcodec/bytestream.h"
#define DEFAULT_APNG_FPS 15
typedef struct APNGDemuxContext {
const AVClass *class;
int max_fps;
int default_fps;
int pkt_duration;
int is_key_frame;
/*
* loop options
*/
int ignore_loop;
uint32_t num_frames;
uint32_t num_play;
uint32_t cur_loop;
} APNGDemuxContext;
/*
* To be a valid APNG file, we mandate, in this order:
* PNGSIG
* IHDR
* ...
* acTL
* ...
* IDAT
*/
static int apng_probe(const AVProbeData *p)
{
GetByteContext gb;
int state = 0;
uint32_t len, tag;
bytestream2_init(&gb, p->buf, p->buf_size);
if (bytestream2_get_be64(&gb) != PNGSIG)
return 0;
for (;;) {
len = bytestream2_get_be32(&gb);
if (len > 0x7fffffff)
return 0;
tag = bytestream2_get_le32(&gb);
/* we don't check IDAT size, as this is the last tag
* we check, and it may be larger than the probe buffer */
if (tag != MKTAG('I', 'D', 'A', 'T') &&
len + 4 > bytestream2_get_bytes_left(&gb))
return 0;
switch (tag) {
case MKTAG('I', 'H', 'D', 'R'):
if (len != 13)
return 0;
if (av_image_check_size(bytestream2_get_be32(&gb), bytestream2_get_be32(&gb), 0, NULL))
return 0;
bytestream2_skip(&gb, 9);
state++;
break;
case MKTAG('a', 'c', 'T', 'L'):
if (state != 1 ||
len != 8 ||
bytestream2_get_be32(&gb) == 0) /* 0 is not a valid value for number of frames */
return 0;
bytestream2_skip(&gb, 8);
state++;
break;
case MKTAG('I', 'D', 'A', 'T'):
if (state != 2)
return 0;
goto end;
default:
/* skip other tags */
bytestream2_skip(&gb, len + 4);
break;
}
}
end:
return AVPROBE_SCORE_MAX;
}
static int append_extradata(AVCodecParameters *par, AVIOContext *pb, int len)
{
int previous_size = par->extradata_size;
int new_size, ret;
uint8_t *new_extradata;
if (previous_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - len)
return AVERROR_INVALIDDATA;
new_size = previous_size + len;
new_extradata = av_realloc(par->extradata, new_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!new_extradata)
return AVERROR(ENOMEM);
memset(new_extradata + new_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
par->extradata = new_extradata;
par->extradata_size = new_size;
if ((ret = avio_read(pb, par->extradata + previous_size, len)) < 0)
return ret;
return previous_size;
}
static int apng_read_header(AVFormatContext *s)
{
APNGDemuxContext *ctx = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t len, tag;
AVStream *st;
int acTL_found = 0;
int64_t ret = AVERROR_INVALIDDATA;
/* verify PNGSIG */
if (avio_rb64(pb) != PNGSIG)
return ret;
/* parse IHDR (must be first chunk) */
len = avio_rb32(pb);
tag = avio_rl32(pb);
if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R'))
return ret;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
/* set the timebase to something large enough (1/100,000 of second)
* to hopefully cope with all sane frame durations */
avpriv_set_pts_info(st, 64, 1, 100000);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_APNG;
st->codecpar->width = avio_rb32(pb);
st->codecpar->height = avio_rb32(pb);
if ((ret = av_image_check_size(st->codecpar->width, st->codecpar->height, 0, s)) < 0)
return ret;
/* extradata will contain every chunk up to the first fcTL (excluded) */
ret = ff_alloc_extradata(st->codecpar, len + 12);
if (ret < 0)
return ret;
AV_WB32(st->codecpar->extradata, len);
AV_WL32(st->codecpar->extradata+4, tag);
AV_WB32(st->codecpar->extradata+8, st->codecpar->width);
AV_WB32(st->codecpar->extradata+12, st->codecpar->height);
if ((ret = avio_read(pb, st->codecpar->extradata+16, 9)) < 0)
goto fail;
while (!avio_feof(pb)) {
if (acTL_found && ctx->num_play != 1) {
int64_t size = avio_size(pb);
int64_t offset = avio_tell(pb);
if (size < 0) {
ret = size;
goto fail;
} else if (offset < 0) {
ret = offset;
goto fail;
} else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) {
av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n");
ctx->num_play = 1;
}
}
if ((ctx->num_play == 1 || !acTL_found) &&
((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0))
goto fail;
len = avio_rb32(pb);
if (len > 0x7fffffff) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
tag = avio_rl32(pb);
switch (tag) {
case MKTAG('a', 'c', 'T', 'L'):
if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
(ret = append_extradata(st->codecpar, pb, len + 12)) < 0)
goto fail;
acTL_found = 1;
ctx->num_frames = AV_RB32(st->codecpar->extradata + ret + 8);
ctx->num_play = AV_RB32(st->codecpar->extradata + ret + 12);
av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n",
ctx->num_frames, ctx->num_play);
break;
case MKTAG('f', 'c', 'T', 'L'):
if (!acTL_found) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
goto fail;
return 0;
default:
if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
(ret = append_extradata(st->codecpar, pb, len + 12)) < 0)
goto fail;
}
}
fail:
return ret;
}
static int decode_fctl_chunk(AVFormatContext *s, APNGDemuxContext *ctx, AVPacket *pkt)
{
uint32_t sequence_number, width, height, x_offset, y_offset;
uint16_t delay_num, delay_den;
uint8_t dispose_op, blend_op;
sequence_number = avio_rb32(s->pb);
width = avio_rb32(s->pb);
height = avio_rb32(s->pb);
x_offset = avio_rb32(s->pb);
y_offset = avio_rb32(s->pb);
delay_num = avio_rb16(s->pb);
delay_den = avio_rb16(s->pb);
dispose_op = avio_r8(s->pb);
blend_op = avio_r8(s->pb);
avio_skip(s->pb, 4); /* crc */
/* default is hundredths of seconds */
if (!delay_den)
delay_den = 100;
if (!delay_num || (ctx->max_fps && delay_den / delay_num > ctx->max_fps)) {
delay_num = 1;
delay_den = ctx->default_fps;
}
ctx->pkt_duration = av_rescale_q(delay_num,
(AVRational){ 1, delay_den },
s->streams[0]->time_base);
av_log(s, AV_LOG_DEBUG, "%s: "
"sequence_number: %"PRId32", "
"width: %"PRIu32", "
"height: %"PRIu32", "
"x_offset: %"PRIu32", "
"y_offset: %"PRIu32", "
"delay_num: %"PRIu16", "
"delay_den: %"PRIu16", "
"dispose_op: %d, "
"blend_op: %d\n",
__FUNCTION__,
sequence_number,
width,
height,
x_offset,
y_offset,
delay_num,
delay_den,
dispose_op,
blend_op);
if (width != s->streams[0]->codecpar->width ||
height != s->streams[0]->codecpar->height ||
x_offset != 0 ||
y_offset != 0) {
if (sequence_number == 0 ||
x_offset >= s->streams[0]->codecpar->width ||
width > s->streams[0]->codecpar->width - x_offset ||
y_offset >= s->streams[0]->codecpar->height ||
height > s->streams[0]->codecpar->height - y_offset)
return AVERROR_INVALIDDATA;
ctx->is_key_frame = 0;
} else {
if (sequence_number == 0 && dispose_op == APNG_DISPOSE_OP_PREVIOUS)
dispose_op = APNG_DISPOSE_OP_BACKGROUND;
ctx->is_key_frame = dispose_op == APNG_DISPOSE_OP_BACKGROUND ||
blend_op == APNG_BLEND_OP_SOURCE;
}
return 0;
}
static int apng_read_packet(AVFormatContext *s, AVPacket *pkt)
{
APNGDemuxContext *ctx = s->priv_data;
int64_t ret;
int64_t size;
AVIOContext *pb = s->pb;
uint32_t len, tag;
/*
* fcTL chunk length, in bytes:
* 4 (length)
* 4 (tag)
* 26 (actual chunk)
* 4 (crc) bytes
* and needed next:
* 4 (length)
* 4 (tag (must be fdAT or IDAT))
*/
/* if num_play is not 1, then the seekback is already guaranteed */
if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 46)) < 0)
return ret;
len = avio_rb32(pb);
tag = avio_rl32(pb);
if (avio_feof(pb))
return AVERROR_EOF;
switch (tag) {
case MKTAG('f', 'c', 'T', 'L'):
if (len != 26)
return AVERROR_INVALIDDATA;
if ((ret = decode_fctl_chunk(s, ctx, pkt)) < 0)
return ret;
/* fcTL must precede fdAT or IDAT */
len = avio_rb32(pb);
tag = avio_rl32(pb);
if (len > 0x7fffffff ||
tag != MKTAG('f', 'd', 'A', 'T') &&
tag != MKTAG('I', 'D', 'A', 'T'))
return AVERROR_INVALIDDATA;
size = 38 /* fcTL */ + 8 /* len, tag */ + len + 4 /* crc */;
if (size > INT_MAX)
return AVERROR(EINVAL);
if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0 ||
(ret = av_append_packet(pb, pkt, size)) < 0)
return ret;
if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
return ret;
len = avio_rb32(pb);
tag = avio_rl32(pb);
while (tag &&
tag != MKTAG('f', 'c', 'T', 'L') &&
tag != MKTAG('I', 'E', 'N', 'D')) {
if (len > 0x7fffffff)
return AVERROR_INVALIDDATA;
if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
(ret = av_append_packet(pb, pkt, len + 12)) < 0)
return ret;
if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
return ret;
len = avio_rb32(pb);
tag = avio_rl32(pb);
}
if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
return ret;
if (ctx->is_key_frame)
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
pkt->duration = ctx->pkt_duration;
return ret;
case MKTAG('I', 'E', 'N', 'D'):
ctx->cur_loop++;
if (ctx->ignore_loop || ctx->num_play >= 1 && ctx->cur_loop == ctx->num_play) {
avio_seek(pb, -8, SEEK_CUR);
return AVERROR_EOF;
}
if ((ret = avio_seek(pb, s->streams[0]->codecpar->extradata_size + 8, SEEK_SET)) < 0)
return ret;
return 0;
default:
avpriv_request_sample(s, "In-stream tag=%s (0x%08"PRIX32") len=%"PRIu32,
av_fourcc2str(tag), tag, len);
avio_skip(pb, len + 4);
}
/* Handle the unsupported yet cases */
return AVERROR_PATCHWELCOME;
}
static const AVOption options[] = {
{ "ignore_loop", "ignore loop setting" , offsetof(APNGDemuxContext, ignore_loop),
AV_OPT_TYPE_BOOL, { .i64 = 1 } , 0, 1 , AV_OPT_FLAG_DECODING_PARAM },
{ "max_fps" , "maximum framerate (0 is no limit)" , offsetof(APNGDemuxContext, max_fps),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ "default_fps", "default framerate (0 is as fast as possible)", offsetof(APNGDemuxContext, default_fps),
AV_OPT_TYPE_INT, { .i64 = DEFAULT_APNG_FPS }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
static const AVClass demuxer_class = {
.class_name = "APNG demuxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_DEMUXER,
};
AVInputFormat ff_apng_demuxer = {
.name = "apng",
.long_name = NULL_IF_CONFIG_SMALL("Animated Portable Network Graphics"),
.priv_data_size = sizeof(APNGDemuxContext),
.read_probe = apng_probe,
.read_header = apng_read_header,
.read_packet = apng_read_packet,
.flags = AVFMT_GENERIC_INDEX,
.priv_class = &demuxer_class,
};

311
externals/ffmpeg/libavformat/apngenc.c vendored Executable file
View File

@@ -0,0 +1,311 @@
/*
* APNG muxer
* Copyright (c) 2015 Donny Yang
*
* first version by Donny Yang <work@kota.moe>
*
* 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 "internal.h"
#include "libavutil/avassert.h"
#include "libavutil/crc.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavcodec/png.h"
#include "libavcodec/apng.h"
typedef struct APNGMuxContext {
AVClass *class;
uint32_t plays;
AVRational last_delay;
uint64_t acTL_offset;
uint32_t frame_number;
AVPacket *prev_packet;
AVRational prev_delay;
int framerate_warned;
uint8_t *extra_data;
int extra_data_size;
} APNGMuxContext;
static uint8_t *apng_find_chunk(uint32_t tag, uint8_t *buf, size_t length)
{
size_t b;
for (b = 0; b < length; b += AV_RB32(buf + b) + 12)
if (AV_RB32(&buf[b + 4]) == tag)
return &buf[b];
return NULL;
}
static void apng_write_chunk(AVIOContext *io_context, uint32_t tag,
uint8_t *buf, size_t length)
{
const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE);
uint32_t crc = ~0U;
uint8_t tagbuf[4];
av_assert0(crc_table);
avio_wb32(io_context, length);
AV_WB32(tagbuf, tag);
crc = av_crc(crc_table, crc, tagbuf, 4);
avio_wb32(io_context, tag);
if (length > 0) {
crc = av_crc(crc_table, crc, buf, length);
avio_write(io_context, buf, length);
}
avio_wb32(io_context, ~crc);
}
static int apng_write_header(AVFormatContext *format_context)
{
APNGMuxContext *apng = format_context->priv_data;
AVCodecParameters *par = format_context->streams[0]->codecpar;
if (format_context->nb_streams != 1 ||
format_context->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
format_context->streams[0]->codecpar->codec_id != AV_CODEC_ID_APNG) {
av_log(format_context, AV_LOG_ERROR,
"APNG muxer supports only a single video APNG stream.\n");
return AVERROR(EINVAL);
}
if (apng->last_delay.num > USHRT_MAX || apng->last_delay.den > USHRT_MAX) {
av_reduce(&apng->last_delay.num, &apng->last_delay.den,
apng->last_delay.num, apng->last_delay.den, USHRT_MAX);
av_log(format_context, AV_LOG_WARNING,
"Last frame delay is too precise. Reducing to %d/%d (%f).\n",
apng->last_delay.num, apng->last_delay.den, (double)apng->last_delay.num / apng->last_delay.den);
}
avio_wb64(format_context->pb, PNGSIG);
// Remaining headers are written when they are copied from the encoder
if (par->extradata_size) {
apng->extra_data = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!apng->extra_data)
return AVERROR(ENOMEM);
apng->extra_data_size = par->extradata_size;
memcpy(apng->extra_data, par->extradata, par->extradata_size);
}
return 0;
}
static int flush_packet(AVFormatContext *format_context, AVPacket *packet)
{
APNGMuxContext *apng = format_context->priv_data;
AVIOContext *io_context = format_context->pb;
AVStream *codec_stream = format_context->streams[0];
uint8_t *side_data = NULL;
int side_data_size = 0;
av_assert0(apng->prev_packet);
side_data = av_packet_get_side_data(apng->prev_packet, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size);
if (side_data_size) {
av_freep(&apng->extra_data);
apng->extra_data = av_mallocz(side_data_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!apng->extra_data)
return AVERROR(ENOMEM);
apng->extra_data_size = side_data_size;
memcpy(apng->extra_data, side_data, apng->extra_data_size);
}
if (apng->frame_number == 0 && !packet) {
uint8_t *existing_acTL_chunk;
uint8_t *existing_fcTL_chunk;
av_log(format_context, AV_LOG_INFO, "Only a single frame so saving as a normal PNG.\n");
// Write normal PNG headers without acTL chunk
existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), apng->extra_data, apng->extra_data_size);
if (existing_acTL_chunk) {
uint8_t *chunk_after_acTL = existing_acTL_chunk + AV_RB32(existing_acTL_chunk) + 12;
avio_write(io_context, apng->extra_data, existing_acTL_chunk - apng->extra_data);
avio_write(io_context, chunk_after_acTL, apng->extra_data + apng->extra_data_size - chunk_after_acTL);
} else {
avio_write(io_context, apng->extra_data, apng->extra_data_size);
}
// Write frame data without fcTL chunk
existing_fcTL_chunk = apng_find_chunk(MKBETAG('f', 'c', 'T', 'L'), apng->prev_packet->data, apng->prev_packet->size);
if (existing_fcTL_chunk) {
uint8_t *chunk_after_fcTL = existing_fcTL_chunk + AV_RB32(existing_fcTL_chunk) + 12;
avio_write(io_context, apng->prev_packet->data, existing_fcTL_chunk - apng->prev_packet->data);
avio_write(io_context, chunk_after_fcTL, apng->prev_packet->data + apng->prev_packet->size - chunk_after_fcTL);
} else {
avio_write(io_context, apng->prev_packet->data, apng->prev_packet->size);
}
} else {
uint8_t *existing_fcTL_chunk;
if (apng->frame_number == 0) {
uint8_t *existing_acTL_chunk;
// Write normal PNG headers
avio_write(io_context, apng->extra_data, apng->extra_data_size);
existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), apng->extra_data, apng->extra_data_size);
if (!existing_acTL_chunk) {
uint8_t buf[8];
// Write animation control header
apng->acTL_offset = avio_tell(io_context);
AV_WB32(buf, UINT_MAX); // number of frames (filled in later)
AV_WB32(buf + 4, apng->plays);
apng_write_chunk(io_context, MKBETAG('a', 'c', 'T', 'L'), buf, 8);
}
}
existing_fcTL_chunk = apng_find_chunk(MKBETAG('f', 'c', 'T', 'L'), apng->prev_packet->data, apng->prev_packet->size);
if (existing_fcTL_chunk) {
AVRational delay;
existing_fcTL_chunk += 8;
delay.num = AV_RB16(existing_fcTL_chunk + 20);
delay.den = AV_RB16(existing_fcTL_chunk + 22);
if (delay.num == 0 && delay.den == 0) {
if (packet) {
int64_t delay_num_raw = (packet->dts - apng->prev_packet->dts) * codec_stream->time_base.num;
int64_t delay_den_raw = codec_stream->time_base.den;
if (!av_reduce(&delay.num, &delay.den, delay_num_raw, delay_den_raw, USHRT_MAX) &&
!apng->framerate_warned) {
av_log(format_context, AV_LOG_WARNING,
"Frame rate is too high or specified too precisely. Unable to copy losslessly.\n");
apng->framerate_warned = 1;
}
} else if (apng->last_delay.num > 0) {
delay = apng->last_delay;
} else {
delay = apng->prev_delay;
}
// Update frame control header with new delay
AV_WB16(existing_fcTL_chunk + 20, delay.num);
AV_WB16(existing_fcTL_chunk + 22, delay.den);
AV_WB32(existing_fcTL_chunk + 26, ~av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), ~0U, existing_fcTL_chunk - 4, 26 + 4));
}
apng->prev_delay = delay;
}
// Write frame data
avio_write(io_context, apng->prev_packet->data, apng->prev_packet->size);
}
++apng->frame_number;
av_packet_unref(apng->prev_packet);
if (packet)
av_packet_ref(apng->prev_packet, packet);
return 0;
}
static int apng_write_packet(AVFormatContext *format_context, AVPacket *packet)
{
APNGMuxContext *apng = format_context->priv_data;
int ret;
if (!apng->prev_packet) {
apng->prev_packet = av_packet_alloc();
if (!apng->prev_packet)
return AVERROR(ENOMEM);
av_packet_ref(apng->prev_packet, packet);
} else {
ret = flush_packet(format_context, packet);
if (ret < 0)
return ret;
}
return 0;
}
static int apng_write_trailer(AVFormatContext *format_context)
{
APNGMuxContext *apng = format_context->priv_data;
AVIOContext *io_context = format_context->pb;
uint8_t buf[8];
int ret;
if (apng->prev_packet) {
ret = flush_packet(format_context, NULL);
if (ret < 0)
return ret;
}
apng_write_chunk(io_context, MKBETAG('I', 'E', 'N', 'D'), NULL, 0);
if (apng->acTL_offset && (io_context->seekable & AVIO_SEEKABLE_NORMAL)) {
avio_seek(io_context, apng->acTL_offset, SEEK_SET);
AV_WB32(buf, apng->frame_number);
AV_WB32(buf + 4, apng->plays);
apng_write_chunk(io_context, MKBETAG('a', 'c', 'T', 'L'), buf, 8);
}
return 0;
}
static void apng_deinit(AVFormatContext *s)
{
APNGMuxContext *apng = s->priv_data;
av_packet_free(&apng->prev_packet);
av_freep(&apng->extra_data);
apng->extra_data_size = 0;
}
#define OFFSET(x) offsetof(APNGMuxContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "plays", "Number of times to play the output: 0 - infinite loop, 1 - no loop", OFFSET(plays),
AV_OPT_TYPE_INT, { .i64 = 1 }, 0, UINT_MAX, ENC },
{ "final_delay", "Force delay after the last frame", OFFSET(last_delay),
AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, USHRT_MAX, ENC },
{ NULL },
};
static const AVClass apng_muxer_class = {
.class_name = "APNG muxer",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
.option = options,
};
AVOutputFormat ff_apng_muxer = {
.name = "apng",
.long_name = NULL_IF_CONFIG_SMALL("Animated Portable Network Graphics"),
.mime_type = "image/png",
.extensions = "apng",
.priv_data_size = sizeof(APNGMuxContext),
.audio_codec = AV_CODEC_ID_NONE,
.video_codec = AV_CODEC_ID_APNG,
.write_header = apng_write_header,
.write_packet = apng_write_packet,
.write_trailer = apng_write_trailer,
.deinit = apng_deinit,
.priv_class = &apng_muxer_class,
.flags = AVFMT_VARIABLE_FPS,
};

128
externals/ffmpeg/libavformat/aptxdec.c vendored Executable file
View File

@@ -0,0 +1,128 @@
/*
* RAW aptX demuxer
*
* Copyright (C) 2017 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
*/
#include "avformat.h"
#include "rawdec.h"
#define APTX_BLOCK_SIZE 4
#define APTX_PACKET_SIZE (256*APTX_BLOCK_SIZE)
#define APTX_HD_BLOCK_SIZE 6
#define APTX_HD_PACKET_SIZE (256*APTX_HD_BLOCK_SIZE)
typedef struct AptXDemuxerContext {
AVClass *class;
int sample_rate;
} AptXDemuxerContext;
static AVStream *aptx_read_header_common(AVFormatContext *s)
{
AptXDemuxerContext *s1 = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return NULL;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->format = AV_SAMPLE_FMT_S32P;
st->codecpar->channels = 2;
st->codecpar->sample_rate = s1->sample_rate;
st->start_time = 0;
return st;
}
static int aptx_read_header(AVFormatContext *s)
{
AVStream *st = aptx_read_header_common(s);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_APTX;
st->codecpar->bits_per_coded_sample = 4;
st->codecpar->block_align = APTX_BLOCK_SIZE;
st->codecpar->frame_size = APTX_PACKET_SIZE;
return 0;
}
static int aptx_hd_read_header(AVFormatContext *s)
{
AVStream *st = aptx_read_header_common(s);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_APTX_HD;
st->codecpar->bits_per_coded_sample = 6;
st->codecpar->block_align = APTX_HD_BLOCK_SIZE;
st->codecpar->frame_size = APTX_HD_PACKET_SIZE;
return 0;
}
static int aptx_read_packet(AVFormatContext *s, AVPacket *pkt)
{
return av_get_packet(s->pb, pkt, APTX_PACKET_SIZE);
}
static int aptx_hd_read_packet(AVFormatContext *s, AVPacket *pkt)
{
return av_get_packet(s->pb, pkt, APTX_HD_PACKET_SIZE);
}
static const AVOption aptx_options[] = {
{ "sample_rate", "", offsetof(AptXDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
#if CONFIG_APTX_DEMUXER
static const AVClass aptx_demuxer_class = {
.class_name = "aptx demuxer",
.item_name = av_default_item_name,
.option = aptx_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_aptx_demuxer = {
.name = "aptx",
.long_name = NULL_IF_CONFIG_SMALL("raw aptX"),
.extensions = "aptx",
.priv_data_size = sizeof(AptXDemuxerContext),
.read_header = aptx_read_header,
.read_packet = aptx_read_packet,
.flags = AVFMT_GENERIC_INDEX,
.priv_class = &aptx_demuxer_class,
};
#endif
#if CONFIG_APTX_HD_DEMUXER
static const AVClass aptx_hd_demuxer_class = {
.class_name = "aptx hd demuxer",
.item_name = av_default_item_name,
.option = aptx_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_aptx_hd_demuxer = {
.name = "aptx_hd",
.long_name = NULL_IF_CONFIG_SMALL("raw aptX HD"),
.extensions = "aptxhd",
.priv_data_size = sizeof(AptXDemuxerContext),
.read_header = aptx_hd_read_header,
.read_packet = aptx_hd_read_packet,
.flags = AVFMT_GENERIC_INDEX,
.priv_class = &aptx_hd_demuxer_class,
};
#endif

151
externals/ffmpeg/libavformat/aqtitledec.c vendored Executable file
View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2012 Clément Bœsch
*
* 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
* AQTitle subtitles format demuxer
*
* @see http://web.archive.org/web/20070210095721/http://www.volny.cz/aberka/czech/aqt.html
* @see https://trac.annodex.net/wiki/AQTitle
*/
#include "avformat.h"
#include "internal.h"
#include "subtitles.h"
#include "libavutil/opt.h"
typedef struct {
const AVClass *class;
FFDemuxSubtitlesQueue q;
AVRational frame_rate;
} AQTitleContext;
static int aqt_probe(const AVProbeData *p)
{
int frame;
const char *ptr = p->buf;
if (sscanf(ptr, "-->> %d", &frame) == 1)
return AVPROBE_SCORE_EXTENSION;
return 0;
}
static int aqt_read_header(AVFormatContext *s)
{
AQTitleContext *aqt = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
int new_event = 1;
int64_t pos = 0, frame = AV_NOPTS_VALUE;
AVPacket *sub = NULL;
if (!st)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 64, aqt->frame_rate.den, aqt->frame_rate.num);
st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
st->codecpar->codec_id = AV_CODEC_ID_TEXT;
while (!avio_feof(s->pb)) {
char line[4096];
int len = ff_get_line(s->pb, line, sizeof(line));
if (!len)
break;
line[strcspn(line, "\r\n")] = 0;
if (sscanf(line, "-->> %"SCNd64, &frame) == 1) {
new_event = 1;
pos = avio_tell(s->pb);
if (sub) {
sub->duration = frame - sub->pts;
sub = NULL;
}
} else if (*line) {
if (!new_event) {
sub = ff_subtitles_queue_insert(&aqt->q, "\n", 1, 1);
if (!sub)
goto fail;
}
sub = ff_subtitles_queue_insert(&aqt->q, line, strlen(line), !new_event);
if (!sub)
goto fail;
if (new_event) {
sub->pts = frame;
sub->duration = -1;
sub->pos = pos;
}
new_event = 0;
}
}
ff_subtitles_queue_finalize(s, &aqt->q);
return 0;
fail:
ff_subtitles_queue_clean(&aqt->q);
return AVERROR(ENOMEM);
}
static int aqt_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AQTitleContext *aqt = s->priv_data;
return ff_subtitles_queue_read_packet(&aqt->q, pkt);
}
static int aqt_read_seek(AVFormatContext *s, int stream_index,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
AQTitleContext *aqt = s->priv_data;
return ff_subtitles_queue_seek(&aqt->q, s, stream_index,
min_ts, ts, max_ts, flags);
}
static int aqt_read_close(AVFormatContext *s)
{
AQTitleContext *aqt = s->priv_data;
ff_subtitles_queue_clean(&aqt->q);
return 0;
}
#define OFFSET(x) offsetof(AQTitleContext, x)
#define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
static const AVOption aqt_options[] = {
{ "subfps", "set the movie frame rate", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=25}, 0, INT_MAX, SD },
{ NULL }
};
static const AVClass aqt_class = {
.class_name = "aqtdec",
.item_name = av_default_item_name,
.option = aqt_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_aqtitle_demuxer = {
.name = "aqtitle",
.long_name = NULL_IF_CONFIG_SMALL("AQTitle subtitles"),
.priv_data_size = sizeof(AQTitleContext),
.read_probe = aqt_probe,
.read_header = aqt_read_header,
.read_packet = aqt_read_packet,
.read_seek2 = aqt_read_seek,
.read_close = aqt_read_close,
.extensions = "aqt",
.priv_class = &aqt_class,
};

249
externals/ffmpeg/libavformat/argo_asf.c vendored Executable file
View File

@@ -0,0 +1,249 @@
/*
* Argonaut Games ASF demuxer
*
* Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.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 "internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/avassert.h"
#define ASF_TAG MKTAG('A', 'S', 'F', '\0')
#define ASF_FILE_HEADER_SIZE 24
#define ASF_CHUNK_HEADER_SIZE 20
typedef struct ArgoASFFileHeader {
uint32_t magic; /*< Magic Number, {'A', 'S', 'F', '\0'} */
uint16_t version_major; /*< File Major Version. */
uint16_t version_minor; /*< File Minor Version. */
uint32_t num_chunks; /*< No. chunks in the file. */
uint32_t chunk_offset; /*< Offset to the first chunk from the start of the file. */
int8_t name[8]; /*< Name. */
} ArgoASFFileHeader;
typedef struct ArgoASFChunkHeader {
uint32_t num_blocks; /*< No. blocks in the chunk. */
uint32_t num_samples; /*< No. samples per channel in a block. */
uint32_t unk1; /*< Unknown */
uint16_t sample_rate; /*< Sample rate. */
uint16_t unk2; /*< Unknown. */
uint32_t flags; /*< Stream flags. */
} ArgoASFChunkHeader;
enum {
ASF_CF_BITS_PER_SAMPLE = (1 << 0), /*< 16-bit if set, 8 otherwise. */
ASF_CF_STEREO = (1 << 1), /*< Stereo if set, mono otherwise. */
ASF_CF_ALWAYS1_1 = (1 << 2), /*< Unknown, always seems to be set. */
ASF_CF_ALWAYS1_2 = (1 << 3), /*< Unknown, always seems to be set. */
ASF_CF_ALWAYS1 = ASF_CF_ALWAYS1_1 | ASF_CF_ALWAYS1_2,
ASF_CF_ALWAYS0 = ~(ASF_CF_BITS_PER_SAMPLE | ASF_CF_STEREO | ASF_CF_ALWAYS1)
};
typedef struct ArgoASFDemuxContext {
ArgoASFFileHeader fhdr;
ArgoASFChunkHeader ckhdr;
uint32_t blocks_read;
} ArgoASFDemuxContext;
static void argo_asf_parse_file_header(ArgoASFFileHeader *hdr, const uint8_t *buf)
{
hdr->magic = AV_RL32(buf + 0);
hdr->version_major = AV_RL16(buf + 4);
hdr->version_minor = AV_RL16(buf + 6);
hdr->num_chunks = AV_RL32(buf + 8);
hdr->chunk_offset = AV_RL32(buf + 12);
for (int i = 0; i < FF_ARRAY_ELEMS(hdr->name); i++)
hdr->name[i] = AV_RL8(buf + 16 + i);
}
static void argo_asf_parse_chunk_header(ArgoASFChunkHeader *hdr, const uint8_t *buf)
{
hdr->num_blocks = AV_RL32(buf + 0);
hdr->num_samples = AV_RL32(buf + 4);
hdr->unk1 = AV_RL32(buf + 8);
hdr->sample_rate = AV_RL16(buf + 12);
hdr->unk2 = AV_RL16(buf + 14);
hdr->flags = AV_RL32(buf + 16);
}
/*
* Known versions:
* 1.1: The sample files in /game-formats/brender/part2.zip
* 1.2: Croc! Legend of the Gobbos
* 2.1: Croc 2
*/
static int argo_asf_is_known_version(const ArgoASFFileHeader *hdr)
{
return (hdr->version_major == 1 && hdr->version_minor == 1) ||
(hdr->version_major == 1 && hdr->version_minor == 2) ||
(hdr->version_major == 2 && hdr->version_minor == 1);
}
static int argo_asf_probe(const AVProbeData *p)
{
ArgoASFFileHeader hdr;
av_assert0(AVPROBE_PADDING_SIZE >= ASF_FILE_HEADER_SIZE);
argo_asf_parse_file_header(&hdr, p->buf);
if (hdr.magic != ASF_TAG)
return 0;
if (!argo_asf_is_known_version(&hdr))
return AVPROBE_SCORE_EXTENSION / 2;
return AVPROBE_SCORE_EXTENSION + 1;
}
static int argo_asf_read_header(AVFormatContext *s)
{
int64_t ret;
AVIOContext *pb = s->pb;
AVStream *st;
ArgoASFDemuxContext *asf = s->priv_data;
uint8_t buf[FFMAX(ASF_FILE_HEADER_SIZE, ASF_CHUNK_HEADER_SIZE)];
if (!(st = avformat_new_stream(s, NULL)))
return AVERROR(ENOMEM);
if ((ret = avio_read(pb, buf, ASF_FILE_HEADER_SIZE)) < 0)
return ret;
else if (ret != ASF_FILE_HEADER_SIZE)
return AVERROR(EIO);
argo_asf_parse_file_header(&asf->fhdr, buf);
if (!argo_asf_is_known_version(&asf->fhdr)) {
avpriv_request_sample(s, "Version %hu.%hu",
asf->fhdr.version_major, asf->fhdr.version_minor
);
return AVERROR_PATCHWELCOME;
}
if (asf->fhdr.num_chunks == 0) {
return AVERROR_INVALIDDATA;
} else if (asf->fhdr.num_chunks > 1) {
avpriv_request_sample(s, ">1 chunk");
return AVERROR_PATCHWELCOME;
}
if (asf->fhdr.chunk_offset < ASF_FILE_HEADER_SIZE)
return AVERROR_INVALIDDATA;
if ((ret = avio_skip(pb, asf->fhdr.chunk_offset - ASF_FILE_HEADER_SIZE)) < 0)
return ret;
if ((ret = avio_read(pb, buf, ASF_CHUNK_HEADER_SIZE)) < 0)
return ret;
else if (ret != ASF_CHUNK_HEADER_SIZE)
return AVERROR(EIO);
argo_asf_parse_chunk_header(&asf->ckhdr, buf);
if ((asf->ckhdr.flags & ASF_CF_ALWAYS1) != ASF_CF_ALWAYS1 || (asf->ckhdr.flags & ASF_CF_ALWAYS0) != 0) {
avpriv_request_sample(s, "Nonstandard flags (0x%08X)", asf->ckhdr.flags);
return AVERROR_PATCHWELCOME;
}
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ARGO;
st->codecpar->format = AV_SAMPLE_FMT_S16P;
if (asf->ckhdr.flags & ASF_CF_STEREO) {
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
st->codecpar->channels = 2;
} else {
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->channels = 1;
}
st->codecpar->sample_rate = asf->ckhdr.sample_rate;
st->codecpar->bits_per_coded_sample = 4;
if (asf->ckhdr.flags & ASF_CF_BITS_PER_SAMPLE)
st->codecpar->bits_per_raw_sample = 16;
else
st->codecpar->bits_per_raw_sample = 8;
if (st->codecpar->bits_per_raw_sample != 16) {
/* The header allows for these, but I've never seen any files with them. */
avpriv_request_sample(s, "Non 16-bit samples");
return AVERROR_PATCHWELCOME;
}
/*
* (nchannel control bytes) + ((bytes_per_channel) * nchannel)
* For mono, this is 17. For stereo, this is 34.
*/
st->codecpar->frame_size = st->codecpar->channels +
(asf->ckhdr.num_samples / 2) *
st->codecpar->channels;
st->codecpar->block_align = st->codecpar->frame_size;
st->codecpar->bit_rate = st->codecpar->channels *
st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->start_time = 0;
st->duration = asf->ckhdr.num_blocks * asf->ckhdr.num_samples;
st->nb_frames = asf->ckhdr.num_blocks;
return 0;
}
static int argo_asf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ArgoASFDemuxContext *asf = s->priv_data;
AVStream *st = s->streams[0];
AVIOContext *pb = s->pb;
int ret;
if (asf->blocks_read >= asf->ckhdr.num_blocks)
return AVERROR_EOF;
if ((ret = av_get_packet(pb, pkt, st->codecpar->frame_size)) < 0)
return ret;
else if (ret != st->codecpar->frame_size)
return AVERROR_INVALIDDATA;
pkt->stream_index = st->index;
pkt->duration = asf->ckhdr.num_samples;
++asf->blocks_read;
return 0;
}
/*
* Not actually sure what ASF stands for.
* - Argonaut Sound File?
* - Audio Stream File?
*/
AVInputFormat ff_argo_asf_demuxer = {
.name = "argo_asf",
.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"),
.priv_data_size = sizeof(ArgoASFDemuxContext),
.read_probe = argo_asf_probe,
.read_header = argo_asf_read_header,
.read_packet = argo_asf_read_packet
};

178
externals/ffmpeg/libavformat/asf.c vendored Executable file
View File

@@ -0,0 +1,178 @@
/*
* 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 "asf.h"
const ff_asf_guid ff_asf_header = {
0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C
};
const ff_asf_guid ff_asf_file_header = {
0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};
const ff_asf_guid ff_asf_stream_header = {
0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};
const ff_asf_guid ff_asf_ext_stream_header = {
0xCB, 0xA5, 0xE6, 0x14, 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A
};
const ff_asf_guid ff_asf_audio_stream = {
0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
const ff_asf_guid ff_asf_audio_conceal_none = {
// 0x40, 0xa4, 0xf1, 0x49, 0x4ece, 0x11d0, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6
// New value lifted from avifile
0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b
};
const ff_asf_guid ff_asf_audio_conceal_spread = {
0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20
};
const ff_asf_guid ff_asf_video_stream = {
0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
const ff_asf_guid ff_asf_jfif_media = {
0x00, 0xE1, 0x1B, 0xB6, 0x4E, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
const ff_asf_guid ff_asf_video_conceal_none = {
0x00, 0x57, 0xFB, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
const ff_asf_guid ff_asf_command_stream = {
0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
};
const ff_asf_guid ff_asf_comment_header = {
0x33, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
};
const ff_asf_guid ff_asf_codec_comment_header = {
0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
};
const ff_asf_guid ff_asf_codec_comment1_header = {
0x41, 0x52, 0xd1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6
};
const ff_asf_guid ff_asf_data_header = {
0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
};
const ff_asf_guid ff_asf_head1_guid = {
0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
const ff_asf_guid ff_asf_head2_guid = {
0x11, 0xd2, 0xd3, 0xab, 0xBA, 0xA9, 0xCF, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
const ff_asf_guid ff_asf_extended_content_header = {
0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50
};
const ff_asf_guid ff_asf_simple_index_header = {
0x90, 0x08, 0x00, 0x33, 0xB1, 0xE5, 0xCF, 0x11, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB
};
const ff_asf_guid ff_asf_ext_stream_embed_stream_header = {
0xe2, 0x65, 0xfb, 0x3a, 0xEF, 0x47, 0xF2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43
};
const ff_asf_guid ff_asf_ext_stream_audio_stream = {
0x9d, 0x8c, 0x17, 0x31, 0xE1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03
};
const ff_asf_guid ff_asf_metadata_header = {
0xea, 0xcb, 0xf8, 0xc5, 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca
};
const ff_asf_guid ff_asf_metadata_library_header = {
0x94, 0x1c, 0x23, 0x44, 0x98, 0x94, 0xd1, 0x49, 0xa1, 0x41, 0x1d, 0x13, 0x4e, 0x45, 0x70, 0x54
};
const ff_asf_guid ff_asf_marker_header = {
0x01, 0xCD, 0x87, 0xF4, 0x51, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};
const ff_asf_guid ff_asf_reserved_4 = {
0x20, 0xdb, 0xfe, 0x4c, 0xf6, 0x75, 0xCF, 0x11, 0x9c, 0x0f, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb
};
/* I am not a number !!! This GUID is the one found on the PC used to
* generate the stream */
const ff_asf_guid ff_asf_my_guid = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
const ff_asf_guid ff_asf_language_guid = {
0xa9, 0x46, 0x43, 0x7c, 0xe0, 0xef, 0xfc, 0x4b, 0xb2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85
};
const ff_asf_guid ff_asf_content_encryption = {
0xfb, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e
};
const ff_asf_guid ff_asf_ext_content_encryption = {
0x14, 0xe6, 0x8a, 0x29, 0x22, 0x26, 0x17, 0x4c, 0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c
};
const ff_asf_guid ff_asf_digital_signature = {
0xfc, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e
};
const ff_asf_guid ff_asf_extended_stream_properties_object = {
0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a
};
const ff_asf_guid ff_asf_group_mutual_exclusion_object = {
0x40, 0x5a, 0x46, 0xd1, 0x79, 0x5a, 0x38, 0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49
};
const ff_asf_guid ff_asf_mutex_language = {
0x00, 0x2a, 0xe2, 0xd6, 0xda, 0x35, 0xd1, 0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe
};
/* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
const AVMetadataConv ff_asf_metadata_conv[] = {
{ "WM/AlbumArtist", "album_artist" },
{ "WM/AlbumTitle", "album" },
{ "Author", "artist" },
{ "Description", "comment" },
{ "WM/Composer", "composer" },
{ "WM/EncodedBy", "encoded_by" },
{ "WM/EncodingSettings", "encoder" },
{ "WM/Genre", "genre" },
{ "WM/Language", "language" },
{ "WM/OriginalFilename", "filename" },
{ "WM/PartOfSet", "disc" },
{ "WM/Publisher", "publisher" },
{ "WM/Tool", "encoder" },
{ "WM/TrackNumber", "track" },
{ "WM/MediaStationCallSign", "service_provider" },
{ "WM/MediaStationName", "service_name" },
// { "Year" , "date" }, TODO: conversion year<->date
{ 0 }
};

169
externals/ffmpeg/libavformat/asf.h vendored Executable file
View File

@@ -0,0 +1,169 @@
/*
* 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 AVFORMAT_ASF_H
#define AVFORMAT_ASF_H
#include <stdint.h>
#include "avformat.h"
#include "metadata.h"
#include "riff.h"
typedef enum ASFDataType {
ASF_UNICODE = 0,
ASF_BYTE_ARRAY = 1,
ASF_BOOL = 2,
ASF_DWORD = 3,
ASF_QWORD = 4,
ASF_WORD = 5,
ASF_GUID = 6,
}ASFDataType;
typedef struct ASFMainHeader {
ff_asf_guid guid; ///< generated by client computer
uint64_t file_size; /**< in bytes
* invalid if broadcasting */
uint64_t create_time; /**< time of creation, in 100-nanosecond units since 1.1.1601
* invalid if broadcasting */
uint64_t play_time; /**< play time, in 100-nanosecond units
* invalid if broadcasting */
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 - subtract from time */
uint32_t ignore; ///< preroll is 64 bits - but let's just ignore it
uint32_t flags; /**< 0x01 - broadcast
* 0x02 - seekable
* rest is reserved should be 0 */
uint32_t min_pktsize; /**< size of a data packet
* invalid if broadcasting */
uint32_t max_pktsize; /**< shall be the same as for min_pktsize
* invalid if broadcasting */
uint32_t max_bitrate; /**< bandwidth of stream in bps
* should be the sum of bitrates of the
* individual media streams */
} ASFMainHeader;
typedef struct ASFIndex {
uint32_t packet_number;
uint16_t packet_count;
uint64_t send_time;
uint64_t offset;
} ASFIndex;
extern const ff_asf_guid ff_asf_header;
extern const ff_asf_guid ff_asf_file_header;
extern const ff_asf_guid ff_asf_stream_header;
extern const ff_asf_guid ff_asf_ext_stream_header;
extern const ff_asf_guid ff_asf_audio_stream;
extern const ff_asf_guid ff_asf_audio_conceal_none;
extern const ff_asf_guid ff_asf_audio_conceal_spread;
extern const ff_asf_guid ff_asf_video_stream;
extern const ff_asf_guid ff_asf_jfif_media;
extern const ff_asf_guid ff_asf_video_conceal_none;
extern const ff_asf_guid ff_asf_command_stream;
extern const ff_asf_guid ff_asf_comment_header;
extern const ff_asf_guid ff_asf_codec_comment_header;
extern const ff_asf_guid ff_asf_codec_comment1_header;
extern const ff_asf_guid ff_asf_data_header;
extern const ff_asf_guid ff_asf_head1_guid;
extern const ff_asf_guid ff_asf_head2_guid;
extern const ff_asf_guid ff_asf_extended_content_header;
extern const ff_asf_guid ff_asf_simple_index_header;
extern const ff_asf_guid ff_asf_ext_stream_embed_stream_header;
extern const ff_asf_guid ff_asf_ext_stream_audio_stream;
extern const ff_asf_guid ff_asf_metadata_header;
extern const ff_asf_guid ff_asf_metadata_library_header;
extern const ff_asf_guid ff_asf_marker_header;
extern const ff_asf_guid ff_asf_reserved_4;
extern const ff_asf_guid ff_asf_my_guid;
extern const ff_asf_guid ff_asf_language_guid;
extern const ff_asf_guid ff_asf_content_encryption;
extern const ff_asf_guid ff_asf_ext_content_encryption;
extern const ff_asf_guid ff_asf_digital_signature;
extern const ff_asf_guid ff_asf_extended_stream_properties_object;
extern const ff_asf_guid ff_asf_group_mutual_exclusion_object;
extern const ff_asf_guid ff_asf_mutex_language;
extern const AVMetadataConv ff_asf_metadata_conv[];
#define ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT 0x80 //1000 0000
// ASF data packet structure
// =========================
//
//
// -----------------------------------
// | Error Correction Data | Optional
// -----------------------------------
// | Payload Parsing Information (PPI) |
// -----------------------------------
// | Payload Data |
// -----------------------------------
// | Padding Data |
// -----------------------------------
// PPI_FLAG - Payload parsing information flags
#define ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT 1
#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE 0x02 //0000 0010
#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD 0x04 //0000 0100
#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD 0x06 //0000 0110
#define ASF_PPI_MASK_SEQUENCE_FIELD_SIZE 0x06 //0000 0110
#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE 0x08 //0000 1000
#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD 0x10 //0001 0000
#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD 0x18 //0001 1000
#define ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE 0x18 //0001 1000
#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE 0x20 //0010 0000
#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD 0x40 //0100 0000
#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD 0x60 //0110 0000
#define ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE 0x60 //0110 0000
// PL_FLAG - Payload flags
#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE 0x01 //0000 0001
#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD 0x02 //0000 0010
#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD 0x03 //0000 0011
#define ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE 0x03 //0000 0011
#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE 0x04 //0000 0100
#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD 0x08 //0000 1000
#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD 0x0c //0000 1100
#define ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE 0x0c //0000 1100
#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE 0x10 //0001 0000
#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD 0x20 //0010 0000
#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD 0x30 //0011 0000
#define ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE 0x30 //0011 0000
#define ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE 0x40 //0100 0000
#define ASF_PL_MASK_STREAM_NUMBER_LENGTH_FIELD_SIZE 0xc0 //1100 0000
#define ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE 0x40 //0100 0000
#define ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD 0x80 //1000 0000
#define ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE 0xc0 //1100 0000
#define ASF_PL_FLAG_KEY_FRAME 0x80 //1000 0000
#endif /* AVFORMAT_ASF_H */

195
externals/ffmpeg/libavformat/asfcrypt.c vendored Executable file
View File

@@ -0,0 +1,195 @@
/*
* 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 "libavutil/bswap.h"
#include "libavutil/common.h"
#include "libavutil/des.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/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)
{
struct AVDES *des;
struct AVRC4 *rc4;
int num_qwords = len >> 3;
uint8_t *qwords = data;
uint64_t rc4buff[8] = { 0 };
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;
}
des = av_des_alloc();
rc4 = av_rc4_alloc();
if (!des || !rc4) {
av_freep(&des);
av_freep(&rc4);
return;
}
av_rc4_init(rc4, key, 12 * 8, 1);
av_rc4_crypt(rc4, (uint8_t *)rc4buff, NULL, sizeof(rc4buff), NULL, 1);
multiswap_init((uint8_t *)rc4buff, ms_keys);
packetkey = AV_RN64(&qwords[num_qwords * 8 - 8]);
packetkey ^= rc4buff[7];
av_des_init(des, key + 12, 64, 1);
av_des_crypt(des, (uint8_t *)&packetkey, (uint8_t *)&packetkey, 1, NULL, 1);
packetkey ^= rc4buff[6];
av_rc4_init(rc4, (uint8_t *)&packetkey, 64, 1);
av_rc4_crypt(rc4, data, data, len, NULL, 1);
ms_state = 0;
for (i = 0; i < num_qwords - 1; i++, qwords += 8)
ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords));
multiswap_invert_keys(ms_keys);
packetkey = (packetkey << 32) | (packetkey >> 32);
packetkey = av_le2ne64(packetkey);
packetkey = multiswap_dec(ms_keys, ms_state, packetkey);
AV_WL64(qwords, packetkey);
av_free(rc4);
av_free(des);
}

29
externals/ffmpeg/libavformat/asfcrypt.h vendored Executable file
View File

@@ -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 AVFORMAT_ASFCRYPT_H
#define AVFORMAT_ASFCRYPT_H
#include <inttypes.h>
void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len);
#endif /* AVFORMAT_ASFCRYPT_H */

1716
externals/ffmpeg/libavformat/asfdec_f.c vendored Executable file

File diff suppressed because it is too large Load Diff

1798
externals/ffmpeg/libavformat/asfdec_o.c vendored Executable file

File diff suppressed because it is too large Load Diff

1205
externals/ffmpeg/libavformat/asfenc.c vendored Executable file

File diff suppressed because it is too large Load Diff

194
externals/ffmpeg/libavformat/assdec.c vendored Executable file
View File

@@ -0,0 +1,194 @@
/*
* SSA/ASS demuxer
* Copyright (c) 2008 Michael Niedermayer
* Copyright (c) 2014 Clément Bœsch
*
* 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 <stdint.h>
#include "avformat.h"
#include "internal.h"
#include "subtitles.h"
#include "libavcodec/internal.h"
#include "libavutil/bprint.h"
typedef struct ASSContext {
FFDemuxSubtitlesQueue q;
unsigned readorder;
} ASSContext;
static int ass_probe(const AVProbeData *p)
{
char buf[13];
FFTextReader tr;
ff_text_init_buf(&tr, p->buf, p->buf_size);
while (ff_text_peek_r8(&tr) == '\r' || ff_text_peek_r8(&tr) == '\n')
ff_text_r8(&tr);
ff_text_read(&tr, buf, sizeof(buf));
if (!memcmp(buf, "[Script Info]", 13))
return AVPROBE_SCORE_MAX;
return 0;
}
static int ass_read_close(AVFormatContext *s)
{
ASSContext *ass = s->priv_data;
ff_subtitles_queue_clean(&ass->q);
return 0;
}
static int read_dialogue(ASSContext *ass, AVBPrint *dst, const uint8_t *p,
int64_t *start, int *duration)
{
int pos = 0;
int64_t end;
int hh1, mm1, ss1, ms1;
int hh2, mm2, ss2, ms2;
if (sscanf(p, "Dialogue: %*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d,%n",
&hh1, &mm1, &ss1, &ms1,
&hh2, &mm2, &ss2, &ms2, &pos) >= 8 && pos > 0) {
/* This is not part of the sscanf itself in order to handle an actual
* number (which would be the Layer) or the form "Marked=N" (which is
* the old SSA field, now replaced by Layer, and will lead to Layer
* being 0 here). */
const int layer = atoi(p + 10);
end = (hh2*3600LL + mm2*60LL + ss2) * 100LL + ms2;
*start = (hh1*3600LL + mm1*60LL + ss1) * 100LL + ms1;
*duration = end - *start;
av_bprint_clear(dst);
av_bprintf(dst, "%u,%d,%s", ass->readorder++, layer, p + pos);
/* right strip the buffer */
while (dst->len > 0 &&
dst->str[dst->len - 1] == '\r' ||
dst->str[dst->len - 1] == '\n')
dst->str[--dst->len] = 0;
return 0;
}
return -1;
}
static int64_t get_line(AVBPrint *buf, FFTextReader *tr)
{
int64_t pos = ff_text_pos(tr);
av_bprint_clear(buf);
for (;;) {
char c = ff_text_r8(tr);
if (!c)
break;
av_bprint_chars(buf, c, 1);
if (c == '\n')
break;
}
return pos;
}
static int ass_read_header(AVFormatContext *s)
{
ASSContext *ass = s->priv_data;
AVBPrint header, line, rline;
int res = 0;
AVStream *st;
FFTextReader tr;
ff_text_init_avio(s, &tr, s->pb);
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 64, 1, 100);
st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
st->codecpar->codec_id = AV_CODEC_ID_ASS;
av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprint_init(&rline, 0, AV_BPRINT_SIZE_UNLIMITED);
ass->q.keep_duplicates = 1;
for (;;) {
int64_t pos = get_line(&line, &tr);
int64_t ts_start = AV_NOPTS_VALUE;
int duration = -1;
AVPacket *sub;
if (!line.str[0]) // EOF
break;
if (read_dialogue(ass, &rline, line.str, &ts_start, &duration) < 0) {
av_bprintf(&header, "%s", line.str);
continue;
}
sub = ff_subtitles_queue_insert(&ass->q, rline.str, rline.len, 0);
if (!sub) {
res = AVERROR(ENOMEM);
goto end;
}
sub->pos = pos;
sub->pts = ts_start;
sub->duration = duration;
}
res = ff_bprint_to_codecpar_extradata(st->codecpar, &header);
if (res < 0)
goto end;
ff_subtitles_queue_finalize(s, &ass->q);
end:
if (res < 0)
ass_read_close(s);
av_bprint_finalize(&header, NULL);
av_bprint_finalize(&line, NULL);
av_bprint_finalize(&rline, NULL);
return res;
}
static int ass_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ASSContext *ass = s->priv_data;
return ff_subtitles_queue_read_packet(&ass->q, pkt);
}
static int ass_read_seek(AVFormatContext *s, int stream_index,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
ASSContext *ass = s->priv_data;
return ff_subtitles_queue_seek(&ass->q, s, stream_index,
min_ts, ts, max_ts, flags);
}
AVInputFormat ff_ass_demuxer = {
.name = "ass",
.long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
.priv_data_size = sizeof(ASSContext),
.read_probe = ass_probe,
.read_header = ass_read_header,
.read_packet = ass_read_packet,
.read_close = ass_read_close,
.read_seek2 = ass_read_seek,
};

241
externals/ffmpeg/libavformat/assenc.c vendored Executable file
View File

@@ -0,0 +1,241 @@
/*
* SSA/ASS muxer
* Copyright (c) 2008 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 "libavutil/avstring.h"
#include "avformat.h"
#include "internal.h"
#include "libavutil/opt.h"
typedef struct DialogueLine {
int readorder;
char *line;
struct DialogueLine *prev, *next;
} DialogueLine;
typedef struct ASSContext {
const AVClass *class;
int expected_readorder;
DialogueLine *dialogue_cache;
DialogueLine *last_added_dialogue;
int cache_size;
int ssa_mode;
int ignore_readorder;
uint8_t *trailer;
size_t trailer_size;
} ASSContext;
static int write_header(AVFormatContext *s)
{
ASSContext *ass = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_ASS) {
av_log(s, AV_LOG_ERROR, "Exactly one ASS/SSA stream is needed.\n");
return AVERROR(EINVAL);
}
avpriv_set_pts_info(s->streams[0], 64, 1, 100);
if (par->extradata_size > 0) {
size_t header_size = par->extradata_size;
uint8_t *trailer = strstr(par->extradata, "\n[Events]");
if (trailer)
trailer = strstr(trailer, "Format:");
if (trailer)
trailer = strstr(trailer, "\n");
if (trailer++) {
header_size = (trailer - par->extradata);
ass->trailer_size = par->extradata_size - header_size;
if (ass->trailer_size)
ass->trailer = trailer;
}
avio_write(s->pb, par->extradata, header_size);
if (par->extradata[header_size - 1] != '\n')
avio_write(s->pb, "\r\n", 2);
ass->ssa_mode = !strstr(par->extradata, "\n[V4+ Styles]");
if (!strstr(par->extradata, "\n[Events]"))
avio_printf(s->pb, "[Events]\r\nFormat: %s, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n",
ass->ssa_mode ? "Marked" : "Layer");
}
return 0;
}
static void purge_dialogues(AVFormatContext *s, int force)
{
int n = 0;
ASSContext *ass = s->priv_data;
DialogueLine *dialogue = ass->dialogue_cache;
while (dialogue && (dialogue->readorder == ass->expected_readorder || force)) {
DialogueLine *next = dialogue->next;
if (dialogue->readorder != ass->expected_readorder) {
av_log(s, AV_LOG_WARNING, "ReadOrder gap found between %d and %d\n",
ass->expected_readorder, dialogue->readorder);
ass->expected_readorder = dialogue->readorder;
}
avio_print(s->pb, "Dialogue: ", dialogue->line, "\r\n");
if (dialogue == ass->last_added_dialogue)
ass->last_added_dialogue = next;
av_freep(&dialogue->line);
av_free(dialogue);
if (next)
next->prev = NULL;
dialogue = ass->dialogue_cache = next;
ass->expected_readorder++;
n++;
}
ass->cache_size -= n;
if (n > 1)
av_log(s, AV_LOG_DEBUG, "wrote %d ASS lines, cached dialogues: %d, waiting for event id %d\n",
n, ass->cache_size, ass->expected_readorder);
}
static void insert_dialogue(ASSContext *ass, DialogueLine *dialogue)
{
DialogueLine *cur, *next = NULL, *prev = NULL;
/* from the last added to the end of the list */
if (ass->last_added_dialogue) {
for (cur = ass->last_added_dialogue; cur; cur = cur->next) {
if (cur->readorder > dialogue->readorder)
break;
prev = cur;
next = cur->next;
}
}
/* from the beginning to the last one added */
if (!prev) {
next = ass->dialogue_cache;
for (cur = next; cur != ass->last_added_dialogue; cur = cur->next) {
if (cur->readorder > dialogue->readorder)
break;
prev = cur;
next = cur->next;
}
}
if (prev) {
prev->next = dialogue;
dialogue->prev = prev;
} else {
dialogue->prev = ass->dialogue_cache;
ass->dialogue_cache = dialogue;
}
if (next) {
next->prev = dialogue;
dialogue->next = next;
}
ass->cache_size++;
ass->last_added_dialogue = dialogue;
}
static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
ASSContext *ass = s->priv_data;
long int layer;
char *p = pkt->data;
int64_t start = pkt->pts;
int64_t end = start + pkt->duration;
int hh1, mm1, ss1, ms1;
int hh2, mm2, ss2, ms2;
DialogueLine *dialogue = av_mallocz(sizeof(*dialogue));
if (!dialogue)
return AVERROR(ENOMEM);
dialogue->readorder = strtol(p, &p, 10);
if (dialogue->readorder < ass->expected_readorder)
av_log(s, AV_LOG_WARNING, "Unexpected ReadOrder %d\n",
dialogue->readorder);
if (*p == ',')
p++;
if (ass->ssa_mode && !strncmp(p, "Marked=", 7))
p += 7;
layer = strtol(p, &p, 10);
if (*p == ',')
p++;
hh1 = (int)(start / 360000); mm1 = (int)(start / 6000) % 60;
hh2 = (int)(end / 360000); mm2 = (int)(end / 6000) % 60;
ss1 = (int)(start / 100) % 60; ms1 = (int)(start % 100);
ss2 = (int)(end / 100) % 60; ms2 = (int)(end % 100);
if (hh1 > 9) hh1 = 9, mm1 = 59, ss1 = 59, ms1 = 99;
if (hh2 > 9) hh2 = 9, mm2 = 59, ss2 = 59, ms2 = 99;
dialogue->line = av_asprintf("%s%ld,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s",
ass->ssa_mode ? "Marked=" : "",
layer, hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, p);
if (!dialogue->line) {
av_free(dialogue);
return AVERROR(ENOMEM);
}
insert_dialogue(ass, dialogue);
purge_dialogues(s, ass->ignore_readorder);
return 0;
}
static int write_trailer(AVFormatContext *s)
{
ASSContext *ass = s->priv_data;
purge_dialogues(s, 1);
if (ass->trailer) {
avio_write(s->pb, ass->trailer, ass->trailer_size);
}
return 0;
}
#define OFFSET(x) offsetof(ASSContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "ignore_readorder", "write events immediately, even if they're out-of-order", OFFSET(ignore_readorder), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
{ NULL },
};
static const AVClass ass_class = {
.class_name = "ass muxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVOutputFormat ff_ass_muxer = {
.name = "ass",
.long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
.mime_type = "text/x-ass",
.extensions = "ass,ssa",
.priv_data_size = sizeof(ASSContext),
.subtitle_codec = AV_CODEC_ID_ASS,
.write_header = write_header,
.write_packet = write_packet,
.write_trailer = write_trailer,
.flags = AVFMT_GLOBALHEADER | AVFMT_NOTIMESTAMPS | AVFMT_TS_NONSTRICT,
.priv_class = &ass_class,
};

29
externals/ffmpeg/libavformat/ast.c vendored Executable file
View File

@@ -0,0 +1,29 @@
/*
* AST common code
* Copyright (c) 2012 James Almer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "internal.h"
const AVCodecTag ff_codec_ast_tags[] = {
{ AV_CODEC_ID_ADPCM_AFC, 0 },
{ AV_CODEC_ID_PCM_S16BE_PLANAR, 1 },
{ AV_CODEC_ID_NONE, 0 },
};

30
externals/ffmpeg/libavformat/ast.h vendored Executable file
View File

@@ -0,0 +1,30 @@
/*
* AST common code
* Copyright (c) 2012 James Almer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_AST_H
#define AVFORMAT_AST_H
#include "avformat.h"
#include "internal.h"
extern const AVCodecTag ff_codec_ast_tags[];
#endif /* AVFORMAT_AST_H */

122
externals/ffmpeg/libavformat/astdec.c vendored Executable file
View File

@@ -0,0 +1,122 @@
/*
* AST demuxer
* Copyright (c) 2012 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
#include "ast.h"
static int ast_probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) != MKTAG('S','T','R','M'))
return 0;
if (!AV_RB16(p->buf + 10) ||
!AV_RB16(p->buf + 12) || AV_RB16(p->buf + 12) > 256 ||
!AV_RB32(p->buf + 16) || AV_RB32(p->buf + 16) > 8*48000)
return AVPROBE_SCORE_MAX / 8;
return AVPROBE_SCORE_MAX / 3 * 2;
}
static int ast_read_header(AVFormatContext *s)
{
int depth;
AVStream *st;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
avio_skip(s->pb, 8);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = ff_codec_get_id(ff_codec_ast_tags, avio_rb16(s->pb));
depth = avio_rb16(s->pb);
if (depth != 16) {
avpriv_request_sample(s, "depth %d", depth);
return AVERROR_INVALIDDATA;
}
st->codecpar->channels = avio_rb16(s->pb);
if (!st->codecpar->channels)
return AVERROR_INVALIDDATA;
if (st->codecpar->channels == 2)
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
else if (st->codecpar->channels == 4)
st->codecpar->channel_layout = AV_CH_LAYOUT_4POINT0;
avio_skip(s->pb, 2);
st->codecpar->sample_rate = avio_rb32(s->pb);
if (st->codecpar->sample_rate <= 0)
return AVERROR_INVALIDDATA;
st->start_time = 0;
st->duration = avio_rb32(s->pb);
avio_skip(s->pb, 40);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int ast_read_packet(AVFormatContext *s, AVPacket *pkt)
{
uint32_t type, size;
int64_t pos;
int ret;
if (avio_feof(s->pb))
return AVERROR_EOF;
pos = avio_tell(s->pb);
type = avio_rl32(s->pb);
size = avio_rb32(s->pb);
if (!s->streams[0]->codecpar->channels || size > INT_MAX / s->streams[0]->codecpar->channels)
return AVERROR_INVALIDDATA;
size *= s->streams[0]->codecpar->channels;
if ((ret = avio_skip(s->pb, 24)) < 0) // padding
return ret;
if (type == MKTAG('B','L','C','K')) {
ret = av_get_packet(s->pb, pkt, size);
pkt->stream_index = 0;
pkt->pos = pos;
} else {
av_log(s, AV_LOG_ERROR, "unknown chunk %"PRIx32"\n", type);
avio_skip(s->pb, size);
ret = AVERROR_INVALIDDATA;
}
return ret;
}
AVInputFormat ff_ast_demuxer = {
.name = "ast",
.long_name = NULL_IF_CONFIG_SMALL("AST (Audio Stream)"),
.read_probe = ast_probe,
.read_header = ast_read_header,
.read_packet = ast_read_packet,
.extensions = "ast",
.flags = AVFMT_GENERIC_INDEX,
.codec_tag = (const AVCodecTag* const []){ff_codec_ast_tags, 0},
};

211
externals/ffmpeg/libavformat/astenc.c vendored Executable file
View File

@@ -0,0 +1,211 @@
/*
* AST muxer
* Copyright (c) 2012 James Almer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
#include "ast.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
typedef struct ASTMuxContext {
AVClass *class;
int64_t size;
int64_t samples;
int64_t loopstart;
int64_t loopend;
int fbs;
} ASTMuxContext;
#define CHECK_LOOP(type) \
if (ast->loop ## type > 0) { \
ast->loop ## type = av_rescale_rnd(ast->loop ## type, par->sample_rate, 1000, AV_ROUND_DOWN); \
if (ast->loop ## type < 0 || ast->loop ## type > UINT_MAX) { \
av_log(s, AV_LOG_ERROR, "Invalid loop" #type " value\n"); \
return AVERROR(EINVAL); \
} \
}
static int ast_write_header(AVFormatContext *s)
{
ASTMuxContext *ast = s->priv_data;
AVIOContext *pb = s->pb;
AVCodecParameters *par;
unsigned int codec_tag;
if (s->nb_streams == 1) {
par = s->streams[0]->codecpar;
} else {
av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
return AVERROR(EINVAL);
}
if (par->codec_id == AV_CODEC_ID_ADPCM_AFC) {
av_log(s, AV_LOG_ERROR, "muxing ADPCM AFC is not implemented\n");
return AVERROR_PATCHWELCOME;
}
codec_tag = ff_codec_get_tag(ff_codec_ast_tags, par->codec_id);
if (!codec_tag) {
av_log(s, AV_LOG_ERROR, "unsupported codec\n");
return AVERROR(EINVAL);
}
if (ast->loopend > 0 && ast->loopstart >= ast->loopend) {
av_log(s, AV_LOG_ERROR, "loopend can't be less or equal to loopstart\n");
return AVERROR(EINVAL);
}
/* Convert milliseconds to samples */
CHECK_LOOP(start)
CHECK_LOOP(end)
ffio_wfourcc(pb, "STRM");
ast->size = avio_tell(pb);
avio_wb32(pb, 0); /* File size minus header */
avio_wb16(pb, codec_tag);
avio_wb16(pb, 16); /* Bit depth */
avio_wb16(pb, par->channels);
avio_wb16(pb, 0); /* Loop flag */
avio_wb32(pb, par->sample_rate);
ast->samples = avio_tell(pb);
avio_wb32(pb, 0); /* Number of samples */
avio_wb32(pb, 0); /* Loopstart */
avio_wb32(pb, 0); /* Loopend */
avio_wb32(pb, 0); /* Size of first block */
/* Unknown */
avio_wb32(pb, 0);
avio_wl32(pb, 0x7F);
avio_wb64(pb, 0);
avio_wb64(pb, 0);
avio_wb32(pb, 0);
return 0;
}
static int ast_write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
ASTMuxContext *ast = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
int size = pkt->size / par->channels;
if (s->streams[0]->nb_frames == 0)
ast->fbs = size;
ffio_wfourcc(pb, "BLCK");
avio_wb32(pb, size); /* Block size */
/* padding */
avio_wb64(pb, 0);
avio_wb64(pb, 0);
avio_wb64(pb, 0);
avio_write(pb, pkt->data, pkt->size);
return 0;
}
static int ast_write_trailer(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
ASTMuxContext *ast = s->priv_data;
AVCodecParameters *par = s->streams[0]->codecpar;
int64_t file_size = avio_tell(pb);
int64_t samples = (file_size - 64 - (32 * s->streams[0]->nb_frames)) / par->block_align; /* PCM_S16BE_PLANAR */
av_log(s, AV_LOG_DEBUG, "total samples: %"PRId64"\n", samples);
if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
/* Number of samples */
avio_seek(pb, ast->samples, SEEK_SET);
avio_wb32(pb, samples);
/* Loopstart if provided */
if (ast->loopstart > 0) {
if (ast->loopstart >= samples) {
av_log(s, AV_LOG_WARNING, "Loopstart value is out of range and will be ignored\n");
ast->loopstart = -1;
avio_skip(pb, 4);
} else
avio_wb32(pb, ast->loopstart);
} else
avio_skip(pb, 4);
/* Loopend if provided. Otherwise number of samples again */
if (ast->loopend && ast->loopstart >= 0) {
if (ast->loopend > samples) {
av_log(s, AV_LOG_WARNING, "Loopend value is out of range and will be ignored\n");
ast->loopend = samples;
}
avio_wb32(pb, ast->loopend);
} else {
avio_wb32(pb, samples);
}
/* Size of first block */
avio_wb32(pb, ast->fbs);
/* File size minus header */
avio_seek(pb, ast->size, SEEK_SET);
avio_wb32(pb, file_size - 64);
/* Loop flag */
if (ast->loopstart >= 0) {
avio_skip(pb, 6);
avio_wb16(pb, 0xFFFF);
}
avio_seek(pb, file_size, SEEK_SET);
}
return 0;
}
#define OFFSET(obj) offsetof(ASTMuxContext, obj)
static const AVOption options[] = {
{ "loopstart", "Loopstart position in milliseconds.", OFFSET(loopstart), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ "loopend", "Loopend position in milliseconds.", OFFSET(loopend), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ NULL },
};
static const AVClass ast_muxer_class = {
.class_name = "AST muxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVOutputFormat ff_ast_muxer = {
.name = "ast",
.long_name = NULL_IF_CONFIG_SMALL("AST (Audio Stream)"),
.extensions = "ast",
.priv_data_size = sizeof(ASTMuxContext),
.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR,
.video_codec = AV_CODEC_ID_NONE,
.write_header = ast_write_header,
.write_packet = ast_write_packet,
.write_trailer = ast_write_trailer,
.priv_class = &ast_muxer_class,
.codec_tag = (const AVCodecTag* const []){ff_codec_ast_tags, 0},
};

699
externals/ffmpeg/libavformat/async.c vendored Executable file
View File

@@ -0,0 +1,699 @@
/*
* Input async protocol.
* Copyright (c) 2015 Zhang Rui <bbcallen@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
*
* Based on libavformat/cache.c by Michael Niedermayer
*/
/**
* @TODO
* support timeout
* support work with concatdec, hls
*/
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/error.h"
#include "libavutil/fifo.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/thread.h"
#include "url.h"
#include <stdint.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#define BUFFER_CAPACITY (4 * 1024 * 1024)
#define READ_BACK_CAPACITY (4 * 1024 * 1024)
#define SHORT_SEEK_THRESHOLD (256 * 1024)
typedef struct RingBuffer
{
AVFifoBuffer *fifo;
int read_back_capacity;
int read_pos;
} RingBuffer;
typedef struct Context {
AVClass *class;
URLContext *inner;
int seek_request;
int64_t seek_pos;
int seek_whence;
int seek_completed;
int64_t seek_ret;
int inner_io_error;
int io_error;
int io_eof_reached;
int64_t logical_pos;
int64_t logical_size;
RingBuffer ring;
pthread_cond_t cond_wakeup_main;
pthread_cond_t cond_wakeup_background;
pthread_mutex_t mutex;
pthread_t async_buffer_thread;
int abort_request;
AVIOInterruptCB interrupt_callback;
} Context;
static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
{
memset(ring, 0, sizeof(RingBuffer));
ring->fifo = av_fifo_alloc(capacity + read_back_capacity);
if (!ring->fifo)
return AVERROR(ENOMEM);
ring->read_back_capacity = read_back_capacity;
return 0;
}
static void ring_destroy(RingBuffer *ring)
{
av_fifo_freep(&ring->fifo);
}
static void ring_reset(RingBuffer *ring)
{
av_fifo_reset(ring->fifo);
ring->read_pos = 0;
}
static int ring_size(RingBuffer *ring)
{
return av_fifo_size(ring->fifo) - ring->read_pos;
}
static int ring_space(RingBuffer *ring)
{
return av_fifo_space(ring->fifo);
}
static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void (*func)(void*, void*, int))
{
int ret;
av_assert2(buf_size <= ring_size(ring));
ret = av_fifo_generic_peek_at(ring->fifo, dest, ring->read_pos, buf_size, func);
ring->read_pos += buf_size;
if (ring->read_pos > ring->read_back_capacity) {
av_fifo_drain(ring->fifo, ring->read_pos - ring->read_back_capacity);
ring->read_pos = ring->read_back_capacity;
}
return ret;
}
static int ring_generic_write(RingBuffer *ring, void *src, int size, int (*func)(void*, void*, int))
{
av_assert2(size <= ring_space(ring));
return av_fifo_generic_write(ring->fifo, src, size, func);
}
static int ring_size_of_read_back(RingBuffer *ring)
{
return ring->read_pos;
}
static int ring_drain(RingBuffer *ring, int offset)
{
av_assert2(offset >= -ring_size_of_read_back(ring));
av_assert2(offset <= ring_size(ring));
ring->read_pos += offset;
return 0;
}
static int async_check_interrupt(void *arg)
{
URLContext *h = arg;
Context *c = h->priv_data;
if (c->abort_request)
return 1;
if (ff_check_interrupt(&c->interrupt_callback))
c->abort_request = 1;
return c->abort_request;
}
static int wrapped_url_read(void *src, void *dst, int size)
{
URLContext *h = src;
Context *c = h->priv_data;
int ret;
ret = ffurl_read(c->inner, dst, size);
c->inner_io_error = ret < 0 ? ret : 0;
return ret;
}
static void *async_buffer_task(void *arg)
{
URLContext *h = arg;
Context *c = h->priv_data;
RingBuffer *ring = &c->ring;
int ret = 0;
int64_t seek_ret;
while (1) {
int fifo_space, to_copy;
pthread_mutex_lock(&c->mutex);
if (async_check_interrupt(h)) {
c->io_eof_reached = 1;
c->io_error = AVERROR_EXIT;
pthread_cond_signal(&c->cond_wakeup_main);
pthread_mutex_unlock(&c->mutex);
break;
}
if (c->seek_request) {
seek_ret = ffurl_seek(c->inner, c->seek_pos, c->seek_whence);
if (seek_ret >= 0) {
c->io_eof_reached = 0;
c->io_error = 0;
ring_reset(ring);
}
c->seek_completed = 1;
c->seek_ret = seek_ret;
c->seek_request = 0;
pthread_cond_signal(&c->cond_wakeup_main);
pthread_mutex_unlock(&c->mutex);
continue;
}
fifo_space = ring_space(ring);
if (c->io_eof_reached || fifo_space <= 0) {
pthread_cond_signal(&c->cond_wakeup_main);
pthread_cond_wait(&c->cond_wakeup_background, &c->mutex);
pthread_mutex_unlock(&c->mutex);
continue;
}
pthread_mutex_unlock(&c->mutex);
to_copy = FFMIN(4096, fifo_space);
ret = ring_generic_write(ring, (void *)h, to_copy, wrapped_url_read);
pthread_mutex_lock(&c->mutex);
if (ret <= 0) {
c->io_eof_reached = 1;
if (c->inner_io_error < 0)
c->io_error = c->inner_io_error;
}
pthread_cond_signal(&c->cond_wakeup_main);
pthread_mutex_unlock(&c->mutex);
}
return NULL;
}
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
int ret;
AVIOInterruptCB interrupt_callback = {.callback = async_check_interrupt, .opaque = h};
av_strstart(arg, "async:", &arg);
ret = ring_init(&c->ring, BUFFER_CAPACITY, READ_BACK_CAPACITY);
if (ret < 0)
goto fifo_fail;
/* wrap interrupt callback */
c->interrupt_callback = h->interrupt_callback;
ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h);
if (ret != 0) {
av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
goto url_fail;
}
c->logical_size = ffurl_size(c->inner);
h->is_streamed = c->inner->is_streamed;
ret = pthread_mutex_init(&c->mutex, NULL);
if (ret != 0) {
av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret));
goto mutex_fail;
}
ret = pthread_cond_init(&c->cond_wakeup_main, NULL);
if (ret != 0) {
av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
goto cond_wakeup_main_fail;
}
ret = pthread_cond_init(&c->cond_wakeup_background, NULL);
if (ret != 0) {
av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
goto cond_wakeup_background_fail;
}
ret = pthread_create(&c->async_buffer_thread, NULL, async_buffer_task, h);
if (ret) {
av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", av_err2str(ret));
goto thread_fail;
}
return 0;
thread_fail:
pthread_cond_destroy(&c->cond_wakeup_background);
cond_wakeup_background_fail:
pthread_cond_destroy(&c->cond_wakeup_main);
cond_wakeup_main_fail:
pthread_mutex_destroy(&c->mutex);
mutex_fail:
ffurl_closep(&c->inner);
url_fail:
ring_destroy(&c->ring);
fifo_fail:
return ret;
}
static int async_close(URLContext *h)
{
Context *c = h->priv_data;
int ret;
pthread_mutex_lock(&c->mutex);
c->abort_request = 1;
pthread_cond_signal(&c->cond_wakeup_background);
pthread_mutex_unlock(&c->mutex);
ret = pthread_join(c->async_buffer_thread, NULL);
if (ret != 0)
av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
pthread_cond_destroy(&c->cond_wakeup_background);
pthread_cond_destroy(&c->cond_wakeup_main);
pthread_mutex_destroy(&c->mutex);
ffurl_closep(&c->inner);
ring_destroy(&c->ring);
return 0;
}
static int async_read_internal(URLContext *h, void *dest, int size, int read_complete,
void (*func)(void*, void*, int))
{
Context *c = h->priv_data;
RingBuffer *ring = &c->ring;
int to_read = size;
int ret = 0;
pthread_mutex_lock(&c->mutex);
while (to_read > 0) {
int fifo_size, to_copy;
if (async_check_interrupt(h)) {
ret = AVERROR_EXIT;
break;
}
fifo_size = ring_size(ring);
to_copy = FFMIN(to_read, fifo_size);
if (to_copy > 0) {
ring_generic_read(ring, dest, to_copy, func);
if (!func)
dest = (uint8_t *)dest + to_copy;
c->logical_pos += to_copy;
to_read -= to_copy;
ret = size - to_read;
if (to_read <= 0 || !read_complete)
break;
} else if (c->io_eof_reached) {
if (ret <= 0) {
if (c->io_error)
ret = c->io_error;
else
ret = AVERROR_EOF;
}
break;
}
pthread_cond_signal(&c->cond_wakeup_background);
pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
}
pthread_cond_signal(&c->cond_wakeup_background);
pthread_mutex_unlock(&c->mutex);
return ret;
}
static int async_read(URLContext *h, unsigned char *buf, int size)
{
return async_read_internal(h, buf, size, 0, NULL);
}
static void fifo_do_not_copy_func(void* dest, void* src, int size) {
// do not copy
}
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
RingBuffer *ring = &c->ring;
int64_t ret;
int64_t new_logical_pos;
int fifo_size;
int fifo_size_of_read_back;
if (whence == AVSEEK_SIZE) {
av_log(h, AV_LOG_TRACE, "async_seek: AVSEEK_SIZE: %"PRId64"\n", (int64_t)c->logical_size);
return c->logical_size;
} else if (whence == SEEK_CUR) {
av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
new_logical_pos = pos + c->logical_pos;
} else if (whence == SEEK_SET){
av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
new_logical_pos = pos;
} else {
return AVERROR(EINVAL);
}
if (new_logical_pos < 0)
return AVERROR(EINVAL);
fifo_size = ring_size(ring);
fifo_size_of_read_back = ring_size_of_read_back(ring);
if (new_logical_pos == c->logical_pos) {
/* current position */
return c->logical_pos;
} else if ((new_logical_pos >= (c->logical_pos - fifo_size_of_read_back)) &&
(new_logical_pos < (c->logical_pos + fifo_size + SHORT_SEEK_THRESHOLD))) {
int pos_delta = (int)(new_logical_pos - c->logical_pos);
/* fast seek */
av_log(h, AV_LOG_TRACE, "async_seek: fask_seek %"PRId64" from %d dist:%d/%d\n",
new_logical_pos, (int)c->logical_pos,
(int)(new_logical_pos - c->logical_pos), fifo_size);
if (pos_delta > 0) {
// fast seek forwards
async_read_internal(h, NULL, pos_delta, 1, fifo_do_not_copy_func);
} else {
// fast seek backwards
ring_drain(ring, pos_delta);
c->logical_pos = new_logical_pos;
}
return c->logical_pos;
} else if (c->logical_size <= 0) {
/* can not seek */
return AVERROR(EINVAL);
} else if (new_logical_pos > c->logical_size) {
/* beyond end */
return AVERROR(EINVAL);
}
pthread_mutex_lock(&c->mutex);
c->seek_request = 1;
c->seek_pos = new_logical_pos;
c->seek_whence = SEEK_SET;
c->seek_completed = 0;
c->seek_ret = 0;
while (1) {
if (async_check_interrupt(h)) {
ret = AVERROR_EXIT;
break;
}
if (c->seek_completed) {
if (c->seek_ret >= 0)
c->logical_pos = c->seek_ret;
ret = c->seek_ret;
break;
}
pthread_cond_signal(&c->cond_wakeup_background);
pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
}
pthread_mutex_unlock(&c->mutex);
return ret;
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{NULL},
};
#undef D
#undef OFFSET
static const AVClass async_context_class = {
.class_name = "Async",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
const URLProtocol ff_async_protocol = {
.name = "async",
.url_open2 = async_open,
.url_read = async_read,
.url_seek = async_seek,
.url_close = async_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &async_context_class,
};
#if 0
#define TEST_SEEK_POS (1536)
#define TEST_STREAM_SIZE (2048)
typedef struct TestContext {
AVClass *class;
int64_t logical_pos;
int64_t logical_size;
/* options */
int opt_read_error;
} TestContext;
static int async_test_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
TestContext *c = h->priv_data;
c->logical_pos = 0;
c->logical_size = TEST_STREAM_SIZE;
return 0;
}
static int async_test_close(URLContext *h)
{
return 0;
}
static int async_test_read(URLContext *h, unsigned char *buf, int size)
{
TestContext *c = h->priv_data;
int i;
int read_len = 0;
if (c->opt_read_error)
return c->opt_read_error;
if (c->logical_pos >= c->logical_size)
return AVERROR_EOF;
for (i = 0; i < size; ++i) {
buf[i] = c->logical_pos & 0xFF;
c->logical_pos++;
read_len++;
if (c->logical_pos >= c->logical_size)
break;
}
return read_len;
}
static int64_t async_test_seek(URLContext *h, int64_t pos, int whence)
{
TestContext *c = h->priv_data;
int64_t new_logical_pos;
if (whence == AVSEEK_SIZE) {
return c->logical_size;
} else if (whence == SEEK_CUR) {
new_logical_pos = pos + c->logical_pos;
} else if (whence == SEEK_SET){
new_logical_pos = pos;
} else {
return AVERROR(EINVAL);
}
if (new_logical_pos < 0)
return AVERROR(EINVAL);
c->logical_pos = new_logical_pos;
return new_logical_pos;
}
#define OFFSET(x) offsetof(TestContext, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption async_test_options[] = {
{ "async-test-read-error", "cause read fail",
OFFSET(opt_read_error), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = D },
{NULL},
};
#undef D
#undef OFFSET
static const AVClass async_test_context_class = {
.class_name = "Async-Test",
.item_name = av_default_item_name,
.option = async_test_options,
.version = LIBAVUTIL_VERSION_INT,
};
const URLProtocol ff_async_test_protocol = {
.name = "async-test",
.url_open2 = async_test_open,
.url_read = async_test_read,
.url_seek = async_test_seek,
.url_close = async_test_close,
.priv_data_size = sizeof(TestContext),
.priv_data_class = &async_test_context_class,
};
int main(void)
{
URLContext *h = NULL;
int i;
int ret;
int64_t size;
int64_t pos;
int64_t read_len;
unsigned char buf[4096];
AVDictionary *opts = NULL;
ffurl_register_protocol(&ff_async_protocol);
ffurl_register_protocol(&ff_async_test_protocol);
/*
* test normal read
*/
ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, NULL);
printf("open: %d\n", ret);
size = ffurl_size(h);
printf("size: %"PRId64"\n", size);
pos = ffurl_seek(h, 0, SEEK_CUR);
read_len = 0;
while (1) {
ret = ffurl_read(h, buf, sizeof(buf));
if (ret == AVERROR_EOF) {
printf("read-error: AVERROR_EOF at %"PRId64"\n", ffurl_seek(h, 0, SEEK_CUR));
break;
}
else if (ret == 0)
break;
else if (ret < 0) {
printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
goto fail;
} else {
for (i = 0; i < ret; ++i) {
if (buf[i] != (pos & 0xFF)) {
printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
(int)buf[i], (int)(pos & 0xFF), pos);
break;
}
pos++;
}
}
read_len += ret;
}
printf("read: %"PRId64"\n", read_len);
/*
* test normal seek
*/
ret = ffurl_read(h, buf, 1);
printf("read: %d\n", ret);
pos = ffurl_seek(h, TEST_SEEK_POS, SEEK_SET);
printf("seek: %"PRId64"\n", pos);
read_len = 0;
while (1) {
ret = ffurl_read(h, buf, sizeof(buf));
if (ret == AVERROR_EOF)
break;
else if (ret == 0)
break;
else if (ret < 0) {
printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
goto fail;
} else {
for (i = 0; i < ret; ++i) {
if (buf[i] != (pos & 0xFF)) {
printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
(int)buf[i], (int)(pos & 0xFF), pos);
break;
}
pos++;
}
}
read_len += ret;
}
printf("read: %"PRId64"\n", read_len);
ret = ffurl_read(h, buf, 1);
printf("read: %d\n", ret);
/*
* test read error
*/
ffurl_close(h);
av_dict_set_int(&opts, "async-test-read-error", -10000, 0);
ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, &opts);
printf("open: %d\n", ret);
ret = ffurl_read(h, buf, 1);
printf("read: %d\n", ret);
fail:
av_dict_free(&opts);
ffurl_close(h);
return 0;
}
#endif

349
externals/ffmpeg/libavformat/au.c vendored Executable file
View File

@@ -0,0 +1,349 @@
/*
* AU muxer and demuxer
* Copyright (c) 2001 Fabrice Bellard
*
* first version by Francois Revol <revol@free.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
*/
/*
* Reference documents:
* http://www.opengroup.org/public/pubs/external/auformat.html
* http://www.goice.co.jp/member/mo/formats/au.html
*/
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
#include "pcm.h"
#include "libavutil/avassert.h"
/* if we don't know the size in advance */
#define AU_UNKNOWN_SIZE ((uint32_t)(~0))
/* the specification requires an annotation field of at least eight bytes */
#define AU_DEFAULT_HEADER_SIZE (24+8)
static const AVCodecTag codec_au_tags[] = {
{ AV_CODEC_ID_PCM_MULAW, 1 },
{ AV_CODEC_ID_PCM_S8, 2 },
{ AV_CODEC_ID_PCM_S16BE, 3 },
{ AV_CODEC_ID_PCM_S24BE, 4 },
{ AV_CODEC_ID_PCM_S32BE, 5 },
{ AV_CODEC_ID_PCM_F32BE, 6 },
{ AV_CODEC_ID_PCM_F64BE, 7 },
{ AV_CODEC_ID_ADPCM_G726LE, 23 },
{ AV_CODEC_ID_ADPCM_G722,24 },
{ AV_CODEC_ID_ADPCM_G726LE, 25 },
{ AV_CODEC_ID_ADPCM_G726LE, 26 },
{ AV_CODEC_ID_PCM_ALAW, 27 },
{ AV_CODEC_ID_ADPCM_G726LE, MKBETAG('7','2','6','2') },
{ AV_CODEC_ID_NONE, 0 },
};
#if CONFIG_AU_DEMUXER
static int au_probe(const AVProbeData *p)
{
if (p->buf[0] == '.' && p->buf[1] == 's' &&
p->buf[2] == 'n' && p->buf[3] == 'd')
return AVPROBE_SCORE_MAX;
else
return 0;
}
static int au_read_annotation(AVFormatContext *s, int size)
{
static const char * keys[] = {
"title",
"artist",
"album",
"track",
"genre",
NULL };
AVIOContext *pb = s->pb;
enum { PARSE_KEY, PARSE_VALUE, PARSE_FINISHED } state = PARSE_KEY;
char c;
AVBPrint bprint;
char * key = NULL;
char * value = NULL;
int i;
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
while (size-- > 0) {
c = avio_r8(pb);
switch(state) {
case PARSE_KEY:
if (c == '\0') {
state = PARSE_FINISHED;
} else if (c == '=') {
av_bprint_finalize(&bprint, &key);
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
state = PARSE_VALUE;
} else {
av_bprint_chars(&bprint, c, 1);
}
break;
case PARSE_VALUE:
if (c == '\0' || c == '\n') {
if (av_bprint_finalize(&bprint, &value) != 0) {
av_log(s, AV_LOG_ERROR, "Memory error while parsing AU metadata.\n");
} else {
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
for (i = 0; keys[i] != NULL && key != NULL; i++) {
if (av_strcasecmp(keys[i], key) == 0) {
av_dict_set(&(s->metadata), keys[i], value, AV_DICT_DONT_STRDUP_VAL);
av_freep(&key);
value = NULL;
}
}
}
av_freep(&key);
av_freep(&value);
state = (c == '\0') ? PARSE_FINISHED : PARSE_KEY;
} else {
av_bprint_chars(&bprint, c, 1);
}
break;
case PARSE_FINISHED:
break;
default:
/* should never happen */
av_assert0(0);
}
}
av_bprint_finalize(&bprint, NULL);
av_freep(&key);
return 0;
}
#define BLOCK_SIZE 1024
static int au_read_header(AVFormatContext *s)
{
int size, data_size = 0;
unsigned int tag;
AVIOContext *pb = s->pb;
unsigned int id, channels, rate;
int bps, ba = 0;
enum AVCodecID codec;
AVStream *st;
tag = avio_rl32(pb);
if (tag != MKTAG('.', 's', 'n', 'd'))
return AVERROR_INVALIDDATA;
size = avio_rb32(pb); /* header size */
data_size = avio_rb32(pb); /* data size in bytes */
if (data_size < 0 && data_size != AU_UNKNOWN_SIZE) {
av_log(s, AV_LOG_ERROR, "Invalid negative data size '%d' found\n", data_size);
return AVERROR_INVALIDDATA;
}
id = avio_rb32(pb);
rate = avio_rb32(pb);
channels = avio_rb32(pb);
if (size > 24) {
/* parse annotation field to get metadata */
au_read_annotation(s, size - 24);
}
codec = ff_codec_get_id(codec_au_tags, id);
if (codec == AV_CODEC_ID_NONE) {
avpriv_request_sample(s, "unknown or unsupported codec tag: %u", id);
return AVERROR_PATCHWELCOME;
}
bps = av_get_bits_per_sample(codec);
if (codec == AV_CODEC_ID_ADPCM_G726LE) {
if (id == MKBETAG('7','2','6','2')) {
bps = 2;
} else {
const uint8_t bpcss[] = {4, 0, 3, 5};
av_assert0(id >= 23 && id < 23 + 4);
ba = bpcss[id - 23];
bps = bpcss[id - 23];
}
} else if (!bps) {
avpriv_request_sample(s, "Unknown bits per sample");
return AVERROR_PATCHWELCOME;
}
if (channels == 0 || channels >= INT_MAX / (BLOCK_SIZE * bps >> 3)) {
av_log(s, AV_LOG_ERROR, "Invalid number of channels %u\n", channels);
return AVERROR_INVALIDDATA;
}
if (rate == 0 || rate > INT_MAX) {
av_log(s, AV_LOG_ERROR, "Invalid sample rate: %u\n", rate);
return AVERROR_INVALIDDATA;
}
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = id;
st->codecpar->codec_id = codec;
st->codecpar->channels = channels;
st->codecpar->sample_rate = rate;
st->codecpar->bits_per_coded_sample = bps;
st->codecpar->bit_rate = channels * rate * bps;
st->codecpar->block_align = ba ? ba : FFMAX(bps * st->codecpar->channels / 8, 1);
if (data_size != AU_UNKNOWN_SIZE)
st->duration = (((int64_t)data_size)<<3) / (st->codecpar->channels * (int64_t)bps);
st->start_time = 0;
avpriv_set_pts_info(st, 64, 1, rate);
return 0;
}
AVInputFormat ff_au_demuxer = {
.name = "au",
.long_name = NULL_IF_CONFIG_SMALL("Sun AU"),
.read_probe = au_probe,
.read_header = au_read_header,
.read_packet = ff_pcm_read_packet,
.read_seek = ff_pcm_read_seek,
.codec_tag = (const AVCodecTag* const []) { codec_au_tags, 0 },
};
#endif /* CONFIG_AU_DEMUXER */
#if CONFIG_AU_MUXER
typedef struct AUContext {
uint32_t header_size;
} AUContext;
#include "rawenc.h"
static int au_get_annotations(AVFormatContext *s, char **buffer)
{
static const char * keys[] = {
"Title",
"Artist",
"Album",
"Track",
"Genre",
NULL };
int i;
int cnt = 0;
AVDictionary *m = s->metadata;
AVDictionaryEntry *t = NULL;
AVBPrint bprint;
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
for (i = 0; keys[i] != NULL; i++) {
t = av_dict_get(m, keys[i], NULL, 0);
if (t != NULL) {
if (cnt++)
av_bprint_chars(&bprint, '\n', 1);
av_bprint_append_data(&bprint, keys[i], strlen(keys[i]));
av_bprint_chars(&bprint, '=', 1);
av_bprint_append_data(&bprint, t->value, strlen(t->value));
}
}
/* pad with 0's */
av_bprint_append_data(&bprint, "\0\0\0\0\0\0\0\0", 8);
return av_bprint_finalize(&bprint, buffer);
}
static int au_write_header(AVFormatContext *s)
{
int ret;
AUContext *au = s->priv_data;
AVIOContext *pb = s->pb;
AVCodecParameters *par = s->streams[0]->codecpar;
char *annotations = NULL;
au->header_size = AU_DEFAULT_HEADER_SIZE;
if (s->nb_streams != 1) {
av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
return AVERROR(EINVAL);
}
par->codec_tag = ff_codec_get_tag(codec_au_tags, par->codec_id);
if (!par->codec_tag) {
av_log(s, AV_LOG_ERROR, "unsupported codec\n");
return AVERROR(EINVAL);
}
if (av_dict_count(s->metadata) > 0) {
ret = au_get_annotations(s, &annotations);
if (ret < 0)
return ret;
if (annotations != NULL) {
au->header_size = (24 + strlen(annotations) + 8) & ~7;
if (au->header_size < AU_DEFAULT_HEADER_SIZE)
au->header_size = AU_DEFAULT_HEADER_SIZE;
}
}
ffio_wfourcc(pb, ".snd"); /* magic number */
avio_wb32(pb, au->header_size); /* header size */
avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */
avio_wb32(pb, par->codec_tag); /* codec ID */
avio_wb32(pb, par->sample_rate);
avio_wb32(pb, par->channels);
if (annotations != NULL) {
avio_write(pb, annotations, au->header_size - 24);
av_freep(&annotations);
} else {
avio_wb64(pb, 0); /* annotation field */
}
return 0;
}
static int au_write_trailer(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AUContext *au = s->priv_data;
int64_t file_size = avio_tell(pb);
if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && file_size < INT32_MAX) {
/* update file size */
avio_seek(pb, 8, SEEK_SET);
avio_wb32(pb, (uint32_t)(file_size - au->header_size));
avio_seek(pb, file_size, SEEK_SET);
}
return 0;
}
AVOutputFormat ff_au_muxer = {
.name = "au",
.long_name = NULL_IF_CONFIG_SMALL("Sun AU"),
.mime_type = "audio/basic",
.extensions = "au",
.priv_data_size = sizeof(AUContext),
.audio_codec = AV_CODEC_ID_PCM_S16BE,
.video_codec = AV_CODEC_ID_NONE,
.write_header = au_write_header,
.write_packet = ff_raw_write_packet,
.write_trailer = au_write_trailer,
.codec_tag = (const AVCodecTag* const []) { codec_au_tags, 0 },
.flags = AVFMT_NOTIMESTAMPS,
};
#endif /* CONFIG_AU_MUXER */

454
externals/ffmpeg/libavformat/av1.c vendored Executable file
View File

@@ -0,0 +1,454 @@
/*
* AV1 helper functions for muxers
* Copyright (c) 2018 James Almer <jamrial@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 "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "libavcodec/av1.h"
#include "libavcodec/av1_parse.h"
#include "libavcodec/profiles.h"
#include "libavcodec/put_bits.h"
#include "av1.h"
#include "avio.h"
#include "avio_internal.h"
static int av1_filter_obus(AVIOContext *pb, const uint8_t *buf,
int size, int *offset)
{
const uint8_t *start = buf, *end = buf + size;
int64_t obu_size;
int off, start_pos, type, temporal_id, spatial_id;
enum {
START_NOT_FOUND,
START_FOUND,
END_FOUND,
OFFSET_IMPOSSIBLE,
} state = START_NOT_FOUND;
off = size = 0;
while (buf < end) {
int len = parse_obu_header(buf, end - buf, &obu_size, &start_pos,
&type, &temporal_id, &spatial_id);
if (len < 0)
return len;
switch (type) {
case AV1_OBU_TEMPORAL_DELIMITER:
case AV1_OBU_REDUNDANT_FRAME_HEADER:
case AV1_OBU_TILE_LIST:
case AV1_OBU_PADDING:
if (state == START_FOUND)
state = END_FOUND;
break;
default:
if (state == START_NOT_FOUND) {
off = buf - start;
state = START_FOUND;
} else if (state == END_FOUND) {
state = OFFSET_IMPOSSIBLE;
}
if (pb)
avio_write(pb, buf, len);
size += len;
break;
}
buf += len;
}
if (offset)
*offset = state != OFFSET_IMPOSSIBLE ? off : -1;
return size;
}
int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
{
return av1_filter_obus(pb, buf, size, NULL);
}
int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
int *size, int *offset)
{
AVIOContext pb;
uint8_t *buf;
int len, off, ret;
len = ret = av1_filter_obus(NULL, in, *size, &off);
if (ret < 0) {
return ret;
}
if (off >= 0) {
*out = (uint8_t *)in;
*size = len;
*offset = off;
return 0;
}
buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
if (!buf)
return AVERROR(ENOMEM);
ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL);
ret = av1_filter_obus(&pb, in, *size, NULL);
av_assert1(ret == len);
memset(buf + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
*out = buf;
*size = len;
*offset = 0;
return 0;
}
static inline void uvlc(GetBitContext *gb)
{
int leading_zeros = 0;
while (get_bits_left(gb)) {
if (get_bits1(gb))
break;
leading_zeros++;
}
if (leading_zeros >= 32)
return;
skip_bits_long(gb, leading_zeros);
}
static int parse_color_config(AV1SequenceParameters *seq_params, GetBitContext *gb)
{
int twelve_bit = 0;
int high_bitdepth = get_bits1(gb);
if (seq_params->profile == FF_PROFILE_AV1_PROFESSIONAL && high_bitdepth)
twelve_bit = get_bits1(gb);
seq_params->bitdepth = 8 + (high_bitdepth * 2) + (twelve_bit * 2);
if (seq_params->profile == FF_PROFILE_AV1_HIGH)
seq_params->monochrome = 0;
else
seq_params->monochrome = get_bits1(gb);
seq_params->color_description_present_flag = get_bits1(gb);
if (seq_params->color_description_present_flag) {
seq_params->color_primaries = get_bits(gb, 8);
seq_params->transfer_characteristics = get_bits(gb, 8);
seq_params->matrix_coefficients = get_bits(gb, 8);
} else {
seq_params->color_primaries = AVCOL_PRI_UNSPECIFIED;
seq_params->transfer_characteristics = AVCOL_TRC_UNSPECIFIED;
seq_params->matrix_coefficients = AVCOL_SPC_UNSPECIFIED;
}
if (seq_params->monochrome) {
seq_params->color_range = get_bits1(gb);
seq_params->chroma_subsampling_x = 1;
seq_params->chroma_subsampling_y = 1;
seq_params->chroma_sample_position = 0;
return 0;
} else if (seq_params->color_primaries == AVCOL_PRI_BT709 &&
seq_params->transfer_characteristics == AVCOL_TRC_IEC61966_2_1 &&
seq_params->matrix_coefficients == AVCOL_SPC_RGB) {
seq_params->chroma_subsampling_x = 0;
seq_params->chroma_subsampling_y = 0;
} else {
seq_params->color_range = get_bits1(gb);
if (seq_params->profile == FF_PROFILE_AV1_MAIN) {
seq_params->chroma_subsampling_x = 1;
seq_params->chroma_subsampling_y = 1;
} else if (seq_params->profile == FF_PROFILE_AV1_HIGH) {
seq_params->chroma_subsampling_x = 0;
seq_params->chroma_subsampling_y = 0;
} else {
if (twelve_bit) {
seq_params->chroma_subsampling_x = get_bits1(gb);
if (seq_params->chroma_subsampling_x)
seq_params->chroma_subsampling_y = get_bits1(gb);
else
seq_params->chroma_subsampling_y = 0;
} else {
seq_params->chroma_subsampling_x = 1;
seq_params->chroma_subsampling_y = 0;
}
}
if (seq_params->chroma_subsampling_x && seq_params->chroma_subsampling_y)
seq_params->chroma_sample_position = get_bits(gb, 2);
}
skip_bits1(gb); // separate_uv_delta_q
return 0;
}
static int parse_sequence_header(AV1SequenceParameters *seq_params, const uint8_t *buf, int size)
{
GetBitContext gb;
int reduced_still_picture_header;
int frame_width_bits_minus_1, frame_height_bits_minus_1;
int size_bits, ret;
size_bits = get_obu_bit_length(buf, size, AV1_OBU_SEQUENCE_HEADER);
if (size_bits < 0)
return size_bits;
ret = init_get_bits(&gb, buf, size_bits);
if (ret < 0)
return ret;
memset(seq_params, 0, sizeof(*seq_params));
seq_params->profile = get_bits(&gb, 3);
skip_bits1(&gb); // still_picture
reduced_still_picture_header = get_bits1(&gb);
if (reduced_still_picture_header) {
seq_params->level = get_bits(&gb, 5);
seq_params->tier = 0;
} else {
int initial_display_delay_present_flag, operating_points_cnt_minus_1;
int decoder_model_info_present_flag, buffer_delay_length_minus_1;
if (get_bits1(&gb)) { // timing_info_present_flag
skip_bits_long(&gb, 32); // num_units_in_display_tick
skip_bits_long(&gb, 32); // time_scale
if (get_bits1(&gb)) // equal_picture_interval
uvlc(&gb); // num_ticks_per_picture_minus_1
decoder_model_info_present_flag = get_bits1(&gb);
if (decoder_model_info_present_flag) {
buffer_delay_length_minus_1 = get_bits(&gb, 5);
skip_bits_long(&gb, 32); // num_units_in_decoding_tick
skip_bits(&gb, 10); // buffer_removal_time_length_minus_1 (5)
// frame_presentation_time_length_minus_1 (5)
}
} else
decoder_model_info_present_flag = 0;
initial_display_delay_present_flag = get_bits1(&gb);
operating_points_cnt_minus_1 = get_bits(&gb, 5);
for (int i = 0; i <= operating_points_cnt_minus_1; i++) {
int seq_level_idx, seq_tier;
skip_bits(&gb, 12); // operating_point_idc
seq_level_idx = get_bits(&gb, 5);
if (seq_level_idx > 7)
seq_tier = get_bits1(&gb);
else
seq_tier = 0;
if (decoder_model_info_present_flag) {
if (get_bits1(&gb)) { // decoder_model_present_for_this_op
skip_bits_long(&gb, buffer_delay_length_minus_1 + 1); // decoder_buffer_delay
skip_bits_long(&gb, buffer_delay_length_minus_1 + 1); // encoder_buffer_delay
skip_bits1(&gb); // low_delay_mode_flag
}
}
if (initial_display_delay_present_flag) {
if (get_bits1(&gb)) // initial_display_delay_present_for_this_op
skip_bits(&gb, 4); // initial_display_delay_minus_1
}
if (i == 0) {
seq_params->level = seq_level_idx;
seq_params->tier = seq_tier;
}
}
}
frame_width_bits_minus_1 = get_bits(&gb, 4);
frame_height_bits_minus_1 = get_bits(&gb, 4);
skip_bits(&gb, frame_width_bits_minus_1 + 1); // max_frame_width_minus_1
skip_bits(&gb, frame_height_bits_minus_1 + 1); // max_frame_height_minus_1
if (!reduced_still_picture_header) {
if (get_bits1(&gb)) // frame_id_numbers_present_flag
skip_bits(&gb, 7); // delta_frame_id_length_minus_2 (4), additional_frame_id_length_minus_1 (3)
}
skip_bits(&gb, 3); // use_128x128_superblock (1), enable_filter_intra (1), enable_intra_edge_filter (1)
if (!reduced_still_picture_header) {
int enable_order_hint, seq_force_screen_content_tools;
skip_bits(&gb, 4); // enable_interintra_compound (1), enable_masked_compound (1)
// enable_warped_motion (1), enable_dual_filter (1)
enable_order_hint = get_bits1(&gb);
if (enable_order_hint)
skip_bits(&gb, 2); // enable_jnt_comp (1), enable_ref_frame_mvs (1)
if (get_bits1(&gb)) // seq_choose_screen_content_tools
seq_force_screen_content_tools = 2;
else
seq_force_screen_content_tools = get_bits1(&gb);
if (seq_force_screen_content_tools) {
if (!get_bits1(&gb)) // seq_choose_integer_mv
skip_bits1(&gb); // seq_force_integer_mv
}
if (enable_order_hint)
skip_bits(&gb, 3); // order_hint_bits_minus_1
}
skip_bits(&gb, 3); // enable_superres (1), enable_cdef (1), enable_restoration (1)
parse_color_config(seq_params, &gb);
skip_bits1(&gb); // film_grain_params_present
if (get_bits_left(&gb))
return AVERROR_INVALIDDATA;
return 0;
}
int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int size)
{
int64_t obu_size;
int start_pos, type, temporal_id, spatial_id;
if (size <= 0)
return AVERROR_INVALIDDATA;
while (size > 0) {
int len = parse_obu_header(buf, size, &obu_size, &start_pos,
&type, &temporal_id, &spatial_id);
if (len < 0)
return len;
switch (type) {
case AV1_OBU_SEQUENCE_HEADER:
if (!obu_size)
return AVERROR_INVALIDDATA;
return parse_sequence_header(seq, buf + start_pos, obu_size);
default:
break;
}
size -= len;
buf += len;
}
return AVERROR_INVALIDDATA;
}
int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
{
AVIOContext *seq_pb = NULL, *meta_pb = NULL;
AV1SequenceParameters seq_params;
PutBitContext pbc;
uint8_t header[4];
uint8_t *seq, *meta;
int64_t obu_size;
int start_pos, type, temporal_id, spatial_id;
int ret, nb_seq = 0, seq_size, meta_size;
if (size <= 0)
return AVERROR_INVALIDDATA;
ret = avio_open_dyn_buf(&seq_pb);
if (ret < 0)
return ret;
ret = avio_open_dyn_buf(&meta_pb);
if (ret < 0)
goto fail;
while (size > 0) {
int len = parse_obu_header(buf, size, &obu_size, &start_pos,
&type, &temporal_id, &spatial_id);
if (len < 0) {
ret = len;
goto fail;
}
switch (type) {
case AV1_OBU_SEQUENCE_HEADER:
nb_seq++;
if (!obu_size || nb_seq > 1) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
ret = parse_sequence_header(&seq_params, buf + start_pos, obu_size);
if (ret < 0)
goto fail;
avio_write(seq_pb, buf, len);
break;
case AV1_OBU_METADATA:
if (!obu_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_write(meta_pb, buf, len);
break;
default:
break;
}
size -= len;
buf += len;
}
seq_size = avio_get_dyn_buf(seq_pb, &seq);
if (!seq_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
init_put_bits(&pbc, header, sizeof(header));
put_bits(&pbc, 1, 1); // marker
put_bits(&pbc, 7, 1); // version
put_bits(&pbc, 3, seq_params.profile);
put_bits(&pbc, 5, seq_params.level);
put_bits(&pbc, 1, seq_params.tier);
put_bits(&pbc, 1, seq_params.bitdepth > 8);
put_bits(&pbc, 1, seq_params.bitdepth == 12);
put_bits(&pbc, 1, seq_params.monochrome);
put_bits(&pbc, 1, seq_params.chroma_subsampling_x);
put_bits(&pbc, 1, seq_params.chroma_subsampling_y);
put_bits(&pbc, 2, seq_params.chroma_sample_position);
put_bits(&pbc, 8, 0); // padding
flush_put_bits(&pbc);
avio_write(pb, header, sizeof(header));
avio_write(pb, seq, seq_size);
meta_size = avio_get_dyn_buf(meta_pb, &meta);
if (meta_size)
avio_write(pb, meta, meta_size);
fail:
ffio_free_dyn_buf(&seq_pb);
ffio_free_dyn_buf(&meta_pb);
return ret;
}

102
externals/ffmpeg/libavformat/av1.h vendored Executable file
View File

@@ -0,0 +1,102 @@
/*
* AV1 helper functions for muxers
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_AV1_H
#define AVFORMAT_AV1_H
#include <stdint.h>
#include "avio.h"
typedef struct AV1SequenceParameters {
uint8_t profile;
uint8_t level;
uint8_t tier;
uint8_t bitdepth;
uint8_t monochrome;
uint8_t chroma_subsampling_x;
uint8_t chroma_subsampling_y;
uint8_t chroma_sample_position;
uint8_t color_description_present_flag;
uint8_t color_primaries;
uint8_t transfer_characteristics;
uint8_t matrix_coefficients;
uint8_t color_range;
} AV1SequenceParameters;
/**
* Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and write
* the resulting bitstream to the provided AVIOContext.
*
* @param pb pointer to the AVIOContext where the filtered bitstream shall be
* written
* @param buf input data buffer
* @param size size of the input data buffer
*
* @return the amount of bytes written in case of success, a negative AVERROR
* code in case of failure
*/
int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size);
/**
* Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and return
* the result in a data buffer, avoiding allocations and copies if possible.
*
* @param in input data buffer
* @param out pointer to pointer for the returned buffer. In case of success,
* it is independently allocated if and only if `*out` differs from in.
* @param size size of the input data buffer. The size of the resulting output
* data buffer will be written here
* @param offset offset of the returned data inside `*out`: It runs from
* `*out + offset` (inclusive) to `*out + offset + size`
* (exclusive); is zero if `*out` is independently allocated.
*
* @return 0 in case of success, a negative AVERROR code in case of failure.
* On failure, *out and *size are unchanged
* @note *out will be treated as unintialized on input and will not be freed.
*/
int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
int *size, int *offset);
/**
* Parses a Sequence Header from the the provided buffer.
*
* @param seq pointer to the AV1SequenceParameters where the parsed values will
* be written
* @param buf input data buffer
* @param size size in bytes of the input data buffer
*
* @return >= 0 in case of success, a negative AVERROR code in case of failure
*/
int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int size);
/**
* Writes AV1 extradata (Sequence Header and Metadata OBUs) to the provided
* AVIOContext.
*
* @param pb pointer to the AVIOContext where the av1C box shall be written
* @param buf input data buffer
* @param size size in bytes of the input data buffer
*
* @return >= 0 in case of success, a negative AVERROR code in case of failure
*/
int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size);
#endif /* AVFORMAT_AV1_H */

279
externals/ffmpeg/libavformat/av1dec.c vendored Executable file
View File

@@ -0,0 +1,279 @@
/*
* AV1 Annex B demuxer
* Copyright (c) 2019 James Almer <jamrial@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 "config.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "libavcodec/av1_parse.h"
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
typedef struct AnnexBContext {
const AVClass *class;
AVBSFContext *bsf;
uint32_t temporal_unit_size;
uint32_t frame_unit_size;
AVRational framerate;
} AnnexBContext;
static int leb(AVIOContext *pb, uint32_t *len) {
int more, i = 0;
uint8_t byte;
*len = 0;
do {
unsigned bits;
byte = avio_r8(pb);
more = byte & 0x80;
bits = byte & 0x7f;
if (i <= 3 || (i == 4 && bits < (1 << 4)))
*len |= bits << (i * 7);
else if (bits)
return AVERROR_INVALIDDATA;
if (++i == 8 && more)
return AVERROR_INVALIDDATA;
if (pb->eof_reached || pb->error)
return pb->error ? pb->error : AVERROR(EIO);
} while (more);
return i;
}
static int read_obu(const uint8_t *buf, int size, int64_t *obu_size, int *type)
{
int start_pos, temporal_id, spatial_id;
int len;
len = parse_obu_header(buf, size, obu_size, &start_pos,
type, &temporal_id, &spatial_id);
if (len < 0)
return len;
return 0;
}
static int annexb_probe(const AVProbeData *p)
{
AVIOContext pb;
int64_t obu_size;
uint32_t temporal_unit_size, frame_unit_size, obu_unit_size;
int seq = 0;
int ret, type, cnt = 0;
ffio_init_context(&pb, p->buf, p->buf_size, 0,
NULL, NULL, NULL, NULL);
ret = leb(&pb, &temporal_unit_size);
if (ret < 0)
return 0;
cnt += ret;
ret = leb(&pb, &frame_unit_size);
if (ret < 0 || ((int64_t)frame_unit_size + ret) > temporal_unit_size)
return 0;
cnt += ret;
temporal_unit_size -= ret;
ret = leb(&pb, &obu_unit_size);
if (ret < 0 || ((int64_t)obu_unit_size + ret) >= frame_unit_size)
return 0;
cnt += ret;
temporal_unit_size -= obu_unit_size + ret;
frame_unit_size -= obu_unit_size + ret;
avio_skip(&pb, obu_unit_size);
if (pb.eof_reached || pb.error)
return 0;
// Check that the first OBU is a Temporal Delimiter.
ret = read_obu(p->buf + cnt, FFMIN(p->buf_size - cnt, obu_unit_size), &obu_size, &type);
if (ret < 0 || type != AV1_OBU_TEMPORAL_DELIMITER || obu_size > 0)
return 0;
cnt += obu_unit_size;
do {
ret = leb(&pb, &obu_unit_size);
if (ret < 0 || ((int64_t)obu_unit_size + ret) > frame_unit_size)
return 0;
cnt += ret;
avio_skip(&pb, obu_unit_size);
if (pb.eof_reached || pb.error)
return 0;
ret = read_obu(p->buf + cnt, FFMIN(p->buf_size - cnt, obu_unit_size), &obu_size, &type);
if (ret < 0)
return 0;
cnt += obu_unit_size;
switch (type) {
case AV1_OBU_SEQUENCE_HEADER:
seq = 1;
break;
case AV1_OBU_FRAME:
case AV1_OBU_FRAME_HEADER:
return seq ? AVPROBE_SCORE_EXTENSION + 1 : 0;
case AV1_OBU_TILE_GROUP:
case AV1_OBU_TEMPORAL_DELIMITER:
return 0;
default:
break;
}
temporal_unit_size -= obu_unit_size + ret;
frame_unit_size -= obu_unit_size + ret;
} while (frame_unit_size);
return 0;
}
static int annexb_read_header(AVFormatContext *s)
{
AnnexBContext *c = s->priv_data;
const AVBitStreamFilter *filter = av_bsf_get_by_name("av1_frame_merge");
AVStream *st;
int ret;
if (!filter) {
av_log(c, AV_LOG_ERROR, "av1_frame_merge bitstream filter "
"not found. This is a bug, please report it.\n");
return AVERROR_BUG;
}
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_AV1;
st->need_parsing = AVSTREAM_PARSE_HEADERS;
st->internal->avctx->framerate = c->framerate;
// taken from rawvideo demuxers
avpriv_set_pts_info(st, 64, 1, 1200000);
ret = av_bsf_alloc(filter, &c->bsf);
if (ret < 0)
return ret;
ret = avcodec_parameters_copy(c->bsf->par_in, st->codecpar);
if (ret < 0) {
av_bsf_free(&c->bsf);
return ret;
}
ret = av_bsf_init(c->bsf);
if (ret < 0)
av_bsf_free(&c->bsf);
return ret;
}
static int annexb_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AnnexBContext *c = s->priv_data;
uint32_t obu_unit_size;
int ret, len;
retry:
if (avio_feof(s->pb)) {
if (c->temporal_unit_size || c->frame_unit_size)
return AVERROR(EIO);
goto end;
}
if (!c->temporal_unit_size) {
len = leb(s->pb, &c->temporal_unit_size);
if (len < 0) return AVERROR_INVALIDDATA;
}
if (!c->frame_unit_size) {
len = leb(s->pb, &c->frame_unit_size);
if (len < 0 || ((int64_t)c->frame_unit_size + len) > c->temporal_unit_size)
return AVERROR_INVALIDDATA;
c->temporal_unit_size -= len;
}
len = leb(s->pb, &obu_unit_size);
if (len < 0 || ((int64_t)obu_unit_size + len) > c->frame_unit_size)
return AVERROR_INVALIDDATA;
ret = av_get_packet(s->pb, pkt, obu_unit_size);
if (ret < 0)
return ret;
if (ret != obu_unit_size)
return AVERROR(EIO);
c->temporal_unit_size -= obu_unit_size + len;
c->frame_unit_size -= obu_unit_size + len;
end:
ret = av_bsf_send_packet(c->bsf, pkt);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Failed to send packet to "
"av1_frame_merge filter\n");
return ret;
}
ret = av_bsf_receive_packet(c->bsf, pkt);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
av_log(s, AV_LOG_ERROR, "av1_frame_merge filter failed to "
"send output packet\n");
if (ret == AVERROR(EAGAIN))
goto retry;
return ret;
}
static int annexb_read_close(AVFormatContext *s)
{
AnnexBContext *c = s->priv_data;
av_bsf_free(&c->bsf);
return 0;
}
#define OFFSET(x) offsetof(AnnexBContext, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption annexb_options[] = {
{ "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
{ NULL },
};
static const AVClass annexb_demuxer_class = {
.class_name = "AV1 Annex B demuxer",
.item_name = av_default_item_name,
.option = annexb_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_av1_demuxer = {
.name = "av1",
.long_name = NULL_IF_CONFIG_SMALL("AV1 Annex B"),
.priv_data_size = sizeof(AnnexBContext),
.read_probe = annexb_probe,
.read_header = annexb_read_header,
.read_packet = annexb_read_packet,
.read_close = annexb_read_close,
.extensions = "obu",
.flags = AVFMT_GENERIC_INDEX,
.priv_class = &annexb_demuxer_class,
};

451
externals/ffmpeg/libavformat/avc.c vendored Executable file
View File

@@ -0,0 +1,451 @@
/*
* 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 "libavutil/intreadwrite.h"
#include "libavcodec/h264.h"
#include "libavcodec/get_bits.h"
#include "avformat.h"
#include "avio.h"
#include "avc.h"
#include "avio_internal.h"
static const uint8_t *ff_avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
{
const uint8_t *a = p + 4 - ((intptr_t)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;
if (p[2] == 0 && p[3] == 1)
return p+1;
}
if (p[3] == 0) {
if (p[2] == 0 && p[4] == 1)
return p+2;
if (p[4] == 0 && p[5] == 1)
return p+3;
}
}
}
for (end += 3; p < end; p++) {
if (p[0] == 0 && p[1] == 0 && p[2] == 1)
return p;
}
return end + 3;
}
const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end){
const uint8_t *out= ff_avc_find_startcode_internal(p, end);
if(p<out && out<end && !out[-1]) out--;
return out;
}
int ff_avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size)
{
const uint8_t *p = buf_in;
const uint8_t *end = p + size;
const uint8_t *nal_start, *nal_end;
size = 0;
nal_start = ff_avc_find_startcode(p, end);
for (;;) {
while (nal_start < end && !*(nal_start++));
if (nal_start == end)
break;
nal_end = ff_avc_find_startcode(nal_start, end);
avio_wb32(pb, nal_end - nal_start);
avio_write(pb, nal_start, nal_end - nal_start);
size += 4 + nal_end - nal_start;
nal_start = nal_end;
}
return size;
}
int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
{
AVIOContext *pb;
int ret = avio_open_dyn_buf(&pb);
if(ret < 0)
return ret;
ff_avc_parse_nal_units(pb, buf_in, *size);
*size = avio_close_dyn_buf(pb, buf);
return 0;
}
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
{
AVIOContext *sps_pb = NULL, *pps_pb = NULL, *sps_ext_pb = NULL;
uint8_t *buf, *end, *start;
uint8_t *sps, *pps, *sps_ext;
uint32_t sps_size = 0, pps_size = 0, sps_ext_size = 0;
int ret, nb_sps = 0, nb_pps = 0, nb_sps_ext = 0;
if (len <= 6)
return AVERROR_INVALIDDATA;
/* check for H.264 start code */
if (AV_RB32(data) != 0x00000001 &&
AV_RB24(data) != 0x000001) {
avio_write(pb, data, len);
return 0;
}
ret = ff_avc_parse_nal_units_buf(data, &buf, &len);
if (ret < 0)
return ret;
start = buf;
end = buf + len;
ret = avio_open_dyn_buf(&sps_pb);
if (ret < 0)
goto fail;
ret = avio_open_dyn_buf(&pps_pb);
if (ret < 0)
goto fail;
ret = avio_open_dyn_buf(&sps_ext_pb);
if (ret < 0)
goto fail;
/* look for sps and pps */
while (end - buf > 4) {
uint32_t size;
uint8_t nal_type;
size = FFMIN(AV_RB32(buf), end - buf - 4);
buf += 4;
nal_type = buf[0] & 0x1f;
if (nal_type == 7) { /* SPS */
nb_sps++;
if (size > UINT16_MAX || nb_sps >= H264_MAX_SPS_COUNT) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_wb16(sps_pb, size);
avio_write(sps_pb, buf, size);
} else if (nal_type == 8) { /* PPS */
nb_pps++;
if (size > UINT16_MAX || nb_pps >= H264_MAX_PPS_COUNT) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_wb16(pps_pb, size);
avio_write(pps_pb, buf, size);
} else if (nal_type == 13) { /* SPS_EXT */
nb_sps_ext++;
if (size > UINT16_MAX || nb_sps_ext >= 256) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_wb16(sps_ext_pb, size);
avio_write(sps_ext_pb, buf, size);
}
buf += size;
}
sps_size = avio_get_dyn_buf(sps_pb, &sps);
pps_size = avio_get_dyn_buf(pps_pb, &pps);
sps_ext_size = avio_get_dyn_buf(sps_ext_pb, &sps_ext);
if (sps_size < 6 || !pps_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_w8(pb, 1); /* version */
avio_w8(pb, sps[3]); /* profile */
avio_w8(pb, sps[4]); /* profile compat */
avio_w8(pb, sps[5]); /* level */
avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
avio_w8(pb, 0xe0 | nb_sps); /* 3 bits reserved (111) + 5 bits number of sps */
avio_write(pb, sps, sps_size);
avio_w8(pb, nb_pps); /* number of pps */
avio_write(pb, pps, pps_size);
if (sps[3] != 66 && sps[3] != 77 && sps[3] != 88) {
H264SPS seq;
ret = ff_avc_decode_sps(&seq, sps + 3, sps_size - 3);
if (ret < 0)
goto fail;
avio_w8(pb, 0xfc | seq.chroma_format_idc); /* 6 bits reserved (111111) + chroma_format_idc */
avio_w8(pb, 0xf8 | (seq.bit_depth_luma - 8)); /* 5 bits reserved (11111) + bit_depth_luma_minus8 */
avio_w8(pb, 0xf8 | (seq.bit_depth_chroma - 8)); /* 5 bits reserved (11111) + bit_depth_chroma_minus8 */
avio_w8(pb, nb_sps_ext); /* number of sps ext */
if (nb_sps_ext)
avio_write(pb, sps_ext, sps_ext_size);
}
fail:
ffio_free_dyn_buf(&sps_pb);
ffio_free_dyn_buf(&pps_pb);
ffio_free_dyn_buf(&sps_ext_pb);
av_free(start);
return ret;
}
int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
{
uint16_t sps_size, pps_size;
uint8_t *out;
int out_size;
*buf = NULL;
if (*size >= 4 && (AV_RB32(in) == 0x00000001 || AV_RB24(in) == 0x000001))
return 0;
if (*size < 11 || in[0] != 1)
return AVERROR_INVALIDDATA;
sps_size = AV_RB16(&in[6]);
if (11 + sps_size > *size)
return AVERROR_INVALIDDATA;
pps_size = AV_RB16(&in[9 + sps_size]);
if (11 + sps_size + pps_size > *size)
return AVERROR_INVALIDDATA;
out_size = 8 + sps_size + pps_size;
out = av_mallocz(out_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!out)
return AVERROR(ENOMEM);
AV_WB32(&out[0], 0x00000001);
memcpy(out + 4, &in[8], sps_size);
AV_WB32(&out[4 + sps_size], 0x00000001);
memcpy(out + 8 + sps_size, &in[11 + sps_size], pps_size);
*buf = out;
*size = out_size;
return 0;
}
const uint8_t *ff_avc_mp4_find_startcode(const uint8_t *start,
const uint8_t *end,
int nal_length_size)
{
unsigned int res = 0;
if (end - start < nal_length_size)
return NULL;
while (nal_length_size--)
res = (res << 8) | *start++;
if (res > end - start)
return NULL;
return start + res;
}
uint8_t *ff_nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len,
uint32_t *dst_len, int header_len)
{
uint8_t *dst;
uint32_t i, len;
dst = av_malloc(src_len + AV_INPUT_BUFFER_PADDING_SIZE);
if (!dst)
return NULL;
/* NAL unit header */
i = len = 0;
while (i < header_len && i < src_len)
dst[len++] = src[i++];
while (i + 2 < src_len)
if (!src[i] && !src[i + 1] && src[i + 2] == 3) {
dst[len++] = src[i++];
dst[len++] = src[i++];
i++; // remove emulation_prevention_three_byte
} else
dst[len++] = src[i++];
while (i < src_len)
dst[len++] = src[i++];
memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
*dst_len = len;
return dst;
}
static const AVRational avc_sample_aspect_ratio[17] = {
{ 0, 1 },
{ 1, 1 },
{ 12, 11 },
{ 10, 11 },
{ 16, 11 },
{ 40, 33 },
{ 24, 11 },
{ 20, 11 },
{ 32, 11 },
{ 80, 33 },
{ 18, 11 },
{ 15, 11 },
{ 64, 33 },
{ 160, 99 },
{ 4, 3 },
{ 3, 2 },
{ 2, 1 },
};
static inline int get_ue_golomb(GetBitContext *gb) {
int i;
for (i = 0; i < 32 && !get_bits1(gb); i++)
;
return get_bitsz(gb, i) + (1 << i) - 1;
}
static inline int get_se_golomb(GetBitContext *gb) {
int v = get_ue_golomb(gb) + 1;
int sign = -(v & 1);
return ((v >> 1) ^ sign) - sign;
}
int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size)
{
int i, j, ret, rbsp_size, aspect_ratio_idc, pic_order_cnt_type;
int num_ref_frames_in_pic_order_cnt_cycle;
int delta_scale, lastScale = 8, nextScale = 8;
int sizeOfScalingList;
GetBitContext gb;
uint8_t *rbsp_buf;
rbsp_buf = ff_nal_unit_extract_rbsp(buf, buf_size, &rbsp_size, 0);
if (!rbsp_buf)
return AVERROR(ENOMEM);
ret = init_get_bits8(&gb, rbsp_buf, rbsp_size);
if (ret < 0)
goto end;
memset(sps, 0, sizeof(*sps));
sps->profile_idc = get_bits(&gb, 8);
sps->constraint_set_flags |= get_bits1(&gb) << 0; // constraint_set0_flag
sps->constraint_set_flags |= get_bits1(&gb) << 1; // constraint_set1_flag
sps->constraint_set_flags |= get_bits1(&gb) << 2; // constraint_set2_flag
sps->constraint_set_flags |= get_bits1(&gb) << 3; // constraint_set3_flag
sps->constraint_set_flags |= get_bits1(&gb) << 4; // constraint_set4_flag
sps->constraint_set_flags |= get_bits1(&gb) << 5; // constraint_set5_flag
skip_bits(&gb, 2); // reserved_zero_2bits
sps->level_idc = get_bits(&gb, 8);
sps->id = get_ue_golomb(&gb);
if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
sps->profile_idc == 122 || sps->profile_idc == 244 || sps->profile_idc == 44 ||
sps->profile_idc == 83 || sps->profile_idc == 86 || sps->profile_idc == 118 ||
sps->profile_idc == 128 || sps->profile_idc == 138 || sps->profile_idc == 139 ||
sps->profile_idc == 134) {
sps->chroma_format_idc = get_ue_golomb(&gb); // chroma_format_idc
if (sps->chroma_format_idc == 3) {
skip_bits1(&gb); // separate_colour_plane_flag
}
sps->bit_depth_luma = get_ue_golomb(&gb) + 8;
sps->bit_depth_chroma = get_ue_golomb(&gb) + 8;
skip_bits1(&gb); // qpprime_y_zero_transform_bypass_flag
if (get_bits1(&gb)) { // seq_scaling_matrix_present_flag
for (i = 0; i < ((sps->chroma_format_idc != 3) ? 8 : 12); i++) {
if (!get_bits1(&gb)) // seq_scaling_list_present_flag
continue;
lastScale = 8;
nextScale = 8;
sizeOfScalingList = i < 6 ? 16 : 64;
for (j = 0; j < sizeOfScalingList; j++) {
if (nextScale != 0) {
delta_scale = get_se_golomb(&gb);
nextScale = (lastScale + delta_scale) & 0xff;
}
lastScale = nextScale == 0 ? lastScale : nextScale;
}
}
}
} else {
sps->chroma_format_idc = 1;
sps->bit_depth_luma = 8;
sps->bit_depth_chroma = 8;
}
get_ue_golomb(&gb); // log2_max_frame_num_minus4
pic_order_cnt_type = get_ue_golomb(&gb);
if (pic_order_cnt_type == 0) {
get_ue_golomb(&gb); // log2_max_pic_order_cnt_lsb_minus4
} else if (pic_order_cnt_type == 1) {
skip_bits1(&gb); // delta_pic_order_always_zero
get_se_golomb(&gb); // offset_for_non_ref_pic
get_se_golomb(&gb); // offset_for_top_to_bottom_field
num_ref_frames_in_pic_order_cnt_cycle = get_ue_golomb(&gb);
for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
get_se_golomb(&gb); // offset_for_ref_frame
}
get_ue_golomb(&gb); // max_num_ref_frames
skip_bits1(&gb); // gaps_in_frame_num_value_allowed_flag
get_ue_golomb(&gb); // pic_width_in_mbs_minus1
get_ue_golomb(&gb); // pic_height_in_map_units_minus1
sps->frame_mbs_only_flag = get_bits1(&gb);
if (!sps->frame_mbs_only_flag)
skip_bits1(&gb); // mb_adaptive_frame_field_flag
skip_bits1(&gb); // direct_8x8_inference_flag
if (get_bits1(&gb)) { // frame_cropping_flag
get_ue_golomb(&gb); // frame_crop_left_offset
get_ue_golomb(&gb); // frame_crop_right_offset
get_ue_golomb(&gb); // frame_crop_top_offset
get_ue_golomb(&gb); // frame_crop_bottom_offset
}
if (get_bits1(&gb)) { // vui_parameters_present_flag
if (get_bits1(&gb)) { // aspect_ratio_info_present_flag
aspect_ratio_idc = get_bits(&gb, 8);
if (aspect_ratio_idc == 0xff) {
sps->sar.num = get_bits(&gb, 16);
sps->sar.den = get_bits(&gb, 16);
} else if (aspect_ratio_idc < FF_ARRAY_ELEMS(avc_sample_aspect_ratio)) {
sps->sar = avc_sample_aspect_ratio[aspect_ratio_idc];
}
}
}
if (!sps->sar.den) {
sps->sar.num = 1;
sps->sar.den = 1;
}
ret = 0;
end:
av_free(rbsp_buf);
return ret;
}

53
externals/ffmpeg/libavformat/avc.h vendored Executable file
View File

@@ -0,0 +1,53 @@
/*
* 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 AVFORMAT_AVC_H
#define AVFORMAT_AVC_H
#include <stdint.h>
#include "avio.h"
int ff_avc_parse_nal_units(AVIOContext *s, const uint8_t *buf, int size);
int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size);
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len);
const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end);
int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size);
const uint8_t *ff_avc_mp4_find_startcode(const uint8_t *start,
const uint8_t *end,
int nal_length_size);
uint8_t *ff_nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len,
uint32_t *dst_len, int header_len);
typedef struct {
uint8_t id;
uint8_t profile_idc;
uint8_t level_idc;
uint8_t constraint_set_flags;
uint8_t chroma_format_idc;
uint8_t bit_depth_luma;
uint8_t bit_depth_chroma;
uint8_t frame_mbs_only_flag;
AVRational sar;
} H264SPS;
int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size);
#endif /* AVFORMAT_AVC_H */

3093
externals/ffmpeg/libavformat/avformat.h vendored Executable file

File diff suppressed because it is too large Load Diff

55
externals/ffmpeg/libavformat/avformatres.rc vendored Executable file
View File

@@ -0,0 +1,55 @@
/*
* Windows resource file for libavformat
*
* Copyright (C) 2012 James Almer
* Copyright (C) 2013 Tiancheng "Timothy" Gu
*
* 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 <windows.h>
#include "libavformat/version.h"
#include "libavutil/ffversion.h"
#include "config.h"
1 VERSIONINFO
FILEVERSION LIBAVFORMAT_VERSION_MAJOR, LIBAVFORMAT_VERSION_MINOR, LIBAVFORMAT_VERSION_MICRO, 0
PRODUCTVERSION LIBAVFORMAT_VERSION_MAJOR, LIBAVFORMAT_VERSION_MINOR, LIBAVFORMAT_VERSION_MICRO, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "CompanyName", "FFmpeg Project"
VALUE "FileDescription", "FFmpeg container format library"
VALUE "FileVersion", AV_STRINGIFY(LIBAVFORMAT_VERSION)
VALUE "InternalName", "libavformat"
VALUE "LegalCopyright", "Copyright (C) 2000-" AV_STRINGIFY(CONFIG_THIS_YEAR) " FFmpeg Project"
VALUE "OriginalFilename", "avformat" BUILDSUF "-" AV_STRINGIFY(LIBAVFORMAT_VERSION_MAJOR) SLIBSUF
VALUE "ProductName", "FFmpeg"
VALUE "ProductVersion", FFMPEG_VERSION
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04B0
}
}

41
externals/ffmpeg/libavformat/avi.h vendored Executable file
View File

@@ -0,0 +1,41 @@
/*
* copyright (c) 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 AVFORMAT_AVI_H
#define AVFORMAT_AVI_H
#define AVIF_HASINDEX 0x00000010 // Index at end of file?
#define AVIF_MUSTUSEINDEX 0x00000020
#define AVIF_ISINTERLEAVED 0x00000100
#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
#define AVIF_WASCAPTUREFILE 0x00010000
#define AVIF_COPYRIGHTED 0x00020000
#define AVI_MAX_RIFF_SIZE 0x40000000LL
#define AVI_MAX_STREAM_COUNT 100
/* stream header flags */
#define AVISF_VIDEO_PALCHANGES 0x00010000
/* index flags */
#define AVIIF_INDEX 0x00000010
#define AVIIF_NO_TIME 0x00000100
#endif /* AVFORMAT_AVI_H */

1947
externals/ffmpeg/libavformat/avidec.c vendored Executable file

File diff suppressed because it is too large Load Diff

1023
externals/ffmpeg/libavformat/avienc.c vendored Executable file

File diff suppressed because it is too large Load Diff

676
externals/ffmpeg/libavformat/avio.c vendored Executable file
View File

@@ -0,0 +1,676 @@
/*
* unbuffered I/O
* Copyright (c) 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 "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "libavutil/time.h"
#include "libavutil/avassert.h"
#include "os_support.h"
#include "avformat.h"
#include "internal.h"
#if CONFIG_NETWORK
#include "network.h"
#endif
#include "url.h"
/** @name Logging context. */
/*@{*/
static const char *urlcontext_to_name(void *ptr)
{
URLContext *h = (URLContext *)ptr;
if (h->prot)
return h->prot->name;
else
return "NULL";
}
static void *urlcontext_child_next(void *obj, void *prev)
{
URLContext *h = obj;
if (!prev && h->priv_data && h->prot->priv_data_class)
return h->priv_data;
return NULL;
}
#define OFFSET(x) offsetof(URLContext,x)
#define E AV_OPT_FLAG_ENCODING_PARAM
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
{"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
{"rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM },
{ NULL }
};
const AVClass ffurl_context_class = {
.class_name = "URLContext",
.item_name = urlcontext_to_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
.child_next = urlcontext_child_next,
.child_class_next = ff_urlcontext_child_class_next,
};
/*@}*/
static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
URLContext *uc;
int err;
#if CONFIG_NETWORK
if (up->flags & URL_PROTOCOL_FLAG_NETWORK && !ff_network_init())
return AVERROR(EIO);
#endif
if ((flags & AVIO_FLAG_READ) && !up->url_read) {
av_log(NULL, AV_LOG_ERROR,
"Impossible to open the '%s' protocol for reading\n", up->name);
return AVERROR(EIO);
}
if ((flags & AVIO_FLAG_WRITE) && !up->url_write) {
av_log(NULL, AV_LOG_ERROR,
"Impossible to open the '%s' protocol for writing\n", up->name);
return AVERROR(EIO);
}
uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
if (!uc) {
err = AVERROR(ENOMEM);
goto fail;
}
uc->av_class = &ffurl_context_class;
uc->filename = (char *)&uc[1];
strcpy(uc->filename, filename);
uc->prot = up;
uc->flags = flags;
uc->is_streamed = 0; /* default = not streamed */
uc->max_packet_size = 0; /* default: stream file */
if (up->priv_data_size) {
uc->priv_data = av_mallocz(up->priv_data_size);
if (!uc->priv_data) {
err = AVERROR(ENOMEM);
goto fail;
}
if (up->priv_data_class) {
int proto_len= strlen(up->name);
char *start = strchr(uc->filename, ',');
*(const AVClass **)uc->priv_data = up->priv_data_class;
av_opt_set_defaults(uc->priv_data);
if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){
int ret= 0;
char *p= start;
char sep= *++p;
char *key, *val;
p++;
if (strcmp(up->name, "subfile"))
ret = AVERROR(EINVAL);
while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){
*val= *key= 0;
if (strcmp(p, "start") && strcmp(p, "end")) {
ret = AVERROR_OPTION_NOT_FOUND;
} else
ret= av_opt_set(uc->priv_data, p, key+1, 0);
if (ret == AVERROR_OPTION_NOT_FOUND)
av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p);
*val= *key= sep;
p= val+1;
}
if(ret<0 || p!=key){
av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start);
av_freep(&uc->priv_data);
av_freep(&uc);
err = AVERROR(EINVAL);
goto fail;
}
memmove(start, key+1, strlen(key));
}
}
}
if (int_cb)
uc->interrupt_callback = *int_cb;
*puc = uc;
return 0;
fail:
*puc = NULL;
if (uc)
av_freep(&uc->priv_data);
av_freep(&uc);
#if CONFIG_NETWORK
if (up->flags & URL_PROTOCOL_FLAG_NETWORK)
ff_network_close();
#endif
return err;
}
int ffurl_connect(URLContext *uc, AVDictionary **options)
{
int err;
AVDictionary *tmp_opts = NULL;
AVDictionaryEntry *e;
if (!options)
options = &tmp_opts;
// Check that URLContext was initialized correctly and lists are matching if set
av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
(uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
(uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
av_log(uc, AV_LOG_ERROR, "Protocol '%s' not on whitelist '%s'!\n", uc->prot->name, uc->protocol_whitelist);
return AVERROR(EINVAL);
}
if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
av_log(uc, AV_LOG_ERROR, "Protocol '%s' on blacklist '%s'!\n", uc->prot->name, uc->protocol_blacklist);
return AVERROR(EINVAL);
}
if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
if (!uc->protocol_whitelist) {
return AVERROR(ENOMEM);
}
} else if (!uc->protocol_whitelist)
av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist
if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
return err;
if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
return err;
err =
uc->prot->url_open2 ? uc->prot->url_open2(uc,
uc->filename,
uc->flags,
options) :
uc->prot->url_open(uc, uc->filename, uc->flags);
av_dict_set(options, "protocol_whitelist", NULL, 0);
av_dict_set(options, "protocol_blacklist", NULL, 0);
if (err)
return err;
uc->is_connected = 1;
/* We must be careful here as ffurl_seek() could be slow,
* for example for http */
if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
uc->is_streamed = 1;
return 0;
}
int ffurl_accept(URLContext *s, URLContext **c)
{
av_assert0(!*c);
if (s->prot->url_accept)
return s->prot->url_accept(s, c);
return AVERROR(EBADF);
}
int ffurl_handshake(URLContext *c)
{
int ret;
if (c->prot->url_handshake) {
ret = c->prot->url_handshake(c);
if (ret)
return ret;
}
c->is_connected = 1;
return 0;
}
#define URL_SCHEME_CHARS \
"abcdefghijklmnopqrstuvwxyz" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"0123456789+-."
static const struct URLProtocol *url_find_protocol(const char *filename)
{
const URLProtocol **protocols;
char proto_str[128], proto_nested[128], *ptr;
size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
int i;
if (filename[proto_len] != ':' &&
(strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) ||
is_dos_path(filename))
strcpy(proto_str, "file");
else
av_strlcpy(proto_str, filename,
FFMIN(proto_len + 1, sizeof(proto_str)));
av_strlcpy(proto_nested, proto_str, sizeof(proto_nested));
if ((ptr = strchr(proto_nested, '+')))
*ptr = '\0';
protocols = ffurl_get_protocols(NULL, NULL);
if (!protocols)
return NULL;
for (i = 0; protocols[i]; i++) {
const URLProtocol *up = protocols[i];
if (!strcmp(proto_str, up->name)) {
av_freep(&protocols);
return up;
}
if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
!strcmp(proto_nested, up->name)) {
av_freep(&protocols);
return up;
}
}
av_freep(&protocols);
if (av_strstart(filename, "https:", NULL) || av_strstart(filename, "tls:", NULL))
av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
"openssl, gnutls or securetransport enabled.\n");
return NULL;
}
int ffurl_alloc(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
const URLProtocol *p = NULL;
p = url_find_protocol(filename);
if (p)
return url_alloc_for_protocol(puc, p, filename, flags, int_cb);
*puc = NULL;
return AVERROR_PROTOCOL_NOT_FOUND;
}
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options,
const char *whitelist, const char* blacklist,
URLContext *parent)
{
AVDictionary *tmp_opts = NULL;
AVDictionaryEntry *e;
int ret = ffurl_alloc(puc, filename, flags, int_cb);
if (ret < 0)
return ret;
if (parent)
av_opt_copy(*puc, parent);
if (options &&
(ret = av_opt_set_dict(*puc, options)) < 0)
goto fail;
if (options && (*puc)->prot->priv_data_class &&
(ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
goto fail;
if (!options)
options = &tmp_opts;
av_assert0(!whitelist ||
!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
!strcmp(whitelist, e->value));
av_assert0(!blacklist ||
!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
!strcmp(blacklist, e->value));
if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
goto fail;
if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
goto fail;
if ((ret = av_opt_set_dict(*puc, options)) < 0)
goto fail;
ret = ffurl_connect(*puc, options);
if (!ret)
return 0;
fail:
ffurl_closep(puc);
return ret;
}
int ffurl_open(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options)
{
return ffurl_open_whitelist(puc, filename, flags,
int_cb, options, NULL, NULL, NULL);
}
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
int size, int size_min,
int (*transfer_func)(URLContext *h,
uint8_t *buf,
int size))
{
int ret, len;
int fast_retries = 5;
int64_t wait_since = 0;
len = 0;
while (len < size_min) {
if (ff_check_interrupt(&h->interrupt_callback))
return AVERROR_EXIT;
ret = transfer_func(h, buf + len, size - len);
if (ret == AVERROR(EINTR))
continue;
if (h->flags & AVIO_FLAG_NONBLOCK)
return ret;
if (ret == AVERROR(EAGAIN)) {
ret = 0;
if (fast_retries) {
fast_retries--;
} else {
if (h->rw_timeout) {
if (!wait_since)
wait_since = av_gettime_relative();
else if (av_gettime_relative() > wait_since + h->rw_timeout)
return AVERROR(EIO);
}
av_usleep(1000);
}
} else if (ret == AVERROR_EOF)
return (len > 0) ? len : AVERROR_EOF;
else if (ret < 0)
return ret;
if (ret) {
fast_retries = FFMAX(fast_retries, 2);
wait_since = 0;
}
len += ret;
}
return len;
}
int ffurl_read(URLContext *h, unsigned char *buf, int size)
{
if (!(h->flags & AVIO_FLAG_READ))
return AVERROR(EIO);
return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
}
int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
{
if (!(h->flags & AVIO_FLAG_READ))
return AVERROR(EIO);
return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read);
}
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
{
if (!(h->flags & AVIO_FLAG_WRITE))
return AVERROR(EIO);
/* avoid sending too big packets */
if (h->max_packet_size && size > h->max_packet_size)
return AVERROR(EIO);
return retry_transfer_wrapper(h, (unsigned char *)buf, size, size,
(int (*)(struct URLContext *, uint8_t *, int))
h->prot->url_write);
}
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
{
int64_t ret;
if (!h->prot->url_seek)
return AVERROR(ENOSYS);
ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE);
return ret;
}
int ffurl_closep(URLContext **hh)
{
URLContext *h= *hh;
int ret = 0;
if (!h)
return 0; /* can happen when ffurl_open fails */
if (h->is_connected && h->prot->url_close)
ret = h->prot->url_close(h);
#if CONFIG_NETWORK
if (h->prot->flags & URL_PROTOCOL_FLAG_NETWORK)
ff_network_close();
#endif
if (h->prot->priv_data_size) {
if (h->prot->priv_data_class)
av_opt_free(h->priv_data);
av_freep(&h->priv_data);
}
av_opt_free(h);
av_freep(hh);
return ret;
}
int ffurl_close(URLContext *h)
{
return ffurl_closep(&h);
}
const char *avio_find_protocol_name(const char *url)
{
const URLProtocol *p = url_find_protocol(url);
return p ? p->name : NULL;
}
int avio_check(const char *url, int flags)
{
URLContext *h;
int ret = ffurl_alloc(&h, url, flags, NULL);
if (ret < 0)
return ret;
if (h->prot->url_check) {
ret = h->prot->url_check(h, flags);
} else {
ret = ffurl_connect(h, NULL);
if (ret >= 0)
ret = flags;
}
ffurl_close(h);
return ret;
}
int avpriv_io_move(const char *url_src, const char *url_dst)
{
URLContext *h_src, *h_dst;
int ret = ffurl_alloc(&h_src, url_src, AVIO_FLAG_READ_WRITE, NULL);
if (ret < 0)
return ret;
ret = ffurl_alloc(&h_dst, url_dst, AVIO_FLAG_WRITE, NULL);
if (ret < 0) {
ffurl_close(h_src);
return ret;
}
if (h_src->prot == h_dst->prot && h_src->prot->url_move)
ret = h_src->prot->url_move(h_src, h_dst);
else
ret = AVERROR(ENOSYS);
ffurl_close(h_src);
ffurl_close(h_dst);
return ret;
}
int avpriv_io_delete(const char *url)
{
URLContext *h;
int ret = ffurl_alloc(&h, url, AVIO_FLAG_WRITE, NULL);
if (ret < 0)
return ret;
if (h->prot->url_delete)
ret = h->prot->url_delete(h);
else
ret = AVERROR(ENOSYS);
ffurl_close(h);
return ret;
}
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options)
{
URLContext *h = NULL;
AVIODirContext *ctx = NULL;
int ret;
av_assert0(s);
ctx = av_mallocz(sizeof(*ctx));
if (!ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
if ((ret = ffurl_alloc(&h, url, AVIO_FLAG_READ, NULL)) < 0)
goto fail;
if (h->prot->url_open_dir && h->prot->url_read_dir && h->prot->url_close_dir) {
if (options && h->prot->priv_data_class &&
(ret = av_opt_set_dict(h->priv_data, options)) < 0)
goto fail;
ret = h->prot->url_open_dir(h);
} else
ret = AVERROR(ENOSYS);
if (ret < 0)
goto fail;
h->is_connected = 1;
ctx->url_context = h;
*s = ctx;
return 0;
fail:
av_free(ctx);
*s = NULL;
ffurl_close(h);
return ret;
}
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next)
{
URLContext *h;
int ret;
if (!s || !s->url_context)
return AVERROR(EINVAL);
h = s->url_context;
if ((ret = h->prot->url_read_dir(h, next)) < 0)
avio_free_directory_entry(next);
return ret;
}
int avio_close_dir(AVIODirContext **s)
{
URLContext *h;
av_assert0(s);
if (!(*s) || !(*s)->url_context)
return AVERROR(EINVAL);
h = (*s)->url_context;
h->prot->url_close_dir(h);
ffurl_close(h);
av_freep(s);
*s = NULL;
return 0;
}
void avio_free_directory_entry(AVIODirEntry **entry)
{
if (!entry || !*entry)
return;
av_free((*entry)->name);
av_freep(entry);
}
int64_t ffurl_size(URLContext *h)
{
int64_t pos, size;
size = ffurl_seek(h, 0, AVSEEK_SIZE);
if (size < 0) {
pos = ffurl_seek(h, 0, SEEK_CUR);
if ((size = ffurl_seek(h, -1, SEEK_END)) < 0)
return size;
size++;
ffurl_seek(h, pos, SEEK_SET);
}
return size;
}
int ffurl_get_file_handle(URLContext *h)
{
if (!h || !h->prot || !h->prot->url_get_file_handle)
return -1;
return h->prot->url_get_file_handle(h);
}
int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
{
if (!h || !h->prot)
return AVERROR(ENOSYS);
if (!h->prot->url_get_multi_file_handle) {
if (!h->prot->url_get_file_handle)
return AVERROR(ENOSYS);
*handles = av_malloc(sizeof(**handles));
if (!*handles)
return AVERROR(ENOMEM);
*numhandles = 1;
*handles[0] = h->prot->url_get_file_handle(h);
return 0;
}
return h->prot->url_get_multi_file_handle(h, handles, numhandles);
}
int ffurl_get_short_seek(URLContext *h)
{
if (!h || !h->prot || !h->prot->url_get_short_seek)
return AVERROR(ENOSYS);
return h->prot->url_get_short_seek(h);
}
int ffurl_shutdown(URLContext *h, int flags)
{
if (!h || !h->prot || !h->prot->url_shutdown)
return AVERROR(ENOSYS);
return h->prot->url_shutdown(h, flags);
}
int ff_check_interrupt(AVIOInterruptCB *cb)
{
if (cb && cb->callback)
return cb->callback(cb->opaque);
return 0;
}
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
{
int ret = avpriv_io_move(url_src, url_dst);
if (ret < 0)
av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", url_src, url_dst, av_err2str(ret));
return ret;
}

888
externals/ffmpeg/libavformat/avio.h vendored Executable file
View File

@@ -0,0 +1,888 @@
/*
* copyright (c) 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 AVFORMAT_AVIO_H
#define AVFORMAT_AVIO_H
/**
* @file
* @ingroup lavf_io
* Buffered I/O operations
*/
#include <stdint.h>
#include "libavutil/common.h"
#include "libavutil/dict.h"
#include "libavutil/log.h"
#include "libavformat/version.h"
/**
* Seeking works like for a local file.
*/
#define AVIO_SEEKABLE_NORMAL (1 << 0)
/**
* Seeking by timestamp with avio_seek_time() is possible.
*/
#define AVIO_SEEKABLE_TIME (1 << 1)
/**
* Callback for checking whether to abort blocking functions.
* AVERROR_EXIT is returned in this case by the interrupted
* function. During blocking operations, callback is called with
* opaque as parameter. If the callback returns 1, the
* blocking operation will be aborted.
*
* No members can be added to this struct without a major bump, if
* new elements have been added after this struct in AVFormatContext
* or AVIOContext.
*/
typedef struct AVIOInterruptCB {
int (*callback)(void*);
void *opaque;
} AVIOInterruptCB;
/**
* Directory entry types.
*/
enum AVIODirEntryType {
AVIO_ENTRY_UNKNOWN,
AVIO_ENTRY_BLOCK_DEVICE,
AVIO_ENTRY_CHARACTER_DEVICE,
AVIO_ENTRY_DIRECTORY,
AVIO_ENTRY_NAMED_PIPE,
AVIO_ENTRY_SYMBOLIC_LINK,
AVIO_ENTRY_SOCKET,
AVIO_ENTRY_FILE,
AVIO_ENTRY_SERVER,
AVIO_ENTRY_SHARE,
AVIO_ENTRY_WORKGROUP,
};
/**
* Describes single entry of the directory.
*
* Only name and type fields are guaranteed be set.
* Rest of fields are protocol or/and platform dependent and might be unknown.
*/
typedef struct AVIODirEntry {
char *name; /**< Filename */
int type; /**< Type of the entry */
int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
Name can be encoded with UTF-8 even though 0 is set. */
int64_t size; /**< File size in bytes, -1 if unknown. */
int64_t modification_timestamp; /**< Time of last modification in microseconds since unix
epoch, -1 if unknown. */
int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch,
-1 if unknown. */
int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix
epoch, -1 if unknown. */
int64_t user_id; /**< User ID of owner, -1 if unknown. */
int64_t group_id; /**< Group ID of owner, -1 if unknown. */
int64_t filemode; /**< Unix file mode, -1 if unknown. */
} AVIODirEntry;
typedef struct AVIODirContext {
struct URLContext *url_context;
} AVIODirContext;
/**
* Different data types that can be returned via the AVIO
* write_data_type callback.
*/
enum AVIODataMarkerType {
/**
* Header data; this needs to be present for the stream to be decodeable.
*/
AVIO_DATA_MARKER_HEADER,
/**
* A point in the output bytestream where a decoder can start decoding
* (i.e. a keyframe). A demuxer/decoder given the data flagged with
* AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,
* should give decodeable results.
*/
AVIO_DATA_MARKER_SYNC_POINT,
/**
* A point in the output bytestream where a demuxer can start parsing
* (for non self synchronizing bytestream formats). That is, any
* non-keyframe packet start point.
*/
AVIO_DATA_MARKER_BOUNDARY_POINT,
/**
* This is any, unlabelled data. It can either be a muxer not marking
* any positions at all, it can be an actual boundary/sync point
* that the muxer chooses not to mark, or a later part of a packet/fragment
* that is cut into multiple write callbacks due to limited IO buffer size.
*/
AVIO_DATA_MARKER_UNKNOWN,
/**
* Trailer data, which doesn't contain actual content, but only for
* finalizing the output file.
*/
AVIO_DATA_MARKER_TRAILER,
/**
* A point in the output bytestream where the underlying AVIOContext might
* flush the buffer depending on latency or buffering requirements. Typically
* means the end of a packet.
*/
AVIO_DATA_MARKER_FLUSH_POINT,
};
/**
* 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(AVIOContext) must not be used outside libav*.
*
* @note None of the function pointers in AVIOContext should be called
* directly, they should only be set by the client application
* when implementing custom I/O. Normally these are set to the
* function pointers specified in avio_alloc_context()
*/
typedef struct AVIOContext {
/**
* A class for private options.
*
* If this AVIOContext is created by avio_open2(), av_class is set and
* passes the options down to protocols.
*
* If this AVIOContext is manually allocated, then av_class may be set by
* the caller.
*
* warning -- this field can be NULL, be sure to not pass this AVIOContext
* to any av_opt_* functions in that case.
*/
const AVClass *av_class;
/*
* The following shows the relationship between buffer, buf_ptr,
* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing
* (since AVIOContext is used for both):
*
**********************************************************************************
* READING
**********************************************************************************
*
* | buffer_size |
* |---------------------------------------|
* | |
*
* buffer buf_ptr buf_end
* +---------------+-----------------------+
* |/ / / / / / / /|/ / / / / / /| |
* read buffer: |/ / consumed / | to be read /| |
* |/ / / / / / / /|/ / / / / / /| |
* +---------------+-----------------------+
*
* pos
* +-------------------------------------------+-----------------+
* input file: | | |
* +-------------------------------------------+-----------------+
*
*
**********************************************************************************
* WRITING
**********************************************************************************
*
* | buffer_size |
* |--------------------------------------|
* | |
*
* buf_ptr_max
* buffer (buf_ptr) buf_end
* +-----------------------+--------------+
* |/ / / / / / / / / / / /| |
* write buffer: | / / to be flushed / / | |
* |/ / / / / / / / / / / /| |
* +-----------------------+--------------+
* buf_ptr can be in this
* due to a backward seek
*
* pos
* +-------------+----------------------------------------------+
* output file: | | |
* +-------------+----------------------------------------------+
*
*/
unsigned char *buffer; /**< Start of the buffer. */
int buffer_size; /**< Maximum buffer size */
unsigned char *buf_ptr; /**< Current position in the buffer */
unsigned char *buf_end; /**< End of the data, may be less than
buffer+buffer_size if the read function returned
less data than requested, e.g. for streams where
no more data has been received yet. */
void *opaque; /**< A private pointer, passed to the read/write/seek/...
functions. */
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
int64_t (*seek)(void *opaque, int64_t offset, int whence);
int64_t pos; /**< position in the file of the current buffer */
int eof_reached; /**< true if was unable to read due to error or eof */
int write_flag; /**< true if open for writing */
int max_packet_size;
unsigned long checksum;
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 */
/**
* Pause or resume playback for network streaming protocols - e.g. MMS.
*/
int (*read_pause)(void *opaque, int pause);
/**
* Seek to a given timestamp in stream with the specified stream_index.
* Needed for some network streaming protocols which don't support seeking
* to byte position.
*/
int64_t (*read_seek)(void *opaque, int stream_index,
int64_t timestamp, int flags);
/**
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
*/
int seekable;
/**
* max filesize, used to limit allocations
* This field is internal to libavformat and access from outside is not allowed.
*/
int64_t maxsize;
/**
* avio_read and avio_write should if possible be satisfied directly
* instead of going through a buffer, and avio_seek will always
* call the underlying seek function directly.
*/
int direct;
/**
* Bytes read statistic
* This field is internal to libavformat and access from outside is not allowed.
*/
int64_t bytes_read;
/**
* seek statistic
* This field is internal to libavformat and access from outside is not allowed.
*/
int seek_count;
/**
* writeout statistic
* This field is internal to libavformat and access from outside is not allowed.
*/
int writeout_count;
/**
* Original buffer size
* used internally after probing and ensure seekback to reset the buffer size
* This field is internal to libavformat and access from outside is not allowed.
*/
int orig_buffer_size;
/**
* Threshold to favor readahead over seek.
* This is current internal only, do not use from outside.
*/
int short_seek_threshold;
/**
* ',' separated list of allowed protocols.
*/
const char *protocol_whitelist;
/**
* ',' separated list of disallowed protocols.
*/
const char *protocol_blacklist;
/**
* A callback that is used instead of write_packet.
*/
int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
enum AVIODataMarkerType type, int64_t time);
/**
* If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,
* but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly
* small chunks of data returned from the callback).
*/
int ignore_boundary_point;
/**
* Internal, not meant to be used from outside of AVIOContext.
*/
enum AVIODataMarkerType current_type;
int64_t last_time;
/**
* A callback that is used instead of short_seek_threshold.
* This is current internal only, do not use from outside.
*/
int (*short_seek_get)(void *opaque);
int64_t written;
/**
* Maximum reached position before a backward seek in the write buffer,
* used keeping track of already written data for a later flush.
*/
unsigned char *buf_ptr_max;
/**
* Try to buffer at least this amount of data before flushing it
*/
int min_packet_size;
} AVIOContext;
/**
* Return the name of the protocol that will handle the passed URL.
*
* NULL is returned if no protocol could be found for the given URL.
*
* @return Name of the protocol or NULL.
*/
const char *avio_find_protocol_name(const char *url);
/**
* Return AVIO_FLAG_* access flags corresponding to the access permissions
* of the resource in url, or a negative value corresponding to an
* AVERROR code in case of failure. The returned access flags are
* masked by the value in flags.
*
* @note This function is intrinsically unsafe, in the sense that the
* checked resource may change its existence or permission status from
* one call to another. Thus you should not trust the returned value,
* unless you are sure that no other processes are accessing the
* checked resource.
*/
int avio_check(const char *url, int flags);
/**
* Move or rename a resource.
*
* @note url_src and url_dst should share the same protocol and authority.
*
* @param url_src url to resource to be moved
* @param url_dst new url to resource if the operation succeeded
* @return >=0 on success or negative on error.
*/
int avpriv_io_move(const char *url_src, const char *url_dst);
/**
* Delete a resource.
*
* @param url resource to be deleted.
* @return >=0 on success or negative on error.
*/
int avpriv_io_delete(const char *url);
/**
* Open directory for reading.
*
* @param s directory read context. Pointer to a NULL pointer must be passed.
* @param url directory to be listed.
* @param options A dictionary filled with protocol-private options. On return
* this parameter will be destroyed and replaced with a dictionary
* containing options that were not found. May be NULL.
* @return >=0 on success or negative on error.
*/
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);
/**
* Get next directory entry.
*
* Returned entry must be freed with avio_free_directory_entry(). In particular
* it may outlive AVIODirContext.
*
* @param s directory read context.
* @param[out] next next entry or NULL when no more entries.
* @return >=0 on success or negative on error. End of list is not considered an
* error.
*/
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next);
/**
* Close directory.
*
* @note Entries created using avio_read_dir() are not deleted and must be
* freeded with avio_free_directory_entry().
*
* @param s directory read context.
* @return >=0 on success or negative on error.
*/
int avio_close_dir(AVIODirContext **s);
/**
* Free entry allocated by avio_read_dir().
*
* @param entry entry to be freed.
*/
void avio_free_directory_entry(AVIODirEntry **entry);
/**
* Allocate and initialize an AVIOContext for buffered I/O. It must be later
* freed with avio_context_free().
*
* @param buffer Memory block for input/output operations via AVIOContext.
* The buffer must be allocated with av_malloc() and friends.
* It may be freed and replaced with a new buffer by libavformat.
* AVIOContext.buffer holds the buffer currently in use,
* which must be later freed with av_free().
* @param buffer_size The buffer size is very important for performance.
* For protocols with fixed blocksize it should be set to this blocksize.
* For others a typical size is a cache page, e.g. 4kb.
* @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.
* @param opaque An opaque pointer to user-specific data.
* @param read_packet A function for refilling the buffer, may be NULL.
* For stream protocols, must never return 0 but rather
* a proper AVERROR code.
* @param write_packet A function for writing the buffer contents, may be NULL.
* The function may not change the input buffers content.
* @param seek A function for seeking to specified byte position, may be NULL.
*
* @return Allocated AVIOContext or NULL on failure.
*/
AVIOContext *avio_alloc_context(
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),
int64_t (*seek)(void *opaque, int64_t offset, int whence));
/**
* Free the supplied IO context and everything associated with it.
*
* @param s Double pointer to the IO context. This function will write NULL
* into s.
*/
void avio_context_free(AVIOContext **s);
void avio_w8(AVIOContext *s, int b);
void avio_write(AVIOContext *s, const unsigned char *buf, int size);
void avio_wl64(AVIOContext *s, uint64_t val);
void avio_wb64(AVIOContext *s, uint64_t val);
void avio_wl32(AVIOContext *s, unsigned int val);
void avio_wb32(AVIOContext *s, unsigned int val);
void avio_wl24(AVIOContext *s, unsigned int val);
void avio_wb24(AVIOContext *s, unsigned int val);
void avio_wl16(AVIOContext *s, unsigned int val);
void avio_wb16(AVIOContext *s, unsigned int val);
/**
* Write a NULL-terminated string.
* @return number of bytes written.
*/
int avio_put_str(AVIOContext *s, const char *str);
/**
* Convert an UTF-8 string to UTF-16LE and write it.
* @param s the AVIOContext
* @param str NULL-terminated UTF-8 string
*
* @return number of bytes written.
*/
int avio_put_str16le(AVIOContext *s, const char *str);
/**
* Convert an UTF-8 string to UTF-16BE and write it.
* @param s the AVIOContext
* @param str NULL-terminated UTF-8 string
*
* @return number of bytes written.
*/
int avio_put_str16be(AVIOContext *s, const char *str);
/**
* Mark the written bytestream as a specific type.
*
* Zero-length ranges are omitted from the output.
*
* @param time the stream time the current bytestream pos corresponds to
* (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not
* applicable
* @param type the kind of data written starting at the current pos
*/
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
/**
* ORing 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
/**
* Passing this flag as the "whence" parameter to a seek function causes it to
* seek by any means (like reopening and linear reading) or other normally unreasonable
* means that can be extremely slow.
* This may be ignored by the seek code.
*/
#define AVSEEK_FORCE 0x20000
/**
* fseek() equivalent for AVIOContext.
* @return new position or AVERROR.
*/
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence);
/**
* Skip given number of bytes forward
* @return new position or AVERROR.
*/
int64_t avio_skip(AVIOContext *s, int64_t offset);
/**
* ftell() equivalent for AVIOContext.
* @return position or AVERROR.
*/
static av_always_inline int64_t avio_tell(AVIOContext *s)
{
return avio_seek(s, 0, SEEK_CUR);
}
/**
* Get the filesize.
* @return filesize or AVERROR
*/
int64_t avio_size(AVIOContext *s);
/**
* Similar to feof() but also returns nonzero on read errors.
* @return non zero if and only if at end of file or a read error happened when reading.
*/
int avio_feof(AVIOContext *s);
/**
* Writes a formatted string to the context.
* @return number of bytes written, < 0 on error.
*/
int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3);
/**
* Write a NULL terminated array of strings to the context.
* Usually you don't need to use this function directly but its macro wrapper,
* avio_print.
*/
void avio_print_string_array(AVIOContext *s, const char *strings[]);
/**
* Write strings (const char *) to the context.
* This is a convenience macro around avio_print_string_array and it
* automatically creates the string array from the variable argument list.
* For simple string concatenations this function is more performant than using
* avio_printf since it does not need a temporary buffer.
*/
#define avio_print(s, ...) \
avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL})
/**
* Force flushing of buffered data.
*
* For write streams, force the buffered data to be immediately written to the output,
* without to wait to fill the internal buffer.
*
* For read streams, discard all currently buffered data, and advance the
* reported file position to that of the underlying stream. This does not
* read new data, and does not perform any seeks.
*/
void avio_flush(AVIOContext *s);
/**
* Read size bytes from AVIOContext into buf.
* @return number of bytes read or AVERROR
*/
int avio_read(AVIOContext *s, unsigned char *buf, int size);
/**
* Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed
* to read fewer bytes than requested. The missing bytes can be read in the next
* call. This always tries to read at least 1 byte.
* Useful to reduce latency in certain cases.
* @return number of bytes read or AVERROR
*/
int avio_read_partial(AVIOContext *s, unsigned char *buf, int size);
/**
* @name Functions for reading from AVIOContext
* @{
*
* @note return 0 if EOF, so you cannot use it if EOF handling is
* necessary
*/
int avio_r8 (AVIOContext *s);
unsigned int avio_rl16(AVIOContext *s);
unsigned int avio_rl24(AVIOContext *s);
unsigned int avio_rl32(AVIOContext *s);
uint64_t avio_rl64(AVIOContext *s);
unsigned int avio_rb16(AVIOContext *s);
unsigned int avio_rb24(AVIOContext *s);
unsigned int avio_rb32(AVIOContext *s);
uint64_t avio_rb64(AVIOContext *s);
/**
* @}
*/
/**
* Read a string from pb into buf. The reading will terminate when either
* a NULL character was encountered, maxlen bytes have been read, or nothing
* more can be read from pb. The result is guaranteed to be NULL-terminated, it
* will be truncated if buf is too small.
* Note that the string is not interpreted or validated in any way, it
* might get truncated in the middle of a sequence for multi-byte encodings.
*
* @return number of bytes read (is always <= maxlen).
* If reading ends on EOF or error, the return value will be one more than
* bytes actually read.
*/
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen);
/**
* Read a UTF-16 string from pb and convert it to UTF-8.
* The reading will terminate when either a null or invalid character was
* encountered or maxlen bytes have been read.
* @return number of bytes read (is always <= maxlen)
*/
int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen);
int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
/**
* @name URL open modes
* The flags argument to avio_open must be one of the following
* constants, optionally ORed with other flags.
* @{
*/
#define AVIO_FLAG_READ 1 /**< read-only */
#define AVIO_FLAG_WRITE 2 /**< write-only */
#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */
/**
* @}
*/
/**
* Use non-blocking mode.
* If this flag is set, operations on the context will return
* AVERROR(EAGAIN) if they can not be performed immediately.
* If this flag is not set, operations on the context will never return
* AVERROR(EAGAIN).
* Note that this flag does not affect the opening/connecting of the
* context. Connecting a protocol will always block if necessary (e.g. on
* network protocols) but never hang (e.g. on busy devices).
* Warning: non-blocking protocols is work-in-progress; this flag may be
* silently ignored.
*/
#define AVIO_FLAG_NONBLOCK 8
/**
* Use direct mode.
* avio_read and avio_write should if possible be satisfied directly
* instead of going through a buffer, and avio_seek will always
* call the underlying seek function directly.
*/
#define AVIO_FLAG_DIRECT 0x8000
/**
* Create and initialize a AVIOContext for accessing the
* resource indicated by url.
* @note When the resource indicated by url has been opened in
* read+write mode, the AVIOContext can be used only for writing.
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
* @param url resource to access
* @param flags flags which control how the resource indicated by url
* is to be opened
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int avio_open(AVIOContext **s, const char *url, int flags);
/**
* Create and initialize a AVIOContext for accessing the
* resource indicated by url.
* @note When the resource indicated by url has been opened in
* read+write mode, the AVIOContext can be used only for writing.
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
* @param url resource to access
* @param flags flags which control how the resource indicated by url
* is to be opened
* @param int_cb an interrupt callback to be used at the protocols level
* @param options A dictionary filled with protocol-private options. On return
* this parameter will be destroyed and replaced with a dict containing options
* that were not found. May be NULL.
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int avio_open2(AVIOContext **s, const char *url, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options);
/**
* Close the resource accessed by the AVIOContext s and free it.
* This function can only be used if s was opened by avio_open().
*
* The internal buffer is automatically flushed before closing the
* resource.
*
* @return 0 on success, an AVERROR < 0 on error.
* @see avio_closep
*/
int avio_close(AVIOContext *s);
/**
* Close the resource accessed by the AVIOContext *s, free it
* and set the pointer pointing to it to NULL.
* This function can only be used if s was opened by avio_open().
*
* The internal buffer is automatically flushed before closing the
* resource.
*
* @return 0 on success, an AVERROR < 0 on error.
* @see avio_close
*/
int avio_closep(AVIOContext **s);
/**
* Open a write only memory stream.
*
* @param s new IO context
* @return zero if no error.
*/
int avio_open_dyn_buf(AVIOContext **s);
/**
* Return the written size and a pointer to the buffer.
* The AVIOContext stream is left intact.
* The buffer must NOT be freed.
* No padding is added to the buffer.
*
* @param s IO context
* @param pbuffer pointer to a byte buffer
* @return the length of the byte buffer
*/
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
/**
* Return the written size and a pointer to the buffer. The buffer
* must be freed with av_free().
* Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer.
*
* @param s IO context
* @param pbuffer pointer to a byte buffer
* @return the length of the byte buffer
*/
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
/**
* Iterate through names of available protocols.
*
* @param opaque A private pointer representing current protocol.
* It must be a pointer to NULL on first iteration and will
* be updated by successive calls to avio_enum_protocols.
* @param output If set to 1, iterate over output protocols,
* otherwise over input protocols.
*
* @return A static string containing the name of current protocol or NULL
*/
const char *avio_enum_protocols(void **opaque, int output);
/**
* Get AVClass by names of available protocols.
*
* @return A AVClass of input protocol name or NULL
*/
const AVClass *avio_protocol_get_class(const char *name);
/**
* Pause and resume playing - only meaningful if using a network streaming
* protocol (e.g. MMS).
*
* @param h IO context from which to call the read_pause function pointer
* @param pause 1 for pause, 0 for resume
*/
int avio_pause(AVIOContext *h, int pause);
/**
* Seek to a given timestamp relative to some component stream.
* Only meaningful if using a network streaming protocol (e.g. MMS.).
*
* @param h IO context from which to call the seek function pointers
* @param stream_index The stream index that the timestamp is relative to.
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
* units from the beginning of the presentation.
* If a stream_index >= 0 is used and the protocol does not support
* seeking based on component streams, the call will fail.
* @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 if used and not supported.
* @return >= 0 on success
* @see AVInputFormat::read_seek
*/
int64_t avio_seek_time(AVIOContext *h, int stream_index,
int64_t timestamp, int flags);
/* Avoid a warning. The header can not be included because it breaks c++. */
struct AVBPrint;
/**
* Read contents of h into print buffer, up to max_size bytes, or up to EOF.
*
* @return 0 for success (max_size bytes read or EOF reached), negative error
* code otherwise
*/
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size);
/**
* Accept and allocate a client context on a server context.
* @param s the server context
* @param c the client context, must be unallocated
* @return >= 0 on success or a negative value corresponding
* to an AVERROR on failure
*/
int avio_accept(AVIOContext *s, AVIOContext **c);
/**
* Perform one step of the protocol handshake to accept a new client.
* This function must be called on a client returned by avio_accept() before
* using it as a read/write context.
* It is separate from avio_accept() because it may block.
* A step of the handshake is defined by places where the application may
* decide to change the proceedings.
* For example, on a protocol with a request header and a reply header, each
* one can constitute a step because the application may use the parameters
* from the request to change parameters in the reply; or each individual
* chunk of the request can constitute a step.
* If the handshake is already finished, avio_handshake() does nothing and
* returns 0 immediately.
*
* @param c the client context to perform the handshake on
* @return 0 on a complete and successful handshake
* > 0 if the handshake progressed, but is not complete
* < 0 for an AVERROR code
*/
int avio_handshake(AVIOContext *c);
#endif /* AVFORMAT_AVIO_H */

188
externals/ffmpeg/libavformat/avio_internal.h vendored Executable file
View File

@@ -0,0 +1,188 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_AVIO_INTERNAL_H
#define AVFORMAT_AVIO_INTERNAL_H
#include "avio.h"
#include "url.h"
#include "libavutil/log.h"
extern const AVClass ff_avio_class;
int ffio_init_context(AVIOContext *s,
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),
int64_t (*seek)(void *opaque, int64_t offset, int whence));
/**
* Read size bytes from AVIOContext, returning a pointer.
* Note that the data pointed at by the returned pointer is only
* valid until the next call that references the same IO context.
* @param s IO context
* @param buf pointer to buffer into which to assemble the requested
* data if it is not available in contiguous addresses in the
* underlying buffer
* @param size number of bytes requested
* @param data address at which to store pointer: this will be a
* a direct pointer into the underlying buffer if the requested
* number of bytes are available at contiguous addresses, otherwise
* will be a copy of buf
* @return number of bytes read or AVERROR
*/
int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data);
void ffio_fill(AVIOContext *s, int b, int count);
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
{
avio_wl32(pb, MKTAG(s[0], s[1], s[2], s[3]));
}
/**
* Rewind the AVIOContext using the specified buffer containing the first buf_size bytes of the file.
* Used after probing to avoid seeking.
* Joins buf and s->buffer, taking any overlap into consideration.
* @note s->buffer must overlap with buf or they can't be joined and the function fails
*
* @param s The read-only AVIOContext to rewind
* @param buf The probe buffer containing the first buf_size bytes of the file
* @param buf_size The size of buf
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **buf, int buf_size);
uint64_t ffio_read_varlen(AVIOContext *bc);
/**
* Read size bytes from AVIOContext into buf.
* Check that exactly size bytes have been read.
* @return number of bytes read or AVERROR
*/
int ffio_read_size(AVIOContext *s, unsigned char *buf, int size);
/** @warning must be called before any I/O */
int ffio_set_buf_size(AVIOContext *s, int buf_size);
/**
* Reallocate a given buffer for AVIOContext.
*
* @param s the AVIOContext to realloc.
* @param buf_size required new buffer size.
* @return 0 on success, a negative AVERROR on failure.
*/
int ffio_realloc_buf(AVIOContext *s, int buf_size);
/**
* Ensures that the requested seekback buffer size will be available
*
* Will ensure that when reading sequentially up to buf_size, seeking
* within the current pos and pos+buf_size is possible.
* Once the stream position moves outside this window this guarantee is lost.
*/
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size);
int ffio_limit(AVIOContext *s, int size);
void ffio_init_checksum(AVIOContext *s,
unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
unsigned long checksum);
unsigned long ffio_get_checksum(AVIOContext *s);
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
unsigned int len);
unsigned long ff_crcEDB88320_update(unsigned long checksum, const uint8_t *buf,
unsigned int len);
unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
unsigned int len);
/**
* Open a write only packetized memory stream with a maximum packet
* size of 'max_packet_size'. The stream is stored in a memory buffer
* with a big-endian 4 byte header giving the packet size in bytes.
*
* @param s new IO context
* @param max_packet_size maximum packet size (must be > 0)
* @return zero if no error.
*/
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size);
/**
* Create and initialize a AVIOContext for accessing the
* resource referenced by the URLContext h.
* @note When the URLContext h has been opened in read+write mode, the
* AVIOContext can be used only for writing.
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int ffio_fdopen(AVIOContext **s, URLContext *h);
/**
* Return the URLContext associated with the AVIOContext
*
* @param s IO context
* @return pointer to URLContext or NULL.
*/
URLContext *ffio_geturlcontext(AVIOContext *s);
/**
* Open a write-only fake memory stream. The written data is not stored
* anywhere - this is only used for measuring the amount of data
* written.
*
* @param s new IO context
* @return zero if no error.
*/
int ffio_open_null_buf(AVIOContext **s);
int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options,
const char *whitelist, const char *blacklist);
/**
* Close a null buffer.
*
* @param s an IO context opened by ffio_open_null_buf
* @return the number of bytes written to the null buffer
*/
int ffio_close_null_buf(AVIOContext *s);
/**
* Reset a dynamic buffer.
*
* Resets everything, but keeps the allocated buffer for later use.
*/
void ffio_reset_dyn_buf(AVIOContext *s);
/**
* Free a dynamic buffer.
*
* @param s a pointer to an IO context opened by avio_open_dyn_buf()
*/
void ffio_free_dyn_buf(AVIOContext **s);
#endif /* AVFORMAT_AVIO_INTERNAL_H */

1477
externals/ffmpeg/libavformat/aviobuf.c vendored Executable file

File diff suppressed because it is too large Load Diff

883
externals/ffmpeg/libavformat/avisynth.c vendored Executable file
View File

@@ -0,0 +1,883 @@
/*
* AviSynth(+) support
* Copyright (c) 2012 AvxSynth Team
*
* This file is part of FFmpeg
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/attributes.h"
#include "libavutil/internal.h"
#include "libavcodec/internal.h"
#include "avformat.h"
#include "internal.h"
#include "config.h"
/* Enable function pointer definitions for runtime loading. */
#define AVSC_NO_DECLSPEC
/* Platform-specific directives. */
#ifdef _WIN32
#include "compat/w32dlfcn.h"
#undef EXTERN_C
#define AVISYNTH_LIB "avisynth"
#else
#include <dlfcn.h>
#define AVISYNTH_NAME "libavisynth"
#define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF
#endif
#include <avisynth/avisynth_c.h>
typedef struct AviSynthLibrary {
void *library;
#define AVSC_DECLARE_FUNC(name) name ## _func name
AVSC_DECLARE_FUNC(avs_bit_blt);
AVSC_DECLARE_FUNC(avs_clip_get_error);
AVSC_DECLARE_FUNC(avs_create_script_environment);
AVSC_DECLARE_FUNC(avs_delete_script_environment);
AVSC_DECLARE_FUNC(avs_get_audio);
AVSC_DECLARE_FUNC(avs_get_error);
AVSC_DECLARE_FUNC(avs_get_frame);
AVSC_DECLARE_FUNC(avs_get_version);
AVSC_DECLARE_FUNC(avs_get_video_info);
AVSC_DECLARE_FUNC(avs_invoke);
AVSC_DECLARE_FUNC(avs_release_clip);
AVSC_DECLARE_FUNC(avs_release_value);
AVSC_DECLARE_FUNC(avs_release_video_frame);
AVSC_DECLARE_FUNC(avs_take_clip);
AVSC_DECLARE_FUNC(avs_bits_per_pixel);
AVSC_DECLARE_FUNC(avs_get_height_p);
AVSC_DECLARE_FUNC(avs_get_pitch_p);
AVSC_DECLARE_FUNC(avs_get_read_ptr_p);
AVSC_DECLARE_FUNC(avs_get_row_size_p);
AVSC_DECLARE_FUNC(avs_is_planar_rgb);
AVSC_DECLARE_FUNC(avs_is_planar_rgba);
#undef AVSC_DECLARE_FUNC
} AviSynthLibrary;
typedef struct AviSynthContext {
AVS_ScriptEnvironment *env;
AVS_Clip *clip;
const AVS_VideoInfo *vi;
/* avisynth_read_packet_video() iterates over this. */
int n_planes;
const int *planes;
int curr_stream;
int curr_frame;
int64_t curr_sample;
int error;
/* Linked list pointers. */
struct AviSynthContext *next;
} AviSynthContext;
static const int avs_planes_packed[1] = { 0 };
static const int avs_planes_grey[1] = { AVS_PLANAR_Y };
static const int avs_planes_yuv[3] = { AVS_PLANAR_Y, AVS_PLANAR_U,
AVS_PLANAR_V };
static const int avs_planes_rgb[3] = { AVS_PLANAR_G, AVS_PLANAR_B,
AVS_PLANAR_R };
static const int avs_planes_yuva[4] = { AVS_PLANAR_Y, AVS_PLANAR_U,
AVS_PLANAR_V, AVS_PLANAR_A };
static const int avs_planes_rgba[4] = { AVS_PLANAR_G, AVS_PLANAR_B,
AVS_PLANAR_R, AVS_PLANAR_A };
/* A conflict between C++ global objects, atexit, and dynamic loading requires
* us to register our own atexit handler to prevent double freeing. */
static AviSynthLibrary avs_library;
static int avs_atexit_called = 0;
/* Linked list of AviSynthContexts. An atexit handler destroys this list. */
static AviSynthContext *avs_ctx_list = NULL;
static av_cold void avisynth_atexit_handler(void);
static av_cold int avisynth_load_library(void)
{
avs_library.library = dlopen(AVISYNTH_LIB, RTLD_NOW | RTLD_LOCAL);
if (!avs_library.library)
return AVERROR_UNKNOWN;
#define LOAD_AVS_FUNC(name, continue_on_fail) \
avs_library.name = (name ## _func) \
dlsym(avs_library.library, #name); \
if (!continue_on_fail && !avs_library.name) \
goto fail;
LOAD_AVS_FUNC(avs_bit_blt, 0);
LOAD_AVS_FUNC(avs_clip_get_error, 0);
LOAD_AVS_FUNC(avs_create_script_environment, 0);
LOAD_AVS_FUNC(avs_delete_script_environment, 0);
LOAD_AVS_FUNC(avs_get_audio, 0);
LOAD_AVS_FUNC(avs_get_error, 1); // New to AviSynth 2.6
LOAD_AVS_FUNC(avs_get_frame, 0);
LOAD_AVS_FUNC(avs_get_version, 0);
LOAD_AVS_FUNC(avs_get_video_info, 0);
LOAD_AVS_FUNC(avs_invoke, 0);
LOAD_AVS_FUNC(avs_release_clip, 0);
LOAD_AVS_FUNC(avs_release_value, 0);
LOAD_AVS_FUNC(avs_release_video_frame, 0);
LOAD_AVS_FUNC(avs_take_clip, 0);
LOAD_AVS_FUNC(avs_bits_per_pixel, 1);
LOAD_AVS_FUNC(avs_get_height_p, 1);
LOAD_AVS_FUNC(avs_get_pitch_p, 1);
LOAD_AVS_FUNC(avs_get_read_ptr_p, 1);
LOAD_AVS_FUNC(avs_get_row_size_p, 1);
LOAD_AVS_FUNC(avs_is_planar_rgb, 1);
LOAD_AVS_FUNC(avs_is_planar_rgba, 1);
#undef LOAD_AVS_FUNC
atexit(avisynth_atexit_handler);
return 0;
fail:
dlclose(avs_library.library);
return AVERROR_UNKNOWN;
}
/* Note that avisynth_context_create and avisynth_context_destroy
* do not allocate or free the actual context! That is taken care of
* by libavformat. */
static av_cold int avisynth_context_create(AVFormatContext *s)
{
AviSynthContext *avs = s->priv_data;
int ret;
if (!avs_library.library)
if (ret = avisynth_load_library())
return ret;
avs->env = avs_library.avs_create_script_environment(3);
if (avs_library.avs_get_error) {
const char *error = avs_library.avs_get_error(avs->env);
if (error) {
av_log(s, AV_LOG_ERROR, "%s\n", error);
return AVERROR_UNKNOWN;
}
}
if (!avs_ctx_list) {
avs_ctx_list = avs;
} else {
avs->next = avs_ctx_list;
avs_ctx_list = avs;
}
return 0;
}
static av_cold void avisynth_context_destroy(AviSynthContext *avs)
{
if (avs_atexit_called)
return;
if (avs == avs_ctx_list) {
avs_ctx_list = avs->next;
} else {
AviSynthContext *prev = avs_ctx_list;
while (prev->next != avs)
prev = prev->next;
prev->next = avs->next;
}
if (avs->clip) {
avs_library.avs_release_clip(avs->clip);
avs->clip = NULL;
}
if (avs->env) {
avs_library.avs_delete_script_environment(avs->env);
avs->env = NULL;
}
}
static av_cold void avisynth_atexit_handler(void)
{
AviSynthContext *avs = avs_ctx_list;
while (avs) {
AviSynthContext *next = avs->next;
avisynth_context_destroy(avs);
avs = next;
}
dlclose(avs_library.library);
avs_atexit_called = 1;
}
/* Create AVStream from audio and video data. */
static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
{
AviSynthContext *avs = s->priv_data;
int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
st->codecpar->width = avs->vi->width;
st->codecpar->height = avs->vi->height;
st->avg_frame_rate = (AVRational) { avs->vi->fps_numerator,
avs->vi->fps_denominator };
st->start_time = 0;
st->duration = avs->vi->num_frames;
st->nb_frames = avs->vi->num_frames;
avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator);
switch (avs->vi->pixel_type) {
/* 10~16-bit YUV pix_fmts (AviSynth+) */
case AVS_CS_YUV444P10:
st->codecpar->format = AV_PIX_FMT_YUV444P10;
planar = 1;
break;
case AVS_CS_YUV422P10:
st->codecpar->format = AV_PIX_FMT_YUV422P10;
planar = 1;
break;
case AVS_CS_YUV420P10:
st->codecpar->format = AV_PIX_FMT_YUV420P10;
planar = 1;
break;
case AVS_CS_YUV444P12:
st->codecpar->format = AV_PIX_FMT_YUV444P12;
planar = 1;
break;
case AVS_CS_YUV422P12:
st->codecpar->format = AV_PIX_FMT_YUV422P12;
planar = 1;
break;
case AVS_CS_YUV420P12:
st->codecpar->format = AV_PIX_FMT_YUV420P12;
planar = 1;
break;
case AVS_CS_YUV444P14:
st->codecpar->format = AV_PIX_FMT_YUV444P14;
planar = 1;
break;
case AVS_CS_YUV422P14:
st->codecpar->format = AV_PIX_FMT_YUV422P14;
planar = 1;
break;
case AVS_CS_YUV420P14:
st->codecpar->format = AV_PIX_FMT_YUV420P14;
planar = 1;
break;
case AVS_CS_YUV444P16:
st->codecpar->format = AV_PIX_FMT_YUV444P16;
planar = 1;
break;
case AVS_CS_YUV422P16:
st->codecpar->format = AV_PIX_FMT_YUV422P16;
planar = 1;
break;
case AVS_CS_YUV420P16:
st->codecpar->format = AV_PIX_FMT_YUV420P16;
planar = 1;
break;
/* 8~16-bit YUV pix_fmts with Alpha (AviSynth+) */
case AVS_CS_YUVA444:
st->codecpar->format = AV_PIX_FMT_YUVA444P;
planar = 4;
break;
case AVS_CS_YUVA422:
st->codecpar->format = AV_PIX_FMT_YUVA422P;
planar = 4;
break;
case AVS_CS_YUVA420:
st->codecpar->format = AV_PIX_FMT_YUVA420P;
planar = 4;
break;
case AVS_CS_YUVA444P10:
st->codecpar->format = AV_PIX_FMT_YUVA444P10;
planar = 4;
break;
case AVS_CS_YUVA422P10:
st->codecpar->format = AV_PIX_FMT_YUVA422P10;
planar = 4;
break;
case AVS_CS_YUVA420P10:
st->codecpar->format = AV_PIX_FMT_YUVA420P10;
planar = 4;
break;
case AVS_CS_YUVA422P12:
st->codecpar->format = AV_PIX_FMT_YUVA422P12;
planar = 4;
break;
case AVS_CS_YUVA444P16:
st->codecpar->format = AV_PIX_FMT_YUVA444P16;
planar = 4;
break;
case AVS_CS_YUVA422P16:
st->codecpar->format = AV_PIX_FMT_YUVA422P16;
planar = 4;
break;
case AVS_CS_YUVA420P16:
st->codecpar->format = AV_PIX_FMT_YUVA420P16;
planar = 4;
break;
/* Planar RGB pix_fmts (AviSynth+) */
case AVS_CS_RGBP:
st->codecpar->format = AV_PIX_FMT_GBRP;
planar = 3;
break;
case AVS_CS_RGBP10:
st->codecpar->format = AV_PIX_FMT_GBRP10;
planar = 3;
break;
case AVS_CS_RGBP12:
st->codecpar->format = AV_PIX_FMT_GBRP12;
planar = 3;
break;
case AVS_CS_RGBP14:
st->codecpar->format = AV_PIX_FMT_GBRP14;
planar = 3;
break;
case AVS_CS_RGBP16:
st->codecpar->format = AV_PIX_FMT_GBRP16;
planar = 3;
break;
/* Single precision floating point Planar RGB (AviSynth+) */
case AVS_CS_RGBPS:
st->codecpar->format = AV_PIX_FMT_GBRPF32;
planar = 3;
break;
/* Planar RGB pix_fmts with Alpha (AviSynth+) */
case AVS_CS_RGBAP:
st->codecpar->format = AV_PIX_FMT_GBRAP;
planar = 5;
break;
case AVS_CS_RGBAP10:
st->codecpar->format = AV_PIX_FMT_GBRAP10;
planar = 5;
break;
case AVS_CS_RGBAP12:
st->codecpar->format = AV_PIX_FMT_GBRAP12;
planar = 5;
break;
case AVS_CS_RGBAP16:
st->codecpar->format = AV_PIX_FMT_GBRAP16;
planar = 5;
break;
/* Single precision floating point Planar RGB with Alpha (AviSynth+) */
case AVS_CS_RGBAPS:
st->codecpar->format = AV_PIX_FMT_GBRAPF32;
planar = 5;
break;
/* 10~16-bit gray pix_fmts (AviSynth+) */
case AVS_CS_Y10:
st->codecpar->format = AV_PIX_FMT_GRAY10;
planar = 2;
break;
case AVS_CS_Y12:
st->codecpar->format = AV_PIX_FMT_GRAY12;
planar = 2;
break;
case AVS_CS_Y14:
st->codecpar->format = AV_PIX_FMT_GRAY14;
planar = 2;
break;
case AVS_CS_Y16:
st->codecpar->format = AV_PIX_FMT_GRAY16;
planar = 2;
break;
/* Single precision floating point gray (AviSynth+) */
case AVS_CS_Y32:
st->codecpar->format = AV_PIX_FMT_GRAYF32;
planar = 2;
break;
/* pix_fmts added in AviSynth 2.6 */
case AVS_CS_YV24:
st->codecpar->format = AV_PIX_FMT_YUV444P;
planar = 1;
break;
case AVS_CS_YV16:
st->codecpar->format = AV_PIX_FMT_YUV422P;
planar = 1;
break;
case AVS_CS_YV411:
st->codecpar->format = AV_PIX_FMT_YUV411P;
planar = 1;
break;
case AVS_CS_Y8:
st->codecpar->format = AV_PIX_FMT_GRAY8;
planar = 2;
break;
/* 16-bit packed RGB pix_fmts (AviSynth+) */
case AVS_CS_BGR48:
st->codecpar->format = AV_PIX_FMT_BGR48;
break;
case AVS_CS_BGR64:
st->codecpar->format = AV_PIX_FMT_BGRA64;
break;
/* AviSynth 2.5 pix_fmts */
case AVS_CS_BGR24:
st->codecpar->format = AV_PIX_FMT_BGR24;
break;
case AVS_CS_BGR32:
st->codecpar->format = AV_PIX_FMT_RGB32;
break;
case AVS_CS_YUY2:
st->codecpar->format = AV_PIX_FMT_YUYV422;
break;
case AVS_CS_YV12:
st->codecpar->format = AV_PIX_FMT_YUV420P;
planar = 1;
break;
case AVS_CS_I420: // Is this even used anywhere?
st->codecpar->format = AV_PIX_FMT_YUV420P;
planar = 1;
break;
default:
av_log(s, AV_LOG_ERROR,
"unknown AviSynth colorspace %d\n", avs->vi->pixel_type);
avs->error = 1;
return AVERROR_UNKNOWN;
}
switch (planar) {
case 5: // Planar RGB + Alpha
avs->n_planes = 4;
avs->planes = avs_planes_rgba;
break;
case 4: // YUV + Alpha
avs->n_planes = 4;
avs->planes = avs_planes_yuva;
break;
case 3: // Planar RGB
avs->n_planes = 3;
avs->planes = avs_planes_rgb;
break;
case 2: // Y8
avs->n_planes = 1;
avs->planes = avs_planes_grey;
break;
case 1: // YUV
avs->n_planes = 3;
avs->planes = avs_planes_yuv;
break;
default:
avs->n_planes = 1;
avs->planes = avs_planes_packed;
}
return 0;
}
static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st)
{
AviSynthContext *avs = s->priv_data;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->sample_rate = avs->vi->audio_samples_per_second;
st->codecpar->channels = avs->vi->nchannels;
st->duration = avs->vi->num_audio_samples;
avpriv_set_pts_info(st, 64, 1, avs->vi->audio_samples_per_second);
switch (avs->vi->sample_type) {
case AVS_SAMPLE_INT8:
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
break;
case AVS_SAMPLE_INT16:
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
break;
case AVS_SAMPLE_INT24:
st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
break;
case AVS_SAMPLE_INT32:
st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
break;
case AVS_SAMPLE_FLOAT:
st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
break;
default:
av_log(s, AV_LOG_ERROR,
"unknown AviSynth sample type %d\n", avs->vi->sample_type);
avs->error = 1;
return AVERROR_UNKNOWN;
}
return 0;
}
static int avisynth_create_stream(AVFormatContext *s)
{
AviSynthContext *avs = s->priv_data;
AVStream *st;
int ret;
int id = 0;
if (avs_has_video(avs->vi)) {
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR_UNKNOWN;
st->id = id++;
if (ret = avisynth_create_stream_video(s, st))
return ret;
}
if (avs_has_audio(avs->vi)) {
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR_UNKNOWN;
st->id = id++;
if (ret = avisynth_create_stream_audio(s, st))
return ret;
}
return 0;
}
static int avisynth_open_file(AVFormatContext *s)
{
AviSynthContext *avs = s->priv_data;
AVS_Value arg, val;
int ret;
#ifdef _WIN32
char filename_ansi[MAX_PATH * 4];
wchar_t filename_wc[MAX_PATH * 4];
#endif
if (ret = avisynth_context_create(s))
return ret;
#ifdef _WIN32
/* Convert UTF-8 to ANSI code page */
MultiByteToWideChar(CP_UTF8, 0, s->url, -1, filename_wc, MAX_PATH * 4);
WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi,
MAX_PATH * 4, NULL, NULL);
arg = avs_new_value_string(filename_ansi);
#else
arg = avs_new_value_string(s->url);
#endif
val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
if (avs_is_error(val)) {
av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
ret = AVERROR_UNKNOWN;
goto fail;
}
if (!avs_is_clip(val)) {
av_log(s, AV_LOG_ERROR, "AviSynth script did not return a clip\n");
ret = AVERROR_UNKNOWN;
goto fail;
}
avs->clip = avs_library.avs_take_clip(val, avs->env);
avs->vi = avs_library.avs_get_video_info(avs->clip);
/* On Windows, FFmpeg supports AviSynth interface version 6 or higher.
* This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher,
* and excludes 2.5 and the 2.6 alphas. */
if (avs_library.avs_get_version(avs->clip) < 6) {
av_log(s, AV_LOG_ERROR,
"AviSynth version is too old. Please upgrade to either AviSynth 2.6 >= RC1 or AviSynth+ >= r1718.\n");
ret = AVERROR_UNKNOWN;
goto fail;
}
/* Release the AVS_Value as it will go out of scope. */
avs_library.avs_release_value(val);
if (ret = avisynth_create_stream(s))
goto fail;
return 0;
fail:
avisynth_context_destroy(avs);
return ret;
}
static void avisynth_next_stream(AVFormatContext *s, AVStream **st,
AVPacket *pkt, int *discard)
{
AviSynthContext *avs = s->priv_data;
avs->curr_stream++;
avs->curr_stream %= s->nb_streams;
*st = s->streams[avs->curr_stream];
if ((*st)->discard == AVDISCARD_ALL)
*discard = 1;
else
*discard = 0;
return;
}
/* Copy AviSynth clip data into an AVPacket. */
static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt,
int discard)
{
AviSynthContext *avs = s->priv_data;
AVS_VideoFrame *frame;
unsigned char *dst_p;
const unsigned char *src_p;
int n, i, plane, rowsize, planeheight, pitch, bits, ret;
const char *error;
int avsplus av_unused;
if (avs->curr_frame >= avs->vi->num_frames)
return AVERROR_EOF;
/* This must happen even if the stream is discarded to prevent desync. */
n = avs->curr_frame++;
if (discard)
return 0;
#ifdef _WIN32
/* Detect whether we're using AviSynth 2.6 or AviSynth+ by
* looking for whether avs_is_planar_rgb exists. */
if (GetProcAddress(avs_library.library, "avs_is_planar_rgb") == NULL)
avsplus = 0;
else
avsplus = 1;
#else
/* AviSynth+ is now the only variant of AviSynth we support
* on Linux and macOS. */
avsplus = 1;
#endif
bits = avs_library.avs_bits_per_pixel(avs->vi);
/* Without the cast to int64_t, calculation overflows at about 9k x 9k
* resolution. */
pkt->size = (((int64_t)avs->vi->width *
(int64_t)avs->vi->height) * bits) / 8;
if (!pkt->size)
return AVERROR_UNKNOWN;
if ((ret = av_new_packet(pkt, pkt->size)) < 0)
return ret;
pkt->pts = n;
pkt->dts = n;
pkt->duration = 1;
pkt->stream_index = avs->curr_stream;
frame = avs_library.avs_get_frame(avs->clip, n);
error = avs_library.avs_clip_get_error(avs->clip);
if (error) {
av_log(s, AV_LOG_ERROR, "%s\n", error);
avs->error = 1;
av_packet_unref(pkt);
return AVERROR_UNKNOWN;
}
dst_p = pkt->data;
for (i = 0; i < avs->n_planes; i++) {
plane = avs->planes[i];
src_p = avs_library.avs_get_read_ptr_p(frame, plane);
pitch = avs_library.avs_get_pitch_p(frame, plane);
rowsize = avs_library.avs_get_row_size_p(frame, plane);
planeheight = avs_library.avs_get_height_p(frame, plane);
/* Flip RGB video. */
if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) {
src_p = src_p + (planeheight - 1) * pitch;
pitch = -pitch;
}
/* Flip Planar RGB video */
if (avsplus && (avs_library.avs_is_planar_rgb(avs->vi) ||
avs_library.avs_is_planar_rgba(avs->vi))) {
src_p = src_p + (planeheight - 1) * pitch;
pitch = -pitch;
}
avs_library.avs_bit_blt(avs->env, dst_p, rowsize, src_p, pitch,
rowsize, planeheight);
dst_p += rowsize * planeheight;
}
avs_library.avs_release_video_frame(frame);
return 0;
}
static int avisynth_read_packet_audio(AVFormatContext *s, AVPacket *pkt,
int discard)
{
AviSynthContext *avs = s->priv_data;
AVRational fps, samplerate;
int samples, ret;
int64_t n;
const char *error;
if (avs->curr_sample >= avs->vi->num_audio_samples)
return AVERROR_EOF;
fps.num = avs->vi->fps_numerator;
fps.den = avs->vi->fps_denominator;
samplerate.num = avs->vi->audio_samples_per_second;
samplerate.den = 1;
if (avs_has_video(avs->vi)) {
if (avs->curr_frame < avs->vi->num_frames)
samples = av_rescale_q(avs->curr_frame, samplerate, fps) -
avs->curr_sample;
else
samples = av_rescale_q(1, samplerate, fps);
} else {
samples = 1000;
}
/* After seeking, audio may catch up with video. */
if (samples <= 0) {
pkt->size = 0;
pkt->data = NULL;
return 0;
}
if (avs->curr_sample + samples > avs->vi->num_audio_samples)
samples = avs->vi->num_audio_samples - avs->curr_sample;
/* This must happen even if the stream is discarded to prevent desync. */
n = avs->curr_sample;
avs->curr_sample += samples;
if (discard)
return 0;
pkt->size = avs_bytes_per_channel_sample(avs->vi) *
samples * avs->vi->nchannels;
if (!pkt->size)
return AVERROR_UNKNOWN;
if ((ret = av_new_packet(pkt, pkt->size)) < 0)
return ret;
pkt->pts = n;
pkt->dts = n;
pkt->duration = samples;
pkt->stream_index = avs->curr_stream;
avs_library.avs_get_audio(avs->clip, pkt->data, n, samples);
error = avs_library.avs_clip_get_error(avs->clip);
if (error) {
av_log(s, AV_LOG_ERROR, "%s\n", error);
avs->error = 1;
av_packet_unref(pkt);
return AVERROR_UNKNOWN;
}
return 0;
}
static av_cold int avisynth_read_header(AVFormatContext *s)
{
int ret;
// Calling library must implement a lock for thread-safe opens.
if (ret = ff_lock_avformat())
return ret;
if (ret = avisynth_open_file(s)) {
ff_unlock_avformat();
return ret;
}
ff_unlock_avformat();
return 0;
}
static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AviSynthContext *avs = s->priv_data;
AVStream *st;
int discard = 0;
int ret;
if (avs->error)
return AVERROR_UNKNOWN;
/* If either stream reaches EOF, try to read the other one before
* giving up. */
avisynth_next_stream(s, &st, pkt, &discard);
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
ret = avisynth_read_packet_video(s, pkt, discard);
if (ret == AVERROR_EOF && avs_has_audio(avs->vi)) {
avisynth_next_stream(s, &st, pkt, &discard);
return avisynth_read_packet_audio(s, pkt, discard);
}
} else {
ret = avisynth_read_packet_audio(s, pkt, discard);
if (ret == AVERROR_EOF && avs_has_video(avs->vi)) {
avisynth_next_stream(s, &st, pkt, &discard);
return avisynth_read_packet_video(s, pkt, discard);
}
}
return ret;
}
static av_cold int avisynth_read_close(AVFormatContext *s)
{
if (ff_lock_avformat())
return AVERROR_UNKNOWN;
avisynth_context_destroy(s->priv_data);
ff_unlock_avformat();
return 0;
}
static int avisynth_read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
AviSynthContext *avs = s->priv_data;
AVStream *st;
AVRational fps, samplerate;
if (avs->error)
return AVERROR_UNKNOWN;
fps = (AVRational) { avs->vi->fps_numerator,
avs->vi->fps_denominator };
samplerate = (AVRational) { avs->vi->audio_samples_per_second, 1 };
st = s->streams[stream_index];
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
/* AviSynth frame counts are signed int. */
if ((timestamp >= avs->vi->num_frames) ||
(timestamp > INT_MAX) ||
(timestamp < 0))
return AVERROR_EOF;
avs->curr_frame = timestamp;
if (avs_has_audio(avs->vi))
avs->curr_sample = av_rescale_q(timestamp, samplerate, fps);
} else {
if ((timestamp >= avs->vi->num_audio_samples) || (timestamp < 0))
return AVERROR_EOF;
/* Force frame granularity for seeking. */
if (avs_has_video(avs->vi)) {
avs->curr_frame = av_rescale_q(timestamp, fps, samplerate);
avs->curr_sample = av_rescale_q(avs->curr_frame, samplerate, fps);
} else {
avs->curr_sample = timestamp;
}
}
return 0;
}
AVInputFormat ff_avisynth_demuxer = {
.name = "avisynth",
.long_name = NULL_IF_CONFIG_SMALL("AviSynth script"),
.priv_data_size = sizeof(AviSynthContext),
.read_header = avisynth_read_header,
.read_packet = avisynth_read_packet,
.read_close = avisynth_read_close,
.read_seek = avisynth_read_seek,
.extensions = "avs",
};

772
externals/ffmpeg/libavformat/avlanguage.c vendored Executable file
View File

@@ -0,0 +1,772 @@
/*
* Cyril Comparon, Larbi Joubala, Resonate-MP4 2009
*
* 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 "avlanguage.h"
#include "libavutil/avstring.h"
#include "libavutil/common.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct LangEntry {
const char str[4];
uint16_t next_equivalent;
} LangEntry;
static const uint16_t lang_table_counts[] = { 484, 20, 184 };
static const uint16_t lang_table_offsets[] = { 0, 484, 504 };
static const LangEntry lang_table[] = {
/*----- AV_LANG_ISO639_2_BIBL entries (484) -----*/
/*0000*/ { "aar", 504 },
/*0001*/ { "abk", 505 },
/*0002*/ { "ace", 2 },
/*0003*/ { "ach", 3 },
/*0004*/ { "ada", 4 },
/*0005*/ { "ady", 5 },
/*0006*/ { "afa", 6 },
/*0007*/ { "afh", 7 },
/*0008*/ { "afr", 507 },
/*0009*/ { "ain", 9 },
/*0010*/ { "aka", 508 },
/*0011*/ { "akk", 11 },
/*0012*/ { "alb", 502 },
/*0013*/ { "ale", 13 },
/*0014*/ { "alg", 14 },
/*0015*/ { "alt", 15 },
/*0016*/ { "amh", 509 },
/*0017*/ { "ang", 17 },
/*0018*/ { "anp", 18 },
/*0019*/ { "apa", 19 },
/*0020*/ { "ara", 511 },
/*0021*/ { "arc", 21 },
/*0022*/ { "arg", 510 },
/*0023*/ { "arm", 492 },
/*0024*/ { "arn", 24 },
/*0025*/ { "arp", 25 },
/*0026*/ { "art", 26 },
/*0027*/ { "arw", 27 },
/*0028*/ { "asm", 512 },
/*0029*/ { "ast", 29 },
/*0030*/ { "ath", 30 },
/*0031*/ { "aus", 31 },
/*0032*/ { "ava", 513 },
/*0033*/ { "ave", 506 },
/*0034*/ { "awa", 34 },
/*0035*/ { "aym", 514 },
/*0036*/ { "aze", 515 },
/*0037*/ { "bad", 37 },
/*0038*/ { "bai", 38 },
/*0039*/ { "bak", 516 },
/*0040*/ { "bal", 40 },
/*0041*/ { "bam", 521 },
/*0042*/ { "ban", 42 },
/*0043*/ { "baq", 489 },
/*0044*/ { "bas", 44 },
/*0045*/ { "bat", 45 },
/*0046*/ { "bej", 46 },
/*0047*/ { "bel", 517 },
/*0048*/ { "bem", 48 },
/*0049*/ { "ben", 522 },
/*0050*/ { "ber", 50 },
/*0051*/ { "bho", 51 },
/*0052*/ { "bih", 519 },
/*0053*/ { "bik", 53 },
/*0054*/ { "bin", 54 },
/*0055*/ { "bis", 520 },
/*0056*/ { "bla", 56 },
/*0057*/ { "bnt", 57 },
/*0058*/ { "bos", 525 },
/*0059*/ { "bra", 59 },
/*0060*/ { "bre", 524 },
/*0061*/ { "btk", 61 },
/*0062*/ { "bua", 62 },
/*0063*/ { "bug", 63 },
/*0064*/ { "bul", 518 },
/*0065*/ { "bur", 498 },
/*0066*/ { "byn", 66 },
/*0067*/ { "cad", 67 },
/*0068*/ { "cai", 68 },
/*0069*/ { "car", 69 },
/*0070*/ { "cat", 526 },
/*0071*/ { "cau", 71 },
/*0072*/ { "ceb", 72 },
/*0073*/ { "cel", 73 },
/*0074*/ { "cha", 528 },
/*0075*/ { "chb", 75 },
/*0076*/ { "che", 527 },
/*0077*/ { "chg", 77 },
/*0078*/ { "chi", 503 },
/*0079*/ { "chk", 79 },
/*0080*/ { "chm", 80 },
/*0081*/ { "chn", 81 },
/*0082*/ { "cho", 82 },
/*0083*/ { "chp", 83 },
/*0084*/ { "chr", 84 },
/*0085*/ { "chu", 532 },
/*0086*/ { "chv", 533 },
/*0087*/ { "chy", 87 },
/*0088*/ { "cmc", 88 },
/*0089*/ { "cop", 89 },
/*0090*/ { "cor", 593 },
/*0091*/ { "cos", 529 },
/*0092*/ { "cpe", 92 },
/*0093*/ { "cpf", 93 },
/*0094*/ { "cpp", 94 },
/*0095*/ { "cre", 530 },
/*0096*/ { "crh", 96 },
/*0097*/ { "crp", 97 },
/*0098*/ { "csb", 98 },
/*0099*/ { "cus", 99 },
/*0100*/ { "cze", 485 },
/*0101*/ { "dak", 101 },
/*0102*/ { "dan", 535 },
/*0103*/ { "dar", 103 },
/*0104*/ { "day", 104 },
/*0105*/ { "del", 105 },
/*0106*/ { "den", 106 },
/*0107*/ { "dgr", 107 },
/*0108*/ { "din", 108 },
/*0109*/ { "div", 537 },
/*0110*/ { "doi", 110 },
/*0111*/ { "dra", 111 },
/*0112*/ { "dsb", 112 },
/*0113*/ { "dua", 113 },
/*0114*/ { "dum", 114 },
/*0115*/ { "dut", 499 },
/*0116*/ { "dyu", 116 },
/*0117*/ { "dzo", 538 },
/*0118*/ { "efi", 118 },
/*0119*/ { "egy", 119 },
/*0120*/ { "eka", 120 },
/*0121*/ { "elx", 121 },
/*0122*/ { "eng", 541 },
/*0123*/ { "enm", 123 },
/*0124*/ { "epo", 542 },
/*0125*/ { "est", 544 },
/*0126*/ { "ewe", 539 },
/*0127*/ { "ewo", 127 },
/*0128*/ { "fan", 128 },
/*0129*/ { "fao", 550 },
/*0130*/ { "fat", 130 },
/*0131*/ { "fij", 549 },
/*0132*/ { "fil", 132 },
/*0133*/ { "fin", 548 },
/*0134*/ { "fiu", 134 },
/*0135*/ { "fon", 135 },
/*0136*/ { "fre", 491 },
/*0137*/ { "frm", 137 },
/*0138*/ { "fro", 138 },
/*0139*/ { "frr", 139 },
/*0140*/ { "frs", 140 },
/*0141*/ { "fry", 552 },
/*0142*/ { "ful", 547 },
/*0143*/ { "fur", 143 },
/*0144*/ { "gaa", 144 },
/*0145*/ { "gay", 145 },
/*0146*/ { "gba", 146 },
/*0147*/ { "gem", 147 },
/*0148*/ { "geo", 494 },
/*0149*/ { "ger", 487 },
/*0150*/ { "gez", 150 },
/*0151*/ { "gil", 151 },
/*0152*/ { "gla", 554 },
/*0153*/ { "gle", 553 },
/*0154*/ { "glg", 555 },
/*0155*/ { "glv", 558 },
/*0156*/ { "gmh", 156 },
/*0157*/ { "goh", 157 },
/*0158*/ { "gon", 158 },
/*0159*/ { "gor", 159 },
/*0160*/ { "got", 160 },
/*0161*/ { "grb", 161 },
/*0162*/ { "grc", 162 },
/*0163*/ { "gre", 488 },
/*0164*/ { "grn", 556 },
/*0165*/ { "gsw", 165 },
/*0166*/ { "guj", 557 },
/*0167*/ { "gwi", 167 },
/*0168*/ { "hai", 168 },
/*0169*/ { "hat", 564 },
/*0170*/ { "hau", 559 },
/*0171*/ { "haw", 171 },
/*0172*/ { "heb", 560 },
/*0173*/ { "her", 567 },
/*0174*/ { "hil", 174 },
/*0175*/ { "him", 175 },
/*0176*/ { "hin", 561 },
/*0177*/ { "hit", 177 },
/*0178*/ { "hmn", 178 },
/*0179*/ { "hmo", 562 },
/*0180*/ { "hrv", 563 },
/*0181*/ { "hsb", 181 },
/*0182*/ { "hun", 565 },
/*0183*/ { "hup", 183 },
/*0184*/ { "iba", 184 },
/*0185*/ { "ibo", 571 },
/*0186*/ { "ice", 493 },
/*0187*/ { "ido", 574 },
/*0188*/ { "iii", 572 },
/*0189*/ { "ijo", 189 },
/*0190*/ { "iku", 577 },
/*0191*/ { "ile", 570 },
/*0192*/ { "ilo", 192 },
/*0193*/ { "ina", 568 },
/*0194*/ { "inc", 194 },
/*0195*/ { "ind", 569 },
/*0196*/ { "ine", 196 },
/*0197*/ { "inh", 197 },
/*0198*/ { "ipk", 573 },
/*0199*/ { "ira", 199 },
/*0200*/ { "iro", 200 },
/*0201*/ { "ita", 576 },
/*0202*/ { "jav", 579 },
/*0203*/ { "jbo", 203 },
/*0204*/ { "jpn", 578 },
/*0205*/ { "jpr", 205 },
/*0206*/ { "jrb", 206 },
/*0207*/ { "kaa", 207 },
/*0208*/ { "kab", 208 },
/*0209*/ { "kac", 209 },
/*0210*/ { "kal", 585 },
/*0211*/ { "kam", 211 },
/*0212*/ { "kan", 587 },
/*0213*/ { "kar", 213 },
/*0214*/ { "kas", 590 },
/*0215*/ { "kau", 589 },
/*0216*/ { "kaw", 216 },
/*0217*/ { "kaz", 584 },
/*0218*/ { "kbd", 218 },
/*0219*/ { "kha", 219 },
/*0220*/ { "khi", 220 },
/*0221*/ { "khm", 586 },
/*0222*/ { "kho", 222 },
/*0223*/ { "kik", 582 },
/*0224*/ { "kin", 640 },
/*0225*/ { "kir", 594 },
/*0226*/ { "kmb", 226 },
/*0227*/ { "kok", 227 },
/*0228*/ { "kom", 592 },
/*0229*/ { "kon", 581 },
/*0230*/ { "kor", 588 },
/*0231*/ { "kos", 231 },
/*0232*/ { "kpe", 232 },
/*0233*/ { "krc", 233 },
/*0234*/ { "krl", 234 },
/*0235*/ { "kro", 235 },
/*0236*/ { "kru", 236 },
/*0237*/ { "kua", 583 },
/*0238*/ { "kum", 238 },
/*0239*/ { "kur", 591 },
/*0240*/ { "kut", 240 },
/*0241*/ { "lad", 241 },
/*0242*/ { "lah", 242 },
/*0243*/ { "lam", 243 },
/*0244*/ { "lao", 600 },
/*0245*/ { "lat", 595 },
/*0246*/ { "lav", 603 },
/*0247*/ { "lez", 247 },
/*0248*/ { "lim", 598 },
/*0249*/ { "lin", 599 },
/*0250*/ { "lit", 601 },
/*0251*/ { "lol", 251 },
/*0252*/ { "loz", 252 },
/*0253*/ { "ltz", 596 },
/*0254*/ { "lua", 254 },
/*0255*/ { "lub", 602 },
/*0256*/ { "lug", 597 },
/*0257*/ { "lui", 257 },
/*0258*/ { "lun", 258 },
/*0259*/ { "luo", 259 },
/*0260*/ { "lus", 260 },
/*0261*/ { "mac", 495 },
/*0262*/ { "mad", 262 },
/*0263*/ { "mag", 263 },
/*0264*/ { "mah", 605 },
/*0265*/ { "mai", 265 },
/*0266*/ { "mak", 266 },
/*0267*/ { "mal", 608 },
/*0268*/ { "man", 268 },
/*0269*/ { "mao", 496 },
/*0270*/ { "map", 270 },
/*0271*/ { "mar", 610 },
/*0272*/ { "mas", 272 },
/*0273*/ { "may", 497 },
/*0274*/ { "mdf", 274 },
/*0275*/ { "mdr", 275 },
/*0276*/ { "men", 276 },
/*0277*/ { "mga", 277 },
/*0278*/ { "mic", 278 },
/*0279*/ { "min", 279 },
/*0280*/ { "mis", 280 },
/*0281*/ { "mkh", 281 },
/*0282*/ { "mlg", 604 },
/*0283*/ { "mlt", 612 },
/*0284*/ { "mnc", 284 },
/*0285*/ { "mni", 285 },
/*0286*/ { "mno", 286 },
/*0287*/ { "moh", 287 },
/*0288*/ { "mon", 609 },
/*0289*/ { "mos", 289 },
/*0290*/ { "mul", 290 },
/*0291*/ { "mun", 291 },
/*0292*/ { "mus", 292 },
/*0293*/ { "mwl", 293 },
/*0294*/ { "mwr", 294 },
/*0295*/ { "myn", 295 },
/*0296*/ { "myv", 296 },
/*0297*/ { "nah", 297 },
/*0298*/ { "nai", 298 },
/*0299*/ { "nap", 299 },
/*0300*/ { "nau", 614 },
/*0301*/ { "nav", 623 },
/*0302*/ { "nbl", 622 },
/*0303*/ { "nde", 616 },
/*0304*/ { "ndo", 618 },
/*0305*/ { "nds", 305 },
/*0306*/ { "nep", 617 },
/*0307*/ { "new", 307 },
/*0308*/ { "nia", 308 },
/*0309*/ { "nic", 309 },
/*0310*/ { "niu", 310 },
/*0311*/ { "nno", 620 },
/*0312*/ { "nob", 615 },
/*0313*/ { "nog", 313 },
/*0314*/ { "non", 314 },
/*0315*/ { "nor", 621 },
/*0316*/ { "nqo", 316 },
/*0317*/ { "nso", 317 },
/*0318*/ { "nub", 318 },
/*0319*/ { "nwc", 319 },
/*0320*/ { "nya", 624 },
/*0321*/ { "nym", 321 },
/*0322*/ { "nyn", 322 },
/*0323*/ { "nyo", 323 },
/*0324*/ { "nzi", 324 },
/*0325*/ { "oci", 625 },
/*0326*/ { "oji", 626 },
/*0327*/ { "ori", 628 },
/*0328*/ { "orm", 627 },
/*0329*/ { "osa", 329 },
/*0330*/ { "oss", 629 },
/*0331*/ { "ota", 331 },
/*0332*/ { "oto", 332 },
/*0333*/ { "paa", 333 },
/*0334*/ { "pag", 334 },
/*0335*/ { "pal", 335 },
/*0336*/ { "pam", 336 },
/*0337*/ { "pan", 630 },
/*0338*/ { "pap", 338 },
/*0339*/ { "pau", 339 },
/*0340*/ { "peo", 340 },
/*0341*/ { "per", 490 },
/*0342*/ { "phi", 342 },
/*0343*/ { "phn", 343 },
/*0344*/ { "pli", 631 },
/*0345*/ { "pol", 632 },
/*0346*/ { "pon", 346 },
/*0347*/ { "por", 634 },
/*0348*/ { "pra", 348 },
/*0349*/ { "pro", 349 },
/*0350*/ { "pus", 633 },
/*0351*/ { "que", 635 },
/*0352*/ { "raj", 352 },
/*0353*/ { "rap", 353 },
/*0354*/ { "rar", 354 },
/*0355*/ { "roa", 355 },
/*0356*/ { "roh", 636 },
/*0357*/ { "rom", 357 },
/*0358*/ { "rum", 500 },
/*0359*/ { "run", 637 },
/*0360*/ { "rup", 360 },
/*0361*/ { "rus", 639 },
/*0362*/ { "sad", 362 },
/*0363*/ { "sag", 645 },
/*0364*/ { "sah", 364 },
/*0365*/ { "sai", 365 },
/*0366*/ { "sal", 366 },
/*0367*/ { "sam", 367 },
/*0368*/ { "san", 641 },
/*0369*/ { "sas", 369 },
/*0370*/ { "sat", 370 },
/*0371*/ { "scn", 371 },
/*0372*/ { "sco", 372 },
/*0373*/ { "sel", 373 },
/*0374*/ { "sem", 374 },
/*0375*/ { "sga", 375 },
/*0376*/ { "sgn", 376 },
/*0377*/ { "shn", 377 },
/*0378*/ { "sid", 378 },
/*0379*/ { "sin", 646 },
/*0380*/ { "sio", 380 },
/*0381*/ { "sit", 381 },
/*0382*/ { "sla", 382 },
/*0383*/ { "slo", 501 },
/*0384*/ { "slv", 648 },
/*0385*/ { "sma", 385 },
/*0386*/ { "sme", 644 },
/*0387*/ { "smi", 387 },
/*0388*/ { "smj", 388 },
/*0389*/ { "smn", 389 },
/*0390*/ { "smo", 649 },
/*0391*/ { "sms", 391 },
/*0392*/ { "sna", 650 },
/*0393*/ { "snd", 643 },
/*0394*/ { "snk", 394 },
/*0395*/ { "sog", 395 },
/*0396*/ { "som", 651 },
/*0397*/ { "son", 397 },
/*0398*/ { "sot", 655 },
/*0399*/ { "spa", 543 },
/*0400*/ { "srd", 642 },
/*0401*/ { "srn", 401 },
/*0402*/ { "srp", 653 },
/*0403*/ { "srr", 403 },
/*0404*/ { "ssa", 404 },
/*0405*/ { "ssw", 654 },
/*0406*/ { "suk", 406 },
/*0407*/ { "sun", 656 },
/*0408*/ { "sus", 408 },
/*0409*/ { "sux", 409 },
/*0410*/ { "swa", 658 },
/*0411*/ { "swe", 657 },
/*0412*/ { "syc", 412 },
/*0413*/ { "syr", 413 },
/*0414*/ { "tah", 672 },
/*0415*/ { "tai", 415 },
/*0416*/ { "tam", 659 },
/*0417*/ { "tat", 670 },
/*0418*/ { "tel", 660 },
/*0419*/ { "tem", 419 },
/*0420*/ { "ter", 420 },
/*0421*/ { "tet", 421 },
/*0422*/ { "tgk", 661 },
/*0423*/ { "tgl", 665 },
/*0424*/ { "tha", 662 },
/*0425*/ { "tib", 484 },
/*0426*/ { "tig", 426 },
/*0427*/ { "tir", 663 },
/*0428*/ { "tiv", 428 },
/*0429*/ { "tkl", 429 },
/*0430*/ { "tlh", 430 },
/*0431*/ { "tli", 431 },
/*0432*/ { "tmh", 432 },
/*0433*/ { "tog", 433 },
/*0434*/ { "ton", 667 },
/*0435*/ { "tpi", 435 },
/*0436*/ { "tsi", 436 },
/*0437*/ { "tsn", 666 },
/*0438*/ { "tso", 669 },
/*0439*/ { "tuk", 664 },
/*0440*/ { "tum", 440 },
/*0441*/ { "tup", 441 },
/*0442*/ { "tur", 668 },
/*0443*/ { "tut", 443 },
/*0444*/ { "tvl", 444 },
/*0445*/ { "twi", 671 },
/*0446*/ { "tyv", 446 },
/*0447*/ { "udm", 447 },
/*0448*/ { "uga", 448 },
/*0449*/ { "uig", 673 },
/*0450*/ { "ukr", 674 },
/*0451*/ { "umb", 451 },
/*0452*/ { "und", 452 },
/*0453*/ { "urd", 675 },
/*0454*/ { "uzb", 676 },
/*0455*/ { "vai", 455 },
/*0456*/ { "ven", 677 },
/*0457*/ { "vie", 678 },
/*0458*/ { "vol", 679 },
/*0459*/ { "vot", 459 },
/*0460*/ { "wak", 460 },
/*0461*/ { "wal", 461 },
/*0462*/ { "war", 462 },
/*0463*/ { "was", 463 },
/*0464*/ { "wel", 486 },
/*0465*/ { "wen", 465 },
/*0466*/ { "wln", 680 },
/*0467*/ { "wol", 681 },
/*0468*/ { "xal", 468 },
/*0469*/ { "xho", 682 },
/*0470*/ { "yao", 470 },
/*0471*/ { "yap", 471 },
/*0472*/ { "yid", 683 },
/*0473*/ { "yor", 684 },
/*0474*/ { "ypk", 474 },
/*0475*/ { "zap", 475 },
/*0476*/ { "zbl", 476 },
/*0477*/ { "zen", 477 },
/*0478*/ { "zha", 685 },
/*0479*/ { "znd", 479 },
/*0480*/ { "zul", 687 },
/*0481*/ { "zun", 481 },
/*0482*/ { "zxx", 482 },
/*0483*/ { "zza", 483 },
/*----- AV_LANG_ISO639_2_TERM entries (20) -----*/
/*0484*/ { "bod", 523 },
/*0485*/ { "ces", 531 },
/*0486*/ { "cym", 534 },
/*0487*/ { "deu", 536 },
/*0488*/ { "ell", 540 },
/*0489*/ { "eus", 545 },
/*0490*/ { "fas", 546 },
/*0491*/ { "fra", 551 },
/*0492*/ { "hye", 566 },
/*0493*/ { "isl", 575 },
/*0494*/ { "kat", 580 },
/*0495*/ { "mkd", 607 },
/*0496*/ { "mri", 606 },
/*0497*/ { "msa", 611 },
/*0498*/ { "mya", 613 },
/*0499*/ { "nld", 619 },
/*0500*/ { "ron", 638 },
/*0501*/ { "slk", 647 },
/*0502*/ { "sqi", 652 },
/*0503*/ { "zho", 686 },
/*----- AV_LANG_ISO639_1 entries (184) -----*/
/*0504*/ { "aa" , 0 },
/*0505*/ { "ab" , 1 },
/*0506*/ { "ae" , 33 },
/*0507*/ { "af" , 8 },
/*0508*/ { "ak" , 10 },
/*0509*/ { "am" , 16 },
/*0510*/ { "an" , 22 },
/*0511*/ { "ar" , 20 },
/*0512*/ { "as" , 28 },
/*0513*/ { "av" , 32 },
/*0514*/ { "ay" , 35 },
/*0515*/ { "az" , 36 },
/*0516*/ { "ba" , 39 },
/*0517*/ { "be" , 47 },
/*0518*/ { "bg" , 64 },
/*0519*/ { "bh" , 52 },
/*0520*/ { "bi" , 55 },
/*0521*/ { "bm" , 41 },
/*0522*/ { "bn" , 49 },
/*0523*/ { "bo" , 425 },
/*0524*/ { "br" , 60 },
/*0525*/ { "bs" , 58 },
/*0526*/ { "ca" , 70 },
/*0527*/ { "ce" , 76 },
/*0528*/ { "ch" , 74 },
/*0529*/ { "co" , 91 },
/*0530*/ { "cr" , 95 },
/*0531*/ { "cs" , 100 },
/*0532*/ { "cu" , 85 },
/*0533*/ { "cv" , 86 },
/*0534*/ { "cy" , 464 },
/*0535*/ { "da" , 102 },
/*0536*/ { "de" , 149 },
/*0537*/ { "dv" , 109 },
/*0538*/ { "dz" , 117 },
/*0539*/ { "ee" , 126 },
/*0540*/ { "el" , 163 },
/*0541*/ { "en" , 122 },
/*0542*/ { "eo" , 124 },
/*0543*/ { "es" , 399 },
/*0544*/ { "et" , 125 },
/*0545*/ { "eu" , 43 },
/*0546*/ { "fa" , 341 },
/*0547*/ { "ff" , 142 },
/*0548*/ { "fi" , 133 },
/*0549*/ { "fj" , 131 },
/*0550*/ { "fo" , 129 },
/*0551*/ { "fr" , 136 },
/*0552*/ { "fy" , 141 },
/*0553*/ { "ga" , 153 },
/*0554*/ { "gd" , 152 },
/*0555*/ { "gl" , 154 },
/*0556*/ { "gn" , 164 },
/*0557*/ { "gu" , 166 },
/*0558*/ { "gv" , 155 },
/*0559*/ { "ha" , 170 },
/*0560*/ { "he" , 172 },
/*0561*/ { "hi" , 176 },
/*0562*/ { "ho" , 179 },
/*0563*/ { "hr" , 180 },
/*0564*/ { "ht" , 169 },
/*0565*/ { "hu" , 182 },
/*0566*/ { "hy" , 23 },
/*0567*/ { "hz" , 173 },
/*0568*/ { "ia" , 193 },
/*0569*/ { "id" , 195 },
/*0570*/ { "ie" , 191 },
/*0571*/ { "ig" , 185 },
/*0572*/ { "ii" , 188 },
/*0573*/ { "ik" , 198 },
/*0574*/ { "io" , 187 },
/*0575*/ { "is" , 186 },
/*0576*/ { "it" , 201 },
/*0577*/ { "iu" , 190 },
/*0578*/ { "ja" , 204 },
/*0579*/ { "jv" , 202 },
/*0580*/ { "ka" , 148 },
/*0581*/ { "kg" , 229 },
/*0582*/ { "ki" , 223 },
/*0583*/ { "kj" , 237 },
/*0584*/ { "kk" , 217 },
/*0585*/ { "kl" , 210 },
/*0586*/ { "km" , 221 },
/*0587*/ { "kn" , 212 },
/*0588*/ { "ko" , 230 },
/*0589*/ { "kr" , 215 },
/*0590*/ { "ks" , 214 },
/*0591*/ { "ku" , 239 },
/*0592*/ { "kv" , 228 },
/*0593*/ { "kw" , 90 },
/*0594*/ { "ky" , 225 },
/*0595*/ { "la" , 245 },
/*0596*/ { "lb" , 253 },
/*0597*/ { "lg" , 256 },
/*0598*/ { "li" , 248 },
/*0599*/ { "ln" , 249 },
/*0600*/ { "lo" , 244 },
/*0601*/ { "lt" , 250 },
/*0602*/ { "lu" , 255 },
/*0603*/ { "lv" , 246 },
/*0604*/ { "mg" , 282 },
/*0605*/ { "mh" , 264 },
/*0606*/ { "mi" , 269 },
/*0607*/ { "mk" , 261 },
/*0608*/ { "ml" , 267 },
/*0609*/ { "mn" , 288 },
/*0610*/ { "mr" , 271 },
/*0611*/ { "ms" , 273 },
/*0612*/ { "mt" , 283 },
/*0613*/ { "my" , 65 },
/*0614*/ { "na" , 300 },
/*0615*/ { "nb" , 312 },
/*0616*/ { "nd" , 303 },
/*0617*/ { "ne" , 306 },
/*0618*/ { "ng" , 304 },
/*0619*/ { "nl" , 115 },
/*0620*/ { "nn" , 311 },
/*0621*/ { "no" , 315 },
/*0622*/ { "nr" , 302 },
/*0623*/ { "nv" , 301 },
/*0624*/ { "ny" , 320 },
/*0625*/ { "oc" , 325 },
/*0626*/ { "oj" , 326 },
/*0627*/ { "om" , 328 },
/*0628*/ { "or" , 327 },
/*0629*/ { "os" , 330 },
/*0630*/ { "pa" , 337 },
/*0631*/ { "pi" , 344 },
/*0632*/ { "pl" , 345 },
/*0633*/ { "ps" , 350 },
/*0634*/ { "pt" , 347 },
/*0635*/ { "qu" , 351 },
/*0636*/ { "rm" , 356 },
/*0637*/ { "rn" , 359 },
/*0638*/ { "ro" , 358 },
/*0639*/ { "ru" , 361 },
/*0640*/ { "rw" , 224 },
/*0641*/ { "sa" , 368 },
/*0642*/ { "sc" , 400 },
/*0643*/ { "sd" , 393 },
/*0644*/ { "se" , 386 },
/*0645*/ { "sg" , 363 },
/*0646*/ { "si" , 379 },
/*0647*/ { "sk" , 383 },
/*0648*/ { "sl" , 384 },
/*0649*/ { "sm" , 390 },
/*0650*/ { "sn" , 392 },
/*0651*/ { "so" , 396 },
/*0652*/ { "sq" , 12 },
/*0653*/ { "sr" , 402 },
/*0654*/ { "ss" , 405 },
/*0655*/ { "st" , 398 },
/*0656*/ { "su" , 407 },
/*0657*/ { "sv" , 411 },
/*0658*/ { "sw" , 410 },
/*0659*/ { "ta" , 416 },
/*0660*/ { "te" , 418 },
/*0661*/ { "tg" , 422 },
/*0662*/ { "th" , 424 },
/*0663*/ { "ti" , 427 },
/*0664*/ { "tk" , 439 },
/*0665*/ { "tl" , 423 },
/*0666*/ { "tn" , 437 },
/*0667*/ { "to" , 434 },
/*0668*/ { "tr" , 442 },
/*0669*/ { "ts" , 438 },
/*0670*/ { "tt" , 417 },
/*0671*/ { "tw" , 445 },
/*0672*/ { "ty" , 414 },
/*0673*/ { "ug" , 449 },
/*0674*/ { "uk" , 450 },
/*0675*/ { "ur" , 453 },
/*0676*/ { "uz" , 454 },
/*0677*/ { "ve" , 456 },
/*0678*/ { "vi" , 457 },
/*0679*/ { "vo" , 458 },
/*0680*/ { "wa" , 466 },
/*0681*/ { "wo" , 467 },
/*0682*/ { "xh" , 469 },
/*0683*/ { "yi" , 472 },
/*0684*/ { "yo" , 473 },
/*0685*/ { "za" , 478 },
/*0686*/ { "zh" , 78 },
/*0687*/ { "zu" , 480 },
{ "", 0 }
};
static int lang_table_compare(const void *lhs, const void *rhs)
{
return strcmp(lhs, ((const LangEntry *)rhs)->str);
}
const char *ff_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace)
{
int i;
const LangEntry *entry = NULL;
const int NB_CODESPACES = FF_ARRAY_ELEMS(lang_table_counts);
if (target_codespace >= NB_CODESPACES)
return NULL;
for (i=0; !entry && i<NB_CODESPACES; i++)
entry = bsearch(lang,
lang_table + lang_table_offsets[i],
lang_table_counts[i],
sizeof(LangEntry),
lang_table_compare);
if (!entry)
return NULL;
for (i=0; i<NB_CODESPACES; i++)
if (entry >= lang_table + lang_table_offsets[target_codespace] &&
entry < lang_table + lang_table_offsets[target_codespace] + lang_table_counts[target_codespace])
return entry->str;
else
entry = lang_table + entry->next_equivalent;
if (target_codespace == AV_LANG_ISO639_2_TERM)
return ff_convert_lang_to(lang, AV_LANG_ISO639_2_BIBL);
return NULL;
}
#if LIBAVFORMAT_VERSION_MAJOR < 58
const char *av_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace)
{
return ff_convert_lang_to(lang, target_codespace);
}
#endif

46
externals/ffmpeg/libavformat/avlanguage.h vendored Executable file
View File

@@ -0,0 +1,46 @@
/*
* Cyril Comparon, Larbi Joubala, Resonate-MP4 2009
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_AVLANGUAGE_H
#define AVFORMAT_AVLANGUAGE_H
#include "libavutil/attributes.h"
#include "libavformat/version.h"
/**
* Known language codespaces
*/
enum AVLangCodespace {
AV_LANG_ISO639_2_BIBL, /** 3-char bibliographic language codes as per ISO-IEC 639-2 */
AV_LANG_ISO639_2_TERM, /** 3-char terminological language codes as per ISO-IEC 639-2 */
AV_LANG_ISO639_1 /** 2-char code of language as per ISO/IEC 639-1 */
};
/**
* Convert a language code to a target codespace. The source codespace is guessed.
* @return NULL if the provided lang is null or invalid.
*/
const char *ff_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace);
#if LIBAVFORMAT_VERSION_MAJOR < 58
attribute_deprecated
const char *av_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace);
#endif
#endif /* AVFORMAT_AVLANGUAGE_H */

99
externals/ffmpeg/libavformat/avr.c vendored Executable file
View File

@@ -0,0 +1,99 @@
/*
* AVR demuxer
* Copyright (c) 2012 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
#include "pcm.h"
static int avr_probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) != MKTAG('2', 'B', 'I', 'T'))
return 0;
if (!AV_RB16(p->buf+12) || AV_RB16(p->buf+12) > 256) // channels
return AVPROBE_SCORE_EXTENSION/2;
if (AV_RB16(p->buf+14) > 256) // bps
return AVPROBE_SCORE_EXTENSION/2;
return AVPROBE_SCORE_EXTENSION;
}
static int avr_read_header(AVFormatContext *s)
{
uint16_t chan, sign, bps;
AVStream *st;
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avio_skip(s->pb, 4); // magic
avio_skip(s->pb, 8); // sample_name
chan = avio_rb16(s->pb);
if (!chan) {
st->codecpar->channels = 1;
} else if (chan == 0xFFFFu) {
st->codecpar->channels = 2;
} else {
avpriv_request_sample(s, "chan %d", chan);
return AVERROR_PATCHWELCOME;
}
st->codecpar->bits_per_coded_sample = bps = avio_rb16(s->pb);
sign = avio_rb16(s->pb);
avio_skip(s->pb, 2); // loop
avio_skip(s->pb, 2); // midi
avio_skip(s->pb, 1); // replay speed
st->codecpar->sample_rate = avio_rb24(s->pb);
avio_skip(s->pb, 4 * 3);
avio_skip(s->pb, 2 * 3);
avio_skip(s->pb, 20);
avio_skip(s->pb, 64);
st->codecpar->codec_id = ff_get_pcm_codec_id(bps, 0, 1, sign);
if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
avpriv_request_sample(s, "Bps %d and sign %d", bps, sign);
return AVERROR_PATCHWELCOME;
}
st->codecpar->block_align = bps * st->codecpar->channels / 8;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
AVInputFormat ff_avr_demuxer = {
.name = "avr",
.long_name = NULL_IF_CONFIG_SMALL("AVR (Audio Visual Research)"),
.read_probe = avr_probe,
.read_header = avr_read_header,
.read_packet = ff_pcm_read_packet,
.read_seek = ff_pcm_read_seek,
.extensions = "avr",
.flags = AVFMT_GENERIC_INDEX,
};

233
externals/ffmpeg/libavformat/avs.c vendored Executable file
View File

@@ -0,0 +1,233 @@
/*
* AVS demuxer.
* Copyright (c) 2006 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
*/
/**
* @file
* Argonaut Games' Creature Shock demuxer
* @see http://wiki.multimedia.cx/index.php?title=AVS
*/
#include "avformat.h"
#include "voc.h"
typedef struct avs_format {
VocDecContext voc;
AVStream *st_video;
AVStream *st_audio;
int width;
int height;
int bits_per_sample;
int fps;
int nb_frames;
int remaining_frame_size;
int remaining_audio_size;
} AvsFormat;
typedef enum avs_block_type {
AVS_NONE = 0x00,
AVS_VIDEO = 0x01,
AVS_AUDIO = 0x02,
AVS_PALETTE = 0x03,
AVS_GAME_DATA = 0x04,
} AvsBlockType;
static int avs_probe(const AVProbeData * p)
{
const uint8_t *d;
d = p->buf;
if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0)
/* Ensure the buffer probe scores higher than the extension probe.
* This avoids problems with misdetection as AviSynth scripts. */
return AVPROBE_SCORE_EXTENSION + 5;
return 0;
}
static int avs_read_header(AVFormatContext * s)
{
AvsFormat *avs = s->priv_data;
s->ctx_flags |= AVFMTCTX_NOHEADER;
avio_skip(s->pb, 4);
avs->width = avio_rl16(s->pb);
avs->height = avio_rl16(s->pb);
avs->bits_per_sample = avio_rl16(s->pb);
avs->fps = avio_rl16(s->pb);
avs->nb_frames = avio_rl32(s->pb);
avs->remaining_frame_size = 0;
avs->remaining_audio_size = 0;
avs->st_video = avs->st_audio = NULL;
if (avs->width != 318 || avs->height != 198)
av_log(s, AV_LOG_ERROR, "This avs pretend to be %dx%d "
"when the avs format is supposed to be 318x198 only.\n",
avs->width, avs->height);
return 0;
}
static int
avs_read_video_packet(AVFormatContext * s, AVPacket * pkt,
AvsBlockType type, int sub_type, int size,
uint8_t * palette, int palette_size)
{
AvsFormat *avs = s->priv_data;
int ret;
ret = av_new_packet(pkt, size + palette_size);
if (ret < 0)
return ret;
if (palette_size) {
pkt->data[0] = 0x00;
pkt->data[1] = 0x03;
pkt->data[2] = palette_size & 0xFF;
pkt->data[3] = (palette_size >> 8) & 0xFF;
memcpy(pkt->data + 4, palette, palette_size - 4);
}
pkt->data[palette_size + 0] = sub_type;
pkt->data[palette_size + 1] = type;
pkt->data[palette_size + 2] = size & 0xFF;
pkt->data[palette_size + 3] = (size >> 8) & 0xFF;
ret = avio_read(s->pb, pkt->data + palette_size + 4, size - 4) + 4;
if (ret < size) {
return AVERROR(EIO);
}
pkt->size = ret + palette_size;
pkt->stream_index = avs->st_video->index;
if (sub_type == 0)
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
}
static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt)
{
AvsFormat *avs = s->priv_data;
int ret, size;
size = avio_tell(s->pb);
ret = ff_voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size);
size = avio_tell(s->pb) - size;
avs->remaining_audio_size -= size;
if (ret == AVERROR(EIO))
return 0; /* this indicate EOS */
if (ret < 0)
return ret;
pkt->stream_index = avs->st_audio->index;
pkt->flags |= AV_PKT_FLAG_KEY;
return size;
}
static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
{
AvsFormat *avs = s->priv_data;
int sub_type = 0, size = 0;
AvsBlockType type = AVS_NONE;
int palette_size = 0;
uint8_t palette[4 + 3 * 256];
int ret;
if (avs->remaining_audio_size > 0)
if (avs_read_audio_packet(s, pkt) > 0)
return 0;
while (1) {
if (avs->remaining_frame_size <= 0) {
if (!avio_rl16(s->pb)) /* found EOF */
return AVERROR(EIO);
avs->remaining_frame_size = avio_rl16(s->pb) - 4;
}
while (avs->remaining_frame_size > 0) {
sub_type = avio_r8(s->pb);
type = avio_r8(s->pb);
size = avio_rl16(s->pb);
if (size < 4)
return AVERROR_INVALIDDATA;
avs->remaining_frame_size -= size;
switch (type) {
case AVS_PALETTE:
if (size - 4 > sizeof(palette))
return AVERROR_INVALIDDATA;
ret = avio_read(s->pb, palette, size - 4);
if (ret < size - 4)
return AVERROR(EIO);
palette_size = size;
break;
case AVS_VIDEO:
if (!avs->st_video) {
avs->st_video = avformat_new_stream(s, NULL);
if (!avs->st_video)
return AVERROR(ENOMEM);
avs->st_video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
avs->st_video->codecpar->codec_id = AV_CODEC_ID_AVS;
avs->st_video->codecpar->width = avs->width;
avs->st_video->codecpar->height = avs->height;
avs->st_video->codecpar->bits_per_coded_sample=avs->bits_per_sample;
avs->st_video->nb_frames = avs->nb_frames;
#if FF_API_R_FRAME_RATE
avs->st_video->r_frame_rate =
#endif
avs->st_video->avg_frame_rate = (AVRational){avs->fps, 1};
}
return avs_read_video_packet(s, pkt, type, sub_type, size,
palette, palette_size);
case AVS_AUDIO:
if (!avs->st_audio) {
avs->st_audio = avformat_new_stream(s, NULL);
if (!avs->st_audio)
return AVERROR(ENOMEM);
avs->st_audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
}
avs->remaining_audio_size = size - 4;
size = avs_read_audio_packet(s, pkt);
if (size != 0)
return size;
break;
default:
avio_skip(s->pb, size - 4);
}
}
}
}
AVInputFormat ff_avs_demuxer = {
.name = "avs",
.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Creature Shock"),
.priv_data_size = sizeof(AvsFormat),
.read_probe = avs_probe,
.read_header = avs_read_header,
.read_packet = avs_read_packet,
};

295
externals/ffmpeg/libavformat/bethsoftvid.c vendored Executable file
View File

@@ -0,0 +1,295 @@
/*
* 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
* @brief Bethesda Softworks VID (.vid) file demuxer
* @author Nicholas Tung [ntung (at. ntung com] (2007-03)
* @see http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
* @see http://www.svatopluk.com/andux/docs/dfvid.html
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
#include "libavcodec/bethsoftvideo.h"
#define BVID_PALETTE_SIZE 3 * 256
#define DEFAULT_SAMPLE_RATE 11111
typedef struct BVID_DemuxContext
{
int nframes;
int sample_rate; /**< audio sample rate */
int width; /**< video width */
int height; /**< video height */
/** 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;
int video_index; /**< video stream index */
int audio_index; /**< audio stream index */
int has_palette;
uint8_t palette[BVID_PALETTE_SIZE];
int is_finished;
} BVID_DemuxContext;
static int vid_probe(const AVProbeData *p)
{
// little-endian VID tag, file starts with "VID\0"
if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
return 0;
if (p->buf[4] != 2)
return AVPROBE_SCORE_MAX / 4;
return AVPROBE_SCORE_MAX;
}
static int vid_read_header(AVFormatContext *s)
{
BVID_DemuxContext *vid = s->priv_data;
AVIOContext *pb = s->pb;
/* load main header. Contents:
* bytes: 'V' 'I' 'D'
* int16s: always_512, nframes, width, height, delay, always_14
*/
avio_skip(pb, 5);
vid->nframes = avio_rl16(pb);
vid->width = avio_rl16(pb);
vid->height = avio_rl16(pb);
vid->bethsoft_global_delay = avio_rl16(pb);
avio_rl16(pb);
// wait until the first packet to create each stream
vid->video_index = -1;
vid->audio_index = -1;
vid->sample_rate = DEFAULT_SAMPLE_RATE;
s->ctx_flags |= AVFMTCTX_NOHEADER;
return 0;
}
#define BUFFER_PADDING_SIZE 1000
static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt,
uint8_t block_type, AVFormatContext *s)
{
uint8_t * vidbuf_start = NULL;
int vidbuf_nbytes = 0;
int code;
int bytes_copied = 0;
int position, duration, npixels;
unsigned int vidbuf_capacity;
int ret = 0;
AVStream *st;
if (vid->video_index < 0) {
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
vid->video_index = st->index;
if (vid->audio_index < 0) {
avpriv_request_sample(s, "Using default video time base since "
"having no audio packet before the first "
"video packet");
}
avpriv_set_pts_info(st, 64, 185, vid->sample_rate);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_BETHSOFTVID;
st->codecpar->width = vid->width;
st->codecpar->height = vid->height;
}
st = s->streams[vid->video_index];
npixels = st->codecpar->width * st->codecpar->height;
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 = avio_tell(pb) - 1;
vidbuf_start[vidbuf_nbytes++] = block_type;
// get the current packet duration
duration = vid->bethsoft_global_delay + avio_rl16(pb);
// set the y offset if it exists (decoder header data should be in data section)
if(block_type == VIDEO_YOFF_P_FRAME){
if (avio_read(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2) {
ret = AVERROR(EIO);
goto fail;
}
vidbuf_nbytes += 2;
}
do{
uint8_t *tmp = av_fast_realloc(vidbuf_start, &vidbuf_capacity,
vidbuf_nbytes + BUFFER_PADDING_SIZE);
if (!tmp) {
ret = AVERROR(ENOMEM);
goto fail;
}
vidbuf_start = tmp;
code = avio_r8(pb);
vidbuf_start[vidbuf_nbytes++] = code;
if(code >= 0x80){ // rle sequence
if(block_type == VIDEO_I_FRAME)
vidbuf_start[vidbuf_nbytes++] = avio_r8(pb);
} else if(code){ // plain sequence
if (avio_read(pb, &vidbuf_start[vidbuf_nbytes], code) != code) {
ret = AVERROR(EIO);
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(avio_r8(pb))
avio_seek(pb, -1, SEEK_CUR);
break;
}
if (bytes_copied > npixels) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
} while(code);
// copy data into packet
if ((ret = av_new_packet(pkt, vidbuf_nbytes)) < 0)
goto fail;
memcpy(pkt->data, vidbuf_start, vidbuf_nbytes);
pkt->pos = position;
pkt->stream_index = vid->video_index;
pkt->duration = duration;
if (block_type == VIDEO_I_FRAME)
pkt->flags |= AV_PKT_FLAG_KEY;
/* if there is a new palette available, add it to packet side data */
if (vid->has_palette) {
uint8_t *pdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
BVID_PALETTE_SIZE);
if (!pdata) {
ret = AVERROR(ENOMEM);
av_log(s, AV_LOG_ERROR, "Failed to allocate palette side data\n");
goto fail;
}
memcpy(pdata, vid->palette, BVID_PALETTE_SIZE);
vid->has_palette = 0;
}
vid->nframes--; // used to check if all the frames were read
fail:
av_free(vidbuf_start);
return ret;
}
static int vid_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
BVID_DemuxContext *vid = s->priv_data;
AVIOContext *pb = s->pb;
unsigned char block_type;
int audio_length;
int ret_value;
if(vid->is_finished || avio_feof(pb))
return AVERROR_EOF;
block_type = avio_r8(pb);
switch(block_type){
case PALETTE_BLOCK:
if (vid->has_palette) {
av_log(s, AV_LOG_WARNING, "discarding unused palette\n");
vid->has_palette = 0;
}
if (avio_read(pb, vid->palette, BVID_PALETTE_SIZE) != BVID_PALETTE_SIZE) {
return AVERROR(EIO);
}
vid->has_palette = 1;
return vid_read_packet(s, pkt);
case FIRST_AUDIO_BLOCK:
avio_rl16(pb);
// soundblaster DAC used for sample rate, as on specification page (link above)
vid->sample_rate = 1000000 / (256 - avio_r8(pb));
case AUDIO_BLOCK:
if (vid->audio_index < 0) {
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
vid->audio_index = st->index;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->bits_per_coded_sample = 8;
st->codecpar->sample_rate = vid->sample_rate;
st->codecpar->bit_rate = 8 * st->codecpar->sample_rate;
st->start_time = 0;
avpriv_set_pts_info(st, 64, 1, vid->sample_rate);
}
audio_length = avio_rl16(pb);
if ((ret_value = av_get_packet(pb, pkt, audio_length)) != audio_length) {
if (ret_value < 0)
return ret_value;
av_log(s, AV_LOG_ERROR, "incomplete audio block\n");
return AVERROR(EIO);
}
pkt->stream_index = vid->audio_index;
pkt->duration = audio_length;
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
case VIDEO_P_FRAME:
case VIDEO_YOFF_P_FRAME:
case VIDEO_I_FRAME:
return read_frame(vid, pb, pkt, block_type, s);
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 AVERROR_INVALIDDATA;
}
}
AVInputFormat ff_bethsoftvid_demuxer = {
.name = "bethsoftvid",
.long_name = NULL_IF_CONFIG_SMALL("Bethesda Softworks VID"),
.priv_data_size = sizeof(BVID_DemuxContext),
.read_probe = vid_probe,
.read_header = vid_read_header,
.read_packet = vid_read_packet,
};

181
externals/ffmpeg/libavformat/bfi.c vendored Executable file
View File

@@ -0,0 +1,181 @@
/*
* Brute Force & Ignorance (BFI) demuxer
* Copyright (c) 2008 Sisir Koppaka
*
* 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
* @brief Brute Force & Ignorance (.bfi) file demuxer
* @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
* @see http://wiki.multimedia.cx/index.php?title=BFI
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
typedef struct BFIContext {
int nframes;
int audio_frame;
int video_frame;
int video_size;
int avflag;
} BFIContext;
static int bfi_probe(const AVProbeData * p)
{
/* Check file header */
if (AV_RL32(p->buf) == MKTAG('B', 'F', '&', 'I'))
return AVPROBE_SCORE_MAX;
else
return 0;
}
static int bfi_read_header(AVFormatContext * s)
{
BFIContext *bfi = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *vstream;
AVStream *astream;
int ret, fps, chunk_header;
/* Initialize the video codec... */
vstream = avformat_new_stream(s, NULL);
if (!vstream)
return AVERROR(ENOMEM);
/* Initialize the audio codec... */
astream = avformat_new_stream(s, NULL);
if (!astream)
return AVERROR(ENOMEM);
/* Set the total number of frames. */
avio_skip(pb, 8);
chunk_header = avio_rl32(pb);
bfi->nframes = avio_rl32(pb);
avio_rl32(pb);
avio_rl32(pb);
avio_rl32(pb);
fps = avio_rl32(pb);
avio_skip(pb, 12);
vstream->codecpar->width = avio_rl32(pb);
vstream->codecpar->height = avio_rl32(pb);
/*Load the palette to extradata */
avio_skip(pb, 8);
ret = ff_get_extradata(s, vstream->codecpar, pb, 768);
if (ret < 0)
return ret;
astream->codecpar->sample_rate = avio_rl32(pb);
if (astream->codecpar->sample_rate <= 0) {
av_log(s, AV_LOG_ERROR, "Invalid sample rate %d\n", astream->codecpar->sample_rate);
return AVERROR_INVALIDDATA;
}
/* Set up the video codec... */
avpriv_set_pts_info(vstream, 32, 1, fps);
vstream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
vstream->codecpar->codec_id = AV_CODEC_ID_BFI;
vstream->codecpar->format = AV_PIX_FMT_PAL8;
vstream->nb_frames =
vstream->duration = bfi->nframes;
/* Set up the audio codec now... */
astream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
astream->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
astream->codecpar->channels = 1;
astream->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
astream->codecpar->bits_per_coded_sample = 8;
astream->codecpar->bit_rate =
(int64_t)astream->codecpar->sample_rate * astream->codecpar->bits_per_coded_sample;
avio_seek(pb, chunk_header - 3, SEEK_SET);
avpriv_set_pts_info(astream, 64, 1, astream->codecpar->sample_rate);
return 0;
}
static int bfi_read_packet(AVFormatContext * s, AVPacket * pkt)
{
BFIContext *bfi = s->priv_data;
AVIOContext *pb = s->pb;
int ret, audio_offset, video_offset, chunk_size, audio_size = 0;
if (bfi->nframes == 0 || avio_feof(pb)) {
return AVERROR_EOF;
}
/* If all previous chunks were completely read, then find a new one... */
if (!bfi->avflag) {
uint32_t state = 0;
while(state != MKTAG('S','A','V','I')){
if (avio_feof(pb))
return AVERROR(EIO);
state = 256*state + avio_r8(pb);
}
/* Now that the chunk's location is confirmed, we proceed... */
chunk_size = avio_rl32(pb);
avio_rl32(pb);
audio_offset = avio_rl32(pb);
avio_rl32(pb);
video_offset = avio_rl32(pb);
audio_size = video_offset - audio_offset;
bfi->video_size = chunk_size - video_offset;
if (audio_size < 0 || bfi->video_size < 0) {
av_log(s, AV_LOG_ERROR, "Invalid audio/video offsets or chunk size\n");
return AVERROR_INVALIDDATA;
}
//Tossing an audio packet at the audio decoder.
ret = av_get_packet(pb, pkt, audio_size);
if (ret < 0)
return ret;
pkt->pts = bfi->audio_frame;
bfi->audio_frame += ret;
} else if (bfi->video_size > 0) {
//Tossing a video packet at the video decoder.
ret = av_get_packet(pb, pkt, bfi->video_size);
if (ret < 0)
return ret;
pkt->pts = bfi->video_frame;
bfi->video_frame += ret / bfi->video_size;
/* One less frame to read. A cursory decrement. */
bfi->nframes--;
} else {
/* Empty video packet */
ret = AVERROR(EAGAIN);
}
bfi->avflag = !bfi->avflag;
pkt->stream_index = bfi->avflag;
return ret;
}
AVInputFormat ff_bfi_demuxer = {
.name = "bfi",
.long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),
.priv_data_size = sizeof(BFIContext),
.read_probe = bfi_probe,
.read_header = bfi_read_header,
.read_packet = bfi_read_packet,
};

335
externals/ffmpeg/libavformat/bink.c vendored Executable file
View File

@@ -0,0 +1,335 @@
/*
* Bink demuxer
* Copyright (c) 2008-2010 Peter Ross (pross@xvid.org)
* Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
*
* 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
* Bink demuxer
*
* Technical details here:
* http://wiki.multimedia.cx/index.php?title=Bink_Container
*/
#include <inttypes.h>
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "internal.h"
enum BinkAudFlags {
BINK_AUD_16BITS = 0x4000, ///< prefer 16-bit output
BINK_AUD_STEREO = 0x2000,
BINK_AUD_USEDCT = 0x1000,
};
#define BINK_EXTRADATA_SIZE 1
#define BINK_MAX_AUDIO_TRACKS 256
#define BINK_MAX_WIDTH 7680
#define BINK_MAX_HEIGHT 4800
#define SMUSH_BLOCK_SIZE 512
typedef struct BinkDemuxContext {
uint32_t file_size;
uint32_t num_audio_tracks;
int current_track; ///< audio track to return in next packet
int64_t video_pts;
int64_t audio_pts[BINK_MAX_AUDIO_TRACKS];
uint32_t remain_packet_size;
int flags;
int smush_size;
} BinkDemuxContext;
static int probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
int smush = AV_RN32(p->buf) == AV_RN32("SMUS");
do {
if (((b[0] == 'B' && b[1] == 'I' && b[2] == 'K' && /* Bink 1 */
(b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i' ||
b[3] == 'k')) ||
(b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
(b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' ||
b[3] == 'i' || b[3] == 'j' || b[3] == 'k'))) &&
AV_RL32(b+8) > 0 && // num_frames
AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0) // fps num,den
return AVPROBE_SCORE_MAX;
b += SMUSH_BLOCK_SIZE;
} while (smush && b < p->buf + p->buf_size - 32);
return 0;
}
static int read_header(AVFormatContext *s)
{
BinkDemuxContext *bink = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t fps_num, fps_den;
AVStream *vst, *ast;
unsigned int i;
uint32_t pos, next_pos;
uint16_t flags;
int next_keyframe = 1;
int keyframe;
int ret;
uint32_t signature;
uint8_t revision;
vst = avformat_new_stream(s, NULL);
if (!vst)
return AVERROR(ENOMEM);
vst->codecpar->codec_tag = avio_rl32(pb);
if (vst->codecpar->codec_tag == AV_RL32("SMUS")) {
do {
bink->smush_size += SMUSH_BLOCK_SIZE;
avio_skip(pb, SMUSH_BLOCK_SIZE - 4);
vst->codecpar->codec_tag = avio_rl32(pb);
} while (!avio_feof(pb) && (vst->codecpar->codec_tag & 0xFFFFFF) != AV_RL32("BIK"));
if (avio_feof(pb)) {
av_log(s, AV_LOG_ERROR, "invalid SMUSH header: BIK not found\n");
return AVERROR_INVALIDDATA;
}
}
bink->file_size = avio_rl32(pb) + 8;
vst->duration = avio_rl32(pb);
if (vst->duration > 1000000) {
av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n");
return AVERROR(EIO);
}
if (avio_rl32(pb) > bink->file_size) {
av_log(s, AV_LOG_ERROR,
"invalid header: largest frame size greater than file size\n");
return AVERROR(EIO);
}
avio_skip(pb, 4);
vst->codecpar->width = avio_rl32(pb);
vst->codecpar->height = avio_rl32(pb);
fps_num = avio_rl32(pb);
fps_den = avio_rl32(pb);
if (fps_num == 0 || fps_den == 0) {
av_log(s, AV_LOG_ERROR,
"invalid header: invalid fps (%"PRIu32"/%"PRIu32")\n",
fps_num, fps_den);
return AVERROR(EIO);
}
avpriv_set_pts_info(vst, 64, fps_den, fps_num);
vst->avg_frame_rate = av_inv_q(vst->time_base);
vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codecpar->codec_id = AV_CODEC_ID_BINKVIDEO;
if ((vst->codecpar->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) {
av_log(s, AV_LOG_WARNING, "Bink 2 video is not implemented\n");
vst->codecpar->codec_id = AV_CODEC_ID_NONE;
}
if ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0)
return ret;
bink->num_audio_tracks = avio_rl32(pb);
if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) {
av_log(s, AV_LOG_ERROR,
"invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%"PRIu32")\n",
bink->num_audio_tracks);
return AVERROR(EIO);
}
signature = (vst->codecpar->codec_tag & 0xFFFFFF);
revision = ((vst->codecpar->codec_tag >> 24) % 0xFF);
if ((signature == AV_RL32("BIK") && (revision == 'k')) ||
(signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k')))
avio_skip(pb, 4); /* unknown new field */
if (bink->num_audio_tracks) {
avio_skip(pb, 4 * bink->num_audio_tracks); /* max decoded size */
for (i = 0; i < bink->num_audio_tracks; i++) {
ast = avformat_new_stream(s, NULL);
if (!ast)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_tag = 0;
ast->codecpar->sample_rate = avio_rl16(pb);
avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
flags = avio_rl16(pb);
ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ?
AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT;
if (flags & BINK_AUD_STEREO) {
ast->codecpar->channels = 2;
ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
} else {
ast->codecpar->channels = 1;
ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
}
if ((ret = ff_alloc_extradata(ast->codecpar, 4)) < 0)
return ret;
AV_WL32(ast->codecpar->extradata, vst->codecpar->codec_tag);
}
for (i = 0; i < bink->num_audio_tracks; i++)
s->streams[i + 1]->id = avio_rl32(pb);
}
/* frame index table */
next_pos = avio_rl32(pb);
for (i = 0; i < vst->duration; i++) {
pos = next_pos;
keyframe = next_keyframe;
if (i == vst->duration - 1) {
next_pos = bink->file_size;
next_keyframe = 0;
} else {
next_pos = avio_rl32(pb);
next_keyframe = next_pos & 1;
}
pos &= ~1;
next_pos &= ~1;
if (next_pos <= pos) {
av_log(s, AV_LOG_ERROR, "invalid frame index table\n");
return AVERROR(EIO);
}
if ((ret = av_add_index_entry(vst, pos, i, next_pos - pos, 0,
keyframe ? AVINDEX_KEYFRAME : 0)) < 0)
return ret;
}
if (vst->index_entries)
avio_seek(pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET);
else
avio_skip(pb, 4);
bink->current_track = -1;
return 0;
}
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
BinkDemuxContext *bink = s->priv_data;
AVIOContext *pb = s->pb;
int ret;
if (bink->current_track < 0) {
int index_entry;
AVStream *st = s->streams[0]; // stream 0 is video stream with index
if (bink->video_pts >= st->duration)
return AVERROR_EOF;
index_entry = av_index_search_timestamp(st, bink->video_pts,
AVSEEK_FLAG_ANY);
if (index_entry < 0) {
av_log(s, AV_LOG_ERROR,
"could not find index entry for frame %"PRId64"\n",
bink->video_pts);
return AVERROR(EIO);
}
bink->remain_packet_size = st->index_entries[index_entry].size;
bink->flags = st->index_entries[index_entry].flags;
bink->current_track = 0;
}
while (bink->current_track < bink->num_audio_tracks) {
uint32_t audio_size = avio_rl32(pb);
if (audio_size > bink->remain_packet_size - 4) {
av_log(s, AV_LOG_ERROR,
"frame %"PRId64": audio size in header (%"PRIu32") > size of packet left (%"PRIu32")\n",
bink->video_pts, audio_size, bink->remain_packet_size);
return AVERROR(EIO);
}
bink->remain_packet_size -= 4 + audio_size;
bink->current_track++;
if (audio_size >= 4) {
/* get one audio packet per track */
if ((ret = av_get_packet(pb, pkt, audio_size)) < 0)
return ret;
pkt->stream_index = bink->current_track;
pkt->pts = bink->audio_pts[bink->current_track - 1];
/* Each audio packet reports the number of decompressed samples
(in bytes). We use this value to calculate the audio PTS */
if (pkt->size >= 4)
bink->audio_pts[bink->current_track -1] +=
AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->channels);
return 0;
} else {
avio_skip(pb, audio_size);
}
}
/* get video packet */
if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) < 0)
return ret;
pkt->stream_index = 0;
pkt->pts = bink->video_pts++;
if (bink->flags & AVINDEX_KEYFRAME)
pkt->flags |= AV_PKT_FLAG_KEY;
/* -1 instructs the next call to read_packet() to read the next frame */
bink->current_track = -1;
return 0;
}
static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{
BinkDemuxContext *bink = s->priv_data;
AVStream *vst = s->streams[0];
int64_t ret;
if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
return -1;
/* seek to the first frame */
ret = avio_seek(s->pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET);
if (ret < 0)
return ret;
bink->video_pts = 0;
memset(bink->audio_pts, 0, sizeof(bink->audio_pts));
bink->current_track = -1;
return 0;
}
AVInputFormat ff_bink_demuxer = {
.name = "bink",
.long_name = NULL_IF_CONFIG_SMALL("Bink"),
.priv_data_size = sizeof(BinkDemuxContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
.read_seek = read_seek,
.flags = AVFMT_SHOW_IDS,
};

439
externals/ffmpeg/libavformat/bintext.c vendored Executable file
View File

@@ -0,0 +1,439 @@
/*
* Binary text demuxer
* eXtended BINary text (XBIN) demuxer
* Artworx Data Format demuxer
* iCEDraw File demuxer
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Binary text demuxer
* eXtended BINary text (XBIN) demuxer
* Artworx Data Format demuxer
* iCEDraw File demuxer
*/
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avformat.h"
#include "internal.h"
#include "sauce.h"
#include "libavcodec/bintext.h"
typedef struct {
const AVClass *class;
int chars_per_frame; /**< characters to send decoder per frame;
set by private options as characters per second, and then
converted to characters per frame at runtime */
int width, height; /**< video size (WxH pixels) (private option) */
AVRational framerate; /**< frames per second (private option) */
uint64_t fsize; /**< file size less metadata buffer */
} BinDemuxContext;
static AVStream * init_stream(AVFormatContext *s)
{
BinDemuxContext *bin = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return NULL;
st->codecpar->codec_tag = 0;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
if (!bin->width) {
st->codecpar->width = (80<<3);
st->codecpar->height = (25<<4);
}
avpriv_set_pts_info(st, 60, bin->framerate.den, bin->framerate.num);
/* simulate tty display speed */
bin->chars_per_frame = av_clip(av_q2d(st->time_base) * bin->chars_per_frame, 1, INT_MAX);
return st;
}
#if CONFIG_BINTEXT_DEMUXER | CONFIG_ADF_DEMUXER | CONFIG_IDF_DEMUXER
/**
* Given filesize and width, calculate height (assume font_height of 16)
*/
static void calculate_height(AVCodecParameters *par, uint64_t fsize)
{
par->height = (fsize / ((par->width>>3)*2)) << 4;
}
#endif
#if CONFIG_BINTEXT_DEMUXER
static const uint8_t next_magic[]={
0x1A, 0x1B, '[', '0', ';', '3', '0', ';', '4', '0', 'm', 'N', 'E', 'X', 'T', 0x00
};
static int next_tag_read(AVFormatContext *avctx, uint64_t *fsize)
{
AVIOContext *pb = avctx->pb;
char buf[36];
int len;
uint64_t start_pos = avio_size(pb) - 256;
avio_seek(pb, start_pos, SEEK_SET);
if (avio_read(pb, buf, sizeof(next_magic)) != sizeof(next_magic))
return -1;
if (memcmp(buf, next_magic, sizeof(next_magic)))
return -1;
if (avio_r8(pb) != 0x01)
return -1;
*fsize -= 256;
#define GET_EFI2_META(name,size) \
len = avio_r8(pb); \
if (len < 1 || len > size) \
return -1; \
if (avio_read(pb, buf, size) == size && *buf) { \
buf[len] = 0; \
av_dict_set(&avctx->metadata, name, buf, 0); \
}
GET_EFI2_META("filename", 12)
GET_EFI2_META("author", 20)
GET_EFI2_META("publisher", 20)
GET_EFI2_META("title", 35)
return 0;
}
static void predict_width(AVCodecParameters *par, uint64_t fsize, int got_width)
{
/** attempt to guess width */
if (!got_width)
par->width = fsize > 4000 ? (160<<3) : (80<<3);
}
static int bin_probe(const AVProbeData *p)
{
const uint8_t *d = p->buf;
int magic = 0, sauce = 0;
int invisible = 0;
int i;
if (p->buf_size > 256)
magic = !memcmp(d + p->buf_size - 256, next_magic, sizeof(next_magic));
if (p->buf_size > 128)
sauce = !memcmp(d + p->buf_size - 128, "SAUCE00", 7);
if (magic)
return AVPROBE_SCORE_EXTENSION + 1;
if (av_match_ext(p->filename, "bin")) {
AVCodecParameters par;
int got_width = 0;
par.width = par.height = 0;
if (sauce)
return AVPROBE_SCORE_EXTENSION + 1;
predict_width(&par, p->buf_size, got_width);
if (par.width < 8)
return 0;
calculate_height(&par, p->buf_size);
if (par.height <= 0)
return 0;
for (i = 0; i < p->buf_size - 256; i+=2) {
if ((d[i+1] & 15) == (d[i+1] >> 4) && d[i] && d[i] != 0xFF && d[i] != ' ') {
invisible ++;
}
}
if (par.width * par.height * 2 / (8*16) == p->buf_size)
return AVPROBE_SCORE_MAX / 2;
return 0;
}
if (sauce)
return 1;
return 0;
}
static int bintext_read_header(AVFormatContext *s)
{
BinDemuxContext *bin = s->priv_data;
AVIOContext *pb = s->pb;
int ret;
AVStream *st = init_stream(s);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_BINTEXT;
if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0)
return ret;
st->codecpar->extradata[0] = 16;
st->codecpar->extradata[1] = 0;
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
int got_width = 0;
bin->fsize = avio_size(pb);
if (ff_sauce_read(s, &bin->fsize, &got_width, 0) < 0)
next_tag_read(s, &bin->fsize);
if (!bin->width) {
predict_width(st->codecpar, bin->fsize, got_width);
if (st->codecpar->width < 8)
return AVERROR_INVALIDDATA;
calculate_height(st->codecpar, bin->fsize);
}
avio_seek(pb, 0, SEEK_SET);
}
return 0;
}
#endif /* CONFIG_BINTEXT_DEMUXER */
#if CONFIG_XBIN_DEMUXER
static int xbin_probe(const AVProbeData *p)
{
const uint8_t *d = p->buf;
if (AV_RL32(d) == MKTAG('X','B','I','N') && d[4] == 0x1A &&
AV_RL16(d+5) > 0 && AV_RL16(d+5) <= 160 &&
d[9] > 0 && d[9] <= 32)
return AVPROBE_SCORE_MAX;
return 0;
}
static int xbin_read_header(AVFormatContext *s)
{
BinDemuxContext *bin = s->priv_data;
AVIOContext *pb = s->pb;
char fontheight, flags;
int ret;
AVStream *st = init_stream(s);
if (!st)
return AVERROR(ENOMEM);
avio_skip(pb, 5);
st->codecpar->width = avio_rl16(pb)<<3;
st->codecpar->height = avio_rl16(pb);
fontheight = avio_r8(pb);
st->codecpar->height *= fontheight;
flags = avio_r8(pb);
st->codecpar->extradata_size = 2;
if ((flags & BINTEXT_PALETTE))
st->codecpar->extradata_size += 48;
if ((flags & BINTEXT_FONT))
st->codecpar->extradata_size += fontheight * (flags & 0x10 ? 512 : 256);
st->codecpar->codec_id = flags & 4 ? AV_CODEC_ID_XBIN : AV_CODEC_ID_BINTEXT;
ret = ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size);
if (ret < 0)
return ret;
st->codecpar->extradata[0] = fontheight;
st->codecpar->extradata[1] = flags;
if (avio_read(pb, st->codecpar->extradata + 2, st->codecpar->extradata_size - 2) < 0)
return AVERROR(EIO);
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
bin->fsize = avio_size(pb) - 9 - st->codecpar->extradata_size;
ff_sauce_read(s, &bin->fsize, NULL, 0);
avio_seek(pb, 9 + st->codecpar->extradata_size, SEEK_SET);
}
return 0;
}
#endif /* CONFIG_XBIN_DEMUXER */
#if CONFIG_ADF_DEMUXER
static int adf_read_header(AVFormatContext *s)
{
BinDemuxContext *bin = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int ret;
if (avio_r8(pb) != 1)
return AVERROR_INVALIDDATA;
st = init_stream(s);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_BINTEXT;
if ((ret = ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) < 0)
return ret;
st->codecpar->extradata[0] = 16;
st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
if (avio_read(pb, st->codecpar->extradata + 2, 24) < 0)
return AVERROR(EIO);
avio_skip(pb, 144);
if (avio_read(pb, st->codecpar->extradata + 2 + 24, 24) < 0)
return AVERROR(EIO);
if (avio_read(pb, st->codecpar->extradata + 2 + 48, 4096) < 0)
return AVERROR(EIO);
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
int got_width = 0;
bin->fsize = avio_size(pb) - 1 - 192 - 4096;
st->codecpar->width = 80<<3;
ff_sauce_read(s, &bin->fsize, &got_width, 0);
if (!bin->width)
calculate_height(st->codecpar, bin->fsize);
avio_seek(pb, 1 + 192 + 4096, SEEK_SET);
}
return 0;
}
#endif /* CONFIG_ADF_DEMUXER */
#if CONFIG_IDF_DEMUXER
static const uint8_t idf_magic[] = {
0x04, 0x31, 0x2e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x15, 0x00
};
static int idf_probe(const AVProbeData *p)
{
if (p->buf_size < sizeof(idf_magic))
return 0;
if (!memcmp(p->buf, idf_magic, sizeof(idf_magic)))
return AVPROBE_SCORE_MAX;
return 0;
}
static int idf_read_header(AVFormatContext *s)
{
BinDemuxContext *bin = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int got_width = 0, ret;
if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
return AVERROR(EIO);
st = init_stream(s);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_IDF;
if ((ret = ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) < 0)
return ret;
st->codecpar->extradata[0] = 16;
st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
avio_seek(pb, avio_size(pb) - 4096 - 48, SEEK_SET);
if (avio_read(pb, st->codecpar->extradata + 2 + 48, 4096) < 0)
return AVERROR(EIO);
if (avio_read(pb, st->codecpar->extradata + 2, 48) < 0)
return AVERROR(EIO);
bin->fsize = avio_size(pb) - 12 - 4096 - 48;
ff_sauce_read(s, &bin->fsize, &got_width, 0);
if (!bin->width)
calculate_height(st->codecpar, bin->fsize);
avio_seek(pb, 12, SEEK_SET);
return 0;
}
#endif /* CONFIG_IDF_DEMUXER */
static int read_packet(AVFormatContext *s,
AVPacket *pkt)
{
BinDemuxContext *bin = s->priv_data;
if (bin->fsize > 0) {
if (av_get_packet(s->pb, pkt, bin->fsize) < 0)
return AVERROR(EIO);
bin->fsize = -1; /* done */
} else if (!bin->fsize) {
if (avio_feof(s->pb))
return AVERROR(EIO);
if (av_get_packet(s->pb, pkt, bin->chars_per_frame) < 0)
return AVERROR(EIO);
} else {
return AVERROR(EIO);
}
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
}
#define OFFSET(x) offsetof(BinDemuxContext, x)
static const AVOption options[] = {
{ "linespeed", "set simulated line speed (bytes per second)", OFFSET(chars_per_frame), AV_OPT_TYPE_INT, {.i64 = 6000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
{ "video_size", "set video size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
{ "framerate", "set framerate (frames per second)", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
#define CLASS(name) \
(const AVClass[1]){{ \
.class_name = name, \
.item_name = av_default_item_name, \
.option = options, \
.version = LIBAVUTIL_VERSION_INT, \
}}
#if CONFIG_BINTEXT_DEMUXER
AVInputFormat ff_bintext_demuxer = {
.name = "bin",
.long_name = NULL_IF_CONFIG_SMALL("Binary text"),
.priv_data_size = sizeof(BinDemuxContext),
.read_probe = bin_probe,
.read_header = bintext_read_header,
.read_packet = read_packet,
.priv_class = CLASS("Binary text demuxer"),
};
#endif
#if CONFIG_XBIN_DEMUXER
AVInputFormat ff_xbin_demuxer = {
.name = "xbin",
.long_name = NULL_IF_CONFIG_SMALL("eXtended BINary text (XBIN)"),
.priv_data_size = sizeof(BinDemuxContext),
.read_probe = xbin_probe,
.read_header = xbin_read_header,
.read_packet = read_packet,
.priv_class = CLASS("eXtended BINary text (XBIN) demuxer"),
};
#endif
#if CONFIG_ADF_DEMUXER
AVInputFormat ff_adf_demuxer = {
.name = "adf",
.long_name = NULL_IF_CONFIG_SMALL("Artworx Data Format"),
.priv_data_size = sizeof(BinDemuxContext),
.read_header = adf_read_header,
.read_packet = read_packet,
.extensions = "adf",
.priv_class = CLASS("Artworx Data Format demuxer"),
};
#endif
#if CONFIG_IDF_DEMUXER
AVInputFormat ff_idf_demuxer = {
.name = "idf",
.long_name = NULL_IF_CONFIG_SMALL("iCE Draw File"),
.priv_data_size = sizeof(BinDemuxContext),
.read_probe = idf_probe,
.read_header = idf_read_header,
.read_packet = read_packet,
.extensions = "idf",
.priv_class = CLASS("iCE Draw File demuxer"),
};
#endif

168
externals/ffmpeg/libavformat/bit.c vendored Executable file
View File

@@ -0,0 +1,168 @@
/*
* G.729 bit format muxer and demuxer
* Copyright (c) 2007-2008 Vladimir Voroshilov
*
* 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 "internal.h"
#include "libavcodec/get_bits.h"
#include "libavcodec/put_bits.h"
#define MAX_FRAME_SIZE 10
#define SYNC_WORD 0x6b21
#define BIT_0 0x7f
#define BIT_1 0x81
#if CONFIG_BIT_DEMUXER
static int probe(const AVProbeData *p)
{
int i = 0, j, valid = 0;
while (2 * i + 3 < p->buf_size){
if (AV_RL16(&p->buf[2 * i++]) != SYNC_WORD)
return 0;
j = AV_RL16(&p->buf[2 * i++]);
if (j != 0 && j != 0x10 && j != 0x40 && j != 0x50 && j != 0x76)
return 0;
if (j)
valid++;
i += j;
}
if (valid > 10)
return AVPROBE_SCORE_MAX;
if (valid > 2)
return AVPROBE_SCORE_EXTENSION - 1;
return 0;
}
static int read_header(AVFormatContext *s)
{
AVStream* st;
st=avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id=AV_CODEC_ID_G729;
st->codecpar->sample_rate=8000;
st->codecpar->block_align = 16;
st->codecpar->channels=1;
avpriv_set_pts_info(st, 64, 1, 100);
return 0;
}
static int read_packet(AVFormatContext *s,
AVPacket *pkt)
{
AVIOContext *pb = s->pb;
PutBitContext pbo;
uint16_t buf[8 * MAX_FRAME_SIZE + 2];
int packet_size;
uint16_t* src=buf;
int i, j, ret;
int64_t pos= avio_tell(pb);
if(avio_feof(pb))
return AVERROR_EOF;
avio_rl16(pb); // sync word
packet_size = avio_rl16(pb) / 8;
if(packet_size > MAX_FRAME_SIZE)
return AVERROR_INVALIDDATA;
ret = avio_read(pb, (uint8_t*)buf, (8 * packet_size) * sizeof(uint16_t));
if(ret<0)
return ret;
if(ret != 8 * packet_size * sizeof(uint16_t))
return AVERROR(EIO);
if ((ret = av_new_packet(pkt, packet_size)) < 0)
return ret;
init_put_bits(&pbo, pkt->data, packet_size);
for(j=0; j < packet_size; j++)
for(i=0; i<8;i++)
put_bits(&pbo,1, AV_RL16(src++) == BIT_1 ? 1 : 0);
flush_put_bits(&pbo);
pkt->duration=1;
pkt->pos = pos;
return 0;
}
AVInputFormat ff_bit_demuxer = {
.name = "bit",
.long_name = NULL_IF_CONFIG_SMALL("G.729 BIT file format"),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
.extensions = "bit",
};
#endif
#if CONFIG_BIT_MUXER
static int write_header(AVFormatContext *s)
{
AVCodecParameters *par = s->streams[0]->codecpar;
if ((par->codec_id != AV_CODEC_ID_G729) || par->channels != 1) {
av_log(s, AV_LOG_ERROR,
"only codec g729 with 1 channel is supported by this format\n");
return AVERROR(EINVAL);
}
par->bits_per_coded_sample = 16;
par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
return 0;
}
static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
GetBitContext gb;
int i;
if (pkt->size != 10)
return AVERROR(EINVAL);
avio_wl16(pb, SYNC_WORD);
avio_wl16(pb, 8 * pkt->size);
init_get_bits(&gb, pkt->data, 8 * pkt->size);
for (i = 0; i < 8 * pkt->size; i++)
avio_wl16(pb, get_bits1(&gb) ? BIT_1 : BIT_0);
return 0;
}
AVOutputFormat ff_bit_muxer = {
.name = "bit",
.long_name = NULL_IF_CONFIG_SMALL("G.729 BIT file format"),
.mime_type = "audio/bit",
.extensions = "bit",
.audio_codec = AV_CODEC_ID_G729,
.video_codec = AV_CODEC_ID_NONE,
.write_header = write_header,
.write_packet = write_packet,
};
#endif

235
externals/ffmpeg/libavformat/bluray.c vendored Executable file
View File

@@ -0,0 +1,235 @@
/*
* BluRay (libbluray) protocol
*
* Copyright (c) 2012 Petri Hintukainen <phintuka <at> users.sourceforge.net>
*
* 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 <libbluray/bluray.h>
#include "libavutil/avstring.h"
#include "libavformat/avformat.h"
#include "libavformat/url.h"
#include "libavutil/opt.h"
#define BLURAY_PROTO_PREFIX "bluray:"
#define MIN_PLAYLIST_LENGTH 180 /* 3 min */
typedef struct {
const AVClass *class;
BLURAY *bd;
int playlist;
int angle;
int chapter;
/*int region;*/
} BlurayContext;
#define OFFSET(x) offsetof(BlurayContext, x)
static const AVOption options[] = {
{"playlist", "", OFFSET(playlist), AV_OPT_TYPE_INT, { .i64=-1 }, -1, 99999, AV_OPT_FLAG_DECODING_PARAM },
{"angle", "", OFFSET(angle), AV_OPT_TYPE_INT, { .i64=0 }, 0, 0xfe, AV_OPT_FLAG_DECODING_PARAM },
{"chapter", "", OFFSET(chapter), AV_OPT_TYPE_INT, { .i64=1 }, 1, 0xfffe, AV_OPT_FLAG_DECODING_PARAM },
/*{"region", "bluray player region code (1 = region A, 2 = region B, 4 = region C)", OFFSET(region), AV_OPT_TYPE_INT, { .i64=0 }, 0, 3, AV_OPT_FLAG_DECODING_PARAM },*/
{NULL}
};
static const AVClass bluray_context_class = {
.class_name = "bluray",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
static int check_disc_info(URLContext *h)
{
BlurayContext *bd = h->priv_data;
const BLURAY_DISC_INFO *disc_info;
disc_info = bd_get_disc_info(bd->bd);
if (!disc_info) {
av_log(h, AV_LOG_ERROR, "bd_get_disc_info() failed\n");
return -1;
}
if (!disc_info->bluray_detected) {
av_log(h, AV_LOG_ERROR, "BluRay disc not detected\n");
return -1;
}
/* AACS */
if (disc_info->aacs_detected && !disc_info->aacs_handled) {
if (!disc_info->libaacs_detected) {
av_log(h, AV_LOG_ERROR,
"Media stream encrypted with AACS, install and configure libaacs\n");
} else {
av_log(h, AV_LOG_ERROR, "Your libaacs can't decrypt this media\n");
}
return -1;
}
/* BD+ */
if (disc_info->bdplus_detected && !disc_info->bdplus_handled) {
/*
if (!disc_info->libbdplus_detected) {
av_log(h, AV_LOG_ERROR,
"Media stream encrypted with BD+, install and configure libbdplus");
} else {
*/
av_log(h, AV_LOG_ERROR, "Unable to decrypt BD+ encrypted media\n");
/*}*/
return -1;
}
return 0;
}
static int bluray_close(URLContext *h)
{
BlurayContext *bd = h->priv_data;
if (bd->bd) {
bd_close(bd->bd);
}
return 0;
}
static int bluray_open(URLContext *h, const char *path, int flags)
{
BlurayContext *bd = h->priv_data;
int num_title_idx;
const char *diskname = path;
av_strstart(path, BLURAY_PROTO_PREFIX, &diskname);
bd->bd = bd_open(diskname, NULL);
if (!bd->bd) {
av_log(h, AV_LOG_ERROR, "bd_open() failed\n");
return AVERROR(EIO);
}
/* check if disc can be played */
if (check_disc_info(h) < 0) {
return AVERROR(EIO);
}
/* setup player registers */
/* region code has no effect without menus
if (bd->region > 0 && bd->region < 5) {
av_log(h, AV_LOG_INFO, "setting region code to %d (%c)\n", bd->region, 'A' + (bd->region - 1));
bd_set_player_setting(bd->bd, BLURAY_PLAYER_SETTING_REGION_CODE, bd->region);
}
*/
/* load title list */
num_title_idx = bd_get_titles(bd->bd, TITLES_RELEVANT, MIN_PLAYLIST_LENGTH);
av_log(h, AV_LOG_INFO, "%d usable playlists:\n", num_title_idx);
if (num_title_idx < 1) {
return AVERROR(EIO);
}
/* if playlist was not given, select longest playlist */
if (bd->playlist < 0) {
uint64_t duration = 0;
int i;
for (i = 0; i < num_title_idx; i++) {
BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0);
av_log(h, AV_LOG_INFO, "playlist %05d.mpls (%d:%02d:%02d)\n",
info->playlist,
((int)(info->duration / 90000) / 3600),
((int)(info->duration / 90000) % 3600) / 60,
((int)(info->duration / 90000) % 60));
if (info->duration > duration) {
bd->playlist = info->playlist;
duration = info->duration;
}
bd_free_title_info(info);
}
av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist);
}
/* select playlist */
if (bd_select_playlist(bd->bd, bd->playlist) <= 0) {
av_log(h, AV_LOG_ERROR, "bd_select_playlist(%05d.mpls) failed\n", bd->playlist);
return AVERROR(EIO);
}
/* select angle */
if (bd->angle >= 0) {
bd_select_angle(bd->bd, bd->angle);
}
/* select chapter */
if (bd->chapter > 1) {
bd_seek_chapter(bd->bd, bd->chapter - 1);
}
return 0;
}
static int bluray_read(URLContext *h, unsigned char *buf, int size)
{
BlurayContext *bd = h->priv_data;
int len;
if (!bd || !bd->bd) {
return AVERROR(EFAULT);
}
len = bd_read(bd->bd, buf, size);
return len == 0 ? AVERROR_EOF : len;
}
static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
{
BlurayContext *bd = h->priv_data;
if (!bd || !bd->bd) {
return AVERROR(EFAULT);
}
switch (whence) {
case SEEK_SET:
case SEEK_CUR:
case SEEK_END:
return bd_seek(bd->bd, pos);
case AVSEEK_SIZE:
return bd_get_title_size(bd->bd);
}
av_log(h, AV_LOG_ERROR, "Unsupported whence operation %d\n", whence);
return AVERROR(EINVAL);
}
const URLProtocol ff_bluray_protocol = {
.name = "bluray",
.url_close = bluray_close,
.url_open = bluray_open,
.url_read = bluray_read,
.url_seek = bluray_seek,
.priv_data_size = sizeof(BlurayContext),
.priv_data_class = &bluray_context_class,
};

136
externals/ffmpeg/libavformat/bmv.c vendored Executable file
View File

@@ -0,0 +1,136 @@
/*
* Discworld II BMV demuxer
* Copyright (c) 2011 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 "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
enum BMVFlags {
BMV_NOP = 0,
BMV_END,
BMV_DELTA,
BMV_INTRA,
BMV_AUDIO = 0x20,
};
typedef struct BMVContext {
uint8_t *packet;
int size;
int get_next;
int64_t audio_pos;
} BMVContext;
static int bmv_read_header(AVFormatContext *s)
{
AVStream *st, *ast;
BMVContext *c = s->priv_data;
st = avformat_new_stream(s, 0);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_BMV_VIDEO;
st->codecpar->width = 640;
st->codecpar->height = 429;
st->codecpar->format = AV_PIX_FMT_PAL8;
avpriv_set_pts_info(st, 16, 1, 12);
ast = avformat_new_stream(s, 0);
if (!ast)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_BMV_AUDIO;
ast->codecpar->channels = 2;
ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
ast->codecpar->sample_rate = 22050;
avpriv_set_pts_info(ast, 16, 1, 22050);
c->get_next = 1;
c->audio_pos = 0;
return 0;
}
static int bmv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
BMVContext *c = s->priv_data;
int type, err;
while (c->get_next) {
if (s->pb->eof_reached)
return AVERROR_EOF;
type = avio_r8(s->pb);
if (type == BMV_NOP)
continue;
if (type == BMV_END)
return AVERROR_EOF;
c->size = avio_rl24(s->pb);
if (!c->size)
return AVERROR_INVALIDDATA;
if ((err = av_reallocp(&c->packet, c->size + 1)) < 0)
return err;
c->packet[0] = type;
if (avio_read(s->pb, c->packet + 1, c->size) != c->size)
return AVERROR(EIO);
if (type & BMV_AUDIO) {
int audio_size = c->packet[1] * 65 + 1;
if (audio_size >= c->size) {
av_log(s, AV_LOG_ERROR, "Reported audio size %d is bigger than packet size (%d)\n",
audio_size, c->size);
return AVERROR_INVALIDDATA;
}
if ((err = av_new_packet(pkt, audio_size)) < 0)
return err;
memcpy(pkt->data, c->packet + 1, pkt->size);
pkt->stream_index = 1;
pkt->pts = c->audio_pos;
pkt->duration = c->packet[1] * 32;
c->audio_pos += pkt->duration;
c->get_next = 0;
return pkt->size;
} else
break;
}
if ((err = av_new_packet(pkt, c->size + 1)) < 0)
return err;
pkt->stream_index = 0;
c->get_next = 1;
memcpy(pkt->data, c->packet, pkt->size);
return pkt->size;
}
static int bmv_read_close(AVFormatContext *s)
{
BMVContext *c = s->priv_data;
av_freep(&c->packet);
return 0;
}
AVInputFormat ff_bmv_demuxer = {
.name = "bmv",
.long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV"),
.priv_data_size = sizeof(BMVContext),
.read_header = bmv_read_header,
.read_packet = bmv_read_packet,
.read_close = bmv_read_close,
.extensions = "bmv",
};

85
externals/ffmpeg/libavformat/boadec.c vendored Executable file
View File

@@ -0,0 +1,85 @@
/*
* Black ops audio demuxer
* Copyright (c) 2013 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 "libavutil/intreadwrite.h"
#include "libavcodec/internal.h"
#include "avformat.h"
#include "internal.h"
static int probe(const AVProbeData *p)
{
if (p->buf_size < 2096)
return 0;
if ( AV_RL32(p->buf ) != 1
|| AV_RL32(p->buf + 8) > 100000
|| AV_RL32(p->buf + 12) > 8
|| AV_RL32(p->buf + 16) != 2096
||!AV_RL32(p->buf + 21)
|| AV_RL16(p->buf + 25) != 2096
|| AV_RL32(p->buf + 48) % AV_RL32(p->buf + 21)
)
return 0;
return AVPROBE_SCORE_EXTENSION;
}
static int read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_MS;
avio_rl32(s->pb);
avio_rl32(s->pb);
st->codecpar->sample_rate = avio_rl32(s->pb);
st->codecpar->channels = avio_rl32(s->pb);
if (st->codecpar->channels > FF_SANE_NB_CHANNELS)
return AVERROR(ENOSYS);
s->internal->data_offset = avio_rl32(s->pb);
avio_r8(s->pb);
st->codecpar->block_align = avio_rl32(s->pb);
if (st->codecpar->block_align > INT_MAX / FF_SANE_NB_CHANNELS)
return AVERROR_INVALIDDATA;
st->codecpar->block_align *= st->codecpar->channels;
avio_seek(s->pb, s->internal->data_offset, SEEK_SET);
return 0;
}
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVStream *st = s->streams[0];
return av_get_packet(s->pb, pkt, st->codecpar->block_align);
}
AVInputFormat ff_boa_demuxer = {
.name = "boa",
.long_name = NULL_IF_CONFIG_SMALL("Black Ops Audio"),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
.flags = AVFMT_GENERIC_INDEX,
};

482
externals/ffmpeg/libavformat/brstm.c vendored Executable file
View File

@@ -0,0 +1,482 @@
/*
* BRSTM demuxer
* Copyright (c) 2012 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "internal.h"
typedef struct BRSTMDemuxContext {
uint32_t block_size;
uint32_t block_count;
uint32_t current_block;
uint32_t samples_per_block;
uint32_t last_block_used_bytes;
uint32_t last_block_size;
uint32_t last_block_samples;
uint32_t data_start;
uint8_t *table;
uint8_t *adpc;
int little_endian;
} BRSTMDemuxContext;
static int probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) == MKTAG('R','S','T','M') &&
(AV_RL16(p->buf + 4) == 0xFFFE ||
AV_RL16(p->buf + 4) == 0xFEFF))
return AVPROBE_SCORE_MAX / 3 * 2;
return 0;
}
static int probe_bfstm(const AVProbeData *p)
{
if ((AV_RL32(p->buf) == MKTAG('F','S','T','M') ||
AV_RL32(p->buf) == MKTAG('C','S','T','M')) &&
(AV_RL16(p->buf + 4) == 0xFFFE ||
AV_RL16(p->buf + 4) == 0xFEFF))
return AVPROBE_SCORE_MAX / 3 * 2;
return 0;
}
static int read_close(AVFormatContext *s)
{
BRSTMDemuxContext *b = s->priv_data;
av_freep(&b->table);
av_freep(&b->adpc);
return 0;
}
static av_always_inline unsigned int read16(AVFormatContext *s)
{
BRSTMDemuxContext *b = s->priv_data;
if (b->little_endian)
return avio_rl16(s->pb);
else
return avio_rb16(s->pb);
}
static av_always_inline unsigned int read32(AVFormatContext *s)
{
BRSTMDemuxContext *b = s->priv_data;
if (b->little_endian)
return avio_rl32(s->pb);
else
return avio_rb32(s->pb);
}
static int read_header(AVFormatContext *s)
{
BRSTMDemuxContext *b = s->priv_data;
int bom, major, minor, codec, chunk;
int64_t h1offset, pos, toffset;
uint32_t size, asize, start = 0;
AVStream *st;
int ret = AVERROR_EOF;
int loop = 0;
int bfstm = !strcmp("bfstm", s->iformat->name);
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avio_skip(s->pb, 4);
bom = avio_rb16(s->pb);
if (bom != 0xFEFF && bom != 0xFFFE) {
av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom);
return AVERROR_INVALIDDATA;
}
if (bom == 0xFFFE)
b->little_endian = 1;
if (!bfstm) {
major = avio_r8(s->pb);
minor = avio_r8(s->pb);
avio_skip(s->pb, 4); // size of file
size = read16(s);
if (size < 14)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, size - 14);
pos = avio_tell(s->pb);
if (avio_rl32(s->pb) != MKTAG('H','E','A','D'))
return AVERROR_INVALIDDATA;
} else {
uint32_t info_offset = 0;
uint16_t section_count, header_size, i;
header_size = read16(s); // 6
avio_skip(s->pb, 4); // Unknown constant 0x00030000
avio_skip(s->pb, 4); // size of file
section_count = read16(s);
avio_skip(s->pb, 2); // padding
for (i = 0; avio_tell(s->pb) < header_size
&& !(start && info_offset)
&& i < section_count; i++) {
uint16_t flag = read16(s);
avio_skip(s->pb, 2);
switch (flag) {
case 0x4000:
info_offset = read32(s);
/*info_size =*/ read32(s);
break;
case 0x4001:
avio_skip(s->pb, 4); // seek offset
avio_skip(s->pb, 4); // seek size
break;
case 0x4002:
start = read32(s) + 8;
avio_skip(s->pb, 4); //data_size = read32(s);
break;
case 0x4003:
avio_skip(s->pb, 4); // REGN offset
avio_skip(s->pb, 4); // REGN size
break;
}
}
if (!info_offset || !start)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, info_offset - avio_tell(s->pb));
pos = avio_tell(s->pb);
if (avio_rl32(s->pb) != MKTAG('I','N','F','O'))
return AVERROR_INVALIDDATA;
}
size = read32(s);
if (size < 40)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 4); // unknown
h1offset = read32(s);
if (h1offset > size)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 12);
toffset = read32(s) + 16LL;
if (toffset > size)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, pos + h1offset + 8 - avio_tell(s->pb));
codec = avio_r8(s->pb);
switch (codec) {
case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR; break;
case 1: codec = b->little_endian ?
AV_CODEC_ID_PCM_S16LE_PLANAR :
AV_CODEC_ID_PCM_S16BE_PLANAR; break;
case 2: codec = b->little_endian ?
AV_CODEC_ID_ADPCM_THP_LE :
AV_CODEC_ID_ADPCM_THP; break;
default:
avpriv_request_sample(s, "codec %d", codec);
return AVERROR_PATCHWELCOME;
}
loop = avio_r8(s->pb); // loop flag
st->codecpar->codec_id = codec;
st->codecpar->channels = avio_r8(s->pb);
if (!st->codecpar->channels)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 1); // padding
st->codecpar->sample_rate = bfstm ? read32(s) : read16(s);
if (st->codecpar->sample_rate <= 0)
return AVERROR_INVALIDDATA;
if (!bfstm)
avio_skip(s->pb, 2); // padding
if (loop) {
if (av_dict_set_int(&s->metadata, "loop_start",
av_rescale(read32(s), AV_TIME_BASE,
st->codecpar->sample_rate),
0) < 0)
return AVERROR(ENOMEM);
} else {
avio_skip(s->pb, 4);
}
st->start_time = 0;
st->duration = read32(s);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
if (!bfstm)
start = read32(s);
b->current_block = 0;
b->block_count = read32(s);
if (b->block_count > UINT16_MAX) {
av_log(s, AV_LOG_WARNING, "too many blocks: %"PRIu32"\n", b->block_count);
return AVERROR_INVALIDDATA;
}
b->block_size = read32(s);
if (b->block_size > UINT32_MAX / st->codecpar->channels)
return AVERROR_INVALIDDATA;
b->samples_per_block = read32(s);
b->last_block_used_bytes = read32(s);
b->last_block_samples = read32(s);
b->last_block_size = read32(s);
if (b->last_block_size > UINT32_MAX / st->codecpar->channels)
return AVERROR_INVALIDDATA;
if (b->last_block_used_bytes > b->last_block_size)
return AVERROR_INVALIDDATA;
if (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE) {
int ch;
avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
if (!bfstm)
toffset = read32(s) + 16LL;
else
toffset = toffset + read32(s) + st->codecpar->channels * 8 - 8;
if (toffset > size)
return AVERROR_INVALIDDATA;
avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
b->table = av_mallocz(32 * st->codecpar->channels);
if (!b->table)
return AVERROR(ENOMEM);
for (ch = 0; ch < st->codecpar->channels; ch++) {
if (avio_read(s->pb, b->table + ch * 32, 32) != 32) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_skip(s->pb, bfstm ? 14 : 24);
}
}
if (size < (avio_tell(s->pb) - pos)) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_skip(s->pb, size - (avio_tell(s->pb) - pos));
while (!avio_feof(s->pb)) {
chunk = avio_rl32(s->pb);
size = read32(s);
if (size < 8) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
size -= 8;
switch (chunk) {
case MKTAG('S','E','E','K'):
case MKTAG('A','D','P','C'):
if (codec != AV_CODEC_ID_ADPCM_THP &&
codec != AV_CODEC_ID_ADPCM_THP_LE)
goto skip;
asize = b->block_count * st->codecpar->channels * 4;
if (size < asize) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
if (b->adpc) {
av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n");
goto skip;
} else {
b->adpc = av_mallocz(asize);
if (!b->adpc) {
ret = AVERROR(ENOMEM);
goto fail;
}
if (bfstm && codec != AV_CODEC_ID_ADPCM_THP_LE) {
// Big-endian BFSTMs have little-endian SEEK tables
// for some strange reason.
int i;
for (i = 0; i < asize; i += 2) {
b->adpc[i+1] = avio_r8(s->pb);
b->adpc[i] = avio_r8(s->pb);
}
} else {
avio_read(s->pb, b->adpc, asize);
}
avio_skip(s->pb, size - asize);
}
break;
case MKTAG('D','A','T','A'):
if ((start < avio_tell(s->pb)) ||
(!b->adpc && (codec == AV_CODEC_ID_ADPCM_THP ||
codec == AV_CODEC_ID_ADPCM_THP_LE))) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
avio_skip(s->pb, start - avio_tell(s->pb));
if (bfstm && (codec == AV_CODEC_ID_ADPCM_THP ||
codec == AV_CODEC_ID_ADPCM_THP_LE))
avio_skip(s->pb, 24);
b->data_start = avio_tell(s->pb);
if (!bfstm && (major != 1 || minor))
avpriv_request_sample(s, "Version %d.%d", major, minor);
return 0;
default:
av_log(s, AV_LOG_WARNING, "skipping unknown chunk: %X\n", chunk);
skip:
avio_skip(s->pb, size);
}
}
fail:
read_close(s);
return ret;
}
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVCodecParameters *par = s->streams[0]->codecpar;
BRSTMDemuxContext *b = s->priv_data;
uint32_t samples, size, skip = 0;
int ret, i;
if (avio_feof(s->pb))
return AVERROR_EOF;
b->current_block++;
if (b->current_block == b->block_count) {
size = b->last_block_used_bytes;
samples = b->last_block_samples;
skip = b->last_block_size - b->last_block_used_bytes;
if (samples < size * 14 / 8) {
uint32_t adjusted_size = samples / 14 * 8;
if (samples % 14)
adjusted_size += (samples % 14 + 1) / 2 + 1;
skip += size - adjusted_size;
size = adjusted_size;
}
} else if (b->current_block < b->block_count) {
size = b->block_size;
samples = b->samples_per_block;
} else {
return AVERROR_EOF;
}
if (par->codec_id == AV_CODEC_ID_ADPCM_THP ||
par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
uint8_t *dst;
if (!b->adpc) {
av_log(s, AV_LOG_ERROR, "adpcm_thp requires ADPC chunk, but none was found.\n");
return AVERROR_INVALIDDATA;
}
if (!b->table) {
b->table = av_mallocz(32 * par->channels);
if (!b->table)
return AVERROR(ENOMEM);
}
if (size > (INT_MAX - 32 - 4) ||
(32 + 4 + size) > (INT_MAX / par->channels) ||
(32 + 4 + size) * par->channels > INT_MAX - 8)
return AVERROR_INVALIDDATA;
if ((ret = av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels)) < 0)
return ret;
dst = pkt->data;
if (par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
bytestream_put_le32(&dst, size * par->channels);
bytestream_put_le32(&dst, samples);
} else {
bytestream_put_be32(&dst, size * par->channels);
bytestream_put_be32(&dst, samples);
}
bytestream_put_buffer(&dst, b->table, 32 * par->channels);
bytestream_put_buffer(&dst, b->adpc + 4 * par->channels *
(b->current_block - 1), 4 * par->channels);
for (i = 0; i < par->channels; i++) {
ret = avio_read(s->pb, dst, size);
dst += size;
avio_skip(s->pb, skip);
if (ret != size) {
return AVERROR(EIO);
}
}
pkt->duration = samples;
} else {
size *= par->channels;
ret = av_get_packet(s->pb, pkt, size);
}
pkt->stream_index = 0;
if (ret != size)
ret = AVERROR(EIO);
return ret;
}
static int read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
AVStream *st = s->streams[stream_index];
BRSTMDemuxContext *b = s->priv_data;
int64_t ret = 0;
timestamp /= b->samples_per_block;
ret = avio_seek(s->pb, b->data_start + timestamp * b->block_size *
st->codecpar->channels, SEEK_SET);
if (ret < 0)
return ret;
b->current_block = timestamp;
ff_update_cur_dts(s, st, timestamp * b->samples_per_block);
return 0;
}
AVInputFormat ff_brstm_demuxer = {
.name = "brstm",
.long_name = NULL_IF_CONFIG_SMALL("BRSTM (Binary Revolution Stream)"),
.priv_data_size = sizeof(BRSTMDemuxContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
.read_close = read_close,
.read_seek = read_seek,
.extensions = "brstm",
};
AVInputFormat ff_bfstm_demuxer = {
.name = "bfstm",
.long_name = NULL_IF_CONFIG_SMALL("BFSTM (Binary Cafe Stream)"),
.priv_data_size = sizeof(BRSTMDemuxContext),
.read_probe = probe_bfstm,
.read_header = read_header,
.read_packet = read_packet,
.read_close = read_close,
.read_seek = read_seek,
.extensions = "bfstm,bcstm",
};

195
externals/ffmpeg/libavformat/c93.c vendored Executable file
View File

@@ -0,0 +1,195 @@
/*
* 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 "internal.h"
#include "voc.h"
#include "libavutil/intreadwrite.h"
typedef struct C93BlockRecord {
uint16_t index;
uint8_t length;
uint8_t frames;
} C93BlockRecord;
typedef struct C93DemuxContext {
VocDecContext 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(const AVProbeData *p)
{
int i;
int index = 1;
if (p->buf_size < 16)
return 0;
for (i = 0; i < 16; i += 4) {
if (AV_RL16(p->buf + i) != index || !p->buf[i + 2] || !p->buf[i + 3])
return 0;
index += p->buf[i + 2];
}
return AVPROBE_SCORE_MAX;
}
static int read_header(AVFormatContext *s)
{
AVStream *video;
AVIOContext *pb = s->pb;
C93DemuxContext *c93 = s->priv_data;
int i;
int framecount = 0;
for (i = 0; i < 512; i++) {
c93->block_records[i].index = avio_rl16(pb);
c93->block_records[i].length = avio_r8(pb);
c93->block_records[i].frames = avio_r8(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 = avformat_new_stream(s, NULL);
if (!video)
return AVERROR(ENOMEM);
video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
video->codecpar->codec_id = AV_CODEC_ID_C93;
video->codecpar->width = 320;
video->codecpar->height = 192;
/* 4:3 320x200 with 8 empty lines */
video->sample_aspect_ratio = (AVRational) { 5, 6 };
avpriv_set_pts_info(video, 64, 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)
{
AVIOContext *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 = avio_rl16(pb);
if (datasize > 42) {
if (!c93->audio) {
c93->audio = avformat_new_stream(s, NULL);
if (!c93->audio)
return AVERROR(ENOMEM);
c93->audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
}
avio_skip(pb, 26); /* VOC header */
ret = ff_voc_get_packet(s, pkt, c93->audio, datasize - 26);
if (ret > 0) {
pkt->stream_index = 1;
pkt->flags |= AV_PKT_FLAG_KEY;
return ret;
}
}
}
if (c93->current_frame >= br->frames) {
if (c93->current_block >= 511 || !br[1].length)
return AVERROR_EOF;
br++;
c93->current_block++;
c93->current_frame = 0;
}
if (c93->current_frame == 0) {
avio_seek(pb, br->index * 2048, SEEK_SET);
for (i = 0; i < 32; i++) {
c93->frame_offsets[i] = avio_rl32(pb);
}
}
avio_seek(pb,br->index * 2048 +
c93->frame_offsets[c93->current_frame], SEEK_SET);
datasize = avio_rl16(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 = avio_read(pb, pkt->data + 1, datasize);
if (ret < datasize) {
return AVERROR(EIO);
}
datasize = avio_rl16(pb); /* palette size */
if (datasize) {
if (datasize != 768) {
av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize);
return AVERROR_INVALIDDATA;
}
pkt->data[0] |= C93_HAS_PALETTE;
ret = avio_read(pb, pkt->data + pkt->size, datasize);
if (ret < datasize) {
return AVERROR(EIO);
}
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 |= AV_PKT_FLAG_KEY;
pkt->data[0] |= C93_FIRST_FRAME;
}
return 0;
}
AVInputFormat ff_c93_demuxer = {
.name = "c93",
.long_name = NULL_IF_CONFIG_SMALL("Interplay C93"),
.priv_data_size = sizeof(C93DemuxContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
};

343
externals/ffmpeg/libavformat/cache.c vendored Executable file
View File

@@ -0,0 +1,343 @@
/*
* Input cache protocol.
* Copyright (c) 2011,2014 Michael Niedermayer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Based on file.c by Fabrice Bellard
*/
/**
* @TODO
* support keeping files
* support filling with a background thread
*/
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/internal.h"
#include "libavutil/opt.h"
#include "libavutil/tree.h"
#include "avformat.h"
#include <fcntl.h>
#if HAVE_IO_H
#include <io.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/stat.h>
#include <stdlib.h>
#include "os_support.h"
#include "url.h"
typedef struct CacheEntry {
int64_t logical_pos;
int64_t physical_pos;
int size;
} CacheEntry;
typedef struct Context {
AVClass *class;
int fd;
char *filename;
struct AVTreeNode *root;
int64_t logical_pos;
int64_t cache_pos;
int64_t inner_pos;
int64_t end;
int is_true_eof;
URLContext *inner;
int64_t cache_hit, cache_miss;
int read_ahead_limit;
} Context;
static int cmp(const void *key, const void *node)
{
return FFDIFFSIGN(*(const int64_t *)key, ((const CacheEntry *) node)->logical_pos);
}
static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
int ret;
char *buffername;
Context *c= h->priv_data;
av_strstart(arg, "cache:", &arg);
c->fd = avpriv_tempfile("ffcache", &buffername, 0, h);
if (c->fd < 0){
av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
return c->fd;
}
ret = unlink(buffername);
if (ret >= 0)
av_freep(&buffername);
else
c->filename = buffername;
return ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback,
options, h->protocol_whitelist, h->protocol_blacklist, h);
}
static int add_entry(URLContext *h, const unsigned char *buf, int size)
{
Context *c= h->priv_data;
int64_t pos = -1;
int ret;
CacheEntry *entry = NULL, *next[2] = {NULL, NULL};
CacheEntry *entry_ret;
struct AVTreeNode *node = NULL;
//FIXME avoid lseek
pos = lseek(c->fd, 0, SEEK_END);
if (pos < 0) {
ret = AVERROR(errno);
av_log(h, AV_LOG_ERROR, "seek in cache failed\n");
goto fail;
}
c->cache_pos = pos;
ret = write(c->fd, buf, size);
if (ret < 0) {
ret = AVERROR(errno);
av_log(h, AV_LOG_ERROR, "write in cache failed\n");
goto fail;
}
c->cache_pos += ret;
entry = av_tree_find(c->root, &c->logical_pos, cmp, (void**)next);
if (!entry)
entry = next[0];
if (!entry ||
entry->logical_pos + entry->size != c->logical_pos ||
entry->physical_pos + entry->size != pos
) {
entry = av_malloc(sizeof(*entry));
node = av_tree_node_alloc();
if (!entry || !node) {
ret = AVERROR(ENOMEM);
goto fail;
}
entry->logical_pos = c->logical_pos;
entry->physical_pos = pos;
entry->size = ret;
entry_ret = av_tree_insert(&c->root, entry, cmp, &node);
if (entry_ret && entry_ret != entry) {
ret = -1;
av_log(h, AV_LOG_ERROR, "av_tree_insert failed\n");
goto fail;
}
} else
entry->size += ret;
return 0;
fail:
//we could truncate the file to pos here if pos >=0 but ftruncate isn't available in VS so
//for simplicty we just leave the file a bit larger
av_free(entry);
av_free(node);
return ret;
}
static int cache_read(URLContext *h, unsigned char *buf, int size)
{
Context *c= h->priv_data;
CacheEntry *entry, *next[2] = {NULL, NULL};
int64_t r;
entry = av_tree_find(c->root, &c->logical_pos, cmp, (void**)next);
if (!entry)
entry = next[0];
if (entry) {
int64_t in_block_pos = c->logical_pos - entry->logical_pos;
av_assert0(entry->logical_pos <= c->logical_pos);
if (in_block_pos < entry->size) {
int64_t physical_target = entry->physical_pos + in_block_pos;
if (c->cache_pos != physical_target) {
r = lseek(c->fd, physical_target, SEEK_SET);
} else
r = c->cache_pos;
if (r >= 0) {
c->cache_pos = r;
r = read(c->fd, buf, FFMIN(size, entry->size - in_block_pos));
}
if (r > 0) {
c->cache_pos += r;
c->logical_pos += r;
c->cache_hit ++;
return r;
}
}
}
// Cache miss or some kind of fault with the cache
if (c->logical_pos != c->inner_pos) {
r = ffurl_seek(c->inner, c->logical_pos, SEEK_SET);
if (r<0) {
av_log(h, AV_LOG_ERROR, "Failed to perform internal seek\n");
return r;
}
c->inner_pos = r;
}
r = ffurl_read(c->inner, buf, size);
if (r == AVERROR_EOF && size>0) {
c->is_true_eof = 1;
av_assert0(c->end >= c->logical_pos);
}
if (r<=0)
return r;
c->inner_pos += r;
c->cache_miss ++;
add_entry(h, buf, r);
c->logical_pos += r;
c->end = FFMAX(c->end, c->logical_pos);
return r;
}
static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
{
Context *c= h->priv_data;
int64_t ret;
if (whence == AVSEEK_SIZE) {
pos= ffurl_seek(c->inner, pos, whence);
if(pos <= 0){
pos= ffurl_seek(c->inner, -1, SEEK_END);
if (ffurl_seek(c->inner, c->inner_pos, SEEK_SET) < 0)
av_log(h, AV_LOG_ERROR, "Inner protocol failed to seekback end : %"PRId64"\n", pos);
}
if (pos > 0)
c->is_true_eof = 1;
c->end = FFMAX(c->end, pos);
return pos;
}
if (whence == SEEK_CUR) {
whence = SEEK_SET;
pos += c->logical_pos;
} else if (whence == SEEK_END && c->is_true_eof) {
resolve_eof:
whence = SEEK_SET;
pos += c->end;
}
if (whence == SEEK_SET && pos >= 0 && pos < c->end) {
//Seems within filesize, assume it will not fail.
c->logical_pos = pos;
return pos;
}
//cache miss
ret= ffurl_seek(c->inner, pos, whence);
if ((whence == SEEK_SET && pos >= c->logical_pos ||
whence == SEEK_END && pos <= 0) && ret < 0) {
if ( (whence == SEEK_SET && c->read_ahead_limit >= pos - c->logical_pos)
|| c->read_ahead_limit < 0) {
uint8_t tmp[32768];
while (c->logical_pos < pos || whence == SEEK_END) {
int size = sizeof(tmp);
if (whence == SEEK_SET)
size = FFMIN(sizeof(tmp), pos - c->logical_pos);
ret = cache_read(h, tmp, size);
if (ret == AVERROR_EOF && whence == SEEK_END) {
av_assert0(c->is_true_eof);
goto resolve_eof;
}
if (ret < 0) {
return ret;
}
}
return c->logical_pos;
}
}
if (ret >= 0) {
c->logical_pos = ret;
c->end = FFMAX(c->end, ret);
}
return ret;
}
static int enu_free(void *opaque, void *elem)
{
av_free(elem);
return 0;
}
static int cache_close(URLContext *h)
{
Context *c= h->priv_data;
int ret;
av_log(h, AV_LOG_INFO, "Statistics, cache hits:%"PRId64" cache misses:%"PRId64"\n",
c->cache_hit, c->cache_miss);
close(c->fd);
if (c->filename) {
ret = unlink(c->filename);
if (ret < 0)
av_log(h, AV_LOG_ERROR, "Could not delete %s.\n", c->filename);
av_freep(&c->filename);
}
ffurl_closep(&c->inner);
av_tree_enumerate(c->root, NULL, NULL, enu_free);
av_tree_destroy(c->root);
return 0;
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{ "read_ahead_limit", "Amount in bytes that may be read ahead when seeking isn't supported, -1 for unlimited", OFFSET(read_ahead_limit), AV_OPT_TYPE_INT, { .i64 = 65536 }, -1, INT_MAX, D },
{NULL},
};
static const AVClass cache_context_class = {
.class_name = "cache",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
const URLProtocol ff_cache_protocol = {
.name = "cache",
.url_open2 = cache_open,
.url_read = cache_read,
.url_seek = cache_seek,
.url_close = cache_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &cache_context_class,
};

80
externals/ffmpeg/libavformat/caf.c vendored Executable file
View File

@@ -0,0 +1,80 @@
/*
* CAF common code
* Copyright (c) 2007 Justin Ruggles
*
* 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
* CAF common code
*/
#include "avformat.h"
#include "internal.h"
#include "caf.h"
/**
* Known codec tags for CAF
*/
const AVCodecTag ff_codec_caf_tags[] = {
{ AV_CODEC_ID_AAC, MKTAG('a','a','c',' ') },
{ AV_CODEC_ID_AAC, MKTAG('a','a','c','l') },
{ AV_CODEC_ID_AC3, MKTAG('a','c','-','3') },
{ AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') },
{ AV_CODEC_ID_ADPCM_IMA_WAV, MKTAG('m','s', 0, 17 ) },
{ AV_CODEC_ID_ADPCM_MS, MKTAG('m','s', 0, 2 ) },
{ AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') },
{ AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },
/* FIXME: use DV demuxer, as done in MOV */
/*{ AV_CODEC_ID_DVAUDIO, MKTAG('v','d','v','a') },*/
/*{ AV_CODEC_ID_DVAUDIO, MKTAG('d','v','c','a') },*/
{ AV_CODEC_ID_GSM, MKTAG('a','g','s','m') },
{ AV_CODEC_ID_GSM_MS, MKTAG('m','s', 0, '1') },
{ AV_CODEC_ID_ILBC, MKTAG('i','l','b','c') },
{ AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') },
{ AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') },
{ AV_CODEC_ID_MP1, MKTAG('.','m','p','1') },
{ AV_CODEC_ID_MP2, MKTAG('.','m','p','2') },
{ AV_CODEC_ID_MP3, MKTAG('.','m','p','3') },
{ AV_CODEC_ID_MP3, MKTAG('m','s', 0 ,'U') },
{ AV_CODEC_ID_OPUS, MKTAG('o','p','u','s') },
{ AV_CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') },
{ AV_CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') },
{ AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') },
{ AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') },
{ AV_CODEC_ID_QDMC, MKTAG('Q','D','M','C') },
/* currently unsupported codecs */
/*{ AC-3 over S/PDIF MKTAG('c','a','c','3') },*/
/*{ MPEG4CELP MKTAG('c','e','l','p') },*/
/*{ MPEG4HVXC MKTAG('h','v','x','c') },*/
/*{ MPEG4TwinVQ MKTAG('t','w','v','q') },*/
{ AV_CODEC_ID_PCM_S8, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S16LE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S16BE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S24LE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S24BE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S32LE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_S32BE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_F32LE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_F32BE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_F64LE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_PCM_F64BE, MKTAG('l','p','c','m') },
{ AV_CODEC_ID_NONE, 0 },
};

34
externals/ffmpeg/libavformat/caf.h vendored Executable file
View File

@@ -0,0 +1,34 @@
/*
* CAF common code
* Copyright (c) 2007 Justin Ruggles
*
* 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
* CAF common code
*/
#ifndef AVFORMAT_CAF_H
#define AVFORMAT_CAF_H
#include "internal.h"
extern const AVCodecTag ff_codec_caf_tags[];
#endif /* AVFORMAT_CAF_H */

456
externals/ffmpeg/libavformat/cafdec.c vendored Executable file
View File

@@ -0,0 +1,456 @@
/*
* Core Audio Format demuxer
* Copyright (c) 2007 Justin Ruggles
* Copyright (c) 2009 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
* Core Audio Format demuxer
*/
#include <inttypes.h>
#include "avformat.h"
#include "internal.h"
#include "isom.h"
#include "mov_chan.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "libavutil/dict.h"
#include "caf.h"
typedef struct CafContext {
int bytes_per_packet; ///< bytes in a packet, or 0 if variable
int frames_per_packet; ///< frames in a packet, or 0 if variable
int64_t num_bytes; ///< total number of bytes in stream
int64_t packet_cnt; ///< packet counter
int64_t frame_cnt; ///< frame counter
int64_t data_start; ///< data start position, in bytes
int64_t data_size; ///< raw data size, in bytes
} CafContext;
static int probe(const AVProbeData *p)
{
if (AV_RB32(p->buf) == MKBETAG('c','a','f','f') && AV_RB16(&p->buf[4]) == 1)
return AVPROBE_SCORE_MAX;
return 0;
}
/** Read audio description chunk */
static int read_desc_chunk(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
CafContext *caf = s->priv_data;
AVStream *st;
int flags;
/* new audio stream */
st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
/* parse format description */
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
st->codecpar->codec_tag = avio_rl32(pb);
flags = avio_rb32(pb);
caf->bytes_per_packet = avio_rb32(pb);
st->codecpar->block_align = caf->bytes_per_packet;
caf->frames_per_packet = avio_rb32(pb);
st->codecpar->channels = avio_rb32(pb);
st->codecpar->bits_per_coded_sample = avio_rb32(pb);
/* calculate bit rate for constant size packets */
if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8
/ (uint64_t)caf->frames_per_packet;
} else {
st->codecpar->bit_rate = 0;
}
/* determine codec */
if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
st->codecpar->codec_id = ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample, (flags ^ 0x2) | 0x4);
else
st->codecpar->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codecpar->codec_tag);
return 0;
}
/** Read magic cookie chunk */
static int read_kuki_chunk(AVFormatContext *s, int64_t size)
{
AVIOContext *pb = s->pb;
AVStream *st = s->streams[0];
int ret;
if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return -1;
if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
/* The magic cookie format for AAC is an mp4 esds atom.
The lavc AAC decoder requires the data from the codec specific
description as extradata input. */
int strt, skip;
strt = avio_tell(pb);
ff_mov_read_esds(s, pb);
skip = size - (avio_tell(pb) - strt);
if (skip < 0 || !st->codecpar->extradata ||
st->codecpar->codec_id != AV_CODEC_ID_AAC) {
av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n");
return AVERROR_INVALIDDATA;
}
avio_skip(pb, skip);
} else if (st->codecpar->codec_id == AV_CODEC_ID_ALAC) {
#define ALAC_PREAMBLE 12
#define ALAC_HEADER 36
#define ALAC_NEW_KUKI 24
uint8_t preamble[12];
if (size < ALAC_NEW_KUKI) {
av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n");
avio_skip(pb, size);
return AVERROR_INVALIDDATA;
}
if (avio_read(pb, preamble, ALAC_PREAMBLE) != ALAC_PREAMBLE) {
av_log(s, AV_LOG_ERROR, "failed to read preamble\n");
return AVERROR_INVALIDDATA;
}
if ((ret = ff_alloc_extradata(st->codecpar, ALAC_HEADER)) < 0)
return ret;
/* For the old style cookie, we skip 12 bytes, then read 36 bytes.
* The new style cookie only contains the last 24 bytes of what was
* 36 bytes in the old style cookie, so we fabricate the first 12 bytes
* in that case to maintain compatibility. */
if (!memcmp(&preamble[4], "frmaalac", 8)) {
if (size < ALAC_PREAMBLE + ALAC_HEADER) {
av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n");
av_freep(&st->codecpar->extradata);
return AVERROR_INVALIDDATA;
}
if (avio_read(pb, st->codecpar->extradata, ALAC_HEADER) != ALAC_HEADER) {
av_log(s, AV_LOG_ERROR, "failed to read kuki header\n");
av_freep(&st->codecpar->extradata);
return AVERROR_INVALIDDATA;
}
avio_skip(pb, size - ALAC_PREAMBLE - ALAC_HEADER);
} else {
AV_WB32(st->codecpar->extradata, 36);
memcpy(&st->codecpar->extradata[4], "alac", 4);
AV_WB32(&st->codecpar->extradata[8], 0);
memcpy(&st->codecpar->extradata[12], preamble, 12);
if (avio_read(pb, &st->codecpar->extradata[24], ALAC_NEW_KUKI - 12) != ALAC_NEW_KUKI - 12) {
av_log(s, AV_LOG_ERROR, "failed to read new kuki header\n");
av_freep(&st->codecpar->extradata);
return AVERROR_INVALIDDATA;
}
avio_skip(pb, size - ALAC_NEW_KUKI);
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
// The data layout for Opus is currently unknown, so we do not export
// extradata at all. Multichannel streams are not supported.
if (st->codecpar->channels > 2) {
avpriv_request_sample(s, "multichannel Opus in CAF");
return AVERROR_PATCHWELCOME;
}
avio_skip(pb, size);
} else if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) {
return ret;
}
return 0;
}
/** Read packet table chunk */
static int read_pakt_chunk(AVFormatContext *s, int64_t size)
{
AVIOContext *pb = s->pb;
AVStream *st = s->streams[0];
CafContext *caf = s->priv_data;
int64_t pos = 0, ccount, num_packets;
int i;
ccount = avio_tell(pb);
num_packets = avio_rb64(pb);
if (num_packets < 0 || INT32_MAX / sizeof(AVIndexEntry) < num_packets)
return AVERROR_INVALIDDATA;
st->nb_frames = avio_rb64(pb); /* valid frames */
st->nb_frames += avio_rb32(pb); /* priming frames */
st->nb_frames += avio_rb32(pb); /* remainder frames */
st->duration = 0;
for (i = 0; i < num_packets; i++) {
av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
}
if (avio_tell(pb) - ccount > size) {
av_log(s, AV_LOG_ERROR, "error reading packet table\n");
return AVERROR_INVALIDDATA;
}
avio_skip(pb, ccount + size - avio_tell(pb));
caf->num_bytes = pos;
return 0;
}
/** Read information chunk */
static void read_info_chunk(AVFormatContext *s, int64_t size)
{
AVIOContext *pb = s->pb;
unsigned int i;
unsigned int nb_entries = avio_rb32(pb);
for (i = 0; i < nb_entries && !avio_feof(pb); i++) {
char key[32];
char value[1024];
avio_get_str(pb, INT_MAX, key, sizeof(key));
avio_get_str(pb, INT_MAX, value, sizeof(value));
av_dict_set(&s->metadata, key, value, 0);
}
}
static int read_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
CafContext *caf = s->priv_data;
AVStream *st;
uint32_t tag = 0;
int found_data, ret;
int64_t size, pos;
avio_skip(pb, 8); /* magic, version, file flags */
/* audio description chunk */
if (avio_rb32(pb) != MKBETAG('d','e','s','c')) {
av_log(s, AV_LOG_ERROR, "desc chunk not present\n");
return AVERROR_INVALIDDATA;
}
size = avio_rb64(pb);
if (size != 32)
return AVERROR_INVALIDDATA;
ret = read_desc_chunk(s);
if (ret)
return ret;
st = s->streams[0];
/* parse each chunk */
found_data = 0;
while (!avio_feof(pb)) {
/* stop at data chunk if seeking is not supported or
data chunk size is unknown */
if (found_data && (caf->data_size < 0 || !(pb->seekable & AVIO_SEEKABLE_NORMAL)))
break;
tag = avio_rb32(pb);
size = avio_rb64(pb);
pos = avio_tell(pb);
if (avio_feof(pb))
break;
switch (tag) {
case MKBETAG('d','a','t','a'):
avio_skip(pb, 4); /* edit count */
caf->data_start = avio_tell(pb);
caf->data_size = size < 0 ? -1 : size - 4;
if (caf->data_size > 0 && (pb->seekable & AVIO_SEEKABLE_NORMAL))
avio_skip(pb, caf->data_size);
found_data = 1;
break;
case MKBETAG('c','h','a','n'):
if ((ret = ff_mov_read_chan(s, s->pb, st, size)) < 0)
return ret;
break;
/* magic cookie chunk */
case MKBETAG('k','u','k','i'):
if (read_kuki_chunk(s, size))
return AVERROR_INVALIDDATA;
break;
/* packet table chunk */
case MKBETAG('p','a','k','t'):
if (read_pakt_chunk(s, size))
return AVERROR_INVALIDDATA;
break;
case MKBETAG('i','n','f','o'):
read_info_chunk(s, size);
break;
default:
av_log(s, AV_LOG_WARNING,
"skipping CAF chunk: %08"PRIX32" (%s), size %"PRId64"\n",
tag, av_fourcc2str(av_bswap32(tag)), size);
case MKBETAG('f','r','e','e'):
if (size < 0 && found_data)
goto found_data;
if (size < 0)
return AVERROR_INVALIDDATA;
break;
}
if (size > 0) {
if (pos > INT64_MAX - size)
return AVERROR_INVALIDDATA;
avio_skip(pb, FFMAX(0, pos + size - avio_tell(pb)));
}
}
if (!found_data)
return AVERROR_INVALIDDATA;
found_data:
if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
if (caf->data_size > 0)
st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet;
} else if (st->nb_index_entries && st->duration > 0) {
if (st->codecpar->sample_rate && caf->data_size / st->duration > INT64_MAX / st->codecpar->sample_rate / 8) {
av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %d * 8 * %"PRId64"\n",
st->codecpar->sample_rate, caf->data_size / st->duration);
return AVERROR_INVALIDDATA;
}
st->codecpar->bit_rate = st->codecpar->sample_rate * 8LL *
(caf->data_size / st->duration);
} else {
av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when "
"block size or frame size are variable.\n");
return AVERROR_INVALIDDATA;
}
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->start_time = 0;
/* position the stream at the start of data */
if (caf->data_size >= 0)
avio_seek(pb, caf->data_start, SEEK_SET);
return 0;
}
#define CAF_MAX_PKT_SIZE 4096
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
AVStream *st = s->streams[0];
CafContext *caf = s->priv_data;
int res, pkt_size = 0, pkt_frames = 0;
int64_t left = CAF_MAX_PKT_SIZE;
if (avio_feof(pb))
return AVERROR_EOF;
/* don't read past end of data chunk */
if (caf->data_size > 0) {
left = (caf->data_start + caf->data_size) - avio_tell(pb);
if (!left)
return AVERROR_EOF;
if (left < 0)
return AVERROR(EIO);
}
pkt_frames = caf->frames_per_packet;
pkt_size = caf->bytes_per_packet;
if (pkt_size > 0 && pkt_frames == 1) {
pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size;
pkt_size = FFMIN(pkt_size, left);
pkt_frames = pkt_size / caf->bytes_per_packet;
} else if (st->nb_index_entries) {
if (caf->packet_cnt < st->nb_index_entries - 1) {
pkt_size = st->index_entries[caf->packet_cnt + 1].pos - st->index_entries[caf->packet_cnt].pos;
pkt_frames = st->index_entries[caf->packet_cnt + 1].timestamp - st->index_entries[caf->packet_cnt].timestamp;
} else if (caf->packet_cnt == st->nb_index_entries - 1) {
pkt_size = caf->num_bytes - st->index_entries[caf->packet_cnt].pos;
pkt_frames = st->duration - st->index_entries[caf->packet_cnt].timestamp;
} else {
return AVERROR(EIO);
}
}
if (pkt_size == 0 || pkt_frames == 0 || pkt_size > left)
return AVERROR(EIO);
res = av_get_packet(pb, pkt, pkt_size);
if (res < 0)
return res;
pkt->size = res;
pkt->stream_index = 0;
pkt->dts = pkt->pts = caf->frame_cnt;
caf->packet_cnt++;
caf->frame_cnt += pkt_frames;
return 0;
}
static int read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
AVStream *st = s->streams[0];
CafContext *caf = s->priv_data;
int64_t pos, packet_cnt, frame_cnt;
timestamp = FFMAX(timestamp, 0);
if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
/* calculate new byte position based on target frame position */
pos = caf->bytes_per_packet * (timestamp / caf->frames_per_packet);
if (caf->data_size > 0)
pos = FFMIN(pos, caf->data_size);
packet_cnt = pos / caf->bytes_per_packet;
frame_cnt = caf->frames_per_packet * packet_cnt;
} else if (st->nb_index_entries) {
packet_cnt = av_index_search_timestamp(st, timestamp, flags);
frame_cnt = st->index_entries[packet_cnt].timestamp;
pos = st->index_entries[packet_cnt].pos;
} else {
return -1;
}
if (avio_seek(s->pb, pos + caf->data_start, SEEK_SET) < 0)
return -1;
caf->packet_cnt = packet_cnt;
caf->frame_cnt = frame_cnt;
return 0;
}
AVInputFormat ff_caf_demuxer = {
.name = "caf",
.long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"),
.priv_data_size = sizeof(CafContext),
.read_probe = probe,
.read_header = read_header,
.read_packet = read_packet,
.read_seek = read_seek,
.codec_tag = (const AVCodecTag* const []){ ff_codec_caf_tags, 0 },
};

278
externals/ffmpeg/libavformat/cafenc.c vendored Executable file
View File

@@ -0,0 +1,278 @@
/*
* Core Audio Format muxer
* Copyright (c) 2011 Carl Eugen Hoyos
*
* 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 "caf.h"
#include "isom.h"
#include "avio_internal.h"
#include "libavutil/intfloat.h"
#include "libavutil/dict.h"
typedef struct {
int64_t data;
uint8_t *pkt_sizes;
int size_buffer_size;
int size_entries_used;
int packets;
} CAFContext;
static uint32_t codec_flags(enum AVCodecID codec_id) {
switch (codec_id) {
case AV_CODEC_ID_PCM_F32BE:
case AV_CODEC_ID_PCM_F64BE:
return 1; //< kCAFLinearPCMFormatFlagIsFloat
case AV_CODEC_ID_PCM_S16LE:
case AV_CODEC_ID_PCM_S24LE:
case AV_CODEC_ID_PCM_S32LE:
return 2; //< kCAFLinearPCMFormatFlagIsLittleEndian
case AV_CODEC_ID_PCM_F32LE:
case AV_CODEC_ID_PCM_F64LE:
return 3; //< kCAFLinearPCMFormatFlagIsFloat | kCAFLinearPCMFormatFlagIsLittleEndian
default:
return 0;
}
}
static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int block_align) {
switch (codec_id) {
case AV_CODEC_ID_PCM_S8:
case AV_CODEC_ID_PCM_S16LE:
case AV_CODEC_ID_PCM_S16BE:
case AV_CODEC_ID_PCM_S24LE:
case AV_CODEC_ID_PCM_S24BE:
case AV_CODEC_ID_PCM_S32LE:
case AV_CODEC_ID_PCM_S32BE:
case AV_CODEC_ID_PCM_F32LE:
case AV_CODEC_ID_PCM_F32BE:
case AV_CODEC_ID_PCM_F64LE:
case AV_CODEC_ID_PCM_F64BE:
case AV_CODEC_ID_PCM_ALAW:
case AV_CODEC_ID_PCM_MULAW:
return 1;
case AV_CODEC_ID_MACE3:
case AV_CODEC_ID_MACE6:
return 6;
case AV_CODEC_ID_ADPCM_IMA_QT:
return 64;
case AV_CODEC_ID_AMR_NB:
case AV_CODEC_ID_GSM:
case AV_CODEC_ID_ILBC:
case AV_CODEC_ID_QCELP:
return 160;
case AV_CODEC_ID_GSM_MS:
return 320;
case AV_CODEC_ID_MP1:
return 384;
case AV_CODEC_ID_OPUS:
return 960;
case AV_CODEC_ID_MP2:
case AV_CODEC_ID_MP3:
return 1152;
case AV_CODEC_ID_AC3:
return 1536;
case AV_CODEC_ID_QDM2:
case AV_CODEC_ID_QDMC:
return 2048 * channels;
case AV_CODEC_ID_ALAC:
return 4096;
case AV_CODEC_ID_ADPCM_IMA_WAV:
return (block_align - 4 * channels) * 8 / (4 * channels) + 1;
case AV_CODEC_ID_ADPCM_MS:
return (block_align - 7 * channels) * 2 / channels + 2;
default:
return 0;
}
}
static int caf_write_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AVCodecParameters *par = s->streams[0]->codecpar;
CAFContext *caf = s->priv_data;
AVDictionaryEntry *t = NULL;
unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id);
int64_t chunk_size = 0;
int frame_size = par->frame_size;
if (s->nb_streams != 1) {
av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n");
return AVERROR(EINVAL);
}
switch (par->codec_id) {
case AV_CODEC_ID_AAC:
av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n");
return AVERROR_PATCHWELCOME;
}
if (par->codec_id == AV_CODEC_ID_OPUS && par->channels > 2) {
av_log(s, AV_LOG_ERROR, "Only mono and stereo are supported for Opus\n");
return AVERROR_INVALIDDATA;
}
if (!codec_tag) {
av_log(s, AV_LOG_ERROR, "unsupported codec\n");
return AVERROR_INVALIDDATA;
}
if (!par->block_align && !(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n");
return AVERROR_INVALIDDATA;
}
if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576)
frame_size = samples_per_packet(par->codec_id, par->channels, par->block_align);
ffio_wfourcc(pb, "caff"); //< mFileType
avio_wb16(pb, 1); //< mFileVersion
avio_wb16(pb, 0); //< mFileFlags
ffio_wfourcc(pb, "desc"); //< Audio Description chunk
avio_wb64(pb, 32); //< mChunkSize
avio_wb64(pb, av_double2int(par->sample_rate)); //< mSampleRate
avio_wl32(pb, codec_tag); //< mFormatID
avio_wb32(pb, codec_flags(par->codec_id)); //< mFormatFlags
avio_wb32(pb, par->block_align); //< mBytesPerPacket
avio_wb32(pb, frame_size); //< mFramesPerPacket
avio_wb32(pb, par->channels); //< mChannelsPerFrame
avio_wb32(pb, av_get_bits_per_sample(par->codec_id)); //< mBitsPerChannel
if (par->channel_layout) {
ffio_wfourcc(pb, "chan");
avio_wb64(pb, 12);
ff_mov_write_chan(pb, par->channel_layout);
}
if (par->codec_id == AV_CODEC_ID_ALAC) {
ffio_wfourcc(pb, "kuki");
avio_wb64(pb, 12 + par->extradata_size);
avio_write(pb, "\0\0\0\14frmaalac", 12);
avio_write(pb, par->extradata, par->extradata_size);
} else if (par->codec_id == AV_CODEC_ID_AMR_NB) {
ffio_wfourcc(pb, "kuki");
avio_wb64(pb, 29);
avio_write(pb, "\0\0\0\14frmasamr", 12);
avio_wb32(pb, 0x11); /* size */
avio_write(pb, "samrFFMP", 8);
avio_w8(pb, 0); /* decoder version */
avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
avio_w8(pb, 0x00); /* Mode change period (no restriction) */
avio_w8(pb, 0x01); /* Frames per sample */
} else if (par->codec_id == AV_CODEC_ID_QDM2 || par->codec_id == AV_CODEC_ID_QDMC) {
ffio_wfourcc(pb, "kuki");
avio_wb64(pb, par->extradata_size);
avio_write(pb, par->extradata, par->extradata_size);
}
ff_standardize_creation_time(s);
if (av_dict_count(s->metadata)) {
ffio_wfourcc(pb, "info"); //< Information chunk
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
chunk_size += strlen(t->key) + strlen(t->value) + 2;
}
avio_wb64(pb, chunk_size + 4);
avio_wb32(pb, av_dict_count(s->metadata));
t = NULL;
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
avio_put_str(pb, t->key);
avio_put_str(pb, t->value);
}
}
ffio_wfourcc(pb, "data"); //< Audio Data chunk
caf->data = avio_tell(pb);
avio_wb64(pb, -1); //< mChunkSize
avio_wb32(pb, 0); //< mEditCount
return 0;
}
static int caf_write_packet(AVFormatContext *s, AVPacket *pkt)
{
CAFContext *caf = s->priv_data;
avio_write(s->pb, pkt->data, pkt->size);
if (!s->streams[0]->codecpar->block_align) {
void *pkt_sizes = caf->pkt_sizes;
int i, alloc_size = caf->size_entries_used + 5;
if (alloc_size < 0) {
caf->pkt_sizes = NULL;
} else {
caf->pkt_sizes = av_fast_realloc(caf->pkt_sizes,
&caf->size_buffer_size,
alloc_size);
}
if (!caf->pkt_sizes) {
av_free(pkt_sizes);
return AVERROR(ENOMEM);
}
for (i = 4; i > 0; i--) {
unsigned top = pkt->size >> i * 7;
if (top)
caf->pkt_sizes[caf->size_entries_used++] = 128 | top;
}
caf->pkt_sizes[caf->size_entries_used++] = pkt->size & 127;
caf->packets++;
}
return 0;
}
static int caf_write_trailer(AVFormatContext *s)
{
CAFContext *caf = s->priv_data;
AVIOContext *pb = s->pb;
AVCodecParameters *par = s->streams[0]->codecpar;
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
int64_t file_size = avio_tell(pb);
avio_seek(pb, caf->data, SEEK_SET);
avio_wb64(pb, file_size - caf->data - 8);
avio_seek(pb, file_size, SEEK_SET);
if (!par->block_align) {
ffio_wfourcc(pb, "pakt");
avio_wb64(pb, caf->size_entries_used + 24);
avio_wb64(pb, caf->packets); ///< mNumberPackets
avio_wb64(pb, caf->packets * samples_per_packet(par->codec_id, par->channels, par->block_align)); ///< mNumberValidFrames
avio_wb32(pb, 0); ///< mPrimingFrames
avio_wb32(pb, 0); ///< mRemainderFrames
avio_write(pb, caf->pkt_sizes, caf->size_entries_used);
caf->size_buffer_size = 0;
}
}
av_freep(&caf->pkt_sizes);
return 0;
}
AVOutputFormat ff_caf_muxer = {
.name = "caf",
.long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"),
.mime_type = "audio/x-caf",
.extensions = "caf",
.priv_data_size = sizeof(CAFContext),
.audio_codec = AV_CODEC_ID_PCM_S16BE,
.video_codec = AV_CODEC_ID_NONE,
.write_header = caf_write_header,
.write_packet = caf_write_packet,
.write_trailer = caf_write_trailer,
.codec_tag = (const AVCodecTag* const []){ff_codec_caf_tags, 0},
};

69
externals/ffmpeg/libavformat/cavsvideodec.c vendored Executable file
View File

@@ -0,0 +1,69 @@
/*
* RAW Chinese AVS video demuxer
* Copyright (c) 2009 Stefan Gehrer <stefan.gehrer@gmx.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
*/
#include "avformat.h"
#include "rawdec.h"
#include "libavcodec/internal.h"
#define CAVS_SEQ_START_CODE 0x000001b0
#define CAVS_PIC_I_START_CODE 0x000001b3
#define CAVS_UNDEF_START_CODE 0x000001b4
#define CAVS_PIC_PB_START_CODE 0x000001b6
#define CAVS_VIDEO_EDIT_CODE 0x000001b7
#define CAVS_PROFILE_JIZHUN 0x20
static int cavsvideo_probe(const AVProbeData *p)
{
uint32_t code= -1;
int pic=0, seq=0, slice_pos = 0;
const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size;
while (ptr < end) {
ptr = avpriv_find_start_code(ptr, end, &code);
if ((code & 0xffffff00) == 0x100) {
if(code < CAVS_SEQ_START_CODE) {
/* slices have to be consecutive */
if(code < slice_pos)
return 0;
slice_pos = code;
} else {
slice_pos = 0;
}
if (code == CAVS_SEQ_START_CODE) {
seq++;
/* check for the only currently supported profile */
if (*ptr != CAVS_PROFILE_JIZHUN)
return 0;
} else if ((code == CAVS_PIC_I_START_CODE) ||
(code == CAVS_PIC_PB_START_CODE)) {
pic++;
} else if ((code == CAVS_UNDEF_START_CODE) ||
(code > CAVS_VIDEO_EDIT_CODE)) {
return 0;
}
}
}
if(seq && seq*9<=pic*10)
return AVPROBE_SCORE_EXTENSION+1;
return 0;
}
FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS)

92
externals/ffmpeg/libavformat/cdg.c vendored Executable file
View File

@@ -0,0 +1,92 @@
/*
* CD Graphics Demuxer
* Copyright (c) 2009 Michael Tison
*
* 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 "internal.h"
#define CDG_PACKET_SIZE 24
#define CDG_COMMAND 0x09
#define CDG_MASK 0x3F
typedef struct CDGContext {
int got_first_packet;
} CDGContext;
static int read_header(AVFormatContext *s)
{
AVStream *vst;
int ret;
vst = avformat_new_stream(s, NULL);
if (!vst)
return AVERROR(ENOMEM);
vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
vst->codecpar->codec_id = AV_CODEC_ID_CDGRAPHICS;
/// 75 sectors/sec * 4 packets/sector = 300 packets/sec
avpriv_set_pts_info(vst, 32, 1, 300);
ret = avio_size(s->pb);
if (ret < 0) {
av_log(s, AV_LOG_WARNING, "Cannot calculate duration as file size cannot be determined\n");
} else
vst->duration = (ret * vst->time_base.den) / (CDG_PACKET_SIZE * 300);
return 0;
}
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
CDGContext *priv = s->priv_data;
int ret;
while (1) {
ret = av_get_packet(s->pb, pkt, CDG_PACKET_SIZE);
if (ret < 1 || (pkt->data[0] & CDG_MASK) == CDG_COMMAND)
break;
av_packet_unref(pkt);
}
if (!priv->got_first_packet) {
pkt->flags |= AV_PKT_FLAG_KEY;
priv->got_first_packet = 1;
}
pkt->stream_index = 0;
pkt->dts=
pkt->pts= pkt->pos / CDG_PACKET_SIZE;
if(ret>5 && (pkt->data[0]&0x3F) == 9 && (pkt->data[1]&0x3F)==1 && !(pkt->data[2+2+1] & 0x0F)){
pkt->flags = AV_PKT_FLAG_KEY;
}
return ret;
}
AVInputFormat ff_cdg_demuxer = {
.name = "cdg",
.long_name = NULL_IF_CONFIG_SMALL("CD Graphics"),
.priv_data_size = sizeof(CDGContext),
.read_header = read_header,
.read_packet = read_packet,
.flags = AVFMT_GENERIC_INDEX,
.extensions = "cdg",
};

249
externals/ffmpeg/libavformat/cdxl.c vendored Executable file
View File

@@ -0,0 +1,249 @@
/*
* CDXL demuxer
* Copyright (c) 2011-2012 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/parseutils.h"
#include "libavutil/opt.h"
#include "avformat.h"
#include "internal.h"
#define CDXL_HEADER_SIZE 32
typedef struct CDXLDemuxContext {
AVClass *class;
int sample_rate;
char *framerate;
AVRational fps;
int read_chunk;
uint8_t header[CDXL_HEADER_SIZE];
int video_stream_index;
int audio_stream_index;
int64_t filesize;
} CDXLDemuxContext;
static int cdxl_read_probe(const AVProbeData *p)
{
int score = AVPROBE_SCORE_EXTENSION + 10;
if (p->buf_size < CDXL_HEADER_SIZE)
return 0;
/* reserved bytes should always be set to 0 */
if (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10]))
return 0;
/* check type */
if (p->buf[0] != 1)
return 0;
/* check palette size */
if (AV_RB16(&p->buf[20]) > 512)
return 0;
/* check number of planes */
if (p->buf[18] || !p->buf[19])
return 0;
/* check widh and height */
if (!AV_RN16(&p->buf[14]) || !AV_RN16(&p->buf[16]))
return 0;
/* chunk size */
if (AV_RB32(&p->buf[2]) < AV_RB16(&p->buf[22]) + AV_RB16(&p->buf[20]) + CDXL_HEADER_SIZE)
return 0;
/* previous chunk size */
if (AV_RN32(&p->buf[6]))
score /= 2;
/* current frame number, usually starts from 1 */
if (AV_RB16(&p->buf[12]) != 1)
score /= 2;
return score;
}
static int cdxl_read_header(AVFormatContext *s)
{
CDXLDemuxContext *cdxl = s->priv_data;
int ret;
if (cdxl->framerate && (ret = av_parse_video_rate(&cdxl->fps, cdxl->framerate)) < 0) {
av_log(s, AV_LOG_ERROR,
"Could not parse framerate: %s.\n", cdxl->framerate);
return ret;
}
cdxl->read_chunk = 0;
cdxl->video_stream_index = -1;
cdxl->audio_stream_index = -1;
cdxl->filesize = avio_size(s->pb);
s->ctx_flags |= AVFMTCTX_NOHEADER;
return 0;
}
static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
{
CDXLDemuxContext *cdxl = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t current_size, video_size, image_size;
uint16_t audio_size, palette_size, width, height;
int64_t pos;
int format, frames, ret;
if (avio_feof(pb))
return AVERROR_EOF;
pos = avio_tell(pb);
if (!cdxl->read_chunk &&
avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE)
return AVERROR_EOF;
if (cdxl->header[0] != 1) {
av_log(s, AV_LOG_ERROR, "non-standard cdxl file\n");
return AVERROR_INVALIDDATA;
}
format = cdxl->header[1] & 0xE0;
current_size = AV_RB32(&cdxl->header[2]);
width = AV_RB16(&cdxl->header[14]);
height = AV_RB16(&cdxl->header[16]);
palette_size = AV_RB16(&cdxl->header[20]);
audio_size = AV_RB16(&cdxl->header[22]);
if (cdxl->header[19] == 0 ||
FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
return AVERROR_INVALIDDATA;
if (format == 0x20)
image_size = width * height * cdxl->header[19] / 8;
else
image_size = FFALIGN(width, 16) * height * cdxl->header[19] / 8;
video_size = palette_size + image_size;
if (palette_size > 512)
return AVERROR_INVALIDDATA;
if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE)
return AVERROR_INVALIDDATA;
if (cdxl->read_chunk && audio_size) {
if (cdxl->audio_stream_index == -1) {
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
if (cdxl->header[1] & 0x10) {
st->codecpar->channels = 2;
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
} else {
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
}
st->codecpar->sample_rate = cdxl->sample_rate;
st->start_time = 0;
cdxl->audio_stream_index = st->index;
avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate);
}
ret = av_get_packet(pb, pkt, audio_size);
if (ret < 0)
return ret;
pkt->stream_index = cdxl->audio_stream_index;
pkt->pos = pos;
pkt->duration = audio_size;
cdxl->read_chunk = 0;
} else {
if (cdxl->video_stream_index == -1) {
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_tag = 0;
st->codecpar->codec_id = AV_CODEC_ID_CDXL;
st->codecpar->width = width;
st->codecpar->height = height;
if (audio_size + video_size && cdxl->filesize > 0) {
frames = cdxl->filesize / (audio_size + video_size);
if(cdxl->framerate)
st->duration = frames;
else
st->duration = frames * (int64_t)audio_size;
}
st->start_time = 0;
cdxl->video_stream_index = st->index;
if (cdxl->framerate)
avpriv_set_pts_info(st, 64, cdxl->fps.den, cdxl->fps.num);
else
avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate);
}
if ((ret = av_new_packet(pkt, video_size + CDXL_HEADER_SIZE)) < 0)
return ret;
memcpy(pkt->data, cdxl->header, CDXL_HEADER_SIZE);
ret = avio_read(pb, pkt->data + CDXL_HEADER_SIZE, video_size);
if (ret < 0) {
return ret;
}
av_shrink_packet(pkt, CDXL_HEADER_SIZE + ret);
pkt->stream_index = cdxl->video_stream_index;
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pos = pos;
pkt->duration = cdxl->framerate ? 1 : audio_size ? audio_size : 220;
cdxl->read_chunk = audio_size;
}
if (!cdxl->read_chunk)
avio_skip(pb, current_size - audio_size - video_size - CDXL_HEADER_SIZE);
return ret;
}
#define OFFSET(x) offsetof(CDXLDemuxContext, x)
static const AVOption cdxl_options[] = {
{ "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 11025 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
static const AVClass cdxl_demuxer_class = {
.class_name = "CDXL demuxer",
.item_name = av_default_item_name,
.option = cdxl_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_cdxl_demuxer = {
.name = "cdxl",
.long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"),
.priv_data_size = sizeof(CDXLDemuxContext),
.read_probe = cdxl_read_probe,
.read_header = cdxl_read_header,
.read_packet = cdxl_read_packet,
.extensions = "cdxl,xl",
.flags = AVFMT_GENERIC_INDEX,
.priv_class = &cdxl_demuxer_class,
};

192
externals/ffmpeg/libavformat/chromaprint.c vendored Executable file
View File

@@ -0,0 +1,192 @@
/*
* Chromaprint fingerprinting muxer
* Copyright (c) 2015 Rodger Combs
*
* 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 "internal.h"
#include "libavutil/opt.h"
#include "libavcodec/internal.h"
#include <chromaprint.h>
#define CPR_VERSION_INT AV_VERSION_INT(CHROMAPRINT_VERSION_MAJOR, \
CHROMAPRINT_VERSION_MINOR, \
CHROMAPRINT_VERSION_PATCH)
typedef enum FingerprintFormat {
FINGERPRINT_RAW,
FINGERPRINT_COMPRESSED,
FINGERPRINT_BASE64,
} FingerprintFormat;
typedef struct ChromaprintMuxContext {
const AVClass *class;
int silence_threshold;
int algorithm;
FingerprintFormat fp_format;
#if CPR_VERSION_INT >= AV_VERSION_INT(1, 4, 0)
ChromaprintContext *ctx;
#else
ChromaprintContext ctx;
#endif
} ChromaprintMuxContext;
static void cleanup(ChromaprintMuxContext *cpr)
{
if (cpr->ctx) {
ff_lock_avformat();
chromaprint_free(cpr->ctx);
ff_unlock_avformat();
}
}
static int write_header(AVFormatContext *s)
{
ChromaprintMuxContext *cpr = s->priv_data;
AVStream *st;
ff_lock_avformat();
cpr->ctx = chromaprint_new(cpr->algorithm);
ff_unlock_avformat();
if (!cpr->ctx) {
av_log(s, AV_LOG_ERROR, "Failed to create chromaprint context.\n");
return AVERROR(ENOMEM);
}
if (cpr->silence_threshold != -1) {
#if CPR_VERSION_INT >= AV_VERSION_INT(0, 7, 0)
if (!chromaprint_set_option(cpr->ctx, "silence_threshold", cpr->silence_threshold)) {
av_log(s, AV_LOG_ERROR, "Failed to set silence threshold. Setting silence_threshold requires -algorithm 3 option.\n");
goto fail;
}
#else
av_log(s, AV_LOG_ERROR, "Setting the silence threshold requires Chromaprint "
"version 0.7.0 or later.\n");
goto fail;
#endif
}
if (s->nb_streams != 1) {
av_log(s, AV_LOG_ERROR, "Only one stream is supported\n");
goto fail;
}
st = s->streams[0];
if (st->codecpar->channels > 2) {
av_log(s, AV_LOG_ERROR, "Only up to 2 channels are supported\n");
goto fail;
}
if (st->codecpar->sample_rate < 1000) {
av_log(s, AV_LOG_ERROR, "Sampling rate must be at least 1000\n");
goto fail;
}
if (!chromaprint_start(cpr->ctx, st->codecpar->sample_rate, st->codecpar->channels)) {
av_log(s, AV_LOG_ERROR, "Failed to start chromaprint\n");
goto fail;
}
return 0;
fail:
cleanup(cpr);
return AVERROR(EINVAL);
}
static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
ChromaprintMuxContext *cpr = s->priv_data;
return chromaprint_feed(cpr->ctx, (const int16_t *)pkt->data, pkt->size / 2) ? 0 : AVERROR(EINVAL);
}
static int write_trailer(AVFormatContext *s)
{
ChromaprintMuxContext *cpr = s->priv_data;
AVIOContext *pb = s->pb;
void *fp = NULL;
char *enc_fp = NULL;
int size, enc_size, ret = AVERROR(EINVAL);
if (!chromaprint_finish(cpr->ctx)) {
av_log(s, AV_LOG_ERROR, "Failed to generate fingerprint\n");
goto fail;
}
if (!chromaprint_get_raw_fingerprint(cpr->ctx, (uint32_t **)&fp, &size)) {
av_log(s, AV_LOG_ERROR, "Failed to retrieve fingerprint\n");
goto fail;
}
switch (cpr->fp_format) {
case FINGERPRINT_RAW:
avio_write(pb, fp, size * 4); //fp points to array of uint32_t
break;
case FINGERPRINT_COMPRESSED:
case FINGERPRINT_BASE64:
if (!chromaprint_encode_fingerprint(fp, size, cpr->algorithm, &enc_fp, &enc_size,
cpr->fp_format == FINGERPRINT_BASE64)) {
av_log(s, AV_LOG_ERROR, "Failed to encode fingerprint\n");
goto fail;
}
avio_write(pb, enc_fp, enc_size);
break;
}
ret = 0;
fail:
if (fp)
chromaprint_dealloc(fp);
if (enc_fp)
chromaprint_dealloc(enc_fp);
cleanup(cpr);
return ret;
}
#define OFFSET(x) offsetof(ChromaprintMuxContext, x)
#define FLAGS AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "silence_threshold", "threshold for detecting silence", OFFSET(silence_threshold), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 32767, FLAGS },
{ "algorithm", "version of the fingerprint algorithm", OFFSET(algorithm), AV_OPT_TYPE_INT, { .i64 = CHROMAPRINT_ALGORITHM_DEFAULT }, CHROMAPRINT_ALGORITHM_TEST1, INT_MAX, FLAGS },
{ "fp_format", "fingerprint format to write", OFFSET(fp_format), AV_OPT_TYPE_INT, { .i64 = FINGERPRINT_BASE64 }, FINGERPRINT_RAW, FINGERPRINT_BASE64, FLAGS, "fp_format" },
{ "raw", "binary raw fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_RAW }, INT_MIN, INT_MAX, FLAGS, "fp_format"},
{ "compressed", "binary compressed fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_COMPRESSED }, INT_MIN, INT_MAX, FLAGS, "fp_format"},
{ "base64", "Base64 compressed fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_BASE64 }, INT_MIN, INT_MAX, FLAGS, "fp_format"},
{ NULL },
};
static const AVClass chromaprint_class = {
.class_name = "chromaprint muxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVOutputFormat ff_chromaprint_muxer = {
.name = "chromaprint",
.long_name = NULL_IF_CONFIG_SMALL("Chromaprint"),
.priv_data_size = sizeof(ChromaprintMuxContext),
.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE),
.write_header = write_header,
.write_packet = write_packet,
.write_trailer = write_trailer,
.flags = AVFMT_NOTIMESTAMPS,
.priv_class = &chromaprint_class,
};

333
externals/ffmpeg/libavformat/cinedec.c vendored Executable file
View File

@@ -0,0 +1,333 @@
/*
* Phantom Cine demuxer
* Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Phantom Cine demuxer
* @author Peter Ross <pross@xvid.org>
*/
#include "libavutil/intreadwrite.h"
#include "libavcodec/bmp.h"
#include "libavutil/intfloat.h"
#include "avformat.h"
#include "internal.h"
typedef struct {
uint64_t pts;
} CineDemuxContext;
/** Compression */
enum {
CC_RGB = 0, /**< Gray */
CC_LEAD = 1, /**< LEAD (M)JPEG */
CC_UNINT = 2 /**< Uninterpolated color image (CFA field indicates color ordering) */
};
/** Color Filter Array */
enum {
CFA_NONE = 0, /**< GRAY */
CFA_VRI = 1, /**< GBRG/RGGB */
CFA_VRIV6 = 2, /**< BGGR/GRBG */
CFA_BAYER = 3, /**< GB/RG */
CFA_BAYERFLIP = 4, /**< RG/GB */
};
#define CFA_TLGRAY 0x80000000U
#define CFA_TRGRAY 0x40000000U
#define CFA_BLGRAY 0x20000000U
#define CFA_BRGRAY 0x10000000U
static int cine_read_probe(const AVProbeData *p)
{
int HeaderSize;
if (p->buf[0] == 'C' && p->buf[1] == 'I' && // Type
(HeaderSize = AV_RL16(p->buf + 2)) >= 0x2C && // HeaderSize
AV_RL16(p->buf + 4) <= CC_UNINT && // Compression
AV_RL16(p->buf + 6) <= 1 && // Version
AV_RL32(p->buf + 20) && // ImageCount
AV_RL32(p->buf + 24) >= HeaderSize && // OffImageHeader
AV_RL32(p->buf + 28) >= HeaderSize && // OffSetup
AV_RL32(p->buf + 32) >= HeaderSize) // OffImageOffsets
return AVPROBE_SCORE_MAX;
return 0;
}
static int set_metadata_int(AVDictionary **dict, const char *key, int value, int allow_zero)
{
if (value || allow_zero) {
return av_dict_set_int(dict, key, value, 0);
}
return 0;
}
static int set_metadata_float(AVDictionary **dict, const char *key, float value, int allow_zero)
{
if (value != 0 || allow_zero) {
char tmp[64];
snprintf(tmp, sizeof(tmp), "%f", value);
return av_dict_set(dict, key, tmp, 0);
}
return 0;
}
static int cine_read_header(AVFormatContext *avctx)
{
AVIOContext *pb = avctx->pb;
AVStream *st;
unsigned int version, compression, offImageHeader, offSetup, offImageOffsets, biBitCount, length, CFA;
int vflip;
char *description;
uint64_t i;
st = avformat_new_stream(avctx, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
st->codecpar->codec_tag = 0;
/* CINEFILEHEADER structure */
avio_skip(pb, 4); // Type, Headersize
compression = avio_rl16(pb);
version = avio_rl16(pb);
if (version != 1) {
avpriv_request_sample(avctx, "unknown version %i", version);
return AVERROR_INVALIDDATA;
}
avio_skip(pb, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber
st->duration = avio_rl32(pb);
offImageHeader = avio_rl32(pb);
offSetup = avio_rl32(pb);
offImageOffsets = avio_rl32(pb);
avio_skip(pb, 8); // TriggerTime
/* BITMAPINFOHEADER structure */
avio_seek(pb, offImageHeader, SEEK_SET);
avio_skip(pb, 4); //biSize
st->codecpar->width = avio_rl32(pb);
st->codecpar->height = avio_rl32(pb);
if (avio_rl16(pb) != 1) // biPlanes
return AVERROR_INVALIDDATA;
biBitCount = avio_rl16(pb);
if (biBitCount != 8 && biBitCount != 16 && biBitCount != 24 && biBitCount != 48) {
avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
return AVERROR_INVALIDDATA;
}
switch (avio_rl32(pb)) {
case BMP_RGB:
vflip = 0;
break;
case 0x100: /* BI_PACKED */
st->codecpar->codec_tag = MKTAG('B', 'I', 'T', 0);
vflip = 1;
break;
default:
avpriv_request_sample(avctx, "unknown bitmap compression");
return AVERROR_INVALIDDATA;
}
avio_skip(pb, 4); // biSizeImage
/* parse SETUP structure */
avio_seek(pb, offSetup, SEEK_SET);
avio_skip(pb, 140); // FrameRatae16 .. descriptionOld
if (avio_rl16(pb) != 0x5453)
return AVERROR_INVALIDDATA;
length = avio_rl16(pb);
if (length < 0x163C) {
avpriv_request_sample(avctx, "short SETUP header");
return AVERROR_INVALIDDATA;
}
avio_skip(pb, 616); // Binning .. bFlipH
if (!avio_rl32(pb) ^ vflip) {
st->codecpar->extradata = av_strdup("BottomUp");
if (!st->codecpar->extradata) {
st->codecpar->extradata_size = 0;
return AVERROR(ENOMEM);
}
st->codecpar->extradata_size = 9;
}
avio_skip(pb, 4); // Grid
avpriv_set_pts_info(st, 64, 1, avio_rl32(pb));
avio_skip(pb, 20); // Shutter .. bEnableColor
set_metadata_int(&st->metadata, "camera_version", avio_rl32(pb), 0);
set_metadata_int(&st->metadata, "firmware_version", avio_rl32(pb), 0);
set_metadata_int(&st->metadata, "software_version", avio_rl32(pb), 0);
set_metadata_int(&st->metadata, "recording_timezone", avio_rl32(pb), 0);
CFA = avio_rl32(pb);
set_metadata_int(&st->metadata, "brightness", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "contrast", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "gamma", avio_rl32(pb), 1);
avio_skip(pb, 12 + 16); // Reserved1 .. AutoExpRect
set_metadata_float(&st->metadata, "wbgain[0].r", av_int2float(avio_rl32(pb)), 1);
set_metadata_float(&st->metadata, "wbgain[0].b", av_int2float(avio_rl32(pb)), 1);
avio_skip(pb, 36); // WBGain[1].. WBView
st->codecpar->bits_per_coded_sample = avio_rl32(pb);
if (compression == CC_RGB) {
if (biBitCount == 8) {
st->codecpar->format = AV_PIX_FMT_GRAY8;
} else if (biBitCount == 16) {
st->codecpar->format = AV_PIX_FMT_GRAY16LE;
} else if (biBitCount == 24) {
st->codecpar->format = AV_PIX_FMT_BGR24;
} else if (biBitCount == 48) {
st->codecpar->format = AV_PIX_FMT_BGR48LE;
} else {
avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
return AVERROR_INVALIDDATA;
}
} else if (compression == CC_UNINT) {
switch (CFA & 0xFFFFFF) {
case CFA_BAYER:
if (biBitCount == 8) {
st->codecpar->format = AV_PIX_FMT_BAYER_GBRG8;
} else if (biBitCount == 16) {
st->codecpar->format = AV_PIX_FMT_BAYER_GBRG16LE;
} else {
avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
return AVERROR_INVALIDDATA;
}
break;
case CFA_BAYERFLIP:
if (biBitCount == 8) {
st->codecpar->format = AV_PIX_FMT_BAYER_RGGB8;
} else if (biBitCount == 16) {
st->codecpar->format = AV_PIX_FMT_BAYER_RGGB16LE;
} else {
avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
return AVERROR_INVALIDDATA;
}
break;
default:
avpriv_request_sample(avctx, "unsupported Color Field Array (CFA) %i", CFA & 0xFFFFFF);
return AVERROR_INVALIDDATA;
}
} else { //CC_LEAD
avpriv_request_sample(avctx, "unsupported compression %i", compression);
return AVERROR_INVALIDDATA;
}
avio_skip(pb, 668); // Conv8Min ... Sensor
set_metadata_int(&st->metadata, "shutter_ns", avio_rl32(pb), 0);
avio_skip(pb, 24); // EDRShutterNs ... ImHeightAcq
#define DESCRIPTION_SIZE 4096
description = av_malloc(DESCRIPTION_SIZE + 1);
if (!description)
return AVERROR(ENOMEM);
i = avio_get_str(pb, DESCRIPTION_SIZE, description, DESCRIPTION_SIZE + 1);
if (i < DESCRIPTION_SIZE)
avio_skip(pb, DESCRIPTION_SIZE - i);
if (description[0])
av_dict_set(&st->metadata, "description", description, AV_DICT_DONT_STRDUP_VAL);
else
av_free(description);
avio_skip(pb, 1176); // RisingEdge ... cmUser
set_metadata_int(&st->metadata, "enable_crop", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "crop_left", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "crop_top", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "crop_right", avio_rl32(pb), 1);
set_metadata_int(&st->metadata, "crop_bottom", avio_rl32(pb), 1);
/* parse image offsets */
avio_seek(pb, offImageOffsets, SEEK_SET);
for (i = 0; i < st->duration; i++) {
if (avio_feof(pb))
return AVERROR_INVALIDDATA;
av_add_index_entry(st, avio_rl64(pb), i, 0, 0, AVINDEX_KEYFRAME);
}
return 0;
}
static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt)
{
CineDemuxContext *cine = avctx->priv_data;
AVStream *st = avctx->streams[0];
AVIOContext *pb = avctx->pb;
int n, size, ret;
if (cine->pts >= st->duration)
return AVERROR_EOF;
avio_seek(pb, st->index_entries[cine->pts].pos, SEEK_SET);
n = avio_rl32(pb);
if (n < 8)
return AVERROR_INVALIDDATA;
avio_skip(pb, n - 8);
size = avio_rl32(pb);
ret = av_get_packet(pb, pkt, size);
if (ret < 0)
return ret;
pkt->pts = cine->pts++;
pkt->stream_index = 0;
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
}
static int cine_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
{
CineDemuxContext *cine = avctx->priv_data;
if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
return AVERROR(ENOSYS);
if (!(avctx->pb->seekable & AVIO_SEEKABLE_NORMAL))
return AVERROR(EIO);
cine->pts = timestamp;
return 0;
}
AVInputFormat ff_cine_demuxer = {
.name = "cine",
.long_name = NULL_IF_CONFIG_SMALL("Phantom Cine"),
.priv_data_size = sizeof(CineDemuxContext),
.read_probe = cine_read_probe,
.read_header = cine_read_header,
.read_packet = cine_read_packet,
.read_seek = cine_read_seek,
};

285
externals/ffmpeg/libavformat/codec2.c vendored Executable file
View File

@@ -0,0 +1,285 @@
/*
* codec2 muxer and demuxers
* Copyright (c) 2017 Tomas Härdin
*
* 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 <memory.h>
#include "libavcodec/codec2utils.h"
#include "libavutil/intreadwrite.h"
#include "avio_internal.h"
#include "avformat.h"
#include "internal.h"
#include "rawdec.h"
#include "rawenc.h"
#include "pcm.h"
#define AVPRIV_CODEC2_HEADER_SIZE 7
#define AVPRIV_CODEC2_MAGIC 0xC0DEC2
//the lowest version we should ever run across is 0.8
//we may run across later versions as the format evolves
#define EXPECTED_CODEC2_MAJOR_VERSION 0
#define EXPECTED_CODEC2_MINOR_VERSION 8
typedef struct {
const AVClass *class;
int mode;
int frames_per_packet;
} Codec2Context;
static int codec2_probe(const AVProbeData *p)
{
//must start wih C0 DE C2
if (AV_RB24(p->buf) != AVPRIV_CODEC2_MAGIC) {
return 0;
}
//no .c2 files prior to 0.8
//be strict about major version while we're at it
if (p->buf[3] != EXPECTED_CODEC2_MAJOR_VERSION ||
p->buf[4] < EXPECTED_CODEC2_MINOR_VERSION) {
return 0;
}
//32 bits of identification -> low score
return AVPROBE_SCORE_EXTENSION + 1;
}
static int codec2_read_header_common(AVFormatContext *s, AVStream *st)
{
int mode = avpriv_codec2_mode_from_extradata(st->codecpar->extradata);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_CODEC2;
st->codecpar->sample_rate = 8000;
st->codecpar->channels = 1;
st->codecpar->format = AV_SAMPLE_FMT_S16;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
st->codecpar->bit_rate = avpriv_codec2_mode_bit_rate(s, mode);
st->codecpar->frame_size = avpriv_codec2_mode_frame_size(s, mode);
st->codecpar->block_align = avpriv_codec2_mode_block_align(s, mode);
if (st->codecpar->bit_rate <= 0 ||
st->codecpar->frame_size <= 0 ||
st->codecpar->block_align <= 0) {
return AVERROR_INVALIDDATA;
}
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
}
static int codec2_read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
int ret, version;
if (!st) {
return AVERROR(ENOMEM);
}
if (avio_rb24(s->pb) != AVPRIV_CODEC2_MAGIC) {
av_log(s, AV_LOG_ERROR, "not a .c2 file\n");
return AVERROR_INVALIDDATA;
}
ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE);
if (ret) {
return ret;
}
ret = ffio_read_size(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE);
if (ret < 0) {
return ret;
}
version = avpriv_codec2_version_from_extradata(st->codecpar->extradata);
if ((version >> 8) != EXPECTED_CODEC2_MAJOR_VERSION) {
avpriv_report_missing_feature(s, "Major version %i", version >> 8);
return AVERROR_PATCHWELCOME;
}
s->internal->data_offset = AVPRIV_CODEC2_HEADER_SIZE;
return codec2_read_header_common(s, st);
}
static int codec2_read_packet(AVFormatContext *s, AVPacket *pkt)
{
Codec2Context *c2 = s->priv_data;
AVStream *st = s->streams[0];
int ret, size, n, block_align, frame_size;
block_align = st->codecpar->block_align;
frame_size = st->codecpar->frame_size;
if (block_align <= 0 || frame_size <= 0 || c2->frames_per_packet <= 0) {
return AVERROR(EINVAL);
}
//try to read desired number of frames, compute n from to actual number of bytes read
size = c2->frames_per_packet * block_align;
ret = av_get_packet(s->pb, pkt, size);
if (ret < 0) {
return ret;
}
//only set duration - compute_pkt_fields() and ff_pcm_read_seek() takes care of everything else
//tested by spamming the seek functionality in ffplay
n = ret / block_align;
pkt->duration = n * frame_size;
return ret;
}
static int codec2_write_header(AVFormatContext *s)
{
AVStream *st;
if (s->nb_streams != 1 || s->streams[0]->codecpar->codec_id != AV_CODEC_ID_CODEC2) {
av_log(s, AV_LOG_ERROR, ".c2 files must have exactly one codec2 stream\n");
return AVERROR(EINVAL);
}
st = s->streams[0];
if (st->codecpar->extradata_size != AVPRIV_CODEC2_EXTRADATA_SIZE) {
av_log(s, AV_LOG_ERROR, ".c2 files require exactly %i bytes of extradata (got %i)\n",
AVPRIV_CODEC2_EXTRADATA_SIZE, st->codecpar->extradata_size);
return AVERROR(EINVAL);
}
avio_wb24(s->pb, AVPRIV_CODEC2_MAGIC);
avio_write(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE);
return 0;
}
static int codec2raw_read_header(AVFormatContext *s)
{
Codec2Context *c2 = s->priv_data;
AVStream *st;
int ret;
if (c2->mode < 0) {
//FIXME: using a default value of -1 for mandatory options is an incredibly ugly hack
av_log(s, AV_LOG_ERROR, "-mode must be set in order to make sense of raw codec2 files\n");
return AVERROR(EINVAL);
}
st = avformat_new_stream(s, NULL);
if (!st) {
return AVERROR(ENOMEM);
}
ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE);
if (ret) {
return ret;
}
s->internal->data_offset = 0;
avpriv_codec2_make_extradata(st->codecpar->extradata, c2->mode);
return codec2_read_header_common(s, st);
}
//transcoding report2074.c2 to wav went from 7.391s to 5.322s with -frames_per_packet 1000 compared to default, same sha1sum
#define FRAMES_PER_PACKET \
{ "frames_per_packet", "Number of frames to read at a time. Higher = faster decoding, lower granularity", \
offsetof(Codec2Context, frames_per_packet), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM}
static const AVOption codec2_options[] = {
FRAMES_PER_PACKET,
{ NULL },
};
static const AVOption codec2raw_options[] = {
AVPRIV_CODEC2_AVOPTIONS("codec2 mode [mandatory]", Codec2Context, -1, -1, AV_OPT_FLAG_DECODING_PARAM),
FRAMES_PER_PACKET,
{ NULL },
};
static const AVClass codec2_mux_class = {
.class_name = "codec2 muxer",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_DEMUXER,
};
static const AVClass codec2_demux_class = {
.class_name = "codec2 demuxer",
.item_name = av_default_item_name,
.option = codec2_options,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_DEMUXER,
};
static const AVClass codec2raw_demux_class = {
.class_name = "codec2raw demuxer",
.item_name = av_default_item_name,
.option = codec2raw_options,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_DEMUXER,
};
#if CONFIG_CODEC2_DEMUXER
AVInputFormat ff_codec2_demuxer = {
.name = "codec2",
.long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 demuxer"),
.priv_data_size = sizeof(Codec2Context),
.extensions = "c2",
.read_probe = codec2_probe,
.read_header = codec2_read_header,
.read_packet = codec2_read_packet,
.read_seek = ff_pcm_read_seek,
.flags = AVFMT_GENERIC_INDEX,
.raw_codec_id = AV_CODEC_ID_CODEC2,
.priv_class = &codec2_demux_class,
};
#endif
#if CONFIG_CODEC2_MUXER
AVOutputFormat ff_codec2_muxer = {
.name = "codec2",
.long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 muxer"),
.priv_data_size = sizeof(Codec2Context),
.extensions = "c2",
.audio_codec = AV_CODEC_ID_CODEC2,
.video_codec = AV_CODEC_ID_NONE,
.write_header = codec2_write_header,
.write_packet = ff_raw_write_packet,
.flags = AVFMT_NOTIMESTAMPS,
.priv_class = &codec2_mux_class,
};
#endif
#if CONFIG_CODEC2RAW_DEMUXER
AVInputFormat ff_codec2raw_demuxer = {
.name = "codec2raw",
.long_name = NULL_IF_CONFIG_SMALL("raw codec2 demuxer"),
.priv_data_size = sizeof(Codec2Context),
.read_header = codec2raw_read_header,
.read_packet = codec2_read_packet,
.read_seek = ff_pcm_read_seek,
.flags = AVFMT_GENERIC_INDEX,
.raw_codec_id = AV_CODEC_ID_CODEC2,
.priv_class = &codec2raw_demux_class,
};
#endif

202
externals/ffmpeg/libavformat/concat.c vendored Executable file
View File

@@ -0,0 +1,202 @@
/*
* Concat URL protocol
* Copyright (c) 2006 Steve Lhomme
* Copyright (c) 2007 Wolfram Gloger
* Copyright (c) 2010 Michele Orrù
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avstring.h"
#include "libavutil/mem.h"
#include "avformat.h"
#include "url.h"
#define AV_CAT_SEPARATOR "|"
struct concat_nodes {
URLContext *uc; ///< node's URLContext
int64_t size; ///< url filesize
};
struct concat_data {
struct concat_nodes *nodes; ///< list of nodes to concat
size_t length; ///< number of cat'ed nodes
size_t current; ///< index of currently read node
uint64_t total_size;
};
static av_cold int concat_close(URLContext *h)
{
int err = 0;
size_t i;
struct concat_data *data = h->priv_data;
struct concat_nodes *nodes = data->nodes;
for (i = 0; i != data->length; i++)
err |= ffurl_closep(&nodes[i].uc);
av_freep(&data->nodes);
return err < 0 ? -1 : 0;
}
static av_cold int concat_open(URLContext *h, const char *uri, int flags)
{
char *node_uri = NULL;
int err = 0;
int64_t size, total_size = 0;
size_t len, i;
URLContext *uc;
struct concat_data *data = h->priv_data;
struct concat_nodes *nodes;
if (!av_strstart(uri, "concat:", &uri)) {
av_log(h, AV_LOG_ERROR, "URL %s lacks prefix\n", uri);
return AVERROR(EINVAL);
}
for (i = 0, len = 1; uri[i]; i++) {
if (uri[i] == *AV_CAT_SEPARATOR) {
/* integer overflow */
if (++len == UINT_MAX / sizeof(*nodes)) {
return AVERROR(ENAMETOOLONG);
}
}
}
if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len)))
return AVERROR(ENOMEM);
else
data->nodes = nodes;
/* handle input */
if (!*uri)
err = AVERROR(ENOENT);
for (i = 0; *uri; i++) {
/* parsing uri */
len = strcspn(uri, AV_CAT_SEPARATOR);
if ((err = av_reallocp(&node_uri, len + 1)) < 0)
break;
av_strlcpy(node_uri, uri, len + 1);
uri += len + strspn(uri + len, AV_CAT_SEPARATOR);
/* creating URLContext */
err = ffurl_open_whitelist(&uc, node_uri, flags,
&h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
if (err < 0)
break;
/* creating size */
if ((size = ffurl_size(uc)) < 0) {
ffurl_close(uc);
err = AVERROR(ENOSYS);
break;
}
/* assembling */
nodes[i].uc = uc;
nodes[i].size = size;
total_size += size;
}
av_free(node_uri);
data->length = i;
if (err < 0)
concat_close(h);
else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) {
concat_close(h);
err = AVERROR(ENOMEM);
} else
data->nodes = nodes;
data->total_size = total_size;
return err;
}
static int concat_read(URLContext *h, unsigned char *buf, int size)
{
int result, total = 0;
struct concat_data *data = h->priv_data;
struct concat_nodes *nodes = data->nodes;
size_t i = data->current;
while (size > 0) {
result = ffurl_read(nodes[i].uc, buf, size);
if (result == AVERROR_EOF) {
if (i + 1 == data->length ||
ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
break;
result = 0;
}
if (result < 0)
return total ? total : result;
total += result;
buf += result;
size -= result;
}
data->current = i;
return total ? total : result;
}
static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
{
int64_t result;
struct concat_data *data = h->priv_data;
struct concat_nodes *nodes = data->nodes;
size_t i;
if ((whence & AVSEEK_SIZE))
return data->total_size;
switch (whence) {
case SEEK_END:
for (i = data->length - 1; i && pos < -nodes[i].size; i--)
pos += nodes[i].size;
break;
case SEEK_CUR:
/* get the absolute position */
for (i = 0; i != data->current; i++)
pos += nodes[i].size;
pos += ffurl_seek(nodes[i].uc, 0, SEEK_CUR);
whence = SEEK_SET;
/* fall through with the absolute position */
case SEEK_SET:
for (i = 0; i != data->length - 1 && pos >= nodes[i].size; i++)
pos -= nodes[i].size;
break;
default:
return AVERROR(EINVAL);
}
result = ffurl_seek(nodes[i].uc, pos, whence);
if (result >= 0) {
data->current = i;
while (i)
result += nodes[--i].size;
}
return result;
}
const URLProtocol ff_concat_protocol = {
.name = "concat",
.url_open = concat_open,
.url_read = concat_read,
.url_seek = concat_seek,
.url_close = concat_close,
.priv_data_size = sizeof(struct concat_data),
.default_whitelist = "concat,file,subfile",
};

788
externals/ffmpeg/libavformat/concatdec.c vendored Executable file
View File

@@ -0,0 +1,788 @@
/*
* Copyright (c) 2012 Nicolas George
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/bprint.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "libavutil/timestamp.h"
#include "avformat.h"
#include "internal.h"
#include "url.h"
typedef enum ConcatMatchMode {
MATCH_ONE_TO_ONE,
MATCH_EXACT_ID,
} ConcatMatchMode;
typedef struct ConcatStream {
AVBSFContext *bsf;
int out_stream_index;
} ConcatStream;
typedef struct {
char *url;
int64_t start_time;
int64_t file_start_time;
int64_t file_inpoint;
int64_t duration;
int64_t user_duration;
int64_t next_dts;
ConcatStream *streams;
int64_t inpoint;
int64_t outpoint;
AVDictionary *metadata;
int nb_streams;
} ConcatFile;
typedef struct {
AVClass *class;
ConcatFile *files;
ConcatFile *cur_file;
unsigned nb_files;
AVFormatContext *avf;
int safe;
int seekable;
int eof;
ConcatMatchMode stream_match_mode;
unsigned auto_convert;
int segment_time_metadata;
} ConcatContext;
static int concat_probe(const AVProbeData *probe)
{
return memcmp(probe->buf, "ffconcat version 1.0", 20) ?
0 : AVPROBE_SCORE_MAX;
}
static char *get_keyword(uint8_t **cursor)
{
char *ret = *cursor += strspn(*cursor, SPACE_CHARS);
*cursor += strcspn(*cursor, SPACE_CHARS);
if (**cursor) {
*((*cursor)++) = 0;
*cursor += strspn(*cursor, SPACE_CHARS);
}
return ret;
}
static int safe_filename(const char *f)
{
const char *start = f;
for (; *f; f++) {
/* A-Za-z0-9_- */
if (!((unsigned)((*f | 32) - 'a') < 26 ||
(unsigned)(*f - '0') < 10 || *f == '_' || *f == '-')) {
if (f == start)
return 0;
else if (*f == '/')
start = f + 1;
else if (*f != '.')
return 0;
}
}
return 1;
}
#define FAIL(retcode) do { ret = (retcode); goto fail; } while(0)
static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
unsigned *nb_files_alloc)
{
ConcatContext *cat = avf->priv_data;
ConcatFile *file;
char *url = NULL;
const char *proto;
size_t url_len, proto_len;
int ret;
if (cat->safe > 0 && !safe_filename(filename)) {
av_log(avf, AV_LOG_ERROR, "Unsafe file name '%s'\n", filename);
FAIL(AVERROR(EPERM));
}
proto = avio_find_protocol_name(filename);
proto_len = proto ? strlen(proto) : 0;
if (proto && !memcmp(filename, proto, proto_len) &&
(filename[proto_len] == ':' || filename[proto_len] == ',')) {
url = filename;
filename = NULL;
} else {
url_len = strlen(avf->url) + strlen(filename) + 16;
if (!(url = av_malloc(url_len)))
FAIL(AVERROR(ENOMEM));
ff_make_absolute_url(url, url_len, avf->url, filename);
av_freep(&filename);
}
if (cat->nb_files >= *nb_files_alloc) {
size_t n = FFMAX(*nb_files_alloc * 2, 16);
ConcatFile *new_files;
if (n <= cat->nb_files || n > SIZE_MAX / sizeof(*cat->files) ||
!(new_files = av_realloc(cat->files, n * sizeof(*cat->files))))
FAIL(AVERROR(ENOMEM));
cat->files = new_files;
*nb_files_alloc = n;
}
file = &cat->files[cat->nb_files++];
memset(file, 0, sizeof(*file));
*rfile = file;
file->url = url;
file->start_time = AV_NOPTS_VALUE;
file->duration = AV_NOPTS_VALUE;
file->next_dts = AV_NOPTS_VALUE;
file->inpoint = AV_NOPTS_VALUE;
file->outpoint = AV_NOPTS_VALUE;
file->user_duration = AV_NOPTS_VALUE;
return 0;
fail:
av_free(url);
av_free(filename);
return ret;
}
static int copy_stream_props(AVStream *st, AVStream *source_st)
{
int ret;
if (st->codecpar->codec_id || !source_st->codecpar->codec_id) {
if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) {
ret = ff_alloc_extradata(st->codecpar,
source_st->codecpar->extradata_size);
if (ret < 0)
return ret;
}
memcpy(st->codecpar->extradata, source_st->codecpar->extradata,
source_st->codecpar->extradata_size);
return 0;
}
if ((ret = avcodec_parameters_copy(st->codecpar, source_st->codecpar)) < 0)
return ret;
st->r_frame_rate = source_st->r_frame_rate;
st->avg_frame_rate = source_st->avg_frame_rate;
st->sample_aspect_ratio = source_st->sample_aspect_ratio;
avpriv_set_pts_info(st, 64, source_st->time_base.num, source_st->time_base.den);
av_dict_copy(&st->metadata, source_st->metadata, 0);
return 0;
}
static int detect_stream_specific(AVFormatContext *avf, int idx)
{
ConcatContext *cat = avf->priv_data;
AVStream *st = cat->avf->streams[idx];
ConcatStream *cs = &cat->cur_file->streams[idx];
const AVBitStreamFilter *filter;
AVBSFContext *bsf;
int ret;
if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264) {
if (!st->codecpar->extradata_size ||
(st->codecpar->extradata_size >= 3 && AV_RB24(st->codecpar->extradata) == 1) ||
(st->codecpar->extradata_size >= 4 && AV_RB32(st->codecpar->extradata) == 1))
return 0;
av_log(cat->avf, AV_LOG_INFO,
"Auto-inserting h264_mp4toannexb bitstream filter\n");
filter = av_bsf_get_by_name("h264_mp4toannexb");
if (!filter) {
av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
"required for H.264 streams\n");
return AVERROR_BSF_NOT_FOUND;
}
ret = av_bsf_alloc(filter, &bsf);
if (ret < 0)
return ret;
cs->bsf = bsf;
ret = avcodec_parameters_copy(bsf->par_in, st->codecpar);
if (ret < 0)
return ret;
ret = av_bsf_init(bsf);
if (ret < 0)
return ret;
ret = avcodec_parameters_copy(st->codecpar, bsf->par_out);
if (ret < 0)
return ret;
}
return 0;
}
static int match_streams_one_to_one(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
AVStream *st;
int i, ret;
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
if (i < avf->nb_streams) {
st = avf->streams[i];
} else {
if (!(st = avformat_new_stream(avf, NULL)))
return AVERROR(ENOMEM);
}
if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
return ret;
cat->cur_file->streams[i].out_stream_index = i;
}
return 0;
}
static int match_streams_exact_id(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
AVStream *st;
int i, j, ret;
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
st = cat->avf->streams[i];
for (j = 0; j < avf->nb_streams; j++) {
if (avf->streams[j]->id == st->id) {
av_log(avf, AV_LOG_VERBOSE,
"Match slave stream #%d with stream #%d id 0x%x\n",
i, j, st->id);
if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
return ret;
cat->cur_file->streams[i].out_stream_index = j;
}
}
}
return 0;
}
static int match_streams(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
ConcatStream *map;
int i, ret;
if (cat->cur_file->nb_streams >= cat->avf->nb_streams)
return 0;
map = av_realloc(cat->cur_file->streams,
cat->avf->nb_streams * sizeof(*map));
if (!map)
return AVERROR(ENOMEM);
cat->cur_file->streams = map;
memset(map + cat->cur_file->nb_streams, 0,
(cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map));
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
map[i].out_stream_index = -1;
if ((ret = detect_stream_specific(avf, i)) < 0)
return ret;
}
switch (cat->stream_match_mode) {
case MATCH_ONE_TO_ONE:
ret = match_streams_one_to_one(avf);
break;
case MATCH_EXACT_ID:
ret = match_streams_exact_id(avf);
break;
default:
ret = AVERROR_BUG;
}
if (ret < 0)
return ret;
cat->cur_file->nb_streams = cat->avf->nb_streams;
return 0;
}
static int64_t get_best_effort_duration(ConcatFile *file, AVFormatContext *avf)
{
if (file->user_duration != AV_NOPTS_VALUE)
return file->user_duration;
if (file->outpoint != AV_NOPTS_VALUE)
return file->outpoint - file->file_inpoint;
if (avf->duration > 0)
return avf->duration - (file->file_inpoint - file->file_start_time);
if (file->next_dts != AV_NOPTS_VALUE)
return file->next_dts - file->file_inpoint;
return AV_NOPTS_VALUE;
}
static int open_file(AVFormatContext *avf, unsigned fileno)
{
ConcatContext *cat = avf->priv_data;
ConcatFile *file = &cat->files[fileno];
int ret;
if (cat->avf)
avformat_close_input(&cat->avf);
cat->avf = avformat_alloc_context();
if (!cat->avf)
return AVERROR(ENOMEM);
cat->avf->flags |= avf->flags & ~AVFMT_FLAG_CUSTOM_IO;
cat->avf->interrupt_callback = avf->interrupt_callback;
if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
return ret;
if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
(ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url);
avformat_close_input(&cat->avf);
return ret;
}
cat->cur_file = file;
file->start_time = !fileno ? 0 :
cat->files[fileno - 1].start_time +
cat->files[fileno - 1].duration;
file->file_start_time = (cat->avf->start_time == AV_NOPTS_VALUE) ? 0 : cat->avf->start_time;
file->file_inpoint = (file->inpoint == AV_NOPTS_VALUE) ? file->file_start_time : file->inpoint;
file->duration = get_best_effort_duration(file, cat->avf);
if (cat->segment_time_metadata) {
av_dict_set_int(&file->metadata, "lavf.concatdec.start_time", file->start_time, 0);
if (file->duration != AV_NOPTS_VALUE)
av_dict_set_int(&file->metadata, "lavf.concatdec.duration", file->duration, 0);
}
if ((ret = match_streams(avf)) < 0)
return ret;
if (file->inpoint != AV_NOPTS_VALUE) {
if ((ret = avformat_seek_file(cat->avf, -1, INT64_MIN, file->inpoint, file->inpoint, 0)) < 0)
return ret;
}
return 0;
}
static int concat_read_close(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
unsigned i, j;
for (i = 0; i < cat->nb_files; i++) {
av_freep(&cat->files[i].url);
for (j = 0; j < cat->files[i].nb_streams; j++) {
if (cat->files[i].streams[j].bsf)
av_bsf_free(&cat->files[i].streams[j].bsf);
}
av_freep(&cat->files[i].streams);
av_dict_free(&cat->files[i].metadata);
}
if (cat->avf)
avformat_close_input(&cat->avf);
av_freep(&cat->files);
return 0;
}
static int concat_read_header(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
AVBPrint bp;
uint8_t *cursor, *keyword;
int line = 0, i;
unsigned nb_files_alloc = 0;
ConcatFile *file = NULL;
int64_t ret, time = 0;
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
while ((ret = ff_read_line_to_bprint_overwrite(avf->pb, &bp)) >= 0) {
line++;
cursor = bp.str;
keyword = get_keyword(&cursor);
if (!*keyword || *keyword == '#')
continue;
if (!strcmp(keyword, "file")) {
char *filename = av_get_token((const char **)&cursor, SPACE_CHARS);
if (!filename) {
av_log(avf, AV_LOG_ERROR, "Line %d: filename required\n", line);
FAIL(AVERROR_INVALIDDATA);
}
if ((ret = add_file(avf, filename, &file, &nb_files_alloc)) < 0)
goto fail;
} else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint") || !strcmp(keyword, "outpoint")) {
char *dur_str = get_keyword(&cursor);
int64_t dur;
if (!file) {
av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
line, keyword);
FAIL(AVERROR_INVALIDDATA);
}
if ((ret = av_parse_time(&dur, dur_str, 1)) < 0) {
av_log(avf, AV_LOG_ERROR, "Line %d: invalid %s '%s'\n",
line, keyword, dur_str);
goto fail;
}
if (!strcmp(keyword, "duration"))
file->user_duration = dur;
else if (!strcmp(keyword, "inpoint"))
file->inpoint = dur;
else if (!strcmp(keyword, "outpoint"))
file->outpoint = dur;
} else if (!strcmp(keyword, "file_packet_metadata")) {
char *metadata;
if (!file) {
av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
line, keyword);
FAIL(AVERROR_INVALIDDATA);
}
metadata = av_get_token((const char **)&cursor, SPACE_CHARS);
if (!metadata) {
av_log(avf, AV_LOG_ERROR, "Line %d: packet metadata required\n", line);
FAIL(AVERROR_INVALIDDATA);
}
if ((ret = av_dict_parse_string(&file->metadata, metadata, "=", "", 0)) < 0) {
av_log(avf, AV_LOG_ERROR, "Line %d: failed to parse metadata string\n", line);
av_freep(&metadata);
FAIL(AVERROR_INVALIDDATA);
}
av_freep(&metadata);
} else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM));
} else if (!strcmp(keyword, "exact_stream_id")) {
if (!avf->nb_streams) {
av_log(avf, AV_LOG_ERROR, "Line %d: exact_stream_id without stream\n",
line);
FAIL(AVERROR_INVALIDDATA);
}
avf->streams[avf->nb_streams - 1]->id =
strtol(get_keyword(&cursor), NULL, 0);
} else if (!strcmp(keyword, "ffconcat")) {
char *ver_kw = get_keyword(&cursor);
char *ver_val = get_keyword(&cursor);
if (strcmp(ver_kw, "version") || strcmp(ver_val, "1.0")) {
av_log(avf, AV_LOG_ERROR, "Line %d: invalid version\n", line);
FAIL(AVERROR_INVALIDDATA);
}
if (cat->safe < 0)
cat->safe = 1;
} else {
av_log(avf, AV_LOG_ERROR, "Line %d: unknown keyword '%s'\n",
line, keyword);
FAIL(AVERROR_INVALIDDATA);
}
}
if (ret != AVERROR_EOF && ret < 0)
goto fail;
if (!cat->nb_files)
FAIL(AVERROR_INVALIDDATA);
for (i = 0; i < cat->nb_files; i++) {
if (cat->files[i].start_time == AV_NOPTS_VALUE)
cat->files[i].start_time = time;
else
time = cat->files[i].start_time;
if (cat->files[i].user_duration == AV_NOPTS_VALUE) {
if (cat->files[i].inpoint == AV_NOPTS_VALUE || cat->files[i].outpoint == AV_NOPTS_VALUE)
break;
cat->files[i].user_duration = cat->files[i].outpoint - cat->files[i].inpoint;
}
cat->files[i].duration = cat->files[i].user_duration;
time += cat->files[i].user_duration;
}
if (i == cat->nb_files) {
avf->duration = time;
cat->seekable = 1;
}
cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID :
MATCH_ONE_TO_ONE;
if ((ret = open_file(avf, 0)) < 0)
goto fail;
av_bprint_finalize(&bp, NULL);
return 0;
fail:
av_bprint_finalize(&bp, NULL);
concat_read_close(avf);
return ret;
}
static int open_next_file(AVFormatContext *avf)
{
ConcatContext *cat = avf->priv_data;
unsigned fileno = cat->cur_file - cat->files;
cat->cur_file->duration = get_best_effort_duration(cat->cur_file, cat->avf);
if (++fileno >= cat->nb_files) {
cat->eof = 1;
return AVERROR_EOF;
}
return open_file(avf, fileno);
}
static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
{
int ret;
if (cs->bsf) {
ret = av_bsf_send_packet(cs->bsf, pkt);
if (ret < 0) {
av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
"failed to send input packet\n");
return ret;
}
while (!ret)
ret = av_bsf_receive_packet(cs->bsf, pkt);
if (ret < 0 && (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)) {
av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
"failed to receive output packet\n");
return ret;
}
}
return 0;
}
/* Returns true if the packet dts is greater or equal to the specified outpoint. */
static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
{
if (cat->cur_file->outpoint != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) {
return av_compare_ts(pkt->dts, cat->avf->streams[pkt->stream_index]->time_base,
cat->cur_file->outpoint, AV_TIME_BASE_Q) >= 0;
}
return 0;
}
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
ConcatContext *cat = avf->priv_data;
int ret;
int64_t delta;
ConcatStream *cs;
AVStream *st;
if (cat->eof)
return AVERROR_EOF;
if (!cat->avf)
return AVERROR(EIO);
while (1) {
ret = av_read_frame(cat->avf, pkt);
if (ret == AVERROR_EOF) {
if ((ret = open_next_file(avf)) < 0)
return ret;
continue;
}
if (ret < 0)
return ret;
if ((ret = match_streams(avf)) < 0) {
return ret;
}
if (packet_after_outpoint(cat, pkt)) {
av_packet_unref(pkt);
if ((ret = open_next_file(avf)) < 0)
return ret;
continue;
}
cs = &cat->cur_file->streams[pkt->stream_index];
if (cs->out_stream_index < 0) {
av_packet_unref(pkt);
continue;
}
break;
}
if ((ret = filter_packet(avf, cs, pkt)) < 0)
return ret;
st = cat->avf->streams[pkt->stream_index];
av_log(avf, AV_LOG_DEBUG, "file:%d stream:%d pts:%s pts_time:%s dts:%s dts_time:%s",
(unsigned)(cat->cur_file - cat->files), pkt->stream_index,
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
delta = av_rescale_q(cat->cur_file->start_time - cat->cur_file->file_inpoint,
AV_TIME_BASE_Q,
cat->avf->streams[pkt->stream_index]->time_base);
if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts += delta;
if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts += delta;
av_log(avf, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
if (cat->cur_file->metadata) {
int metadata_len;
char* packed_metadata = av_packet_pack_dictionary(cat->cur_file->metadata, &metadata_len);
if (!packed_metadata)
return AVERROR(ENOMEM);
ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA,
packed_metadata, metadata_len);
if (ret < 0) {
av_freep(&packed_metadata);
return ret;
}
}
if (cat->cur_file->duration == AV_NOPTS_VALUE && st->cur_dts != AV_NOPTS_VALUE) {
int64_t next_dts = av_rescale_q(st->cur_dts, st->time_base, AV_TIME_BASE_Q);
if (cat->cur_file->next_dts == AV_NOPTS_VALUE || next_dts > cat->cur_file->next_dts) {
cat->cur_file->next_dts = next_dts;
}
}
pkt->stream_index = cs->out_stream_index;
return 0;
}
static void rescale_interval(AVRational tb_in, AVRational tb_out,
int64_t *min_ts, int64_t *ts, int64_t *max_ts)
{
*ts = av_rescale_q (* ts, tb_in, tb_out);
*min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
*max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
}
static int try_seek(AVFormatContext *avf, int stream,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
ConcatContext *cat = avf->priv_data;
int64_t t0 = cat->cur_file->start_time - cat->cur_file->file_inpoint;
ts -= t0;
min_ts = min_ts == INT64_MIN ? INT64_MIN : min_ts - t0;
max_ts = max_ts == INT64_MAX ? INT64_MAX : max_ts - t0;
if (stream >= 0) {
if (stream >= cat->avf->nb_streams)
return AVERROR(EIO);
rescale_interval(AV_TIME_BASE_Q, cat->avf->streams[stream]->time_base,
&min_ts, &ts, &max_ts);
}
return avformat_seek_file(cat->avf, stream, min_ts, ts, max_ts, flags);
}
static int real_seek(AVFormatContext *avf, int stream,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags, AVFormatContext *cur_avf)
{
ConcatContext *cat = avf->priv_data;
int ret, left, right;
if (stream >= 0) {
if (stream >= avf->nb_streams)
return AVERROR(EINVAL);
rescale_interval(avf->streams[stream]->time_base, AV_TIME_BASE_Q,
&min_ts, &ts, &max_ts);
}
left = 0;
right = cat->nb_files;
/* Always support seek to start */
if (ts <= 0)
right = 1;
else if (!cat->seekable)
return AVERROR(ESPIPE); /* XXX: can we use it? */
while (right - left > 1) {
int mid = (left + right) / 2;
if (ts < cat->files[mid].start_time)
right = mid;
else
left = mid;
}
if (cat->cur_file != &cat->files[left]) {
if ((ret = open_file(avf, left)) < 0)
return ret;
} else {
cat->avf = cur_avf;
}
ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
if (ret < 0 &&
left < cat->nb_files - 1 &&
cat->files[left + 1].start_time < max_ts) {
if (cat->cur_file == &cat->files[left])
cat->avf = NULL;
if ((ret = open_file(avf, left + 1)) < 0)
return ret;
ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
}
return ret;
}
static int concat_seek(AVFormatContext *avf, int stream,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
ConcatContext *cat = avf->priv_data;
ConcatFile *cur_file_saved = cat->cur_file;
AVFormatContext *cur_avf_saved = cat->avf;
int ret;
if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))
return AVERROR(ENOSYS);
cat->avf = NULL;
if ((ret = real_seek(avf, stream, min_ts, ts, max_ts, flags, cur_avf_saved)) < 0) {
if (cat->cur_file != cur_file_saved) {
if (cat->avf)
avformat_close_input(&cat->avf);
}
cat->avf = cur_avf_saved;
cat->cur_file = cur_file_saved;
} else {
if (cat->cur_file != cur_file_saved) {
avformat_close_input(&cur_avf_saved);
}
cat->eof = 0;
}
return ret;
}
#define OFFSET(x) offsetof(ConcatContext, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{ "safe", "enable safe mode",
OFFSET(safe), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, DEC },
{ "auto_convert", "automatically convert bitstream format",
OFFSET(auto_convert), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC },
{ "segment_time_metadata", "output file segment start time and duration as packet metadata",
OFFSET(segment_time_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
{ NULL }
};
static const AVClass concat_class = {
.class_name = "concat demuxer",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_concat_demuxer = {
.name = "concat",
.long_name = NULL_IF_CONFIG_SMALL("Virtual concatenation script"),
.priv_data_size = sizeof(ConcatContext),
.read_probe = concat_probe,
.read_header = concat_read_header,
.read_packet = concat_read_packet,
.read_close = concat_read_close,
.read_seek2 = concat_seek,
.priv_class = &concat_class,
};

69
externals/ffmpeg/libavformat/crcenc.c vendored Executable file
View File

@@ -0,0 +1,69 @@
/*
* 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 <inttypes.h>
#include "libavutil/adler32.h"
#include "avformat.h"
typedef struct CRCState {
uint32_t crcval;
} CRCState;
static int crc_write_header(struct AVFormatContext *s)
{
CRCState *crc = s->priv_data;
/* init CRC */
crc->crcval = 1;
return 0;
}
static int crc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
{
CRCState *crc = s->priv_data;
crc->crcval = av_adler32_update(crc->crcval, pkt->data, pkt->size);
return 0;
}
static int crc_write_trailer(struct AVFormatContext *s)
{
CRCState *crc = s->priv_data;
char buf[64];
snprintf(buf, sizeof(buf), "CRC=0x%08"PRIx32"\n", crc->crcval);
avio_write(s->pb, buf, strlen(buf));
return 0;
}
AVOutputFormat ff_crc_muxer = {
.name = "crc",
.long_name = NULL_IF_CONFIG_SMALL("CRC testing"),
.priv_data_size = sizeof(CRCState),
.audio_codec = AV_CODEC_ID_PCM_S16LE,
.video_codec = AV_CODEC_ID_RAWVIDEO,
.write_header = crc_write_header,
.write_packet = crc_write_packet,
.write_trailer = crc_write_trailer,
.flags = AVFMT_NOTIMESTAMPS,
};

405
externals/ffmpeg/libavformat/crypto.c vendored Executable file
View File

@@ -0,0 +1,405 @@
/*
* Decryption protocol handler
* Copyright (c) 2011 Martin Storsjo
*
* 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 "libavutil/aes.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "internal.h"
#include "url.h"
// encourage reads of 4096 bytes - 1 block is always retained.
#define MAX_BUFFER_BLOCKS 257
#define BLOCKSIZE 16
typedef struct CryptoContext {
const AVClass *class;
URLContext *hd;
uint8_t inbuffer [BLOCKSIZE*MAX_BUFFER_BLOCKS],
outbuffer[BLOCKSIZE*MAX_BUFFER_BLOCKS];
uint8_t *outptr;
int indata, indata_used, outdata;
int64_t position; // position in file - used in seek
int flags;
int eof;
uint8_t *key;
int keylen;
uint8_t *iv;
int ivlen;
uint8_t *decrypt_key;
int decrypt_keylen;
uint8_t *decrypt_iv;
int decrypt_ivlen;
uint8_t *encrypt_key;
int encrypt_keylen;
uint8_t *encrypt_iv;
int encrypt_ivlen;
struct AVAES *aes_decrypt;
struct AVAES *aes_encrypt;
uint8_t *write_buf;
unsigned int write_buf_size;
uint8_t pad[BLOCKSIZE];
int pad_len;
} CryptoContext;
#define OFFSET(x) offsetof(CryptoContext, x)
#define D AV_OPT_FLAG_DECODING_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{"key", "AES encryption/decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, .flags = D|E },
{"iv", "AES encryption/decryption initialization vector", OFFSET(iv), AV_OPT_TYPE_BINARY, .flags = D|E },
{"decryption_key", "AES decryption key", OFFSET(decrypt_key), AV_OPT_TYPE_BINARY, .flags = D },
{"decryption_iv", "AES decryption initialization vector", OFFSET(decrypt_iv), AV_OPT_TYPE_BINARY, .flags = D },
{"encryption_key", "AES encryption key", OFFSET(encrypt_key), AV_OPT_TYPE_BINARY, .flags = E },
{"encryption_iv", "AES encryption initialization vector", OFFSET(encrypt_iv), AV_OPT_TYPE_BINARY, .flags = E },
{ NULL }
};
static const AVClass crypto_class = {
.class_name = "crypto",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
static int set_aes_arg(URLContext *h, uint8_t **buf, int *buf_len,
uint8_t *default_buf, int default_buf_len,
const char *desc)
{
if (!*buf_len) {
if (!default_buf_len) {
av_log(h, AV_LOG_ERROR, "%s not set\n", desc);
return AVERROR(EINVAL);
} else if (default_buf_len != BLOCKSIZE) {
av_log(h, AV_LOG_ERROR,
"invalid %s size (%d bytes, block size is %d)\n",
desc, default_buf_len, BLOCKSIZE);
return AVERROR(EINVAL);
}
*buf = av_memdup(default_buf, default_buf_len);
if (!*buf)
return AVERROR(ENOMEM);
*buf_len = default_buf_len;
} else if (*buf_len != BLOCKSIZE) {
av_log(h, AV_LOG_ERROR,
"invalid %s size (%d bytes, block size is %d)\n",
desc, *buf_len, BLOCKSIZE);
return AVERROR(EINVAL);
}
return 0;
}
static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary **options)
{
const char *nested_url;
int ret = 0;
CryptoContext *c = h->priv_data;
c->flags = flags;
if (!av_strstart(uri, "crypto+", &nested_url) &&
!av_strstart(uri, "crypto:", &nested_url)) {
av_log(h, AV_LOG_ERROR, "Unsupported url %s\n", uri);
ret = AVERROR(EINVAL);
goto err;
}
if (flags & AVIO_FLAG_READ) {
if ((ret = set_aes_arg(h, &c->decrypt_key, &c->decrypt_keylen,
c->key, c->keylen, "decryption key")) < 0)
goto err;
if ((ret = set_aes_arg(h, &c->decrypt_iv, &c->decrypt_ivlen,
c->iv, c->ivlen, "decryption IV")) < 0)
goto err;
}
if (flags & AVIO_FLAG_WRITE) {
if ((ret = set_aes_arg(h, &c->encrypt_key, &c->encrypt_keylen,
c->key, c->keylen, "encryption key")) < 0)
if (ret < 0)
goto err;
if ((ret = set_aes_arg(h, &c->encrypt_iv, &c->encrypt_ivlen,
c->iv, c->ivlen, "encryption IV")) < 0)
goto err;
}
if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags,
&h->interrupt_callback, options,
h->protocol_whitelist, h->protocol_blacklist, h)) < 0) {
av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
goto err;
}
if (flags & AVIO_FLAG_READ) {
c->aes_decrypt = av_aes_alloc();
if (!c->aes_decrypt) {
ret = AVERROR(ENOMEM);
goto err;
}
ret = av_aes_init(c->aes_decrypt, c->decrypt_key, BLOCKSIZE * 8, 1);
if (ret < 0)
goto err;
// pass back information about the context we openned
if (c->hd->is_streamed)
h->is_streamed = c->hd->is_streamed;
}
if (flags & AVIO_FLAG_WRITE) {
c->aes_encrypt = av_aes_alloc();
if (!c->aes_encrypt) {
ret = AVERROR(ENOMEM);
goto err;
}
ret = av_aes_init(c->aes_encrypt, c->encrypt_key, BLOCKSIZE * 8, 0);
if (ret < 0)
goto err;
// for write, we must be streamed
// - linear write only for crytpo aes-128-cbc
h->is_streamed = 1;
}
err:
return ret;
}
static int crypto_read(URLContext *h, uint8_t *buf, int size)
{
CryptoContext *c = h->priv_data;
int blocks;
retry:
if (c->outdata > 0) {
size = FFMIN(size, c->outdata);
memcpy(buf, c->outptr, size);
c->outptr += size;
c->outdata -= size;
c->position = c->position + size;
return size;
}
// We avoid using the last block until we've found EOF,
// since we'll remove PKCS7 padding at the end. So make
// sure we've got at least 2 blocks, so we can decrypt
// at least one.
while (c->indata - c->indata_used < 2*BLOCKSIZE) {
int n = ffurl_read(c->hd, c->inbuffer + c->indata,
sizeof(c->inbuffer) - c->indata);
if (n <= 0) {
c->eof = 1;
break;
}
c->indata += n;
}
blocks = (c->indata - c->indata_used) / BLOCKSIZE;
if (!blocks)
return AVERROR_EOF;
if (!c->eof)
blocks--;
av_aes_crypt(c->aes_decrypt, c->outbuffer, c->inbuffer + c->indata_used,
blocks, c->decrypt_iv, 1);
c->outdata = BLOCKSIZE * blocks;
c->outptr = c->outbuffer;
c->indata_used += BLOCKSIZE * blocks;
if (c->indata_used >= sizeof(c->inbuffer)/2) {
memmove(c->inbuffer, c->inbuffer + c->indata_used,
c->indata - c->indata_used);
c->indata -= c->indata_used;
c->indata_used = 0;
}
if (c->eof) {
// Remove PKCS7 padding at the end
int padding = c->outbuffer[c->outdata - 1];
c->outdata -= padding;
}
goto retry;
}
static int64_t crypto_seek(URLContext *h, int64_t pos, int whence)
{
CryptoContext *c = h->priv_data;
int64_t block;
int64_t newpos;
if (c->flags & AVIO_FLAG_WRITE) {
av_log(h, AV_LOG_ERROR,
"Crypto: seek not supported for write\r\n");
/* seems the most appropriate error to return */
return AVERROR(ESPIPE);
}
// reset eof, else we won't read it correctly if we already hit eof.
c->eof = 0;
switch (whence) {
case SEEK_SET:
break;
case SEEK_CUR:
pos = pos + c->position;
break;
case SEEK_END: {
int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE );
if (newpos < 0) {
av_log(h, AV_LOG_ERROR,
"Crypto: seek_end - can't get file size (pos=%lld)\r\n", (long long int)pos);
return newpos;
}
pos = newpos - pos;
}
break;
case AVSEEK_SIZE: {
int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE );
return newpos;
}
break;
default:
av_log(h, AV_LOG_ERROR,
"Crypto: no support for seek where 'whence' is %d\r\n", whence);
return AVERROR(EINVAL);
}
c->outdata = 0;
c->indata = 0;
c->indata_used = 0;
c->outptr = c->outbuffer;
// identify the block containing the IV for the
// next block we will decrypt
block = pos/BLOCKSIZE;
if (block == 0) {
// restore the iv to the seed one - this is the iv for the FIRST block
memcpy( c->decrypt_iv, c->iv, c->ivlen );
c->position = 0;
} else {
// else, go back one block - we will get av_cyrpt to read this block
// which it will then store use as the iv.
// note that the DECRYPTED result will not be correct,
// but will be discarded
block--;
c->position = (block * BLOCKSIZE);
}
newpos = ffurl_seek( c->hd, c->position, SEEK_SET );
if (newpos < 0) {
av_log(h, AV_LOG_ERROR,
"Crypto: nested protocol no support for seek or seek failed\n");
return newpos;
}
// read and discard from here up to required position
// (which will set the iv correctly to it).
if (pos - c->position) {
uint8_t buff[BLOCKSIZE*2]; // maximum size of pos-c->position
int len = pos - c->position;
int res;
while (len > 0) {
// note: this may not return all the bytes first time
res = crypto_read(h, buff, len);
if (res < 0)
break;
len -= res;
}
// if we did not get all the bytes
if (len != 0) {
char errbuf[100] = "unknown error";
av_strerror(res, errbuf, sizeof(errbuf));
av_log(h, AV_LOG_ERROR,
"Crypto: discard read did not get all the bytes (%d remain) - read returned (%d)-%s\n",
len, res, errbuf);
return AVERROR(EINVAL);
}
}
return c->position;
}
static int crypto_write(URLContext *h, const unsigned char *buf, int size)
{
CryptoContext *c = h->priv_data;
int total_size, blocks, pad_len, out_size;
int ret = 0;
total_size = size + c->pad_len;
pad_len = total_size % BLOCKSIZE;
out_size = total_size - pad_len;
blocks = out_size / BLOCKSIZE;
if (out_size) {
av_fast_malloc(&c->write_buf, &c->write_buf_size, out_size);
if (!c->write_buf)
return AVERROR(ENOMEM);
if (c->pad_len) {
memcpy(&c->pad[c->pad_len], buf, BLOCKSIZE - c->pad_len);
av_aes_crypt(c->aes_encrypt, c->write_buf, c->pad, 1, c->encrypt_iv, 0);
blocks--;
}
av_aes_crypt(c->aes_encrypt,
&c->write_buf[c->pad_len ? BLOCKSIZE : 0],
&buf[c->pad_len ? BLOCKSIZE - c->pad_len : 0],
blocks, c->encrypt_iv, 0);
ret = ffurl_write(c->hd, c->write_buf, out_size);
if (ret < 0)
return ret;
memcpy(c->pad, &buf[size - pad_len], pad_len);
} else
memcpy(&c->pad[c->pad_len], buf, size);
c->pad_len = pad_len;
return size;
}
static int crypto_close(URLContext *h)
{
CryptoContext *c = h->priv_data;
int ret = 0;
if (c->aes_encrypt) {
uint8_t out_buf[BLOCKSIZE];
int pad = BLOCKSIZE - c->pad_len;
memset(&c->pad[c->pad_len], pad, pad);
av_aes_crypt(c->aes_encrypt, out_buf, c->pad, 1, c->encrypt_iv, 0);
ret = ffurl_write(c->hd, out_buf, BLOCKSIZE);
}
ffurl_closep(&c->hd);
av_freep(&c->aes_decrypt);
av_freep(&c->aes_encrypt);
av_freep(&c->write_buf);
return ret;
}
const URLProtocol ff_crypto_protocol = {
.name = "crypto",
.url_open2 = crypto_open2,
.url_seek = crypto_seek,
.url_read = crypto_read,
.url_write = crypto_write,
.url_close = crypto_close,
.priv_data_size = sizeof(CryptoContext),
.priv_data_class = &crypto_class,
.flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,
};

39
externals/ffmpeg/libavformat/cutils.c vendored Executable file
View File

@@ -0,0 +1,39 @@
/*
* various simple utilities for libavformat
* 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 "libavutil/time_internal.h"
#include "avformat.h"
#include "internal.h"
#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
couple of places, though. */
struct tm *ff_brktimegm(time_t secs, struct tm *tm)
{
tm = gmtime_r(&secs, tm);
tm->tm_year += 1900; /* unlike gmtime_r we store complete year here */
tm->tm_mon += 1; /* unlike gmtime_r tm_mon is from 1 to 12 */
return tm;
}

157
externals/ffmpeg/libavformat/dash.c vendored Executable file
View File

@@ -0,0 +1,157 @@
/*
* MPEG-DASH ISO BMFF segmenter
* Copyright (c) 2014 Martin Storsjo
*
* 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 "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/rational.h"
#include "libavutil/time_internal.h"
#include "avc.h"
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
#include "isom.h"
#include "os_support.h"
#include "url.h"
#include "dash.h"
static DASHTmplId dash_read_tmpl_id(const char *identifier, char *format_tag,
size_t format_tag_size, const char **ptr) {
const char *next_ptr;
DASHTmplId id_type = DASH_TMPL_ID_UNDEFINED;
if (av_strstart(identifier, "$$", &next_ptr)) {
id_type = DASH_TMPL_ID_ESCAPE;
*ptr = next_ptr;
} else if (av_strstart(identifier, "$RepresentationID$", &next_ptr)) {
id_type = DASH_TMPL_ID_REP_ID;
// default to basic format, as $RepresentationID$ identifiers
// are not allowed to have custom format-tags.
av_strlcpy(format_tag, "%d", format_tag_size);
*ptr = next_ptr;
} else { // the following identifiers may have an explicit format_tag
if (av_strstart(identifier, "$Number", &next_ptr))
id_type = DASH_TMPL_ID_NUMBER;
else if (av_strstart(identifier, "$Bandwidth", &next_ptr))
id_type = DASH_TMPL_ID_BANDWIDTH;
else if (av_strstart(identifier, "$Time", &next_ptr))
id_type = DASH_TMPL_ID_TIME;
else
id_type = DASH_TMPL_ID_UNDEFINED;
// next parse the dash format-tag and generate a c-string format tag
// (next_ptr now points at the first '%' at the beginning of the format-tag)
if (id_type != DASH_TMPL_ID_UNDEFINED) {
const char *number_format = (id_type == DASH_TMPL_ID_TIME) ? PRId64 : "d";
if (next_ptr[0] == '$') { // no dash format-tag
snprintf(format_tag, format_tag_size, "%%%s", number_format);
*ptr = &next_ptr[1];
} else {
const char *width_ptr;
// only tolerate single-digit width-field (i.e. up to 9-digit width)
if (av_strstart(next_ptr, "%0", &width_ptr) &&
av_isdigit(width_ptr[0]) &&
av_strstart(&width_ptr[1], "d$", &next_ptr)) {
// yes, we're using a format tag to build format_tag.
snprintf(format_tag, format_tag_size, "%s%c%s", "%0", width_ptr[0], number_format);
*ptr = next_ptr;
} else {
av_log(NULL, AV_LOG_WARNING, "Failed to parse format-tag beginning with %s. Expected either a "
"closing '$' character or a format-string like '%%0[width]d', "
"where width must be a single digit\n", next_ptr);
id_type = DASH_TMPL_ID_UNDEFINED;
}
}
}
}
return id_type;
}
void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size,
const char *template, int rep_id,
int number, int bit_rate,
int64_t time) {
int dst_pos = 0;
const char *t_cur = template;
while (dst_pos < buffer_size - 1 && *t_cur) {
char format_tag[7]; // May be "%d", "%0Xd", or "%0Xlld" (for $Time$), where X is in [0-9]
int n = 0;
DASHTmplId id_type;
const char *t_next = strchr(t_cur, '$'); // copy over everything up to the first '$' character
if (t_next) {
int num_copy_bytes = FFMIN(t_next - t_cur, buffer_size - dst_pos - 1);
av_strlcpy(&dst[dst_pos], t_cur, num_copy_bytes + 1);
// advance
dst_pos += num_copy_bytes;
t_cur = t_next;
} else { // no more DASH identifiers to substitute - just copy the rest over and break
av_strlcpy(&dst[dst_pos], t_cur, buffer_size - dst_pos);
break;
}
if (dst_pos >= buffer_size - 1 || !*t_cur)
break;
// t_cur is now pointing to a '$' character
id_type = dash_read_tmpl_id(t_cur, format_tag, sizeof(format_tag), &t_next);
switch (id_type) {
case DASH_TMPL_ID_ESCAPE:
av_strlcpy(&dst[dst_pos], "$", 2);
n = 1;
break;
case DASH_TMPL_ID_REP_ID:
n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, rep_id);
break;
case DASH_TMPL_ID_NUMBER:
n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, number);
break;
case DASH_TMPL_ID_BANDWIDTH:
n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, bit_rate);
break;
case DASH_TMPL_ID_TIME:
n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, time);
break;
case DASH_TMPL_ID_UNDEFINED:
// copy over one byte and advance
av_strlcpy(&dst[dst_pos], t_cur, 2);
n = 1;
t_next = &t_cur[1];
break;
}
// t_next points just past the processed identifier
// n is the number of bytes that were attempted to be written to dst
// (may have failed to write all because buffer_size).
// advance
dst_pos += FFMIN(n, buffer_size - dst_pos - 1);
t_cur = t_next;
}
}

39
externals/ffmpeg/libavformat/dash.h vendored Executable file
View File

@@ -0,0 +1,39 @@
/*
* MPEG-DASH ISO BMFF segmenter
* Copyright (c) 2014 Martin Storsjo
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFORMAT_DASH_H
#define AVFORMAT_DASH_H
#include "avformat.h"
// See ISO/IEC 23009-1:2014 5.3.9.4.4
typedef enum {
DASH_TMPL_ID_UNDEFINED = -1,
DASH_TMPL_ID_ESCAPE,
DASH_TMPL_ID_REP_ID,
DASH_TMPL_ID_NUMBER,
DASH_TMPL_ID_BANDWIDTH,
DASH_TMPL_ID_TIME,
} DASHTmplId;
void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size, const char *template, int rep_id, int number, int bit_rate, int64_t time);
#endif /* AVFORMAT_DASH_H */

2418
externals/ffmpeg/libavformat/dashdec.c vendored Executable file

File diff suppressed because it is too large Load Diff

2398
externals/ffmpeg/libavformat/dashenc.c vendored Executable file

File diff suppressed because it is too large Load Diff

118
externals/ffmpeg/libavformat/data_uri.c vendored Executable file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2012 Nicolas George
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include "libavutil/avstring.h"
#include "libavutil/base64.h"
#include "url.h"
typedef struct {
const uint8_t *data;
void *tofree;
size_t size;
size_t pos;
} DataContext;
static av_cold int data_open(URLContext *h, const char *uri, int flags)
{
DataContext *dc = h->priv_data;
const char *data, *opt, *next;
char *ddata;
int ret, base64 = 0;
size_t in_size;
/* data:content/type[;base64],payload */
av_strstart(uri, "data:", &uri);
data = strchr(uri, ',');
if (!data) {
av_log(h, AV_LOG_ERROR, "No ',' delimiter in URI\n");
return AVERROR(EINVAL);
}
opt = uri;
while (opt < data) {
next = av_x_if_null(memchr(opt, ';', data - opt), data);
if (opt == uri) {
if (!memchr(opt, '/', next - opt)) { /* basic validity check */
av_log(h, AV_LOG_ERROR, "Invalid content-type '%.*s'\n",
(int)(next - opt), opt);
return AVERROR(EINVAL);
}
av_log(h, AV_LOG_VERBOSE, "Content-type: %.*s\n",
(int)(next - opt), opt);
} else {
if (!av_strncasecmp(opt, "base64", next - opt)) {
base64 = 1;
} else {
av_log(h, AV_LOG_VERBOSE, "Ignoring option '%.*s'\n",
(int)(next - opt), opt);
}
}
opt = next + 1;
}
data++;
in_size = strlen(data);
if (base64) {
size_t out_size = 3 * (in_size / 4) + 1;
if (out_size > INT_MAX || !(ddata = av_malloc(out_size)))
return AVERROR(ENOMEM);
if ((ret = av_base64_decode(ddata, data, out_size)) < 0) {
av_free(ddata);
av_log(h, AV_LOG_ERROR, "Invalid base64 in URI\n");
return ret;
}
dc->data = dc->tofree = ddata;
dc->size = ret;
} else {
dc->data = data;
dc->size = in_size;
}
return 0;
}
static av_cold int data_close(URLContext *h)
{
DataContext *dc = h->priv_data;
av_freep(&dc->tofree);
return 0;
}
static int data_read(URLContext *h, unsigned char *buf, int size)
{
DataContext *dc = h->priv_data;
if (dc->pos >= dc->size)
return AVERROR_EOF;
size = FFMIN(size, dc->size - dc->pos);
memcpy(buf, dc->data + dc->pos, size);
dc->pos += size;
return size;
}
const URLProtocol ff_data_protocol = {
.name = "data",
.url_open = data_open,
.url_close = data_close,
.url_read = data_read,
.priv_data_size = sizeof(DataContext),
};

59
externals/ffmpeg/libavformat/dauddec.c vendored Executable file
View File

@@ -0,0 +1,59 @@
/*
* D-Cinema audio demuxer
* Copyright (c) 2005 Reimar Döffinger
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "avformat.h"
static int daud_header(AVFormatContext *s) {
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S24DAUD;
st->codecpar->codec_tag = MKTAG('d', 'a', 'u', 'd');
st->codecpar->channels = 6;
st->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1;
st->codecpar->sample_rate = 96000;
st->codecpar->bit_rate = 3 * 6 * 96000 * 8;
st->codecpar->block_align = 3 * 6;
st->codecpar->bits_per_coded_sample = 24;
return 0;
}
static int daud_packet(AVFormatContext *s, AVPacket *pkt) {
AVIOContext *pb = s->pb;
int ret, size;
if (avio_feof(pb))
return AVERROR(EIO);
size = avio_rb16(pb);
avio_rb16(pb); // unknown
ret = av_get_packet(pb, pkt, size);
pkt->stream_index = 0;
return ret;
}
AVInputFormat ff_daud_demuxer = {
.name = "daud",
.long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"),
.read_header = daud_header,
.read_packet = daud_packet,
.extensions = "302,daud",
};

Some files were not shown because too many files have changed in this diff Show More