Commit 0147f198 authored by François Revol's avatar François Revol Committed by Michael Niedermayer

beos/mov/adpcm patch by François Revol <revol at free dot fr>

* Some BeOS fixes:
- errno stuff
- nanosleep() replacement
- added a doc/README.beos

* mov reader still has problems with most videos (skips many chunks),
- It should now read .mov files with zlib-compressed moov headers (aka cmov)
- added SVQ1 support.
- removed mapping 'raw ' and 'yuv2' to h263, was my mistake.
- added IMA4 support. (tested)
- fixed frame rate (it reported 0 fps or something before)
- extended file probing ('wide' and 'free' atoms)
- improved .mov/.mp4 detection (or so I think)

* adpcm
* added zlib support, with header file and lib check

Originally committed as revision 780 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent e1707f52
......@@ -3,6 +3,9 @@
#include <Errors.h>
// mmu_man: this is needed for http.c (defined errno)
#include <errno.h>
#ifdef ENOENT
#undef ENOENT
#endif
......
......@@ -43,6 +43,7 @@ gprof="no"
v4l="yes"
audio_oss="yes"
network="yes"
zlib="yes"
mp3lame="no"
a52="yes"
a52bin="no"
......@@ -123,6 +124,8 @@ for opt do
;;
--disable-network) network="no"
;;
--disable-zlib) zlib="no"
;;
--disable-a52) a52="no"
;;
--enable-a52bin) a52bin="yes" ; extralibs="-ldl $extralibs"
......@@ -195,6 +198,25 @@ EOF
$cc -o $TMPO $TMPC 2> /dev/null || _memalign=no
fi
if test "$zlib" = "yes"; then
# check for zlib - mmu_man
cat > $TMPC << EOF
#include <zlib.h>
int main ( void ) {
if (zlibVersion() != ZLIB_VERSION)
puts("zlib version differs !!!");
return 1;
return 0;
}
EOF
$cc -o $TMPO $TMPC -lz 2> /dev/null || zlib="no"
# $TMPO 2> /dev/null > /dev/null || zlib="no"
# XXX: more tests needed - runtime test
fi
if test "$zlib" = "yes"; then
extralibs="$extralibs -lz"
fi
_restrict=
for restrict_keyword in restrict __restrict__ __restrict; do
echo "void foo(char * $restrict_keyword p);" > $TMPC
......@@ -233,6 +255,7 @@ echo " --disable-mmx disable mmx usage"
echo " --disable-audio-oss disable OSS audio support [default=no]"
echo " --disable-v4l disable video4linux grabbing [default=no]"
echo " --disable-network disable network support [default=no]"
echo " --disable-zlib disable zlib [default=no]"
echo " --disable-simple_idct disable simple IDCT routines [default=no]"
echo " --enable-gprof enable profiling with gprof [$gprof]"
echo " --disable-mpegaudio-hp faster (but less accurate)"
......@@ -250,6 +273,7 @@ echo "CPU $cpu"
echo "Big Endian $bigendian"
echo "MMX enabled $mmx"
echo "gprof enabled $gprof"
echo "zlib enabled $zlib"
echo "mp3lame enabled $mp3lame"
echo "a52 support $a52"
echo "a52 dlopened $a52bin"
......@@ -339,6 +363,11 @@ if test "$network" = "yes" ; then
echo "CONFIG_NETWORK=yes" >> config.mak
fi
if test "$zlib" = "yes" ; then
echo "#define CONFIG_ZLIB 1" >> $TMPH
echo "CONFIG_ZLIB=yes" >> config.mak
fi
if test "$mp3lame" = "yes" ; then
echo "#define CONFIG_MP3LAME 1" >> $TMPH
echo "CONFIG_MP3LAME=yes" >> config.mak
......
Compilation on BeOS:
--------------------
François Revol - revol@free.fr - July 2002
The configure script should guess the configuration itself.
Networking support is currently not finished.
errno issues fixed by Andrew Bachmann.
Old stuff:
François Revol - revol@free.fr - April 2002
The configure script should guess the configuration itself,
however I still didn't tested building on net_server version of BeOS.
ffserver is broken (needs poll() implementation).
There is still issues with errno codes, which are negative in BeOs, and
that ffmpeg negates when returning. This ends up turning errors into
valid results, then crashes.
(To be fixed)
......@@ -19,12 +19,17 @@
#include "avformat.h"
#include "avi.h"
#ifdef CONFIG_ZLIB
#include <zlib.h>
#endif
/*
* First version by Francois Revol revol@free.fr
*
* Features and limitations:
* - reads most of the QT files I have (at least the structure),
* the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
* FIXED, Francois Revol, 07/17/2002
* - ffmpeg has nearly none of the usual QuickTime codecs,
* although I succesfully dumped raw and mp3 audio tracks off .mov files.
* Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
......@@ -79,8 +84,8 @@ void print_atom(const char *str, UINT32 type, UINT64 offset, UINT64 size)
static const CodecTag mov_video_tags[] = {
/* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
/* { CODEC_ID_JPEG, MKTAG('j', 'p', 'e', 'g') }, *//* JPEG */
{ CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, /* Uncompressed RGB */
{ CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, /* Uncompressed YUV422 */
/* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
/* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
/* Graphics */
/* Animation */
/* Apple video */
......@@ -91,9 +96,12 @@ static const CodecTag mov_video_tags[] = {
{ CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
/* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
/* Sorenson video */
{ CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
{ CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
{ CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, /* OpenDiVX *//* yeah ! */
{ CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
/* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
{ CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
{ 0, 0 },
};
......@@ -105,7 +113,7 @@ static const CodecTag mov_audio_tags[] = {
{ CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
{ CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
{ CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
/* { CODEC_ID_, MKTAG('i', 'm', 'a', '4') }, *//* IMA-4 */
{ CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
{ CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
{ CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
......@@ -139,6 +147,7 @@ typedef struct MOVStreamContext {
long sample_size;
long sample_count;
long *sample_sizes;
long time_scale;
} MOVStreamContext;
typedef struct MOVContext {
......@@ -266,6 +275,9 @@ static int parse_mvhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
get_be32(pb); /* creation time */
get_be32(pb); /* modification time */
c->time_scale = get_be32(pb); /* time scale */
#ifdef DEBUG
printf("time scale = %li\n", c->time_scale);
#endif
get_be32(pb); /* duration */
get_be32(pb); /* preferred scale */
......@@ -390,6 +402,38 @@ static int parse_tkhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
return 0;
}
static int parse_mdhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param)
{
MOVContext *c;
AVStream *st;
#ifdef DEBUG
print_atom("mdhd", atom_type, atom_offset, atom_size);
#endif
c = (MOVContext *)param;
st = c->fc->streams[c->fc->nb_streams-1];
get_byte(pb); /* version */
get_byte(pb); get_byte(pb);
get_byte(pb); /* flags */
get_be32(pb); /* creation time */
get_be32(pb); /* modification time */
c->streams[c->total_streams]->time_scale = get_be32(pb);
#ifdef DEBUG
printf("track[%i].time_scale = %li\n", c->fc->nb_streams-1, c->streams[c->total_streams]->time_scale); /* time scale */
#endif
get_be32(pb); /* duration */
get_be16(pb); /* language */
get_be16(pb); /* quality */
return 0;
}
static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param)
{
MOVContext *c;
......@@ -435,11 +479,15 @@ static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
#endif
if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */
/* helps parsing the string hereafter... */
c->mp4 = 0;
if(type == MKTAG('v', 'i', 'd', 'e'))
st->codec.codec_type = CODEC_TYPE_VIDEO;
else if(type == MKTAG('s', 'o', 'u', 'n'))
st->codec.codec_type = CODEC_TYPE_AUDIO;
} else if(ctype == 0) { /* MP4 */
/* helps parsing the string hereafter... */
c->mp4 = 1;
if(type == MKTAG('v', 'i', 'd', 'e'))
st->codec.codec_type = CODEC_TYPE_VIDEO;
else if(type == MKTAG('s', 'o', 'u', 'n'))
......@@ -453,6 +501,22 @@ static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
return 0; /* nothing left to read */
/* XXX: MP4 uses a C string, not a pascal one */
/* component name */
if(c->mp4) {
/* .mp4: C string */
while(get_byte(pb) && (++len < (atom_size - 24)));
} else {
/* .mov: PASCAL string */
len = get_byte(pb);
buf = av_malloc(len+1);
get_buffer(pb, buf, len);
buf[len] = '\0';
#ifdef DEBUG
printf("**buf='%s'\n", buf);
#endif
av_free(buf);
}
#if 0
len = get_byte(pb);
/* XXX: use a better heuristic */
if(len < 32) {
......@@ -472,6 +536,7 @@ static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
len = get_byte(pb);
}
}
#endif
return 0;
}
......@@ -559,7 +624,7 @@ static int parse_stsd(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
if(format == MKTAG('m', 'p', '4', 'v')) { /* XXX */
st->codec.codec_type=CODEC_TYPE_VIDEO; /* force things */
st->codec.codec_id = CODEC_ID_MPEG4;
st->codec.frame_rate = 25;
st->codec.frame_rate = 25 * FRAME_RATE_BASE;
st->codec.bit_rate = 100000;
}
......@@ -673,7 +738,9 @@ static int parse_stsz(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
sc->sample_size = get_be32(pb);
entries = get_be32(pb);
sc->sample_count = entries;
#ifdef DEBUG
printf("sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
#endif
if(sc->sample_size)
return 0; /* there isn't any table following */
sc->sample_sizes = av_malloc(entries * sizeof(long));
......@@ -686,6 +753,91 @@ static int parse_stsz(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
return 0;
}
static int parse_stts(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param)
{
MOVContext *c;
int entries, i;
AVStream *st;
MOVStreamContext *sc;
#ifdef DEBUG
print_atom("stts", atom_type, atom_offset, atom_size);
#endif
c = (MOVContext *)param;
st = c->fc->streams[c->fc->nb_streams-1];
sc = (MOVStreamContext *)st->priv_data;
get_byte(pb); /* version */
get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
entries = get_be32(pb);
for(i=0; i<entries; i++) {
int sample_duration;
get_be32(pb);
sample_duration = get_be32(pb);
if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) {
st->codec.frame_rate = FRAME_RATE_BASE * c->streams[c->total_streams]->time_scale / sample_duration;
#ifdef DEBUG
printf("VIDEO FRAME RATE= %li (sd= %li)\n", st->codec.frame_rate, sample_duration);
#endif
}
}
return 0;
}
#ifdef CONFIG_ZLIB
static int null_read_packet(void *opaque, UINT8 *buf, int buf_size)
{
return -1;
}
static int parse_cmov(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param)
{
MOVContext *c;
ByteIOContext ctx;
char *cmov_data;
unsigned char *moov_data; /* uncompressed data */
long cmov_len, moov_len;
int ret;
#ifdef DEBUG
print_atom("cmov", atom_type, atom_offset, atom_size);
#endif
c = (MOVContext *)param;
get_be32(pb); /* dcom atom */
if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
return -1;
if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
puts("unknown compression for cmov atom !");
return -1;
}
get_be32(pb); /* cmvd atom */
if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
return -1;
moov_len = get_be32(pb); /* uncompressed size */
cmov_len = atom_size - 6 * 4;
cmov_data = av_malloc(cmov_len);
if (!cmov_data)
return -1;
moov_data = av_malloc(moov_len);
if (!moov_data) {
av_free(cmov_data);
return -1;
}
get_buffer(pb, cmov_data, cmov_len);
if(uncompress (moov_data, &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
return -1;
if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
return -1;
ctx.buf_end = ctx.buffer + moov_len;
ret = parse_default(parse_table, &ctx, MKTAG( 'm', 'o', 'o', 'v' ), 0, moov_len, param);
av_free(moov_data);
av_free(cmov_data);
return ret;
}
#endif
static const MOVParseTableEntry mov_default_parse_table[] = {
/* mp4 atoms */
{ MKTAG( 'm', 'p', '4', 'a' ), parse_default },
......@@ -711,7 +863,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG( 'm', 'p', '4', 's' ), parse_default },
{ MKTAG( 'm', 'd', 'i', 'a' ), parse_default },
{ MKTAG( 'm', 'd', 'a', 't' ), parse_mdat },
{ MKTAG( 'm', 'd', 'h', 'd' ), parse_leaf },
{ MKTAG( 'm', 'd', 'h', 'd' ), parse_mdhd },
{ MKTAG( 'm', 'i', 'n', 'f' ), parse_default },
{ MKTAG( 'm', 'o', 'o', 'v' ), parse_moov },
{ MKTAG( 'm', 'v', 'h', 'd' ), parse_mvhd },
......@@ -728,7 +880,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG( 's', 'm', 'h', 'd' ), parse_leaf },
{ MKTAG( 'd', 'p', 'n', 'd' ), parse_leaf },
{ MKTAG( 's', 't', 's', 's' ), parse_leaf },
{ MKTAG( 's', 't', 't', 's' ), parse_leaf },
{ MKTAG( 's', 't', 't', 's' ), parse_stts },
{ MKTAG( 't', 'r', 'a', 'k' ), parse_trak },
{ MKTAG( 't', 'k', 'h', 'd' ), parse_tkhd },
{ MKTAG( 't', 'r', 'e', 'f' ), parse_default }, /* not really */
......@@ -753,6 +905,11 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG( 's', 's', 'r', 'c' ), parse_leaf },
{ MKTAG( 't', 'c', 'm', 'd' ), parse_leaf },
{ MKTAG( 'w', 'i', 'd', 'e' ), parse_leaf }, /* place holder */
#ifdef CONFIG_ZLIB
{ MKTAG( 'c', 'm', 'o', 'v' ), parse_cmov },
#else
{ MKTAG( 'c', 'm', 'o', 'v' ), parse_leaf },
#endif
{ 0L, parse_leaf }
};
......@@ -773,6 +930,10 @@ static int mov_probe(AVProbeData *p)
return 0;
if ((p->buf[4] == 'm' && p->buf[5] == 'o' &&
p->buf[6] == 'o' && p->buf[7] == 'v') ||
(p->buf[4] == 'w' && p->buf[5] == 'i' &&
p->buf[6] == 'd' && p->buf[7] == 'e') ||
(p->buf[4] == 'f' && p->buf[5] == 'r' &&
p->buf[6] == 'e' && p->buf[7] == 'e') ||
(p->buf[4] == 'm' && p->buf[5] == 'd' &&
p->buf[6] == 'a' && p->buf[7] == 't'))
return AVPROBE_SCORE_MAX;
......
......@@ -27,6 +27,8 @@ CodecTag codec_wav_tags[] = {
{ CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
{ CODEC_ID_PCM_ALAW, 0x06 },
{ CODEC_ID_PCM_MULAW, 0x07 },
{ CODEC_ID_ADPCM_MS, 0x02 },
{ CODEC_ID_ADPCM_IMA_WAV, 0x11 },
{ 0, 0 },
};
......@@ -56,6 +58,8 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3LAME) {
blkalign = 1;
//blkalign = 144 * enc->bit_rate/enc->sample_rate;
} else if (enc->block_align != 0) { /* specified by the codec */
blkalign = enc->block_align;
} else
blkalign = enc->channels*bps >> 3;
if (enc->codec_id == CODEC_ID_PCM_U8 ||
......@@ -205,6 +209,7 @@ static int wav_read_header(AVFormatContext *s,
unsigned int tag;
ByteIOContext *pb = &s->pb;
unsigned int id, channels, rate, bit_rate, extra_size, bps;
unsigned int blkalign;
AVStream *st;
/* check RIFF header */
......@@ -225,7 +230,7 @@ static int wav_read_header(AVFormatContext *s,
channels = get_le16(pb);
rate = get_le32(pb);
bit_rate = get_le32(pb) * 8;
get_le16(pb); /* block align */
blkalign = get_le16(pb); /* block align */
bps = get_le16(pb); /* bits per sample */
if (size >= 18) {
/* wav_extra_size */
......@@ -248,6 +253,7 @@ static int wav_read_header(AVFormatContext *s,
st->codec.codec_id = wav_codec_get_id(id, bps);
st->codec.channels = channels;
st->codec.sample_rate = rate;
st->codec.block_align = blkalign;
return 0;
}
......
......@@ -15,7 +15,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \
mpegaudio.o ac3enc.o mjpeg.o resample.o dsputil.o \
motion_est.o imgconvert.o imgresample.o msmpeg4.o \
mpeg12.o h263dec.o svq1.o rv10.o mpegaudiodec.o pcm.o simple_idct.o \
ratecontrol.o
ratecontrol.o adpcm.o
ASM_OBJS=
# currently using liba52 for ac3 decoding
......
/*
* ADPCM codecs
* Copyright (c) 2001 Fabrice Bellard.
*
* This library 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 of the License, or (at your option) any later version.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "avcodec.h"
/*
* First version by Francois Revol revol@free.fr
*
* Features and limitations:
*
* Reference documents:
* http://www.pcisys.net/~melanson/codecs/adpcm.txt
* http://www.geocities.com/SiliconValley/8682/aud3.txt
* http://openquicktime.sourceforge.net/plugins.htm
* XAnim sources (xa_codec.c) http://www.rasnaimaging.com/people/lapus/download.html
*/
#define BLKSIZE 1024
#define CLAMP_TO_SHORT(value) \
if (value > 32767) \
value = 32767; \
else if (value < -32768) \
value = -32768; \
/* step_table[] and index_table[] are from the ADPCM reference source */
/* This is the index table: */
static int index_table[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};
/* This is the step table. Note that many programs use slight deviations from
* this table, but such deviations are negligible:
*/
static int step_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
/* AdaptationTable[], AdaptCoeff1[], and AdaptCoeff2[] are from libsndfile */
static int AdaptationTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
static int AdaptCoeff1[] = {
256, 512, 0, 192, 240, 460, 392
};
static int AdaptCoeff2[] = {
0, -256, 0, 64, 0, -208, -232
};
/* end of tables */
typedef struct ADPCMChannelStatus {
int predictor;
short int step_index;
int step;
/* MS version */
short sample1;
short sample2;
int coeff1;
int coeff2;
int idelta;
} ADPCMChannelStatus;
typedef struct ADPCMContext {
int channel; /* for stereo MOVs, decode left, then decode right, then tell it's decoded */
ADPCMChannelStatus status[2];
short sample_buffer[32]; /* hold left samples while waiting for right samples */
} ADPCMContext;
/* XXX: implement encoding */
static int adpcm_encode_init(AVCodecContext *avctx)
{
switch(avctx->codec->id) {
case CODEC_ID_ADPCM_IMA_QT:
avctx->frame_size = 64; /* XXX: ??? */
break;
case CODEC_ID_ADPCM_IMA_WAV:
avctx->frame_size = 64; /* XXX: ??? */
break;
default:
avctx->frame_size = 1;
break;
}
return 0;
}
static int adpcm_encode_close(AVCodecContext *avctx)
{
switch(avctx->codec->id) {
default:
/* nothing to free */
break;
}
return 0;
}
static int adpcm_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
int n, sample_size, v;
short *samples;
unsigned char *dst;
switch(avctx->codec->id) {
default:
return -1;
}
avctx->key_frame = 1;
//avctx->frame_size = (dst - frame) / (sample_size * avctx->channels);
return dst - frame;
}
static int adpcm_decode_init(AVCodecContext * avctx)
{
ADPCMContext *c = avctx->priv_data;
c->channel = 0;
c->status[0].predictor = c->status[1].predictor = 0;
c->status[0].step_index = c->status[1].step_index = 0;
c->status[0].step = c->status[1].step = 0;
switch(avctx->codec->id) {
default:
break;
}
return 0;
}
static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble)
{
int step_index;
int predictor;
int sign, delta, diff, step;
predictor = c->predictor;
step_index = c->step_index + index_table[(unsigned)nibble];
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
step = c->step;
/*
diff = ((signed)((nibble & 0x08)?(nibble | 0xF0):(nibble)) + 0.5) * step / 4;
predictor += diff;
*/
sign = nibble & 8;
delta = nibble & 7;
diff = step >> 3;
if (delta & 4) diff += step;
if (delta & 2) diff += step >> 1;
if (delta & 1) diff += step >> 2;
if (sign) predictor -= diff;
else predictor += diff;
CLAMP_TO_SHORT(predictor);
c->predictor = predictor;
c->step_index = step_index;
c->step = step_table[step_index];
return (short)predictor;
}
static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
{
int predictor;
predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 256;
predictor += (signed)((nibble & 0x08)?(nibble - 0x10):(nibble)) * c->idelta;
CLAMP_TO_SHORT(predictor);
c->sample2 = c->sample1;
c->sample1 = predictor;
c->idelta = (AdaptationTable[(int)nibble] * c->idelta) / 256;
if (c->idelta < 16) c->idelta = 16;
return (short)predictor;
}
static int adpcm_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
UINT8 *buf, int buf_size)
{
ADPCMContext *c = avctx->priv_data;
ADPCMChannelStatus *cs;
int n, m, channel;
int block_predictor[2];
short *samples;
UINT8 *src;
int st; /* stereo */
samples = data;
src = buf;
//printf("adpcm_decode_frame() buf_size=%i\n", buf_size);
st = avctx->channels == 2;
switch(avctx->codec->id) {
case CODEC_ID_ADPCM_IMA_QT:
n = (buf_size - 2);/* >> 2*avctx->channels;*/
channel = c->channel;
cs = &(c->status[channel]);
/* (pppppp) (piiiiiii) */
/* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */
cs->predictor = (*src++) << 8;
cs->predictor |= (*src & 0x80);
cs->predictor &= 0xFF80;
/* sign extension */
if(cs->predictor & 0x8000)
cs->predictor -= 0x10000;
CLAMP_TO_SHORT(cs->predictor);
cs->step_index = (*src++) & 0x7F;
if (cs->step_index > 88) printf("ERROR: step_index = %i\n", cs->step_index);
if (cs->step_index > 88) cs->step_index = 88;
cs->step = step_table[cs->step_index];
if (st && channel)
samples++;
for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */
*samples = adpcm_ima_expand_nibble(cs, src[0] & 0x0F);
samples += avctx->channels;
*samples = adpcm_ima_expand_nibble(cs, (src[0] >> 4) & 0x0F);
samples += avctx->channels;
src ++;
}
if(st) { /* handle stereo interlacing */
c->channel = (channel + 1) % 2; /* we get one packet for left, then one for right data */
if(channel == 0) { /* wait for the other packet before outputing anything */
*data_size = 0;
return src - buf;
}
}
break;
case CODEC_ID_ADPCM_IMA_WAV:
if (buf_size > BLKSIZE) {
if (avctx->block_align != 0)
buf_size = avctx->block_align;
else
buf_size = BLKSIZE;
}
n = buf_size - 4 * avctx->channels;
cs = &(c->status[0]);
cs->predictor = (*src++) & 0x0FF;
cs->predictor |= ((*src++) << 8) & 0x0FF00;
if(cs->predictor & 0x8000)
cs->predictor -= 0x10000;
CLAMP_TO_SHORT(cs->predictor);
cs->step_index = *src++;
if (cs->step_index < 0) cs->step_index = 0;
if (cs->step_index > 88) cs->step_index = 88;
if (*src++) puts("unused byte should be null !!"); /* unused */
if (st) {
cs = &(c->status[1]);
cs->predictor = (*src++) & 0x0FF;
cs->predictor |= ((*src++) << 8) & 0x0FF00;
if(cs->predictor & 0x8000)
cs->predictor -= 0x10000;
CLAMP_TO_SHORT(cs->predictor);
cs->step_index = *src++;
if (cs->step_index < 0) cs->step_index = 0;
if (cs->step_index > 88) cs->step_index = 88;
src++; /* unused */
}
cs = &(c->status[0]);
for(m=3; n>0; n--, m--) {
*samples++ = adpcm_ima_expand_nibble(&c->status[0], src[0] & 0x0F);
if (st)
*samples++ = adpcm_ima_expand_nibble(&c->status[1], src[4] & 0x0F);
*samples++ = adpcm_ima_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F);
if (st)
*samples++ = adpcm_ima_expand_nibble(&c->status[1], (src[4] >> 4) & 0x0F);
src ++;
if (st && !m) {
m=3;
src+=4;
}
}
break;
case CODEC_ID_ADPCM_MS:
if (buf_size > BLKSIZE) {
if (avctx->block_align != 0)
buf_size = avctx->block_align;
else
buf_size = BLKSIZE;
}
n = buf_size - 7 * avctx->channels;
if (n < 0)
return -1;
block_predictor[0] = (*src++); /* should be bound */
block_predictor[0] = (block_predictor[0] < 0)?(0):((block_predictor[0] > 7)?(7):(block_predictor[0]));
block_predictor[1] = 0;
if (st)
block_predictor[1] = (*src++);
block_predictor[1] = (block_predictor[1] < 0)?(0):((block_predictor[1] > 7)?(7):(block_predictor[1]));
c->status[0].idelta = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
if (c->status[0].idelta & 0x08000)
c->status[0].idelta -= 0x10000;
src+=2;
if (st)
c->status[1].idelta = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
if (st && c->status[1].idelta & 0x08000)
c->status[1].idelta |= 0xFFFF0000;
if (st)
src+=2;
c->status[0].coeff1 = AdaptCoeff1[block_predictor[0]];
c->status[0].coeff2 = AdaptCoeff2[block_predictor[0]];
c->status[1].coeff1 = AdaptCoeff1[block_predictor[1]];
c->status[1].coeff2 = AdaptCoeff2[block_predictor[1]];
c->status[0].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
src+=2;
if (st) c->status[1].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
if (st) src+=2;
c->status[0].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
src+=2;
if (st) c->status[1].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
if (st) src+=2;
*samples++ = c->status[0].sample1;
if (st) *samples++ = c->status[1].sample1;
*samples++ = c->status[0].sample2;
if (st) *samples++ = c->status[1].sample2;
for(;n>0;n--) {
*samples++ = adpcm_ms_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F);
*samples++ = adpcm_ms_expand_nibble(&c->status[st], src[0] & 0x0F);
src ++;
}
break;
default:
*data_size = 0;
return -1;
}
*data_size = (UINT8 *)samples - (UINT8 *)data;
return src - buf;
}
#define ADPCM_CODEC(id, name) \
AVCodec name ## _encoder = { \
#name, \
CODEC_TYPE_AUDIO, \
id, \
sizeof(ADPCMContext), \
adpcm_encode_init, \
adpcm_encode_frame, \
adpcm_encode_close, \
NULL, \
}; \
AVCodec name ## _decoder = { \
#name, \
CODEC_TYPE_AUDIO, \
id, \
sizeof(ADPCMContext), \
adpcm_decode_init, \
NULL, \
NULL, \
adpcm_decode_frame, \
};
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
#undef ADPCM_CODEC
......@@ -89,6 +89,11 @@ PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);
/* adpcm codecs */
PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
#undef PCM_CODEC
}
......@@ -5,8 +5,8 @@
#define LIBAVCODEC_VERSION_INT 0x000406
#define LIBAVCODEC_VERSION "0.4.6"
#define LIBAVCODEC_BUILD 4617
#define LIBAVCODEC_BUILD_STR "4617"
#define LIBAVCODEC_BUILD 4618
#define LIBAVCODEC_BUILD_STR "4618"
enum CodecID {
CODEC_ID_NONE,
......@@ -37,6 +37,11 @@ enum CodecID {
CODEC_ID_PCM_U8,
CODEC_ID_PCM_MULAW,
CODEC_ID_PCM_ALAW,
/* various adpcm codecs */
CODEC_ID_ADPCM_IMA_QT,
CODEC_ID_ADPCM_IMA_WAV,
CODEC_ID_ADPCM_MS,
};
#define CODEC_ID_MSMPEG4 CODEC_ID_MSMPEG4V3
......@@ -263,6 +268,7 @@ typedef struct AVCodecContext {
int has_b_frames; // is 1 if the decoded stream contains b frames
int dr_uvstride;
int dr_ip_buffer_count;
int block_align; /* currently only for adpcm codec in wav/avi */
//FIXME this should be reordered after kabis API is finished ...
/*
......@@ -286,7 +292,7 @@ typedef struct AVCodecContext {
ul_res0,ul_res1,ul_res2,ul_res3,ul_res4,ul_res5,
ul_res6,ul_res7,ul_res8,ul_res9,ul_res10,ul_res11,ul_res12;
unsigned int
ui_res0,ui_res1,ui_res2;
ui_res0,ui_res1;
unsigned short int
us_res0,us_res1,us_res2,us_res3,us_res4,us_res5,
us_res6,us_res7,us_res8,us_res9,us_res10,us_res11,us_res12;
......@@ -376,6 +382,12 @@ PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);
/* adpcm codecs */
PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
#undef PCM_CODEC
/* dummy raw video codec */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment