add a Creative VOC (de)muxer

Originally committed as revision 4967 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Aurelien Jacobs 19 years ago
parent 9b2283cc33
commit ea395e8c6c
  1. 1
      Changelog
  2. 1
      MAINTAINERS
  3. 1
      doc/ffmpeg-doc.texi
  4. 3
      libavformat/Makefile
  5. 1
      libavformat/allformats.c
  6. 7
      libavformat/avformat.h
  7. 2
      libavformat/avio.h
  8. 14
      libavformat/aviobuf.c
  9. 280
      libavformat/voc.c
  10. 32
      libavformat/voc.h
  11. 3
      tests/libav.regression.ref
  12. 5
      tests/regression.sh

@ -35,6 +35,7 @@ version <next>
- tabs and trailing whitespace removed from the codebase - tabs and trailing whitespace removed from the codebase
- AIFF/AIFF-C audio format, encoding and decoding - AIFF/AIFF-C audio format, encoding and decoding
- ADTS AAC file reading and writing - ADTS AAC file reading and writing
- Creative VOC file reading and writing
version 0.4.9-pre1: version 0.4.9-pre1:

@ -183,6 +183,7 @@ Muxers/Demuxers:
raw.c Michael Niedermayer raw.c Michael Niedermayer
rm.c Roberto Togni rm.c Roberto Togni
segafilm.c Mike Melanson segafilm.c Mike Melanson
voc.c Aurelien Jacobs
wav.c Michael Niedermayer wav.c Michael Niedermayer
wc3movie.c Mike Melanson wc3movie.c Mike Melanson
westwood.c Mike Melanson westwood.c Mike Melanson

@ -697,6 +697,7 @@ library:
@tab Used in various EA games; files have extensions like WVE and UV2. @tab Used in various EA games; files have extensions like WVE and UV2.
@item Nullsoft Video (NSV) format @tab @tab X @item Nullsoft Video (NSV) format @tab @tab X
@item ADTS AAC audio @tab X @tab X @item ADTS AAC audio @tab X @tab X
@item Creative VOC @tab X @tab X @tab Created for the Sound Blaster Pro.
@end multitable @end multitable
@code{X} means that encoding (resp. decoding) is supported. @code{X} means that encoding (resp. decoding) is supported.

@ -22,7 +22,8 @@ OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o img2.o raw.o rm.o \
yuv4mpeg.o 4xm.o flvdec.o psxstr.o idroq.o ipmovie.o \ yuv4mpeg.o 4xm.o flvdec.o psxstr.o idroq.o ipmovie.o \
nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \ nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \
sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \ sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \
ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.o ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.o \
voc.o
# muxers # muxers
ifeq ($(CONFIG_MUXERS),yes) ifeq ($(CONFIG_MUXERS),yes)

@ -114,6 +114,7 @@ void av_register_all(void)
ea_init(); ea_init();
nsvdec_init(); nsvdec_init();
daud_init(); daud_init();
voc_init();
#ifdef CONFIG_MUXERS #ifdef CONFIG_MUXERS
/* image formats */ /* image formats */

@ -5,8 +5,8 @@
extern "C" { extern "C" {
#endif #endif
#define LIBAVFORMAT_VERSION_INT ((50<<16)+(1<<8)+0) #define LIBAVFORMAT_VERSION_INT ((50<<16)+(2<<8)+0)
#define LIBAVFORMAT_VERSION 50.1.0 #define LIBAVFORMAT_VERSION 50.2.0
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
@ -552,6 +552,9 @@ int daud_init(void);
/* aiff.c */ /* aiff.c */
int ff_aiff_init(void); int ff_aiff_init(void);
/* voc.c */
int voc_init(void);
#include "rtp.h" #include "rtp.h"
#include "rtsp.h" #include "rtsp.h"

@ -99,6 +99,7 @@ void put_le64(ByteIOContext *s, uint64_t val);
void put_be64(ByteIOContext *s, uint64_t val); void put_be64(ByteIOContext *s, uint64_t val);
void put_le32(ByteIOContext *s, unsigned int val); void put_le32(ByteIOContext *s, unsigned int val);
void put_be32(ByteIOContext *s, unsigned int val); void put_be32(ByteIOContext *s, unsigned int val);
void put_le24(ByteIOContext *s, unsigned int val);
void put_be24(ByteIOContext *s, unsigned int val); void put_be24(ByteIOContext *s, unsigned int val);
void put_le16(ByteIOContext *s, unsigned int val); void put_le16(ByteIOContext *s, unsigned int val);
void put_be16(ByteIOContext *s, unsigned int val); void put_be16(ByteIOContext *s, unsigned int val);
@ -127,6 +128,7 @@ void put_flush_packet(ByteIOContext *s);
int get_buffer(ByteIOContext *s, unsigned char *buf, int size); int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size); int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
int get_byte(ByteIOContext *s); int get_byte(ByteIOContext *s);
unsigned int get_le24(ByteIOContext *s);
unsigned int get_le32(ByteIOContext *s); unsigned int get_le32(ByteIOContext *s);
uint64_t get_le64(ByteIOContext *s); uint64_t get_le64(ByteIOContext *s);
unsigned int get_le16(ByteIOContext *s); unsigned int get_le16(ByteIOContext *s);

@ -239,6 +239,12 @@ void put_be16(ByteIOContext *s, unsigned int val)
put_byte(s, val); put_byte(s, val);
} }
void put_le24(ByteIOContext *s, unsigned int val)
{
put_le16(s, val & 0xffff);
put_byte(s, val >> 16);
}
void put_be24(ByteIOContext *s, unsigned int val) void put_be24(ByteIOContext *s, unsigned int val)
{ {
put_be16(s, val >> 8); put_be16(s, val >> 8);
@ -396,6 +402,14 @@ unsigned int get_le16(ByteIOContext *s)
return val; return val;
} }
unsigned int get_le24(ByteIOContext *s)
{
unsigned int val;
val = get_le16(s);
val |= get_byte(s) << 16;
return val;
}
unsigned int get_le32(ByteIOContext *s) unsigned int get_le32(ByteIOContext *s)
{ {
unsigned int val; unsigned int val;

@ -0,0 +1,280 @@
/*
* Creative Voice File demuxer.
* Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "avi.h" /* for CodecTag */
#include "voc.h"
typedef enum voc_type {
VOC_TYPE_EOF = 0x00,
VOC_TYPE_VOICE_DATA = 0x01,
VOC_TYPE_VOICE_DATA_CONT = 0x02,
VOC_TYPE_SILENCE = 0x03,
VOC_TYPE_MARKER = 0x04,
VOC_TYPE_ASCII = 0x05,
VOC_TYPE_REPETITION_START = 0x06,
VOC_TYPE_REPETITION_END = 0x07,
VOC_TYPE_EXTENDED = 0x08,
VOC_TYPE_NEW_VOICE_DATA = 0x09,
} voc_type_t;
static const int voc_max_pkt_size = 2048;
static const unsigned char voc_magic[] = "Creative Voice File\x1A";
static const CodecTag voc_codec_tags[] = {
{CODEC_ID_PCM_U8, 0x00},
{CODEC_ID_PCM_S16LE, 0x04},
{CODEC_ID_PCM_ALAW, 0x06},
{CODEC_ID_PCM_MULAW, 0x07},
{CODEC_ID_ADPCM_CT, 0x0200},
{0, 0},
};
#ifdef CONFIG_DEMUXERS
static int voc_probe(AVProbeData *p)
{
int version, check;
if (p->buf_size < 26)
return 0;
if (memcmp(p->buf, voc_magic, sizeof(voc_magic) - 1))
return 0;
version = p->buf[22] | (p->buf[23] << 8);
check = p->buf[24] | (p->buf[25] << 8);
if (~version + 0x1234 != check)
return 10;
return AVPROBE_SCORE_MAX;
}
static int voc_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
voc_dec_context_t *voc = s->priv_data;
ByteIOContext *pb = &s->pb;
int header_size;
AVStream *st;
url_fskip(pb, 20);
header_size = get_le16(pb) - 22;
if (header_size != 4) {
av_log(s, AV_LOG_ERROR, "unkown header size: %d\n", header_size);
return AVERROR_NOTSUPP;
}
url_fskip(pb, header_size);
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
st->codec->codec_type = CODEC_TYPE_AUDIO;
voc->remaining_size = 0;
return 0;
}
int
voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
{
voc_dec_context_t *voc = s->priv_data;
AVCodecContext *dec = st->codec;
ByteIOContext *pb = &s->pb;
voc_type_t type;
int size;
int sample_rate = 0;
int channels = 1;
while (!voc->remaining_size) {
type = get_byte(pb);
if (type == VOC_TYPE_EOF)
return AVERROR_IO;
voc->remaining_size = get_le24(pb);
max_size -= 4;
switch (type) {
case VOC_TYPE_VOICE_DATA:
dec->sample_rate = 1000000 / (256 - get_byte(pb));
if (sample_rate)
dec->sample_rate = sample_rate;
dec->channels = channels;
dec->codec_id = codec_get_id(voc_codec_tags, get_byte(pb));
voc->remaining_size -= 2;
max_size -= 2;
channels = 1;
break;
case VOC_TYPE_VOICE_DATA_CONT:
break;
case VOC_TYPE_EXTENDED:
sample_rate = get_le16(pb);
get_byte(pb);
channels = get_byte(pb) + 1;
sample_rate = 256000000 / (channels * (65536 - sample_rate));
voc->remaining_size = 0;
max_size -= 4;
break;
case VOC_TYPE_NEW_VOICE_DATA:
dec->sample_rate = get_le32(pb);
dec->bits_per_sample = get_byte(pb);
dec->channels = get_byte(pb);
dec->codec_id = codec_get_id(voc_codec_tags, get_le16(pb));
url_fskip(pb, 4);
voc->remaining_size -= 12;
max_size -= 12;
break;
default:
url_fskip(pb, voc->remaining_size);
max_size -= voc->remaining_size;
voc->remaining_size = 0;
break;
}
}
dec->bit_rate = dec->sample_rate * dec->bits_per_sample;
if (max_size <= 0)
max_size = voc_max_pkt_size;
size = FFMIN(voc->remaining_size, max_size);
voc->remaining_size -= size;
return av_get_packet(pb, pkt, size);
}
static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
{
return voc_get_packet(s, pkt, s->streams[0], 0);
}
static int voc_read_close(AVFormatContext *s)
{
return 0;
}
static AVInputFormat voc_iformat = {
"voc",
"Creative Voice File format",
sizeof(voc_dec_context_t),
voc_probe,
voc_read_header,
voc_read_packet,
voc_read_close,
};
#endif /* CONFIG_DEMUXERS */
#ifdef CONFIG_MUXERS
typedef struct voc_enc_context {
int param_written;
} voc_enc_context_t;
static int voc_write_header(AVFormatContext *s)
{
ByteIOContext *pb = &s->pb;
const int header_size = 26;
const int version = 0x0114;
if (s->nb_streams != 1
|| s->streams[0]->codec->codec_type != CODEC_TYPE_AUDIO)
return AVERROR_NOTSUPP;
put_buffer(pb, voc_magic, sizeof(voc_magic) - 1);
put_le16(pb, header_size);
put_le16(pb, version);
put_le16(pb, ~version + 0x1234);
return 0;
}
static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
{
voc_enc_context_t *voc = s->priv_data;
AVCodecContext *enc = s->streams[0]->codec;
ByteIOContext *pb = &s->pb;
if (!voc->param_written) {
int format = codec_get_tag(voc_codec_tags, enc->codec_id);
if (format > 0xFF) {
put_byte(pb, VOC_TYPE_NEW_VOICE_DATA);
put_le24(pb, pkt->size + 12);
put_le32(pb, enc->sample_rate);
put_byte(pb, enc->bits_per_sample);
put_byte(pb, enc->channels);
put_le16(pb, format);
put_le32(pb, 0);
} else {
if (s->streams[0]->codec->channels > 1) {
put_byte(pb, VOC_TYPE_EXTENDED);
put_le24(pb, 4);
put_le16(pb, 65536-256000000/(enc->sample_rate*enc->channels));
put_byte(pb, format);
put_byte(pb, enc->channels - 1);
}
put_byte(pb, VOC_TYPE_VOICE_DATA);
put_le24(pb, pkt->size + 2);
put_byte(pb, 256 - 1000000 / enc->sample_rate);
put_byte(pb, format);
}
voc->param_written = 1;
} else {
put_byte(pb, VOC_TYPE_VOICE_DATA_CONT);
put_le24(pb, pkt->size);
}
put_buffer(pb, pkt->data, pkt->size);
return 0;
}
static int voc_write_trailer(AVFormatContext *s)
{
put_byte(&s->pb, 0);
return 0;
}
static AVOutputFormat voc_oformat = {
"voc",
"Creative Voice File format",
"audio/x-voc",
"voc",
sizeof(voc_enc_context_t),
CODEC_ID_PCM_U8,
CODEC_ID_NONE,
voc_write_header,
voc_write_packet,
voc_write_trailer,
};
#endif /* CONFIG_MUXERS */
int voc_init(void)
{
#ifdef CONFIG_DEMUXERS
av_register_input_format(&voc_iformat);
#endif /* CONFIG_DEMUXERS */
#ifdef CONFIG_MUXERS
av_register_output_format(&voc_oformat);
#endif /* CONFIG_MUXERS */
return 0;
}

@ -0,0 +1,32 @@
/*
* Creative Voice File demuxer.
* Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VOC_H
#define VOC_H
#include "avformat.h"
typedef struct voc_dec_context {
int remaining_size;
} voc_dec_context_t;
int voc_get_packet(AVFormatContext *s, AVPacket *pkt,
AVStream *st, int max_size);
#endif

@ -65,6 +65,9 @@ e2a6d6fae17394dfe87cb5bb8ae11837 *./data/b-libav.al
a324baee6d76c53ab7c74616cfc31616 *./data/b-libav.aif a324baee6d76c53ab7c74616cfc31616 *./data/b-libav.aif
89168 ./data/b-libav.aif 89168 ./data/b-libav.aif
./data/b-libav.aif CRC=0x2a09519c ./data/b-libav.aif CRC=0x2a09519c
8d117c49d6b210abe783d1b0b897cec7 *./data/b-libav.voc
32768 ./data/b-libav.voc
./data/b-libav.voc CRC=0x49972c8c
ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv420p.yuv ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv420p.yuv
304128 ./data/b-libav-yuv420p.yuv 304128 ./data/b-libav-yuv420p.yuv
ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv422p.yuv ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv422p.yuv

@ -712,6 +712,11 @@ file=${outfile}libav.aif
do_ffmpeg $file -t 1 -y -qscale 10 -f s16le -i $pcm_src $file do_ffmpeg $file -t 1 -y -qscale 10 -f s16le -i $pcm_src $file
do_ffmpeg_crc $file -i $file do_ffmpeg_crc $file -i $file
# voc
file=${outfile}libav.voc
do_ffmpeg $file -t 1 -y -qscale 10 -f s16le -i $pcm_src $file
do_ffmpeg_crc $file -i $file
#################### ####################
# pix_fmt conversions # pix_fmt conversions
conversions="yuv420p yuv422p yuv444p yuv422 yuv410p yuv411p yuvj420p \ conversions="yuv420p yuv422p yuv444p yuv422 yuv410p yuv411p yuvj420p \

Loading…
Cancel
Save