* jamrial/adpcm: ADPCM IMA Radical decoder RedSpark demuxer RSD demuxer adpcm_thp: Allow the use of extradata for the adpcm table ADP demuxer ADPCM DTK decoder Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.0
@@ -40,6 +40,11 @@ version <next>: | |||
- Matroska muxer can now put the index at the beginning of the file. | |||
- extractplanes filter | |||
- avectorscope filter | |||
- ADPCM DTK decoder | |||
- ADP demuxer | |||
- RSD demuxer | |||
- RedSpark demuxer | |||
- ADPCM IMA Radical decoder | |||
version 1.2: | |||
@@ -147,6 +147,8 @@ library: | |||
@tab Multimedia format used in game Heart Of Darkness. | |||
@item Apple HTTP Live Streaming @tab @tab X | |||
@item Artworx Data Format @tab @tab X | |||
@item ADP @tab @tab X | |||
@tab Audio format used on the Nintendo Gamecube. | |||
@item AFC @tab @tab X | |||
@tab Audio format used on the Nintendo Gamecube. | |||
@item ASF @tab X @tab X | |||
@@ -348,11 +350,13 @@ library: | |||
@tab File format used by RED Digital cameras, contains JPEG 2000 frames and PCM audio. | |||
@item RealMedia @tab X @tab X | |||
@item Redirector @tab @tab X | |||
@item RedSpark @tab @tab X | |||
@item Renderware TeXture Dictionary @tab @tab X | |||
@item RL2 @tab @tab X | |||
@tab Audio and video format used in some games by Entertainment Software Partners. | |||
@item RPL/ARMovie @tab @tab X | |||
@item Lego Mindstorms RSO @tab X @tab X | |||
@item RSD @tab @tab X | |||
@item RTMP @tab X @tab X | |||
@tab Output is performed by publishing stream to RTMP server | |||
@item RTP @tab X @tab X | |||
@@ -768,9 +772,11 @@ following image formats are supported: | |||
@tab Used in some Sega Saturn console games. | |||
@item ADPCM IMA Duck DK4 @tab @tab X | |||
@tab Used in some Sega Saturn console games. | |||
@item ADPCM IMA Radical @tab @tab X | |||
@item ADPCM Microsoft @tab X @tab X | |||
@item ADPCM MS IMA @tab X @tab X | |||
@item ADPCM Nintendo Gamecube AFC @tab @tab X | |||
@item ADPCM Nintendo Gamecube DTK @tab @tab X | |||
@item ADPCM Nintendo Gamecube THP @tab @tab X | |||
@item ADPCM QT IMA @tab X @tab X | |||
@item ADPCM SEGA CRI ADX @tab X @tab X | |||
@@ -569,6 +569,7 @@ OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o | |||
OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o adx.o | |||
OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_DTK_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_EA_MAXIS_XA_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o adpcm_data.o | |||
@@ -589,6 +590,7 @@ OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcmenc.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_RAD_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o adpcm_data.o | |||
OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcmenc.o adpcm_data.o | |||
@@ -95,6 +95,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) | |||
unsigned int max_channels = 2; | |||
switch(avctx->codec->id) { | |||
case AV_CODEC_ID_ADPCM_DTK: | |||
case AV_CODEC_ID_ADPCM_EA: | |||
min_channels = 2; | |||
break; | |||
@@ -147,6 +148,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) | |||
case AV_CODEC_ID_ADPCM_EA_XAS: | |||
case AV_CODEC_ID_ADPCM_THP: | |||
case AV_CODEC_ID_ADPCM_AFC: | |||
case AV_CODEC_ID_ADPCM_DTK: | |||
avctx->sample_fmt = AV_SAMPLE_FMT_S16P; | |||
break; | |||
case AV_CODEC_ID_ADPCM_IMA_WS: | |||
@@ -549,6 +551,11 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, | |||
buf_size = FFMIN(buf_size, avctx->block_align); | |||
nb_samples = 1 + (buf_size - 4 * ch) * 2 / ch; | |||
break; | |||
case AV_CODEC_ID_ADPCM_IMA_RAD: | |||
if (avctx->block_align > 0) | |||
buf_size = FFMIN(buf_size, avctx->block_align); | |||
nb_samples = (buf_size - 4 * ch) * 2 / ch; | |||
break; | |||
case AV_CODEC_ID_ADPCM_IMA_WAV: | |||
if (avctx->block_align > 0) | |||
buf_size = FFMIN(buf_size, avctx->block_align); | |||
@@ -590,6 +597,10 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, | |||
break; | |||
} | |||
case AV_CODEC_ID_ADPCM_THP: | |||
if (avctx->extradata) { | |||
nb_samples = buf_size / (8 * ch) * 14; | |||
break; | |||
} | |||
has_coded_samples = 1; | |||
bytestream2_skip(gb, 4); // channel size | |||
*coded_samples = bytestream2_get_be32(gb); | |||
@@ -602,6 +613,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, | |||
case AV_CODEC_ID_ADPCM_XA: | |||
nb_samples = (buf_size / 128) * 224 / ch; | |||
break; | |||
case AV_CODEC_ID_ADPCM_DTK: | |||
nb_samples = buf_size / (16 * ch) * 28; | |||
break; | |||
} | |||
/* validate coded sample count */ | |||
@@ -903,6 +917,31 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
*samples++ = adpcm_ima_oki_expand_nibble(&c->status[st], v & 0x0F); | |||
} | |||
break; | |||
case AV_CODEC_ID_ADPCM_IMA_RAD: | |||
for (channel = 0; channel < avctx->channels; channel++) { | |||
cs = &c->status[channel]; | |||
cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); | |||
cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); | |||
if (cs->step_index > 88u){ | |||
av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", | |||
channel, cs->step_index); | |||
return AVERROR_INVALIDDATA; | |||
} | |||
} | |||
for (n = 0; n < nb_samples / 2; n++) { | |||
int byte[2]; | |||
byte[0] = bytestream2_get_byteu(&gb); | |||
if (st) | |||
byte[1] = bytestream2_get_byteu(&gb); | |||
for(channel = 0; channel < avctx->channels; channel++) { | |||
*samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] & 0x0F, 3); | |||
} | |||
for(channel = 0; channel < avctx->channels; channel++) { | |||
*samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] >> 4 , 3); | |||
} | |||
} | |||
break; | |||
case AV_CODEC_ID_ADPCM_IMA_WS: | |||
if (c->vqa_version == 3) { | |||
for (channel = 0; channel < avctx->channels; channel++) { | |||
@@ -1320,6 +1359,18 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
int table[6][16]; | |||
int ch; | |||
if (avctx->extradata) { | |||
GetByteContext tb; | |||
if (avctx->extradata_size < 32 * avctx->channels) { | |||
av_log(avctx, AV_LOG_ERROR, "Missing coeff table\n"); | |||
return AVERROR_INVALIDDATA; | |||
} | |||
bytestream2_init(&tb, avctx->extradata, avctx->extradata_size); | |||
for (i = 0; i < avctx->channels; i++) | |||
for (n = 0; n < 16; n++) | |||
table[i][n] = sign_extend(bytestream2_get_be16u(&tb), 16); | |||
} else { | |||
for (i = 0; i < avctx->channels; i++) | |||
for (n = 0; n < 16; n++) | |||
table[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16); | |||
@@ -1329,6 +1380,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
c->status[i].sample1 = sign_extend(bytestream2_get_be16u(&gb), 16); | |||
c->status[i].sample2 = sign_extend(bytestream2_get_be16u(&gb), 16); | |||
} | |||
} | |||
for (ch = 0; ch < avctx->channels; ch++) { | |||
samples = samples_p[ch]; | |||
@@ -1362,6 +1414,54 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
} | |||
break; | |||
} | |||
case AV_CODEC_ID_ADPCM_DTK: | |||
for (channel = 0; channel < avctx->channels; channel++) { | |||
samples = samples_p[channel]; | |||
/* Read in every sample for this channel. */ | |||
for (i = 0; i < nb_samples / 28; i++) { | |||
int byte, header; | |||
if (channel) | |||
bytestream2_skipu(&gb, 1); | |||
header = bytestream2_get_byteu(&gb); | |||
bytestream2_skipu(&gb, 3 - channel); | |||
/* Decode 28 samples. */ | |||
for (n = 0; n < 28; n++) { | |||
int32_t sampledat, prev; | |||
switch (header >> 4) { | |||
case 1: | |||
prev = (c->status[channel].sample1 * 0x3c); | |||
break; | |||
case 2: | |||
prev = (c->status[channel].sample1 * 0x73) - (c->status[channel].sample2 * 0x34); | |||
break; | |||
case 3: | |||
prev = (c->status[channel].sample1 * 0x62) - (c->status[channel].sample2 * 0x37); | |||
break; | |||
default: | |||
prev = 0; | |||
} | |||
prev = av_clip((prev + 0x20) >> 6, -0x200000, 0x1fffff); | |||
byte = bytestream2_get_byteu(&gb); | |||
if (!channel) | |||
sampledat = sign_extend(byte, 4); | |||
else | |||
sampledat = sign_extend(byte >> 4, 4); | |||
sampledat = (((sampledat << 12) >> (header & 0xf)) << 6) + prev; | |||
*samples++ = av_clip_int16(sampledat >> 6); | |||
c->status[channel].sample2 = c->status[channel].sample1; | |||
c->status[channel].sample1 = sampledat; | |||
} | |||
} | |||
if (!channel) | |||
bytestream2_seek(&gb, 0, SEEK_SET); | |||
} | |||
break; | |||
default: | |||
return -1; | |||
@@ -1403,6 +1503,7 @@ AVCodec ff_ ## name_ ## _decoder = { \ | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM, sample_fmts_s16p, adpcm_4xm, "ADPCM 4X Movie"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nintendo Gamecube AFC"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_CT, sample_fmts_s16, adpcm_ct, "ADPCM Creative Technology"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_DTK, sample_fmts_s16p, adpcm_dtk, "ADPCM Nintendo Gamecube DTK"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA, sample_fmts_s16, adpcm_ea, "ADPCM Electronic Arts"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_MAXIS_XA, sample_fmts_s16, adpcm_ea_maxis_xa, "ADPCM Electronic Arts Maxis CDROM XA"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R1, sample_fmts_s16p, adpcm_ea_r1, "ADPCM Electronic Arts R1"); | |||
@@ -1418,6 +1519,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_RAD, sample_fmts_s16, adpcm_ima_rad, "ADPCM IMA Radical"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG, sample_fmts_s16, adpcm_ima_smjpeg, "ADPCM IMA Loki SDL MJPEG"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV, sample_fmts_s16p, adpcm_ima_wav, "ADPCM IMA WAV"); | |||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS, sample_fmts_both, adpcm_ima_ws, "ADPCM IMA Westwood"); | |||
@@ -38,8 +38,8 @@ typedef struct ADPCMChannelStatus { | |||
int prev_sample; | |||
/* MS version */ | |||
int16_t sample1; | |||
int16_t sample2; | |||
int sample1; | |||
int sample2; | |||
int coeff1; | |||
int coeff2; | |||
int idelta; | |||
@@ -419,6 +419,7 @@ void avcodec_register_all(void) | |||
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx); | |||
REGISTER_DECODER(ADPCM_AFC, adpcm_afc); | |||
REGISTER_DECODER(ADPCM_CT, adpcm_ct); | |||
REGISTER_DECODER(ADPCM_DTK, adpcm_dtk); | |||
REGISTER_DECODER(ADPCM_EA, adpcm_ea); | |||
REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa); | |||
REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1); | |||
@@ -436,6 +437,7 @@ void avcodec_register_all(void) | |||
REGISTER_DECODER(ADPCM_IMA_ISS, adpcm_ima_iss); | |||
REGISTER_DECODER(ADPCM_IMA_OKI, adpcm_ima_oki); | |||
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt); | |||
REGISTER_DECODER(ADPCM_IMA_RAD, adpcm_ima_rad); | |||
REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg); | |||
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav); | |||
REGISTER_DECODER(ADPCM_IMA_WS, adpcm_ima_ws); | |||
@@ -362,6 +362,8 @@ enum AVCodecID { | |||
AV_CODEC_ID_VIMA = MKBETAG('V','I','M','A'), | |||
AV_CODEC_ID_ADPCM_AFC = MKBETAG('A','F','C',' '), | |||
AV_CODEC_ID_ADPCM_IMA_OKI = MKBETAG('O','K','I',' '), | |||
AV_CODEC_ID_ADPCM_DTK = MKBETAG('D','T','K',' '), | |||
AV_CODEC_ID_ADPCM_IMA_RAD = MKBETAG('R','A','D',' '), | |||
/* AMR */ | |||
AV_CODEC_ID_AMR_NB = 0x12000, | |||
@@ -1816,6 +1816,20 @@ static const AVCodecDescriptor codec_descriptors[] = { | |||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Dialogic OKI"), | |||
.props = AV_CODEC_PROP_LOSSY, | |||
}, | |||
{ | |||
.id = AV_CODEC_ID_ADPCM_DTK, | |||
.type = AVMEDIA_TYPE_AUDIO, | |||
.name = "adpcm_dtk", | |||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube DTK"), | |||
.props = AV_CODEC_PROP_LOSSY, | |||
}, | |||
{ | |||
.id = AV_CODEC_ID_ADPCM_IMA_RAD, | |||
.type = AVMEDIA_TYPE_AUDIO, | |||
.name = "adpcm_ima_rad", | |||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Radical"), | |||
.props = AV_CODEC_PROP_LOSSY, | |||
}, | |||
/* AMR */ | |||
{ | |||
@@ -2835,6 +2835,8 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) | |||
switch (id) { | |||
case AV_CODEC_ID_ADPCM_AFC: | |||
return frame_bytes / (9 * ch) * 16; | |||
case AV_CODEC_ID_ADPCM_DTK: | |||
return frame_bytes / (16 * ch) * 28; | |||
case AV_CODEC_ID_ADPCM_4XM: | |||
case AV_CODEC_ID_ADPCM_IMA_ISS: | |||
return (frame_bytes - 4 * ch) * 2 / ch; | |||
@@ -2881,6 +2883,8 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) | |||
return blocks * (((ba - 16) * 2 / 3 * 4) / ch); | |||
case AV_CODEC_ID_ADPCM_IMA_DK4: | |||
return blocks * (1 + (ba - 4 * ch) * 2 / ch); | |||
case AV_CODEC_ID_ADPCM_IMA_RAD: | |||
return blocks * ((ba - 4 * ch) * 2 / ch); | |||
case AV_CODEC_ID_ADPCM_MS: | |||
return blocks * (2 + (ba - 7 * ch) * 2 / ch); | |||
} | |||
@@ -29,7 +29,7 @@ | |||
#include "libavutil/avutil.h" | |||
#define LIBAVCODEC_VERSION_MAJOR 55 | |||
#define LIBAVCODEC_VERSION_MINOR 7 | |||
#define LIBAVCODEC_VERSION_MINOR 9 | |||
#define LIBAVCODEC_VERSION_MICRO 100 | |||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | |||
@@ -55,6 +55,7 @@ OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o | |||
OBJS-$(CONFIG_AC3_MUXER) += rawenc.o | |||
OBJS-$(CONFIG_ACT_DEMUXER) += act.o | |||
OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o | |||
OBJS-$(CONFIG_ADP_DEMUXER) += adp.o | |||
OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o | |||
OBJS-$(CONFIG_ADX_MUXER) += rawenc.o | |||
OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o | |||
@@ -307,11 +308,13 @@ 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_RSO_DEMUXER) += rsodec.o rso.o pcm.o | |||
OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o | |||
OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o | |||
@@ -0,0 +1,91 @@ | |||
/* | |||
* 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(AVProbeData *p) | |||
{ | |||
int i; | |||
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; | |||
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->codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||
st->codec->codec_id = AV_CODEC_ID_ADPCM_DTK; | |||
st->codec->channel_layout = AV_CH_LAYOUT_STEREO; | |||
st->codec->channels = 2; | |||
st->codec->sample_rate = 48000; | |||
st->start_time = 0; | |||
if (s->pb->seekable) | |||
st->duration = av_get_audio_frame_duration(st->codec, avio_size(s->pb)); | |||
avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); | |||
return 0; | |||
} | |||
static int adp_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
{ | |||
int ret, size = 1024; | |||
if (url_feof(s->pb)) | |||
return AVERROR_EOF; | |||
ret = av_get_packet(s->pb, pkt, size); | |||
if (ret != size) { | |||
if (ret < 0) { | |||
av_free_packet(pkt); | |||
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", | |||
}; |
@@ -65,6 +65,7 @@ void av_register_all(void) | |||
REGISTER_MUXDEMUX(AC3, ac3); | |||
REGISTER_DEMUXER (ACT, act); | |||
REGISTER_DEMUXER (ADF, adf); | |||
REGISTER_DEMUXER (ADP, adp); | |||
REGISTER_MUXER (ADTS, adts); | |||
REGISTER_MUXDEMUX(ADX, adx); | |||
REGISTER_DEMUXER (AEA, aea); | |||
@@ -232,10 +233,12 @@ void av_register_all(void) | |||
REGISTER_DEMUXER (R3D, r3d); | |||
REGISTER_MUXDEMUX(RAWVIDEO, rawvideo); | |||
REGISTER_DEMUXER (REALTEXT, realtext); | |||
REGISTER_DEMUXER (REDSPARK, redspark); | |||
REGISTER_DEMUXER (RL2, rl2); | |||
REGISTER_MUXDEMUX(RM, rm); | |||
REGISTER_MUXDEMUX(ROQ, roq); | |||
REGISTER_DEMUXER (RPL, rpl); | |||
REGISTER_DEMUXER (RSD, rsd); | |||
REGISTER_MUXDEMUX(RSO, rso); | |||
REGISTER_MUXDEMUX(RTP, rtp); | |||
REGISTER_MUXDEMUX(RTSP, rtsp); | |||
@@ -0,0 +1,157 @@ | |||
/* | |||
* RedSpark 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 "libavcodec/bytestream.h" | |||
#include "libavutil/intreadwrite.h" | |||
#include "avformat.h" | |||
#include "avio.h" | |||
#include "internal.h" | |||
#define HEADER_SIZE 4096 | |||
typedef struct RedSparkContext { | |||
int samples_count; | |||
} RedSparkContext; | |||
static int redspark_probe(AVProbeData *p) | |||
{ | |||
uint32_t key, data; | |||
uint8_t header[8]; | |||
/* Decrypt first 8 bytes of the header */ | |||
data = AV_RB32(p->buf); | |||
data = data ^ (key = data ^ 0x52656453); | |||
AV_WB32(header, data); | |||
key = (key << 11) | (key >> 21); | |||
data = AV_RB32(p->buf + 4) ^ (((key << 3) | (key >> 29)) + key); | |||
AV_WB32(header + 4, data); | |||
if (AV_RB64(header) == AV_RB64("RedSpark")) | |||
return AVPROBE_SCORE_MAX; | |||
return 0; | |||
} | |||
static int redspark_read_header(AVFormatContext *s) | |||
{ | |||
AVIOContext *pb = s->pb; | |||
RedSparkContext *redspark = s->priv_data; | |||
AVCodecContext *codec; | |||
GetByteContext gbc; | |||
int i, coef_off; | |||
uint32_t key, data; | |||
uint8_t *header, *pbc; | |||
AVStream *st; | |||
st = avformat_new_stream(s, NULL); | |||
if (!st) | |||
return AVERROR(ENOMEM); | |||
codec = st->codec; | |||
header = av_malloc(HEADER_SIZE); | |||
if (!header) | |||
return AVERROR(ENOMEM); | |||
pbc = header; | |||
/* Decrypt header */ | |||
data = avio_rb32(pb); | |||
data = data ^ (key = data ^ 0x52656453); | |||
bytestream_put_be32(&pbc, data); | |||
key = (key << 11) | (key >> 21); | |||
for (i = 4; i < HEADER_SIZE; i += 4) { | |||
data = avio_rb32(pb) ^ (key = ((key << 3) | (key >> 29)) + key); | |||
bytestream_put_be32(&pbc, data); | |||
} | |||
codec->codec_id = AV_CODEC_ID_ADPCM_THP; | |||
codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||
bytestream2_init(&gbc, header, HEADER_SIZE); | |||
bytestream2_seek(&gbc, 0x3c, SEEK_SET); | |||
codec->sample_rate = bytestream2_get_be32u(&gbc); | |||
if (codec->sample_rate <= 0 || codec->sample_rate > 96000) { | |||
av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", codec->sample_rate); | |||
return AVERROR_INVALIDDATA; | |||
} | |||
st->duration = bytestream2_get_be32u(&gbc) * 14; | |||
redspark->samples_count = 0; | |||
bytestream2_skipu(&gbc, 10); | |||
codec->channels = bytestream2_get_byteu(&gbc); | |||
if (!codec->channels) | |||
return AVERROR_INVALIDDATA; | |||
coef_off = 0x54 + codec->channels * 8; | |||
if (bytestream2_get_byteu(&gbc)) // Loop flag | |||
coef_off += 16; | |||
codec->extradata_size = 32 * codec->channels; | |||
codec->extradata = av_malloc(codec->extradata_size); | |||
if (!codec->extradata) | |||
return AVERROR(ENOMEM); | |||
/* Get the ADPCM table */ | |||
bytestream2_seek(&gbc, coef_off, SEEK_SET); | |||
for (i = 0; i < codec->channels; i++) { | |||
if (bytestream2_get_bufferu(&gbc, codec->extradata + i * 32, 32) != 32) | |||
return AVERROR_INVALIDDATA; | |||
bytestream2_skipu(&gbc, 14); | |||
} | |||
avpriv_set_pts_info(st, 64, 1, codec->sample_rate); | |||
return 0; | |||
} | |||
static int redspark_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
{ | |||
AVCodecContext *codec = s->streams[0]->codec; | |||
RedSparkContext *redspark = s->priv_data; | |||
uint32_t size = 8 * codec->channels; | |||
int ret; | |||
if (url_feof(s->pb) || redspark->samples_count == s->streams[0]->duration) | |||
return AVERROR_EOF; | |||
ret = av_get_packet(s->pb, pkt, size); | |||
if (ret != size) { | |||
av_free_packet(pkt); | |||
return AVERROR(EIO); | |||
} | |||
pkt->duration = 14; | |||
redspark->samples_count += pkt->duration; | |||
pkt->stream_index = 0; | |||
return ret; | |||
} | |||
AVInputFormat ff_redspark_demuxer = { | |||
.name = "redspark", | |||
.long_name = NULL_IF_CONFIG_SMALL("RedSpark"), | |||
.priv_data_size = sizeof(RedSparkContext), | |||
.read_probe = redspark_probe, | |||
.read_header = redspark_read_header, | |||
.read_packet = redspark_read_packet, | |||
.extensions = "rsd", | |||
}; |
@@ -0,0 +1,170 @@ | |||
/* | |||
* RSD 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 "libavcodec/bytestream.h" | |||
#include "libavutil/intreadwrite.h" | |||
#include "avformat.h" | |||
#include "avio.h" | |||
#include "internal.h" | |||
static const AVCodecTag rsd_tags[] = { | |||
{ AV_CODEC_ID_ADPCM_THP, MKTAG('G','A','D','P') }, | |||
{ AV_CODEC_ID_ADPCM_IMA_RAD, MKTAG('R','A','D','P') }, | |||
{ AV_CODEC_ID_PCM_S16BE, MKTAG('P','C','M','B') }, | |||
{ AV_CODEC_ID_PCM_S16LE, MKTAG('P','C','M',' ') }, | |||
{ AV_CODEC_ID_NONE, 0 }, | |||
}; | |||
static const uint32_t rsd_unsupported_tags[] = { | |||
MKTAG('O','G','G',' '), | |||
MKTAG('V','A','G',' '), | |||
MKTAG('W','A','D','P'), | |||
MKTAG('X','A','D','P'), | |||
MKTAG('X','M','A',' '), | |||
}; | |||
static int rsd_probe(AVProbeData *p) | |||
{ | |||
if (!memcmp(p->buf, "RSD", 3) && | |||
p->buf[3] - '0' >= 2 && p->buf[3] - '0' <= 6) | |||
return AVPROBE_SCORE_EXTENSION; | |||
return 0; | |||
} | |||
static int rsd_read_header(AVFormatContext *s) | |||
{ | |||
AVIOContext *pb = s->pb; | |||
int i, version, start = 0x800; | |||
AVCodecContext *codec; | |||
AVStream *st = avformat_new_stream(s, NULL); | |||
if (!st) | |||
return AVERROR(ENOMEM); | |||
avio_skip(pb, 3); // "RSD" | |||
version = avio_r8(pb) - '0'; | |||
codec = st->codec; | |||
codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||
codec->codec_tag = avio_rl32(pb); | |||
codec->codec_id = ff_codec_get_id(rsd_tags, codec->codec_tag); | |||
if (!codec->codec_id) { | |||
char tag_buf[5]; | |||
av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag); | |||
for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) { | |||
if (codec->codec_tag == rsd_unsupported_tags[i]) { | |||
avpriv_request_sample(s, "Codec tag: %s", tag_buf); | |||
return AVERROR_PATCHWELCOME; | |||
} | |||
} | |||
av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf); | |||
return AVERROR_INVALIDDATA; | |||
} | |||
codec->channels = avio_rl32(pb); | |||
if (!codec->channels) | |||
return AVERROR_INVALIDDATA; | |||
avio_skip(pb, 4); // Bit depth | |||
codec->sample_rate = avio_rl32(pb); | |||
if (!codec->sample_rate) | |||
return AVERROR_INVALIDDATA; | |||
avio_skip(pb, 4); // Unknown | |||
switch (codec->codec_id) { | |||
case AV_CODEC_ID_ADPCM_IMA_RAD: | |||
codec->block_align = 20 * codec->channels; | |||
if (pb->seekable) | |||
st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); | |||
break; | |||
case AV_CODEC_ID_ADPCM_THP: | |||
/* RSD3GADP is mono, so only alloc enough memory | |||
to store the coeff table for a single channel. */ | |||
codec->extradata_size = 32; | |||
codec->extradata = av_malloc(codec->extradata_size); | |||
if (!codec->extradata) | |||
return AVERROR(ENOMEM); | |||
start = avio_rl32(pb); | |||
if (avio_read(s->pb, codec->extradata, 32) != 32) | |||
return AVERROR_INVALIDDATA; | |||
for (i = 0; i < 16; i++) | |||
AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); | |||
if (pb->seekable) | |||
st->duration = (avio_size(pb) - start) / 8 * 14; | |||
break; | |||
case AV_CODEC_ID_PCM_S16LE: | |||
case AV_CODEC_ID_PCM_S16BE: | |||
if (version != 4) | |||
start = avio_rl32(pb); | |||
if (pb->seekable) | |||
st->duration = (avio_size(pb) - start) / 2 / codec->channels; | |||
break; | |||
} | |||
avio_skip(pb, start - avio_tell(pb)); | |||
avpriv_set_pts_info(st, 64, 1, codec->sample_rate); | |||
return 0; | |||
} | |||
static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
{ | |||
AVCodecContext *codec = s->streams[0]->codec; | |||
int ret, size = 1024; | |||
if (url_feof(s->pb)) | |||
return AVERROR_EOF; | |||
if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD) | |||
ret = av_get_packet(s->pb, pkt, codec->block_align); | |||
else | |||
ret = av_get_packet(s->pb, pkt, size); | |||
if (ret != size) { | |||
if (ret < 0) { | |||
av_free_packet(pkt); | |||
return ret; | |||
} | |||
av_shrink_packet(pkt, ret); | |||
} | |||
pkt->stream_index = 0; | |||
return ret; | |||
} | |||
AVInputFormat ff_rsd_demuxer = { | |||
.name = "rsd", | |||
.long_name = NULL_IF_CONFIG_SMALL("GameCube RSD"), | |||
.read_probe = rsd_probe, | |||
.read_header = rsd_read_header, | |||
.read_packet = rsd_read_packet, | |||
.extensions = "rsd", | |||
.codec_tag = (const AVCodecTag* const []){rsd_tags, 0}, | |||
}; |
@@ -30,8 +30,8 @@ | |||
#include "libavutil/avutil.h" | |||
#define LIBAVFORMAT_VERSION_MAJOR 55 | |||
#define LIBAVFORMAT_VERSION_MINOR 4 | |||
#define LIBAVFORMAT_VERSION_MICRO 101 | |||
#define LIBAVFORMAT_VERSION_MINOR 7 | |||
#define LIBAVFORMAT_VERSION_MICRO 100 | |||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | |||
LIBAVFORMAT_VERSION_MINOR, \ | |||
@@ -16,6 +16,9 @@ fate-adpcm-creative-8-2.6bit: CMD = md5 -i $(SAMPLES)/creative/BBC_3BIT.VOC -f s | |||
FATE_ADPCM-$(call DEMDEC, VOC, ADPCM_SBPRO_4) += fate-adpcm-creative-8-4bit | |||
fate-adpcm-creative-8-4bit: CMD = md5 -i $(SAMPLES)/creative/BBC_4BIT.VOC -f s16le | |||
FATE_ADPCM-$(call DEMDEC, ADP, ADPCM_DTK) += fate-adpcm-dtk | |||
fate-adpcm-dtk: CMD = framecrc -i $(SAMPLES)/adp/shakespr_partial.adp -f s16le | |||
FATE_ADPCM-$(call DEMDEC, EA, ADPCM_EA) += fate-adpcm-ea-1 | |||
fate-adpcm-ea-1: CMD = framecrc -i $(SAMPLES)/ea-wve/networkBackbone-partial.wve -frames:a 26 -vn | |||
@@ -58,6 +61,9 @@ fate-adpcm-ima-iss: CMD = md5 -i $(SAMPLES)/funcom-iss/0004010100.iss -f s16le | |||
FATE_ADPCM-$(call DEMDEC, WAV, ADPCM_IMA_OKI) += fate-adpcm-ima-oki | |||
fate-adpcm-ima-oki: CMD = md5 -i $(SAMPLES)/oki/test.wav -f s16le | |||
FATE_ADPCM-$(call DEMDEC, RSD, ADPCM_IMA_RAD) += fate-adpcm-ima-rad | |||
fate-adpcm-ima-rad: CMD = md5 -i $(SAMPLES)/rsd/hit_run_partial.rsd -f s16le | |||
FATE_ADPCM-$(call DEMDEC, SMJPEG, ADPCM_IMA_SMJPEG) += fate-adpcm-ima-smjpeg | |||
fate-adpcm-ima-smjpeg: CMD = framecrc -i $(SAMPLES)/smjpeg/scenwin.mjpg -vn | |||
@@ -67,6 +67,12 @@ fate-paf-demux: CMD = framecrc -i $(SAMPLES)/paf/hod1-partial.paf -vcodec copy - | |||
FATE_SAMPLES_DEMUX-$(CONFIG_PMP_DEMUXER) += fate-pmp-demux | |||
fate-pmp-demux: CMD = framecrc -i $(SAMPLES)/pmp/demo.pmp -vn -c:a copy | |||
FATE_SAMPLES_DEMUX-$(CONFIG_RSD_DEMUXER) += fate-rsd-demux | |||
fate-rsd-demux: CMD = crc -i $(SAMPLES)/rsd/hum01_partial.rsd -c:a copy | |||
FATE_SAMPLES_DEMUX-$(CONFIG_REDSPARK_DEMUXER) += fate-redspark-demux | |||
fate-redspark-demux: CMD = crc -i $(SAMPLES)/redspark/jingle04_partial.rsd -c:a copy | |||
FATE_SAMPLES_DEMUX-$(CONFIG_STR_DEMUXER) += fate-psx-str-demux | |||
fate-psx-str-demux: CMD = framecrc -i $(SAMPLES)/psx-str/descent-partial.str -c copy | |||
@@ -0,0 +1,33 @@ | |||
#tb 0: 1/48000 | |||
0, 0, 0, 896, 3584, 0xdae789d5 | |||
0, 896, 896, 896, 3584, 0x168ed9b6 | |||
0, 1792, 1792, 896, 3584, 0x8920c8d5 | |||
0, 2688, 2688, 896, 3584, 0xaf0a3245 | |||
0, 3584, 3584, 896, 3584, 0x884ee935 | |||
0, 4480, 4480, 896, 3584, 0xe6a832ad | |||
0, 5376, 5376, 896, 3584, 0x1fa12ea2 | |||
0, 6272, 6272, 896, 3584, 0xf119198c | |||
0, 7168, 7168, 896, 3584, 0x0a6dbf72 | |||
0, 8064, 8064, 896, 3584, 0xd3467881 | |||
0, 8960, 8960, 896, 3584, 0x25d504ec | |||
0, 9856, 9856, 896, 3584, 0x452730c9 | |||
0, 10752, 10752, 896, 3584, 0x42b92ff1 | |||
0, 11648, 11648, 896, 3584, 0x85c67bf3 | |||
0, 12544, 12544, 896, 3584, 0xab4d99e9 | |||
0, 13440, 13440, 896, 3584, 0xe5bfc4da | |||
0, 14336, 14336, 896, 3584, 0x7a5210e9 | |||
0, 15232, 15232, 896, 3584, 0x5265fcd3 | |||
0, 16128, 16128, 896, 3584, 0x76531427 | |||
0, 17024, 17024, 896, 3584, 0xb2b8d7ab | |||
0, 17920, 17920, 896, 3584, 0x05a453e8 | |||
0, 18816, 18816, 896, 3584, 0x742c45bb | |||
0, 19712, 19712, 896, 3584, 0x57aaee3b | |||
0, 20608, 20608, 896, 3584, 0x997bf703 | |||
0, 21504, 21504, 896, 3584, 0xe2d14b13 | |||
0, 22400, 22400, 896, 3584, 0xdafbdd2f | |||
0, 23296, 23296, 896, 3584, 0x448cec3a | |||
0, 24192, 24192, 896, 3584, 0xe6f6fb9c | |||
0, 25088, 25088, 896, 3584, 0x0310276a | |||
0, 25984, 25984, 896, 3584, 0x44bf04e9 | |||
0, 26880, 26880, 896, 3584, 0xe2105d33 | |||
0, 27776, 27776, 896, 3584, 0x08b7d5e0 |
@@ -0,0 +1 @@ | |||
495f0ae514c28c6bdcbd40811a17e2a5 |
@@ -0,0 +1 @@ | |||
CRC=0xc0fd1aa2 |
@@ -0,0 +1 @@ | |||
CRC=0x7b7807d8 |