Bug 480521 - Update libfishsound to e98a05 and liboggz to ef3b0e. rs=roc

This commit is contained in:
Chris Double 2009-04-05 11:17:48 +12:00
parent 968e728351
commit 0614eb4541
25 changed files with 602 additions and 317 deletions

View File

@ -4,6 +4,9 @@ Conrad Parker <conrad@metadecks.org>
Tobias Gehrig
- FLAC support
Michel Salim
- libFLAC 1.1.3 support
Silvia Pfeiffer <silvia@annodex.net>
- MS Windows porting, general packaging.

View File

@ -1,10 +1,11 @@
The source from this directory was copied from the libfishsound-0.9.1
source distribution using the update.sh script. The only changes made
The source from this directory was copied from the libfishsound git
distribution using the update.sh script. The only changes made
were those applied by update.sh and the addition/upate of Makefile.in
files for the Mozilla build system.
Some files are renamed during the copy to prevent clashes with object
file names with other Mozilla libraries.
The git commit id used was e98a05 from git://git.xiph.org/libfishsound.git
endian.patch is applied to fix Bug 45269.
bu481601.patch is applied to fix bug 481601.

View File

@ -35,7 +35,7 @@
/* #undef HAVE_SPEEX_1_1 */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* #define HAVE_STDINT_H 1 */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

View File

@ -106,6 +106,9 @@ typedef enum _FishSoundError {
/** The requested operation is not suitable for this FishSound* handle */
FISH_SOUND_ERR_INVALID = -3,
/** Out of memory */
FISH_SOUND_ERR_OUT_OF_MEMORY = -4,
/** Functionality disabled at build time */
FISH_SOUND_ERR_DISABLED = -10,

View File

@ -79,7 +79,9 @@ typedef int (*FishSoundDecoded_FloatIlv) (FishSound * fsound, float ** pcm,
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param decoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \returns 0 on success, -1 on failure
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
int fish_sound_set_decoded_float (FishSound * fsound,
FishSoundDecoded_Float decoded,
@ -91,7 +93,9 @@ int fish_sound_set_decoded_float (FishSound * fsound,
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param decoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \returns 0 on success, -1 on failure
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
int fish_sound_set_decoded_float_ilv (FishSound * fsound,
FishSoundDecoded_FloatIlv decoded,
@ -113,6 +117,8 @@ int fish_sound_set_decoded_float_ilv (FishSound * fsound,
* callback returning FISH_SOUND_STOP_ERR before any input bytes were consumed.
* This will occur when PCM is decoded from previously buffered input, and
* stopping is immediately requested.
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
long fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes);

View File

@ -41,27 +41,6 @@
extern "C" {
#endif
/**
* DEPRECATED FUNCTION.
* Set the PCM format used by a FishSound object. The default value is
* non-interleaved.
* Prior to libfishsound 0.7.0, you would (optionally) specify whether you
* wanted to receive interleaved or per-channel PCM data using
* fish_sound_set_interleave(), the default being per-channel
* (non-interleaved) PCM.
* Whether or not your decoded callback expects interleaved or
* non-interleaved data is now implied by the particular
* fish_sound_set_decoded_TYPE() method you use to set it, such as
* fish_sound_set_decoded_float() or fish_sound_set_decode_float_ilv().
*
* \param fsound A FishSound* handle
* \param interleave Whether to use interleaved PCM or not. Valid values are
* 0 for non-interleaved, and 1 for interleaved.
* \retval 0 Success
* \retval -1 Invalid \a fsound
*/
int fish_sound_set_interleave (FishSound * fsound, int interleave);
/**
* DEPRECATED TYPE.
* Signature of a callback for libfishsound to call when it has decoded
@ -99,7 +78,7 @@ int fish_sound_set_decoded_callback (FishSound * fsound,
* Whether or not your decoded callback expects interleaved or
* non-interleaved data is now implied by the particular
* fish_sound_set_decoded_TYPE() method you use to set it, such as
* fish_sound_set_decoded_float() or fish_sound_set_decode_float_ilv().
* fish_sound_set_decoded_float() or fish_sound_set_decoded_float_ilv().
*
* \param fsound A FishSound* handle
* \param interleave Whether to use interleaved PCM or not. Valid values are

View File

@ -505,7 +505,7 @@ int fish_sound_command (FishSound * fsound, int command, void * data,
* \param fsound A FishSound* handle
* \retval 0 \a fsound uses non-interleaved PCM
* \retval 1 \a fsound uses interleaved PCM
* \retval -1 Invalid \a fsound
* \retval -1 Invalid \a fsound, or out of memory.
*/
int fish_sound_get_interleave (FishSound * fsound);

View File

@ -35,7 +35,7 @@
/* #undef HAVE_SPEEX_1_1 */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* #define HAVE_STDINT_H 1 */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

View File

@ -70,7 +70,7 @@ fish_sound_set_format (FishSound * fsound, int format)
}
if (fsound->codec && fsound->codec->init)
fsound->codec->init (fsound);
if (fsound->codec->init (fsound) == NULL) return -1;
fsound->info.format = format;
@ -105,6 +105,7 @@ fish_sound_new (int mode, FishSoundInfo * fsinfo)
}
fsound = fs_malloc (sizeof (FishSound));
if (fsound == NULL) return NULL;
fsound->mode = mode;
fsound->interleave = 0;

View File

@ -35,27 +35,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* ULONG_MAX */
#ifndef WIN32
#include <strings.h>
#endif
#include "private.h"
/*#define DEBUG*/
/* Ensure comment vector length can be expressed in 32 bits
* including space for the trailing NUL */
#define MAX_COMMENT_LENGTH 0xFFFFFFFE
#define fs_comment_clamp(c) MIN((c),MAX_COMMENT_LENGTH)
static size_t
fs_comment_len (const char * s)
{
size_t len;
if (s == NULL) return 0;
len = strlen (s);
return fs_comment_clamp(len);
}
static char *
fs_strdup (const char * s)
{
char * ret;
if (s == NULL) return NULL;
ret = fs_malloc (strlen(s) + 1);
ret = fs_malloc (fs_comment_len(s) + 1);
if (ret == NULL) return NULL;
return strcpy (ret, s);
}
static char *
fs_strdup_len (const char * s, int len)
fs_strdup_len (const char * s, size_t len)
{
char * ret;
if (s == NULL) return NULL;
if (len == 0) return NULL;
len = fs_comment_clamp(len);
ret = fs_malloc (len + 1);
if (ret == NULL) return NULL;
if (strncpy (ret, s, len) == NULL) {
fs_free (ret);
return NULL;
@ -79,11 +102,6 @@ fs_index_len (const char * s, char c, int len)
return NULL;
}
#if 0
static void comment_init(char **comments, int* length, char *vendor_string);
static void comment_add(char **comments, int* length, char *tag, char *val);
#endif
/*
Comments will be stored in the Vorbis style.
It is describled in the "Structure" section of
@ -114,47 +132,6 @@ The comment header is decoded as follows:
buf[base]=(val)&0xff; \
}while(0)
#if 0
static void
comment_init(char **comments, int* length, char *vendor_string)
{
int vendor_length=strlen(vendor_string);
int user_comment_list_length=0;
int len=4+vendor_length+4;
char *p=(char*)fs_malloc(len);
if(p==NULL){
}
writeint(p, 0, vendor_length);
memcpy(p+4, vendor_string, vendor_length);
writeint(p, 4+vendor_length, user_comment_list_length);
*length=len;
*comments=p;
}
static void
comment_add(char **comments, int* length, char *tag, char *val)
{
char* p=*comments;
int vendor_length=readint(p, 0);
int user_comment_list_length=readint(p, 4+vendor_length);
int tag_len=(tag?strlen(tag):0);
int val_len=strlen(val);
int len=(*length)+4+tag_len+val_len;
p=(char*)fs_realloc(p, len);
if(p==NULL){
}
writeint(p, *length, tag_len+val_len); /* length of comment */
if(tag) memcpy(p+*length+4, tag, tag_len); /* comment */
memcpy(p+*length+4+tag_len, val, val_len); /* comment */
writeint(p, 4+vendor_length, user_comment_list_length+1);
*comments=p;
*length=len;
}
#endif
static int
fs_comment_validate_byname (const char * name, const char * value)
{
@ -182,10 +159,23 @@ fs_comment_new (const char * name, const char * value)
FishSoundComment * comment;
if (!fs_comment_validate_byname (name, value)) return NULL;
/* Ensures that name != NULL, value != NULL, and validates strings */
comment = fs_malloc (sizeof (FishSoundComment));
if (comment == NULL) return NULL;
comment->name = fs_strdup (name);
if (comment->name == NULL) {
fs_free (comment);
return NULL;
}
comment->value = fs_strdup (value);
if (comment->value == NULL) {
fs_free (comment->name);
fs_free (comment);
return NULL;
}
return comment;
}
@ -211,6 +201,19 @@ fs_comment_cmp (const FishSoundComment * comment1, const FishSoundComment * comm
return 1;
}
int
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor_string)
{
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->vendor) fs_free (fsound->vendor);
if ((fsound->vendor = fs_strdup (vendor_string)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return 0;
}
/* Public API */
const char *
@ -221,18 +224,6 @@ fish_sound_comment_get_vendor (FishSound * fsound)
return fsound->vendor;
}
int
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor_string)
{
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->vendor) fs_free (fsound->vendor);
fsound->vendor = fs_strdup (vendor_string);
return 0;
}
const FishSoundComment *
fish_sound_comment_first (FishSound * fsound)
{
@ -311,11 +302,13 @@ fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
if (!fs_comment_validate_byname (comment->name, comment->value))
return FISH_SOUND_ERR_COMMENT_INVALID;
new_comment = fs_comment_new (comment->name, comment->value);
if ((new_comment = fs_comment_new (comment->name, comment->value)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
_fs_comment_add (fsound, new_comment);
if (_fs_comment_add (fsound, new_comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return 0;
return FISH_SOUND_OK;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
@ -336,9 +329,13 @@ fish_sound_comment_add_byname (FishSound * fsound, const char * name,
if (!fs_comment_validate_byname (name, value))
return FISH_SOUND_ERR_COMMENT_INVALID;
comment = fs_comment_new (name, value);
if ((comment = fs_comment_new (name, value)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
_fs_comment_add (fsound, comment);
if (_fs_comment_add (fsound, comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return FISH_SOUND_OK;
return 0;
@ -429,7 +426,8 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
long length)
{
char *c= (char *)comments;
int len, i, nb_fields, n;
int i, nb_fields, n;
size_t len;
char *end;
char * name, * value, * nvalue = NULL;
FishSoundComment * comment;
@ -439,14 +437,20 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
end = c+length;
len=readint(c, 0);
if (len<0) return -1;
c+=4;
if (c+len>end) return -1;
if (len>end-c) return -1;
/* Vendor */
nvalue = fs_strdup_len (c, len);
fish_sound_comment_set_vendor (fsound, nvalue);
if (nvalue) fs_free (nvalue);
if (len > 0) {
if ((nvalue = fs_strdup_len (c, len)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (fish_sound_comment_set_vendor (fsound, nvalue) == FISH_SOUND_ERR_OUT_OF_MEMORY)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fs_free (nvalue);
}
#ifdef DEBUG
fwrite(c, 1, len, stderr); fputc ('\n', stderr);
#endif
@ -454,6 +458,8 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
if (c+4>end) return -1;
/* This value gets checked effectively by the 'for' condition
and the checks within the loop for c running off the end. */
nb_fields=readint(c, 0);
#ifdef DEBUG
printf ("fish_sound_comments_decode: %d comments\n", nb_fields);
@ -468,9 +474,10 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
#ifdef DEBUG
printf ("fish_sound_comments_decode: [%d] len %d\n", i, len);
#endif
if (len<0) return -1;
c+=4;
if (c+len>end) return -1;
if (len>end-c) return -1;
name = c;
value = fs_index_len (c, '=', len);
@ -479,22 +486,33 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
value++;
n = c+len - value;
nvalue = fs_strdup_len (value, n);
if ((nvalue = fs_strdup_len (value, n)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
#ifdef DEBUG
printf ("fish_sound_comments_decode: %s -> %s (length %d)\n",
name, nvalue, n);
#endif
comment = fs_comment_new (name, nvalue);
_fs_comment_add (fsound, comment);
if ((comment = fs_comment_new (name, nvalue)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (_fs_comment_add (fsound, comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fs_free (nvalue);
} else {
#ifdef DEBUG
printf ("fish_sound_comments_decode: [%d] %s (no value)\n",
i, name, len);
#endif
nvalue = fs_strdup_len (name, len);
comment = fs_comment_new (nvalue, NULL);
_fs_comment_add (fsound, comment);
if ((nvalue = fs_strdup_len (name, len)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if ((comment = fs_comment_new (nvalue, NULL)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (_fs_comment_add (fsound, comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fs_free (nvalue);
}
@ -505,7 +523,28 @@ fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
printf ("fish_sound_comments_decode: done\n");
#endif
return 0;
return FISH_SOUND_OK;
}
/*
* Pre-condition: at least one of accum, delta are non-zero,
* ie. don't call accum_length (0, 0);
* \retval 0 Failure: integer overflow
*/
static unsigned long
accum_length (unsigned long * accum, unsigned long delta)
{
/* Pre-condition: don't call accum_length (0, 0) */
if (*accum == 0 && delta == 0)
return 0;
/* Check for integer overflow */
if (delta > ULONG_MAX - (*accum))
return 0;
*accum += delta;
return *accum;
}
long
@ -514,21 +553,29 @@ fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
{
char * c = (char *)buf;
const FishSoundComment * comment;
int nb_fields = 0, vendor_length, field_length;
long actual_length, remaining = length;
int nb_fields = 0, vendor_length = 0;
unsigned long actual_length = 0, remaining = length, field_length;
/* Vendor string */
vendor_length = strlen (fsound->vendor);
actual_length = 4 + vendor_length;
if (fsound->vendor)
vendor_length = fs_comment_len (fsound->vendor);
if (accum_length (&actual_length, 4 + vendor_length) == 0)
return 0;
/* user comment list length */
actual_length += 4;
if (accum_length (&actual_length, 4) == 0)
return 0;
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
actual_length += 4 + strlen (comment->name); /* [size]"name" */
if (comment->value)
actual_length += 1 + strlen (comment->value); /* "=value" */
/* [size]"name" */
if (accum_length (&actual_length, 4 + fs_comment_len (comment->name)) == 0)
return 0;
if (comment->value) {
/* "=value" */
if (accum_length (&actual_length, 1 + fs_comment_len (comment->value)) == 0)
return 0;
}
#ifdef DEBUG
printf ("fish_sound_comments_encode: %s = %s\n",
@ -538,7 +585,11 @@ fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
nb_fields++;
}
actual_length++; /* framing bit */
/* framing bit */
if (accum_length (&actual_length, 1) == 0)
return 0;
/* NB. actual_length is not modified from here onwards */
if (buf == NULL) return actual_length;
@ -547,10 +598,12 @@ fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
writeint (c, 0, vendor_length);
c += 4;
field_length = strlen (fsound->vendor);
memcpy (c, fsound->vendor, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0 ) return actual_length;
if (fsound->vendor) {
field_length = fs_comment_len (fsound->vendor);
memcpy (c, fsound->vendor, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;
}
remaining -= 4;
if (remaining <= 0) return actual_length;
@ -560,16 +613,16 @@ fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
field_length = strlen (comment->name); /* [size]"name" */
field_length = fs_comment_len (comment->name); /* [size]"name" */
if (comment->value)
field_length += 1 + strlen (comment->value); /* "=value" */
field_length += 1 + fs_comment_len (comment->value); /* "=value" */
remaining -= 4;
if (remaining <= 0) return actual_length;
writeint (c, 0, field_length);
c += 4;
field_length = strlen (comment->name);
field_length = fs_comment_len (comment->name);
memcpy (c, comment->name, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;
@ -580,7 +633,7 @@ fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
*c = '=';
c++;
field_length = strlen (comment->value);
field_length = fs_comment_len (comment->value);
memcpy (c, comment->value, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;

View File

@ -58,7 +58,7 @@ int fish_sound_set_decoded_float (FishSound * fsound,
{
int ret = 0;
if (fsound == NULL) return -1;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
ret = fs_decode_update (fsound, 0);
@ -80,7 +80,7 @@ int fish_sound_set_decoded_float_ilv (FishSound * fsound,
{
int ret = 0;
if (fsound == NULL) return -1;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
ret = fs_decode_update (fsound, 1);
@ -101,7 +101,7 @@ fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes)
{
int format;
if (fsound == NULL) return -1;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
if (fsound->info.format == FISH_SOUND_UNKNOWN) {

View File

@ -141,6 +141,7 @@ fs_flac_write_callback(const FLAC__StreamDecoder *decoder,
FishSound* fsound = (FishSound*)client_data;
FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
int i, j, channels, blocksize, offset;
float * ipcm;
channels = frame->header.channels;
blocksize = frame->header.blocksize;
@ -158,7 +159,10 @@ fs_flac_write_callback(const FLAC__StreamDecoder *decoder,
FishSoundDecoded_FloatIlv dfi;
float* retpcm;
fi->ipcm = realloc(fi->ipcm, sizeof(float) * channels * blocksize);
if ((ipcm = realloc(fi->ipcm, sizeof(float) * channels * blocksize)) == NULL)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
fi->ipcm = ipcm;
retpcm = (float*) fi->ipcm;
for (i = 0; i < blocksize; i++) {
offset = i * channels;
@ -173,7 +177,9 @@ fs_flac_write_callback(const FLAC__StreamDecoder *decoder,
float *d; /* de-interleave dest */
for (j = 0; j < channels; j++) {
fi->pcm_out[j] = realloc(fi->pcm_out[j], sizeof(float) * blocksize);
if ((ipcm = realloc(fi->pcm_out[j], sizeof(float) * blocksize)) == NULL)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
fi->pcm_out[j] = ipcm;
}
for (i = 0; i < blocksize; i++)
for (j = 0; j < channels; j++) {
@ -231,6 +237,8 @@ static void*
fs_flac_decode_header (FishSound * fsound, unsigned char *buf, long bytes)
{
FishSoundFlacInfo *fi = fsound->codec_data;
if (bytes < 9) return NULL;
if (buf[0] != 0x7f) return NULL;
if (strncmp((char *)buf+1, "FLAC", 4) != 0) return NULL;
fi->version.major = buf[5];
@ -252,6 +260,7 @@ fs_flac_decode_header (FishSound * fsound, unsigned char *buf, long bytes)
return NULL;
}
#if defined (HAVE_FLAC_1_1_2)
FLAC__stream_decoder_set_read_callback(fi->fsd, fs_flac_read_callback);
FLAC__stream_decoder_set_write_callback(fi->fsd, fs_flac_write_callback);
FLAC__stream_decoder_set_metadata_callback(fi->fsd, fs_flac_meta_callback);
@ -260,6 +269,21 @@ fs_flac_decode_header (FishSound * fsound, unsigned char *buf, long bytes)
if (FLAC__stream_decoder_init(fi->fsd) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
return NULL;
#elif defined (HAVE_FLAC_1_1_3)
if (FLAC__stream_decoder_init_stream
(fi->fsd,
fs_flac_read_callback,
NULL, /* seek callback */
NULL, /* tell callback */
NULL, /* length callback */
NULL, /* EOF callback */
fs_flac_write_callback,
fs_flac_meta_callback,
fs_flac_error_callback,
fsound
) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
return NULL;
#endif
return fi->fsd;
}
@ -280,12 +304,14 @@ fs_flac_decode (FishSound * fsound, unsigned char * buf, long bytes)
#endif
return -1;
}
fi->buffer = fs_malloc(sizeof(unsigned char)*bytes);
if ((fi->buffer = fs_malloc(sizeof(unsigned char)*bytes)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
memcpy(fi->buffer, buf+9, bytes-9);
fi->bufferlength = bytes-9;
}
else if (fi->packetno <= fi->header_packets){
unsigned char* tmp = fs_malloc(sizeof(unsigned char)*(fi->bufferlength+bytes));
unsigned char* tmp;
#ifdef DEBUG
printf("fs_flac_decode: handling header (fi->header_packets = %d)\n",
fi->header_packets);
@ -300,26 +326,44 @@ fs_flac_decode (FishSound * fsound, unsigned char * buf, long bytes)
#ifdef DEBUG
printf ("fs_flac_decode: got vorbiscomments len %d\n", len);
#endif
fish_sound_comments_decode (fsound, buf+4, len);
if (fish_sound_comments_decode (fsound, buf+4, len) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fi->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
}
if ((tmp = fs_malloc(sizeof(unsigned char)*(fi->bufferlength+bytes))) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
memcpy(tmp, fi->buffer, fi->bufferlength);
memcpy(tmp+fi->bufferlength, buf, bytes);
fi->bufferlength += bytes;
fs_free(fi->buffer);
fi->buffer = tmp;
if (fi->packetno == fi->header_packets) {
FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd);
if (FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd) == false) {
goto dec_err;
}
fs_free(fi->buffer);
}
} else {
fi->buffer = buf;
fi->bufferlength = bytes;
FLAC__stream_decoder_process_single(fi->fsd);
if (FLAC__stream_decoder_process_single(fi->fsd) == false) {
goto dec_err;
}
}
fi->packetno++;
return 0;
dec_err:
switch (FLAC__stream_decoder_get_state(fi->fsd)) {
case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
return FISH_SOUND_ERR_OUT_OF_MEMORY;
default:
return FISH_SOUND_ERR_GENERIC;
}
}
#else /* !FS_DECODE */
@ -353,7 +397,9 @@ fs_flac_enc_write_callback(const FLAC__StreamEncoder *encoder,
printf("fs_flac_enc_write_callback: generating FLAC header packet: "
"%c%c%c%c\n", buffer[0], buffer[1], buffer[2], buffer[3]);
#endif
fi->buffer = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+9));
if ((fi->buffer = (unsigned char*)fs_malloc(sizeof(unsigned char)*(bytes+9))) == NULL)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
fi->buffer[0] = 0x7f;
fi->buffer[1] = 0x46; /* 'F' */
fi->buffer[2] = 0x4c; /* 'L' */
@ -371,7 +417,11 @@ fs_flac_enc_write_callback(const FLAC__StreamEncoder *encoder,
/* Make a temporary copy of the metadata header to pass to the user
* callback.
*/
unsigned char* tmp = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+fi->bufferlength));
unsigned char* tmp;
if ((tmp = (unsigned char*)fs_malloc(sizeof(unsigned char)*(bytes+fi->bufferlength))) == NULL)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
memcpy (tmp, fi->buffer, fi->bufferlength);
memcpy (tmp+fi->bufferlength, buffer, bytes);
fs_free(fi->buffer);
@ -462,7 +512,8 @@ fs_flac_encode_vcentry (const FishSoundComment * comment)
length += value_len + 1;
}
entry = fs_malloc (length);
if ((entry = fs_malloc (length)) == NULL)
return NULL;
/* We assume that comment->name, value are NUL terminated, as they were
* produced by our own comments.c */
@ -482,7 +533,7 @@ static FLAC__StreamMetadata *
fs_flac_encode_vorbiscomments (FishSound * fsound)
{
FishSoundFlacInfo * fi = fsound->codec_data;
FLAC__StreamMetadata * metadata;
FLAC__StreamMetadata * metadata = NULL;
const FishSoundComment * comment;
unsigned int i=0, length=0, total_length;
FLAC__VCEntry * comments;
@ -502,11 +553,13 @@ fs_flac_encode_vorbiscomments (FishSound * fsound)
if (length == 0) return NULL;
comments = (FLAC__VCEntry *)fs_malloc (sizeof(FLAC__VCEntry) * length);
if ((comments = (FLAC__VCEntry *)fs_malloc (sizeof(FLAC__VCEntry) * length)) == NULL)
goto encode_vc_oom;
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
comments[i].entry = fs_flac_encode_vcentry (comment);
if ((comments[i].entry = fs_flac_encode_vcentry (comment)) == NULL) {
}
comments[i].length = strlen((char *)comments[i].entry);
/* In the generated vorbiscomment data, each entry is preceded by a
@ -515,7 +568,9 @@ fs_flac_encode_vorbiscomments (FishSound * fsound)
i++;
}
metadata = (FLAC__StreamMetadata *) fs_malloc (sizeof (*metadata));
if ((metadata = (FLAC__StreamMetadata *) fs_malloc (sizeof (*metadata))) == NULL)
goto encode_vc_oom;
metadata->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
metadata->is_last = true;
metadata->length = total_length;
@ -527,6 +582,21 @@ fs_flac_encode_vorbiscomments (FishSound * fsound)
fi->enc_vc_metadata = metadata;
return metadata;
encode_vc_oom:
if (metadata != NULL)
fs_free (metadata);
/* Unwind allocated comment entries */
for (i--; i >= 0; i--) {
if (comments[i].entry != NULL)
fs_free (comments[i].entry);
}
if (comments != NULL)
fs_free (comments);
return NULL;
}
static FishSound *
@ -539,26 +609,51 @@ fs_flac_enc_headers (FishSound * fsound)
FLAC__stream_encoder_set_channels(fi->fse, fsound->info.channels);
FLAC__stream_encoder_set_sample_rate(fi->fse, fsound->info.samplerate);
FLAC__stream_encoder_set_bits_per_sample(fi->fse, BITS_PER_SAMPLE);
#if defined (HAVE_FLAC_1_1_2)
FLAC__stream_encoder_set_write_callback(fi->fse, fs_flac_enc_write_callback);
FLAC__stream_encoder_set_metadata_callback(fi->fse, fs_flac_enc_meta_callback);
FLAC__stream_encoder_set_client_data(fi->fse, fsound);
#endif
metadata = fs_flac_encode_vorbiscomments (fsound);
if (metadata != NULL)
FLAC__stream_encoder_set_metadata (fi->fse, &metadata, 1);
/* FLAC__stream_encoder_set_total_samples_estimate(fi->fse, ...);*/
#if defined (HAVE_FLAC_1_1_2)
if (FLAC__stream_encoder_init(fi->fse) != FLAC__STREAM_ENCODER_OK)
return NULL;
#elif defined (HAVE_FLAC_1_1_3)
if (FLAC__stream_encoder_init_stream
(fi->fse,
fs_flac_enc_write_callback,
NULL, /* seek callback */
NULL, /* tell callback */
fs_flac_enc_meta_callback,
fsound
) != FLAC__STREAM_ENCODER_OK)
return NULL;
#endif
return fsound;
}
static long
fs_flac_encode_fatal (FishSoundFlacInfo *fi, long err)
{
FLAC__stream_encoder_delete (fi->fse);
fi->fse = NULL;
return err;
}
static long
fs_flac_encode_f (FishSound * fsound, float * pcm[], long frames)
{
FishSoundFlacInfo *fi = fsound->codec_data;
FLAC__int32 *buffer;
FLAC__int32 *buffer, *ipcm;
float * p, norm = (1 << (BITS_PER_SAMPLE - 1));
long i;
int j, channels = fsound->info.channels;
@ -567,7 +662,10 @@ fs_flac_encode_f (FishSound * fsound, float * pcm[], long frames)
printf("fs_flac_encode_f: IN, frames = %ld\n", frames);
#endif
fi->ipcm = realloc(fi->ipcm, sizeof(FLAC__int32) * channels * frames);
if ((ipcm = realloc(fi->ipcm, sizeof(FLAC__int32) * channels * frames)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fi->ipcm = ipcm;
buffer = (FLAC__int32*) fi->ipcm;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
@ -581,7 +679,17 @@ fs_flac_encode_f (FishSound * fsound, float * pcm[], long frames)
/* We could have used FLAC__stream_encoder_process() and a more direct
* conversion loop above, rather than converting and interleaving. */
FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames);
if (FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames) == false) {
switch (FLAC__stream_encoder_get_state (fi->fse)) {
case FLAC__STREAM_ENCODER_OK:
case FLAC__STREAM_ENCODER_UNINITIALIZED:
break;
case FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_OUT_OF_MEMORY);
default:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_GENERIC);
}
}
fi->packetno++;
@ -592,7 +700,7 @@ static long
fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
{
FishSoundFlacInfo *fi = fsound->codec_data;
FLAC__int32 *buffer;
FLAC__int32 *buffer, *ipcm;
float * p = (float*)pcm, norm = (1 << (BITS_PER_SAMPLE - 1));
long i, length = frames * fsound->info.channels;
@ -600,7 +708,10 @@ fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
printf("fs_flac_encode_f_ilv: IN, frames = %ld\n", frames);
#endif
fi->ipcm = realloc(fi->ipcm, sizeof(FLAC__int32)*fsound->info.channels*frames);
if ((ipcm = realloc(fi->ipcm, sizeof(FLAC__int32)*fsound->info.channels*frames)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fi->ipcm = ipcm;
buffer = (FLAC__int32*) fi->ipcm;
for (i=0; i<length; i++)
buffer[i] = p[i] * norm;
@ -608,7 +719,17 @@ fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
if (fi->packetno == 0)
fs_flac_enc_headers (fsound);
FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames);
if (FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames) == false) {
switch (FLAC__stream_encoder_get_state (fi->fse)) {
case FLAC__STREAM_ENCODER_OK:
case FLAC__STREAM_ENCODER_UNINITIALIZED:
break;
case FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_OUT_OF_MEMORY);
default:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_GENERIC);
}
}
fi->packetno++;
@ -738,6 +859,7 @@ fish_sound_flac_codec (void)
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_FLAC;
codec->format.name = "Flac (Xiph.Org)";

View File

@ -36,6 +36,10 @@
#include <stdlib.h>
#include <string.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#include <ctype.h>
#include "private.h"
@ -132,59 +136,46 @@ process_header(unsigned char * buf, long bytes, int enh_enabled,
header = speex_packet_to_header((char*)buf, (int)bytes);
if (!header) {
/*info_dialog_new ("Speex error", NULL, "Speex: cannot read header");*/
/* cannot read header */
return NULL;
}
if (header->mode >= SPEEX_NB_MODES || header->mode < 0) {
/*
info_dialog_new ("Speex error", NULL,
"Mode number %d does not (any longer) exist in this version\n",
header->mode);
*/
/* Mode number does not (any longer) exist in this version */
return NULL;
}
modeID = header->mode;
if (forceMode!=-1)
modeID = forceMode;
#if HAVE_SPEEX_LIB_GET_MODE
mode = (SpeexMode *) speex_lib_get_mode (modeID);
#else
/* speex_mode_list[] is declared const in speex 1.1.x, hence the cast */
mode = (SpeexMode *)speex_mode_list[modeID];
#endif
if (header->speex_version_id > 1) {
/*
info_dialog_new ("Speex error", NULL,
"This file was encoded with Speex bit-stream version %d, "
"which I don't know how to decode\n",
header->speex_version_id);
*/
/* Unknown bitstream version */
return NULL;
}
if (mode->bitstream_version < header->mode_bitstream_version) {
/*
info_dialog_new ("Speex error", NULL,
"The file was encoded with a newer version of Speex. "
"You need to upgrade in order to play it.\n");
*/
/* The file was encoded with a newer version of Speex,
* need to upgrade in order to play it */
return NULL;
}
if (mode->bitstream_version > header->mode_bitstream_version) {
/*
info_dialog_new ("Speex error", NULL,
"The file was encoded with an older version of Speex. "
"You would need to downgrade the version in order to play it.\n");
*/
/* The file was encoded with an older version of Speex.
* You would need to downgrade the version in order to play it */
return NULL;
}
st = speex_decoder_init(mode);
if (!st) {
/*
info_dialog_new ("Speex error", NULL,
"Decoder initialization failed.\n");
*/
/* Decoder initialization failed */
return NULL;
}
@ -292,7 +283,8 @@ fs_speex_decode (FishSound * fsound, unsigned char * buf, long bytes)
&fss->extra_headers);
if (fss->st == NULL) {
/* XXX: error */
/* TODO: Return more specific error identifiers for invalid header fields */
return FISH_SOUND_ERR_GENERIC;
}
#ifdef DEBUG
@ -302,20 +294,50 @@ fs_speex_decode (FishSound * fsound, unsigned char * buf, long bytes)
fsound->info.samplerate = rate;
fsound->info.channels = channels;
/* Sanity check the channels value, as we will use it to determine buffer
sizes below.
*/
if (channels < 1 || channels > 2)
return FISH_SOUND_ERR_GENERIC;
#if HAVE_UINTPTR_T
/* Sanity check: frame_size is not so large that the buffer size calculations
* would wrap. In reality, frame_size is set by libspeex according to the
* mode index specified in the file header, and is usually equal to 320.
*/
if (fss->frame_size > UINTPTR_MAX / (sizeof(float) * channels))
return FISH_SOUND_ERR_GENERIC;
#endif
fss->ipcm = fs_malloc (sizeof (float) * fss->frame_size * channels);
if (fss->ipcm == NULL) {
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (channels == 1) {
fss->pcm[0] = fss->ipcm;
} else if (channels == 2) {
fss->pcm[0] = fs_malloc (sizeof (float) * fss->frame_size);
if (fss->pcm[0] == NULL) {
fs_free (fss->ipcm);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fss->pcm[1] = fs_malloc (sizeof (float) * fss->frame_size);
if (fss->pcm[1] == NULL) {
fs_free (fss->pcm[0]);
fs_free (fss->ipcm);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
}
if (fss->nframes == 0) fss->nframes = 1;
} else if (fss->packetno == 1) {
/* Comments */
fish_sound_comments_decode (fsound, buf, bytes);
if (fish_sound_comments_decode (fsound, buf, bytes) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fss->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
} else if (fss->packetno <= 1+fss->extra_headers) {
/* Unknown extra headers */
} else {
@ -363,15 +385,21 @@ static FishSound *
fs_speex_enc_headers (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
int modeID;
SpeexMode * mode = NULL;
SpeexHeader header;
unsigned char * buf;
int bytes;
unsigned char * header_buf = NULL, * comments_buf = NULL;
int header_bytes, comments_bytes;
size_t buflen;
/* XXX: set wb, nb, uwb modes */
/* These modes are declared const in speex 1.1.x, hence the explicit cast */
mode = (SpeexMode *)&speex_wb_mode;
modeID = 1;
#if HAVE_SPEEX_LIB_GET_MODE
mode = (SpeexMode *) speex_lib_get_mode (modeID);
#else
/* speex_mode_list[] is declared const in speex 1.1.x, hence the cast */
mode = (SpeexMode *)speex_mode_list[modeID];
#endif
speex_init_header (&header, fsound->info.samplerate, 1, mode);
header.frames_per_packet = fss->nframes; /* XXX: frames per packet */
@ -381,24 +409,26 @@ fs_speex_enc_headers (FishSound * fsound)
fss->st = speex_encoder_init (mode);
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
char vendor_string[128];
/* header */
buf = (unsigned char *) speex_header_to_packet (&header, &bytes);
encoded (fsound, buf, (long)bytes, fsound->user_data);
fss->packetno++;
fs_free (buf);
/* Allocate and create header */
header_buf = (unsigned char *) speex_header_to_packet (&header, &header_bytes);
if (header_buf == NULL) {
return NULL;
}
/* comments */
/* Allocate and create comments */
snprintf (vendor_string, 128, VENDOR_FORMAT, header.speex_version);
fish_sound_comment_set_vendor (fsound, vendor_string);
bytes = fish_sound_comments_encode (fsound, NULL, 0);
buf = fs_malloc (bytes);
bytes = fish_sound_comments_encode (fsound, buf, bytes);
encoded (fsound, buf, (long)bytes, fsound->user_data);
fss->packetno++;
fs_free (buf);
if (fish_sound_comment_set_vendor (fsound, vendor_string) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fs_free (header_buf);
return NULL;
}
comments_bytes = fish_sound_comments_encode (fsound, NULL, 0);
comments_buf = fs_malloc (comments_bytes);
if (comments_buf == NULL) {
fs_free (header_buf);
return NULL;
}
}
speex_encoder_ctl (fss->st, SPEEX_SET_SAMPLING_RATE,
@ -410,12 +440,33 @@ fs_speex_enc_headers (FishSound * fsound)
printf ("got frame size %d\n", fss->frame_size);
#endif
/* XXX: blah blah blah ... set VBR etc. */
/* XXX: set VBR etc. */
buflen = fss->frame_size * fsound->info.channels * sizeof (float);
fss->ipcm = fs_malloc (buflen);
if (fss->ipcm == NULL) {
if (comments_buf) fs_free (comments_buf);
if (header_buf) fs_free (header_buf);
return NULL;
}
memset (fss->ipcm, 0, buflen);
/* Allocations succeeded, actually call encoded callback for headers */
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
/* header */
encoded (fsound, header_buf, (long)header_bytes, fsound->user_data);
fss->packetno++;
fs_free (header_buf);
/* comments */
comments_bytes = fish_sound_comments_encode (fsound, comments_buf, comments_bytes);
encoded (fsound, comments_buf, (long)comments_bytes, fsound->user_data);
fss->packetno++;
fs_free (comments_buf);
}
return fsound;
}
@ -593,10 +644,13 @@ fs_speex_update (FishSound * fsound, int interleave)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
size_t pcm_size = sizeof (float);
float *ipcm_new, *pcm0, *pcm1;
fss->ipcm = (float *)
fs_realloc (fss->ipcm,
pcm_size * fss->frame_size * fsound->info.channels);
ipcm_new = (float *)fs_realloc (fss->ipcm,
pcm_size * fss->frame_size * fsound->info.channels);
if (ipcm_new == NULL) return FISH_SOUND_ERR_OUT_OF_MEMORY;
fss->ipcm = ipcm_new;
if (interleave) {
/* if transitioning from non-interleave to interleave,
@ -611,8 +665,28 @@ fs_speex_update (FishSound * fsound, int interleave)
if (fsound->info.channels == 1) {
fss->pcm[0] = (float *) fss->ipcm;
} else if (fsound->info.channels == 2) {
fss->pcm[0] = fs_realloc (fss->pcm[0], pcm_size * fss->frame_size);
fss->pcm[1] = fs_realloc (fss->pcm[1], pcm_size * fss->frame_size);
#if HAVE_UINTPTR_T
/* Sanity check: frame_size is not so large that the buffer size calculations
* would wrap. In reality, frame_size is set by libspeex according to the
* mode index specified in the file header, and is usually equal to 320.
*/
if (fss->frame_size > UINTPTR_MAX / pcm_size)
return FISH_SOUND_ERR_GENERIC;
#endif
pcm0 = fs_realloc (fss->pcm[0], pcm_size * fss->frame_size);
if (pcm0 == NULL) {
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
pcm1 = fs_realloc (fss->pcm[1], pcm_size * fss->frame_size);
if (pcm1 == NULL) {
fs_free (pcm0);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fss->pcm[0] = pcm0;
fss->pcm[1] = pcm1;
}
}
@ -694,6 +768,7 @@ fish_sound_speex_codec (void)
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_SPEEX;
codec->format.name = "Speex (Xiph.Org)";

View File

@ -115,6 +115,7 @@ fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
ogg_packet op;
long samples;
float * pcm_new;
int ret;
/* Make an ogg_packet structure to pass the data to libvorbis */
@ -142,7 +143,10 @@ fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
* start of vorbiscomment packet. */
if (fsv->packetno == 1 && bytes > 7 && buf[0] == 0x03 &&
!strncmp ((char *)&buf[1], "vorbis", 6)) {
fish_sound_comments_decode (fsound, buf+7, bytes-7);
if (fish_sound_comments_decode (fsound, buf+7, bytes-7) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fsv->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
} else if (fsv->packetno == 2) {
vorbis_synthesis_init (&fsv->vd, &fsv->vi);
vorbis_block_init (&fsv->vd, &fsv->vb);
@ -162,9 +166,15 @@ fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
if (fsound->interleave) {
if (samples > fsv->max_pcm) {
fsv->ipcm = realloc (fsv->ipcm, sizeof(float) * samples *
fsound->info.channels);
fsv->max_pcm = samples;
pcm_new = realloc (fsv->ipcm, sizeof(float) * samples *
fsound->info.channels);
if (pcm_new == NULL) {
/* Allocation failure; just truncate here, fail gracefully elsewhere */
samples = fsv->max_pcm;
} else {
fsv->ipcm = pcm_new;
fsv->max_pcm = samples;
}
}
_fs_interleave (fsv->pcm, (float **)fsv->ipcm, samples,
fsound->info.channels, 1.0);
@ -204,12 +214,14 @@ fs_vorbis_enc_headers (FishSound * fsound)
ogg_packet header_comm;
ogg_packet header_code;
/* Vorbis streams begin with three headers; the initial header (with
most of the codec setup parameters) which is mandated by the Ogg
bitstream spec. The second header holds any comment fields. The
third header holds the bitstream codebook. We merely need to
make the headers, then pass them to libvorbis one at a time;
libvorbis handles the additional Ogg bitstream constraints */
/* Vorbis streams begin with three headers:
* 1. The initial header (with most of the codec setup parameters),
* which is mandated by the Ogg bitstream spec,
* 2. The second header which holds any comment fields,
* 3. The third header which contains the bitstream codebook.
* We merely need to make the headers, then pass them to libvorbis one at
* a time; libvorbis handles the additional Ogg bitstream constraints.
*/
/* Update the comments */
for (comment = fish_sound_comment_first (fsound); comment;
@ -333,7 +345,6 @@ fs_vorbis_encode_f (FishSound * fsound, float * pcm[], long frames)
float ** vpcm;
long len, remaining = frames;
int i;
float ** ppcm = alloca (sizeof (float *) * fsound->info.channels);
if (fsv->packetno == 0) {
fs_vorbis_enc_headers (fsound);
@ -344,10 +355,6 @@ fs_vorbis_encode_f (FishSound * fsound, float * pcm[], long frames)
return 0;
}
for (i = 0; i < fsound->info.channels; i++) {
ppcm[i] = pcm[i];
}
while (remaining > 0) {
len = MIN (1024, remaining);
@ -359,7 +366,7 @@ fs_vorbis_encode_f (FishSound * fsound, float * pcm[], long frames)
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
for (i = 0; i < fsound->info.channels; i++) {
memcpy (vpcm[i], ppcm[i], sizeof (float) * len);
memcpy (vpcm[i], pcm[i], sizeof (float) * len);
}
fs_vorbis_encode_write (fsound, len);
@ -428,7 +435,7 @@ fs_vorbis_init (FishSound * fsound)
fsv->finished = 0;
vorbis_info_init (&fsv->vi);
vorbis_comment_init (&fsv->vc);
vorbis_dsp_init (&fsv->vd);
memset(&fsv->vd, 0, sizeof(fsv->vd));
vorbis_block_init (&fsv->vd, &fsv->vb);
fsv->pcm = NULL;
fsv->ipcm = NULL;
@ -475,6 +482,7 @@ fish_sound_vorbis_codec (void)
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_VORBIS;
codec->format.name = "Vorbis (Xiph.Org)";

View File

@ -58,6 +58,7 @@ fs_vector_new (FishSoundCmpFunc cmp)
FishSoundVector * vector;
vector = fs_malloc (sizeof (FishSoundVector));
if (vector == NULL) return NULL;
vector->max_elements = 0;
vector->nr_elements = 0;
@ -176,6 +177,8 @@ fs_vector_grow (FishSoundVector * vector)
void *
fs_vector_insert (FishSoundVector * vector, void * data)
{
if (vector == NULL) return NULL;
if (fs_vector_grow (vector) == NULL)
return NULL;

View File

@ -38,5 +38,4 @@ cp $1/src/libfishsound/fs_vector.h ./src/libfishsound/fs_vector.h
cp $1/src/libfishsound/fs_vector.c ./src/libfishsound/fs_vector.c
cp $1/src/libfishsound/convert.h ./src/libfishsound/convert.h
cp $1/AUTHORS ./AUTHORS
patch -p4 <endian.patch
patch -p3 <bug481601.patch
patch -p3 <endian.patch

View File

@ -104,36 +104,41 @@ and mux and demux examples can be read online at:
http://www.annodex.net/software/liboggz/html/
Tools
-----
oggz tool
---------
The Oggz source tarball also contains the following command-line tools,
which are useful for debugging and testing Ogg bitstreams:
Usage: oggz <subcommand> [options] filename ...
* oggz-chop: Extract the part of an Ogg file between given start
and/or end times.
oggz is a commandline tool for manipulating Ogg files. It supports
multiplexed files conformant with RFC3533. Oggz can parse headers for
CELT, CMML, FLAC, Kate, PCM, Speex, Theora and Vorbis, and can read and write
Ogg Skeleton logical bitstreams.
* oggz-comment: List or edit comments in an Ogg file.
Commands:
help Display help for a specific subcommand (eg. "oggz help chop")
* oggz-diff: Hexdump the packets of two Ogg files and output
differences.
Reporting:
diff Hexdump the packets of two Ogg files and output differences.
dump Hexdump packets of an Ogg file, or revert an Ogg file from
such a hexdump.
info Display information about one or more Ogg files and their
bitstreams.
scan Scan an Ogg file and output characteristic landmarks.
validate Validate the Ogg framing of one or more files.
* oggz-dump: Hexdump packets of an Ogg file, or revert an Ogg file
from such a hexdump.
Extraction:
rip Extract one or more logical bitstreams from an Ogg file.
* oggz-info: Display information about one or more Ogg files and
their bitstreams.
Editing:
chop Extract the part of an Ogg file between given start and/or
end times.
comment List or edit comments in an Ogg file.
merge Merge Ogg files together, interleaving pages in order of
presentation time.
sort Sort the pages of an Ogg file in order of presentation time.
* oggz-merge: Merge Ogg files together, interleaving pages in order
of presentation time.
* oggz-rip: Extract one or more logical bitstreams from an Ogg file.
* oggz-scan: Scan an Ogg file and output characteristic landmarks.
* oggz-sort: Sort the pages of an Ogg file in order of presentation time.
* oggz-validate: Validate the Ogg framing of one or more files.
Miscellaneous:
known-codecs List codecs known by this version of oggz
The script bash-completion/oggz enables completion of tool options and codec
names when using the bash shell. Source it from your .profile, or install it

View File

@ -1,15 +1,12 @@
The source from this directory was copied from the liboggz svn
The source from this directory was copied from the liboggz git
source repository using the update.sh script. The only changes made
were those applied by update.sh, which applies patches described
below, and the addition/upate of Makefile.in files for the
Mozilla build system.
The svn revision number used was r3867.
The git commit id used was ef3b0e from git://git.xiph.org/liboggz.git
The wince.patch addresses the lack of posix file IO support on windows ce,
see bug 461844 for details.
endian.patch is applied to fix bug 452698.
oggz-seek-crash-fix.patch is applied to fix the crash reported in
bug 475441 comment #44.

View File

@ -135,5 +135,4 @@
/* Define for MSVC as <stdint.h> is unavailable there */
typedef unsigned char uint8_t;
#define inline __inline // MSVC
#undef DEBUG
#define inline __inline // MSVC#undef DEBUG

View File

@ -158,6 +158,7 @@ int oggz_set_read_page (OGGZ * oggz, long serialno,
* returning OGGZ_STOP_OK
* \retval OGGZ_ERR_STOP_ERR Reading was stopped by a user callback
* returning OGGZ_STOP_ERR
* \retval OGGZ_ERR_HOLE_IN_DATA Hole (sequence number gap) detected in input data
* \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
*/
long oggz_read (OGGZ * oggz, long n);
@ -174,6 +175,8 @@ long oggz_read (OGGZ * oggz, long n);
* returning OGGZ_STOP_OK
* \retval OGGZ_ERR_STOP_ERR Reading was stopped by a user callback
* returning OGGZ_STOP_ERR
* \retval OGGZ_ERR_HOLE_IN_DATA Hole (sequence number gap) detected in input data
* \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
*/
long oggz_read_input (OGGZ * oggz, unsigned char * buf, long n);

View File

@ -1,22 +0,0 @@
diff --git a/media/liboggz/src/liboggz/oggz_seek.c b/media/liboggz/src/liboggz/oggz_seek.c
--- a/media/liboggz/src/liboggz/oggz_seek.c
+++ b/media/liboggz/src/liboggz/oggz_seek.c
@@ -717,17 +717,17 @@ oggz_seek_set (OGGZ * oggz, ogg_int64_t
&serialno);
unit_end = oggz_get_unit (oggz, serialno, granule_at);
#ifdef DEBUG
printf ("oggz_seek_set: [C] offset_next @%" PRI_OGGZ_OFF_T "d, g%lld, (s%ld)\n",
offset_next, granule_at, serialno);
printf ("oggz_seek_set: [c] u%lld\n",
oggz_get_unit (oggz, serialno, granule_at));
#endif
- } else {
+ } else if (offset_next >= 0) {
serialno = ogg_page_serialno (og);
granule_at = ogg_page_granulepos (og);
}
if (offset_next < 0) {
goto notfound;
}

View File

@ -638,7 +638,7 @@ oggz_map_return_value_to_error (int cb_ret)
case OGGZ_STOP_ERR:
return OGGZ_ERR_STOP_ERR;
default:
return OGGZ_ERR_STOP_ERR;
return cb_ret;
}
}

View File

@ -375,11 +375,6 @@ auto_dirac (OGGZ * oggz, long serialno, unsigned char * data, long length, void
dirac_parse_info(info, data, length);
#ifdef DEBUG
printf ("Got dirac fps %d/%d granule_shift %d\n",
fps_numerator, fps_denominator, granule_shift);
#endif
/* the granulerate is twice the frame rate (in order to handle interlace) */
oggz_set_granulerate (oggz, serialno,
2 * (ogg_int64_t)info->fps_numerator,
@ -558,8 +553,7 @@ auto_calc_celt (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
* are marked by a set 2MSB in the first byte. Intra packets (keyframes)
* are any that are left over ;-)
*
* (see http://www.theora.org/doc/Theora_I_spec.pdf for the theora
* specification)
* (see http://theora.org/doc/Theora.pdf for the theora specification)
*/
typedef struct {
@ -695,6 +689,7 @@ static ogg_int64_t
auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
auto_calc_vorbis_info_t *info;
int ii;
if (stream->calculate_data == NULL) {
/*
@ -830,19 +825,32 @@ auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
}
if (offset > 4) {
size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
} else {
/* mask part of byte from current_pos */
size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
/* shift to appropriate position */
size_check <<= (5 - offset);
/* or in part of byte from current_pos - 1 */
size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
(offset + 3);
/* Give ourselves a chance to recover if we went back too far by using
* the size check. */
for (ii=0; ii < 2; ii++) {
if (offset > 4) {
size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
} else {
/* mask part of byte from current_pos */
size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
/* shift to appropriate position */
size_check <<= (5 - offset);
/* or in part of byte from current_pos - 1 */
size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
(offset + 3);
}
size_check += 1;
if (size_check == size) {
break;
}
offset = (offset + 1) % 8;
if (offset == 0)
current_pos += 1;
current_pos += 5;
size -= 1;
}
size_check += 1;
#ifdef DEBUG
if (size_check != size)
{

View File

@ -57,9 +57,12 @@
#define strcasecmp _stricmp
#endif
/* Ensure comment vector length can be expressed in 32 bits
* including space for the trailing NUL */
#define MAX_COMMENT_LENGTH 0xFFFFFFFE
#define oggz_comment_clamp(c) MIN((c),MAX_COMMENT_LENGTH)
/* Ensure comment vector length can be expressed in 32 bits */
static unsigned long
static size_t
oggz_comment_len (const char * s)
{
size_t len;
@ -67,7 +70,7 @@ oggz_comment_len (const char * s)
if (s == NULL) return 0;
len = strlen (s);
return (unsigned long) MIN(len, 0xFFFFFFFF);
return oggz_comment_clamp(len);
}
static char *
@ -82,11 +85,12 @@ oggz_strdup (const char * s)
}
static char *
oggz_strdup_len (const char * s, int len)
oggz_strdup_len (const char * s, size_t len)
{
char * ret;
if (s == NULL) return NULL;
if (len == 0) return NULL;
len = oggz_comment_clamp(len);
ret = oggz_malloc (len + 1);
if (!ret) return NULL;
if (strncpy (ret, s, len) == NULL) {
@ -173,12 +177,23 @@ oggz_comment_new (const char * name, const char * value)
OggzComment * comment;
if (!oggz_comment_validate_byname (name, value)) return NULL;
/* Ensures that name != NULL, value != NULL, and validates strings */
comment = oggz_malloc (sizeof (OggzComment));
if (comment == NULL) return NULL;
comment->name = oggz_strdup (name);
if (comment->name == NULL) {
oggz_free (comment);
return NULL;
}
comment->value = oggz_strdup (value);
if (comment->value == NULL) {
oggz_free (comment->name);
oggz_free (comment);
return NULL;
}
return comment;
}
@ -217,7 +232,8 @@ _oggz_comment_set_vendor (OGGZ * oggz, long serialno,
if (stream->vendor) oggz_free (stream->vendor);
stream->vendor = oggz_strdup (vendor_string);
if ((stream->vendor = oggz_strdup (vendor_string)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
return 0;
}
@ -364,9 +380,11 @@ oggz_comment_add (OGGZ * oggz, long serialno, const OggzComment * comment)
if (!oggz_comment_validate_byname (comment->name, comment->value))
return OGGZ_ERR_COMMENT_INVALID;
new_comment = oggz_comment_new (comment->name, comment->value);
if ((new_comment = oggz_comment_new (comment->name, comment->value)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
_oggz_comment_add (stream, new_comment);
if (_oggz_comment_add (stream, new_comment) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
return 0;
} else {
@ -398,9 +416,11 @@ oggz_comment_add_byname (OGGZ * oggz, long serialno,
if (!oggz_comment_validate_byname (name, value))
return OGGZ_ERR_COMMENT_INVALID;
new_comment = oggz_comment_new (name, value);
if ((new_comment = oggz_comment_new (name, value)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
_oggz_comment_add (stream, new_comment);
if (_oggz_comment_add (stream, new_comment) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
return 0;
} else {
@ -531,7 +551,8 @@ oggz_comments_decode (OGGZ * oggz, long serialno,
{
oggz_stream_t * stream;
char *c= (char *)comments;
int len, i, nb_fields, n;
int i, nb_fields, n;
size_t len;
char *end;
char * name, * value, * nvalue = NULL;
OggzComment * comment;
@ -543,16 +564,22 @@ oggz_comments_decode (OGGZ * oggz, long serialno,
len=readint(c, 0);
c+=4;
if (c+len>end) return -1;
if (len>(size_t)(end-c)) return -1;
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
/* Vendor */
nvalue = oggz_strdup_len (c, len);
if (!nvalue) return -1;
_oggz_comment_set_vendor (oggz, serialno, nvalue);
if (nvalue) oggz_free (nvalue);
if (len > 0) {
if ((nvalue = oggz_strdup_len (c, len)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
if (_oggz_comment_set_vendor (oggz, serialno, nvalue) == OGGZ_ERR_OUT_OF_MEMORY)
return OGGZ_ERR_OUT_OF_MEMORY;
oggz_free (nvalue);
}
#ifdef DEBUG
fwrite(c, 1, len, stderr); fputc ('\n', stderr);
#endif
@ -560,6 +587,8 @@ oggz_comments_decode (OGGZ * oggz, long serialno,
if (c+4>end) return -1;
/* This value gets checked effectively by the 'for' condition
and the checks within the loop for c running off the end. */
nb_fields=readint(c, 0);
c+=4;
for (i=0;i<nb_fields;i++) {
@ -568,7 +597,7 @@ oggz_comments_decode (OGGZ * oggz, long serialno,
len=readint(c, 0);
c+=4;
if (c+len>end) return -1;
if (len>(size_t)(end-c)) return -1;
name = c;
value = oggz_index_len (c, '=', len);
@ -577,18 +606,30 @@ oggz_comments_decode (OGGZ * oggz, long serialno,
value++;
n = c+len - value;
nvalue = oggz_strdup_len (value, n);
if ((nvalue = oggz_strdup_len (value, n)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
#ifdef DEBUG
printf ("oggz_comments_decode: %s -> %s (length %d)\n",
name, nvalue, n);
#endif
comment = oggz_comment_new (name, nvalue);
_oggz_comment_add (stream, comment);
if ((comment = oggz_comment_new (name, nvalue)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
if (_oggz_comment_add (stream, comment) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
oggz_free (nvalue);
} else {
nvalue = oggz_strdup_len (name, len);
comment = oggz_comment_new (nvalue, NULL);
_oggz_comment_add (stream, comment);
if ((nvalue = oggz_strdup_len (name, len)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
if ((comment = oggz_comment_new (nvalue, NULL)) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
if (_oggz_comment_add (stream, comment) == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
oggz_free (nvalue);
}
@ -648,7 +689,9 @@ oggz_comments_encode (OGGZ * oggz, long serialno,
#endif
/* user comment list length */
actual_length += 4;
if (accum_length (&actual_length, 4) == 0)
return 0;
for (comment = oggz_comment_first (oggz, serialno); comment;
comment = oggz_comment_next (oggz, serialno, comment)) {
@ -686,7 +729,7 @@ oggz_comments_encode (OGGZ * oggz, long serialno,
field_length = oggz_comment_len (stream->vendor);
memcpy (c, stream->vendor, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0 ) return actual_length;
if (remaining <= 0) return actual_length;
}
remaining -= 4;

View File

@ -47,4 +47,3 @@ cp $1/AUTHORS ./AUTHORS
patch -p3 <wince.patch
patch -p3 <endian.patch
patch -p4 <seek.patch
patch -p3 <seek-error-fix.patch