forked from len0rd/rockbox
First Rockbox version of ALAC decoder - porting to work in Rockbox environment and some simple (but significant) optimisations
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7544 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
567718d837
commit
debbe9747e
8 changed files with 405 additions and 197 deletions
47
apps/codecs/libalac/Makefile
Normal file
47
apps/codecs/libalac/Makefile
Normal file
|
@ -0,0 +1,47 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
INCLUDES=-I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
|
||||
-I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(BUILDDIR)
|
||||
|
||||
ifdef APPEXTRA
|
||||
INCLUDES += -I$(APPSDIR)/$(APPEXTRA)
|
||||
endif
|
||||
|
||||
ALACOPTS = -O3
|
||||
CFLAGS = $(GCCOPTS) $(ALACOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEMORYSIZE}
|
||||
|
||||
# This sets up 'SRC' based on the files mentioned in SOURCES
|
||||
include $(TOOLSDIR)/makesrc.inc
|
||||
|
||||
SOURCES = $(SRC)
|
||||
OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
|
||||
DEPFILE = $(OBJDIR)/dep-libalac
|
||||
DIRS =
|
||||
|
||||
OUTPUT = $(BUILDDIR)/libalac.a
|
||||
|
||||
all: $(OUTPUT)
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
@echo "AR $@"
|
||||
@$(AR) ruv $@ $+ >/dev/null 2>&1
|
||||
|
||||
$(OBJDIR)/libalac/%.o: $(APPSDIR)/codecs/libalac/%.c
|
||||
@echo "(libalac) CC $<"
|
||||
@$(CC) -c $(CFLAGS) -I$(APPSDIR)/codecs/libalac/ $< -o $@
|
||||
|
||||
include $(TOOLSDIR)/make.inc
|
||||
|
||||
clean:
|
||||
@echo "cleaning libalac"
|
||||
@rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
|
||||
|
||||
-include $(DEPFILE)
|
80
apps/codecs/libalac/README.rockbox
Normal file
80
apps/codecs/libalac/README.rockbox
Normal file
|
@ -0,0 +1,80 @@
|
|||
Library: Reverse-engineered ALAC decoder v0.1.0
|
||||
Imported: 2005-08-14 by Dave Chapman
|
||||
|
||||
|
||||
This directory contains a local version of an ALAC (Apple Lossless Audio
|
||||
Codec) for use by Rockbox for software decoding of ALAC files. It is
|
||||
based on the reverse-engineered decoder by David Hamilton.
|
||||
|
||||
LICENSING INFORMATION
|
||||
|
||||
/*
|
||||
* ALAC (Apple Lossless Audio Codec) decoder
|
||||
* Copyright (c) 2005 David Hammerton
|
||||
* All rights reserved.
|
||||
*
|
||||
* This is the actual decoder.
|
||||
*
|
||||
* http://crazney.net/programs/itunes/alac.html
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
IMPORT DETAILS
|
||||
|
||||
The base version first imported into Rockbox was the first release
|
||||
(v0.1.0) of the ALAC decoder by David Hammerton.
|
||||
|
||||
Only the files alac.[ch], demux.[ch] and stream.h were used.
|
||||
|
||||
stream.c (the original FILE* based I/O implementation) was replaced with
|
||||
functions in the ALAC codec - to interface with the Rockbox audio playback
|
||||
system.
|
||||
|
||||
References to <stdint.h> were replaced with <inttypes.h> and debugging
|
||||
calls to fprintf were removed.
|
||||
|
||||
The ALAC decoder itself was modified to return samples in host-endian
|
||||
order, instead of little-endian.
|
||||
|
||||
The run-time detection of CPU endianness was replaced with
|
||||
compile-time tests of the ROCKBOX_LITTLE_ENDIAN define.
|
||||
|
||||
All malloc calls were removed from alac.c, but some are still present
|
||||
in the metadata parser in demux.c - to store unbounded data such as
|
||||
the size in bytes of each compressed block in the file.
|
||||
|
||||
The only changes to demux.c were to remove debugging calls to fprintf.
|
||||
|
||||
The most-used buffers (the temporary 32-bit output buffer) were moved
|
||||
into IRAM (on the iRiver). This was enough to make the decoder work
|
||||
in real-time.
|
||||
|
||||
A point of interest - the -O3 gcc option (the setting used in the
|
||||
original Makefile provided with the alac decoder) gives a significant
|
||||
speedup compared to -O2. With -O2, the Coldfire runs at a constant
|
||||
120MHz, but with -O3, it can power-down to 40MHz for a small amount of
|
||||
time.
|
||||
|
||||
The file alac.c contained some hints from the original author for
|
||||
places where major optimisations can be made - specifically the
|
||||
unrolling and optimisation of certain cases of general loops.
|
2
apps/codecs/libalac/SOURCES
Normal file
2
apps/codecs/libalac/SOURCES
Normal file
|
@ -0,0 +1,2 @@
|
|||
alac.c
|
||||
demux.c
|
|
@ -33,8 +33,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "../codec.h"
|
||||
#include "decomp.h"
|
||||
|
||||
#define _Swap32(v) do { \
|
||||
|
@ -47,53 +48,13 @@
|
|||
v = (((v) & 0x00FF) << 0x08) | \
|
||||
(((v) & 0xFF00) >> 0x08); } while (0)
|
||||
|
||||
|
||||
extern int host_bigendian;
|
||||
|
||||
struct alac_file
|
||||
{
|
||||
unsigned char *input_buffer;
|
||||
int input_buffer_bitaccumulator; /* used so we can do arbitary
|
||||
bit reads */
|
||||
|
||||
int samplesize;
|
||||
int numchannels;
|
||||
int bytespersample;
|
||||
|
||||
|
||||
/* buffers */
|
||||
int32_t *predicterror_buffer_a;
|
||||
int32_t *predicterror_buffer_b;
|
||||
|
||||
int32_t *outputsamples_buffer_a;
|
||||
int32_t *outputsamples_buffer_b;
|
||||
|
||||
|
||||
/* stuff from setinfo */
|
||||
uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
|
||||
uint8_t setinfo_7a; /* 0x00 */
|
||||
uint8_t setinfo_sample_size; /* 0x10 */
|
||||
uint8_t setinfo_rice_historymult; /* 0x28 */
|
||||
uint8_t setinfo_rice_initialhistory; /* 0x0a */
|
||||
uint8_t setinfo_rice_kmodifier; /* 0x0e */
|
||||
uint8_t setinfo_7f; /* 0x02 */
|
||||
uint16_t setinfo_80; /* 0x00ff */
|
||||
uint32_t setinfo_82; /* 0x000020e7 */
|
||||
uint32_t setinfo_86; /* 0x00069fe4 */
|
||||
uint32_t setinfo_8a_rate; /* 0x0000ac44 */
|
||||
/* end setinfo stuff */
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void allocate_buffers(alac_file *alac)
|
||||
{
|
||||
alac->predicterror_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
|
||||
alac->predicterror_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
|
||||
|
||||
alac->outputsamples_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
|
||||
alac->outputsamples_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
|
||||
}
|
||||
int16_t predictor_coef_table[32] IDATA_ATTR;
|
||||
int16_t predictor_coef_table_a[32] IDATA_ATTR;
|
||||
int16_t predictor_coef_table_b[32] IDATA_ATTR;
|
||||
int32_t predicterror_buffer_a[4096];
|
||||
int32_t predicterror_buffer_b[4096];
|
||||
int32_t outputsamples_buffer_a[4096] IDATA_ATTR;
|
||||
int32_t outputsamples_buffer_b[4096] IDATA_ATTR;
|
||||
|
||||
void alac_set_info(alac_file *alac, char *inputbuffer)
|
||||
{
|
||||
|
@ -107,8 +68,9 @@ void alac_set_info(alac_file *alac, char *inputbuffer)
|
|||
ptr += 4; /* 0 ? */
|
||||
|
||||
alac->setinfo_max_samples_per_frame = *(uint32_t*)ptr; /* buffer size / 2 ? */
|
||||
if (!host_bigendian)
|
||||
_Swap32(alac->setinfo_max_samples_per_frame);
|
||||
#ifdef ROCKBOX_LITTLE_ENDIAN
|
||||
_Swap32(alac->setinfo_max_samples_per_frame);
|
||||
#endif
|
||||
ptr += 4;
|
||||
alac->setinfo_7a = *(uint8_t*)ptr;
|
||||
ptr += 1;
|
||||
|
@ -123,24 +85,25 @@ void alac_set_info(alac_file *alac, char *inputbuffer)
|
|||
alac->setinfo_7f = *(uint8_t*)ptr;
|
||||
ptr += 1;
|
||||
alac->setinfo_80 = *(uint16_t*)ptr;
|
||||
if (!host_bigendian)
|
||||
_Swap16(alac->setinfo_80);
|
||||
#ifdef ROCKBOX_LITTLE_ENDIAN
|
||||
_Swap16(alac->setinfo_80);
|
||||
#endif
|
||||
ptr += 2;
|
||||
alac->setinfo_82 = *(uint32_t*)ptr;
|
||||
if (!host_bigendian)
|
||||
_Swap32(alac->setinfo_82);
|
||||
#ifdef ROCKBOX_LITTLE_ENDIAN
|
||||
_Swap32(alac->setinfo_82);
|
||||
#endif
|
||||
ptr += 4;
|
||||
alac->setinfo_86 = *(uint32_t*)ptr;
|
||||
if (!host_bigendian)
|
||||
_Swap32(alac->setinfo_86);
|
||||
#ifdef ROCKBOX_LITTLE_ENDIAN
|
||||
_Swap32(alac->setinfo_86);
|
||||
#endif
|
||||
ptr += 4;
|
||||
alac->setinfo_8a_rate = *(uint32_t*)ptr;
|
||||
if (!host_bigendian)
|
||||
_Swap32(alac->setinfo_8a_rate);
|
||||
#ifdef ROCKBOX_LITTLE_ENDIAN
|
||||
_Swap32(alac->setinfo_8a_rate);
|
||||
#endif
|
||||
ptr += 4;
|
||||
|
||||
allocate_buffers(alac);
|
||||
|
||||
}
|
||||
|
||||
/* stream reading */
|
||||
|
@ -432,23 +395,150 @@ static void predictor_decompress_fir_adapt(int32_t *error_buffer,
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* 4 and 8 are very common cases (the only ones i've seen). these
|
||||
* should be unrolled and optimised
|
||||
/* 4 and 8 are very common cases (the only ones i've seen).
|
||||
|
||||
The following code is an initial attempt to unroll and optimise
|
||||
these two cases by the Rockbox project. More work is needed.
|
||||
*/
|
||||
|
||||
/* optimised case: 4 */
|
||||
if (predictor_coef_num == 4)
|
||||
{
|
||||
/* FIXME: optimised general case */
|
||||
for (i = 4 + 1; i < output_size; i++)
|
||||
{
|
||||
int sum = 0;
|
||||
int outval;
|
||||
int error_val = error_buffer[i];
|
||||
|
||||
sum = (buffer_out[4] - buffer_out[0]) * predictor_coef_table[0]
|
||||
+ (buffer_out[3] - buffer_out[0]) * predictor_coef_table[1]
|
||||
+ (buffer_out[2] - buffer_out[0]) * predictor_coef_table[2]
|
||||
+ (buffer_out[1] - buffer_out[0]) * predictor_coef_table[3];
|
||||
|
||||
outval = (1 << (predictor_quantitization-1)) + sum;
|
||||
outval = outval >> predictor_quantitization;
|
||||
outval = outval + buffer_out[0] + error_val;
|
||||
outval = SIGN_EXTENDED32(outval, readsamplesize);
|
||||
|
||||
buffer_out[4+1] = outval;
|
||||
|
||||
if (error_val > 0)
|
||||
{
|
||||
int predictor_num = 4 - 1;
|
||||
|
||||
while (predictor_num >= 0 && error_val > 0)
|
||||
{
|
||||
int val = buffer_out[0] - buffer_out[4 - predictor_num];
|
||||
|
||||
if (val!=0) {
|
||||
if (val < 0) {
|
||||
predictor_coef_table[predictor_num]++;
|
||||
val=-val;
|
||||
} else {
|
||||
predictor_coef_table[predictor_num]--;;
|
||||
}
|
||||
error_val -= ((val >> predictor_quantitization) * (4 - predictor_num));
|
||||
}
|
||||
predictor_num--;
|
||||
}
|
||||
}
|
||||
else if (error_val < 0)
|
||||
{
|
||||
int predictor_num = 4 - 1;
|
||||
|
||||
while (predictor_num >= 0 && error_val < 0)
|
||||
{
|
||||
int val = buffer_out[0] - buffer_out[4 - predictor_num];
|
||||
|
||||
if (val != 0) {
|
||||
if (val > 0) {
|
||||
predictor_coef_table[predictor_num]++;
|
||||
val=-val; /* neg value */
|
||||
} else {
|
||||
predictor_coef_table[predictor_num]--;
|
||||
}
|
||||
error_val -= ((val >> predictor_quantitization) * (4 - predictor_num));
|
||||
}
|
||||
predictor_num--;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_out++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (predictor_coef_table == 8)
|
||||
/* optimised case: 8 */
|
||||
if (predictor_coef_num == 8)
|
||||
{
|
||||
/* FIXME: optimised general case */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
for (i = 8 + 1;
|
||||
i < output_size;
|
||||
i++)
|
||||
{
|
||||
int sum;
|
||||
int outval;
|
||||
int error_val = error_buffer[i];
|
||||
|
||||
sum = (buffer_out[8] - buffer_out[0]) * predictor_coef_table[0]
|
||||
+ (buffer_out[7] - buffer_out[0]) * predictor_coef_table[1]
|
||||
+ (buffer_out[6] - buffer_out[0]) * predictor_coef_table[2]
|
||||
+ (buffer_out[5] - buffer_out[0]) * predictor_coef_table[3]
|
||||
+ (buffer_out[4] - buffer_out[0]) * predictor_coef_table[4]
|
||||
+ (buffer_out[3] - buffer_out[0]) * predictor_coef_table[5]
|
||||
+ (buffer_out[2] - buffer_out[0]) * predictor_coef_table[6]
|
||||
+ (buffer_out[1] - buffer_out[0]) * predictor_coef_table[7];
|
||||
|
||||
outval = (1 << (predictor_quantitization-1)) + sum;
|
||||
outval = outval >> predictor_quantitization;
|
||||
outval = outval + buffer_out[0] + error_val;
|
||||
outval = SIGN_EXTENDED32(outval, readsamplesize);
|
||||
|
||||
buffer_out[8+1] = outval;
|
||||
|
||||
if (error_val > 0)
|
||||
{
|
||||
int predictor_num = 8 - 1;
|
||||
|
||||
while (predictor_num >= 0 && error_val > 0)
|
||||
{
|
||||
int val = buffer_out[0] - buffer_out[8 - predictor_num];
|
||||
|
||||
if (val!=0) {
|
||||
if (val < 0) {
|
||||
predictor_coef_table[predictor_num]++;
|
||||
val=-val;
|
||||
} else {
|
||||
predictor_coef_table[predictor_num]--;;
|
||||
}
|
||||
error_val -= ((val >> predictor_quantitization) * (8 - predictor_num));
|
||||
}
|
||||
predictor_num--;
|
||||
}
|
||||
}
|
||||
else if (error_val < 0)
|
||||
{
|
||||
int predictor_num = 8 - 1;
|
||||
|
||||
while (predictor_num >= 0 && error_val < 0)
|
||||
{
|
||||
int val = buffer_out[0] - buffer_out[8 - predictor_num];
|
||||
if (val != 0) {
|
||||
if (val > 0) {
|
||||
predictor_coef_table[predictor_num]++;
|
||||
val=-val; /* neg value */
|
||||
} else {
|
||||
predictor_coef_table[predictor_num]--;
|
||||
}
|
||||
error_val -= ((val >> predictor_quantitization) * (8 - predictor_num));
|
||||
}
|
||||
predictor_num--;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_out++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* general case */
|
||||
if (predictor_coef_num > 0)
|
||||
|
@ -534,26 +624,12 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
|
|||
for (i = 0; i < numsamples; i++)
|
||||
{
|
||||
int32_t difference, midright;
|
||||
int16_t left;
|
||||
int16_t right;
|
||||
|
||||
midright = buffer_a[i];
|
||||
difference = buffer_b[i];
|
||||
|
||||
|
||||
right = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
|
||||
left = (midright - ((difference * interlacing_leftweight) >> interlacing_shift))
|
||||
+ difference;
|
||||
|
||||
/* output is always little endian */
|
||||
if (host_bigendian)
|
||||
{
|
||||
_Swap16(left);
|
||||
_Swap16(right);
|
||||
}
|
||||
|
||||
buffer_out[i*numchannels] = left;
|
||||
buffer_out[i*numchannels + 1] = right;
|
||||
buffer_out[i*numchannels] = (midright - ((difference * interlacing_leftweight) >> interlacing_shift)) + difference;
|
||||
buffer_out[i*numchannels + 1] = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -562,34 +638,27 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
|
|||
/* otherwise basic interlacing took place */
|
||||
for (i = 0; i < numsamples; i++)
|
||||
{
|
||||
int16_t left, right;
|
||||
|
||||
left = buffer_a[i];
|
||||
right = buffer_b[i];
|
||||
|
||||
/* output is always little endian */
|
||||
if (host_bigendian)
|
||||
{
|
||||
_Swap16(left);
|
||||
_Swap16(right);
|
||||
}
|
||||
|
||||
buffer_out[i*numchannels] = left;
|
||||
buffer_out[i*numchannels + 1] = right;
|
||||
buffer_out[i*numchannels] = buffer_a[i];
|
||||
buffer_out[i*numchannels + 1] = buffer_b[i];
|
||||
}
|
||||
}
|
||||
|
||||
void decode_frame(alac_file *alac,
|
||||
int16_t* decode_frame(alac_file *alac,
|
||||
unsigned char *inbuffer,
|
||||
void *outbuffer, int *outputsize)
|
||||
int *outputsize)
|
||||
{
|
||||
int channels;
|
||||
int16_t* outbuffer;
|
||||
int32_t outputsamples = alac->setinfo_max_samples_per_frame;
|
||||
|
||||
/* setup the stream */
|
||||
alac->input_buffer = inbuffer;
|
||||
alac->input_buffer_bitaccumulator = 0;
|
||||
|
||||
/* We can share the same buffer for outputbuffer
|
||||
and outputsamples_buffer_b - and hence have them both in IRAM*/
|
||||
outbuffer=(int16_t*)outputsamples_buffer_b;
|
||||
|
||||
channels = readbits(alac, 3);
|
||||
|
||||
*outputsize = outputsamples * alac->bytespersample;
|
||||
|
@ -631,7 +700,6 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
if (!isnotcompressed)
|
||||
{ /* so it is compressed */
|
||||
int16_t predictor_coef_table[32];
|
||||
int predictor_coef_num;
|
||||
int prediction_type;
|
||||
int prediction_quantitization;
|
||||
|
@ -659,11 +727,11 @@ void decode_frame(alac_file *alac,
|
|||
/* these bytes seem to have something to do with
|
||||
* > 2 channel files.
|
||||
*/
|
||||
fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
|
||||
//fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
|
||||
}
|
||||
|
||||
basterdised_rice_decompress(alac,
|
||||
alac->predicterror_buffer_a,
|
||||
predicterror_buffer_a,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
alac->setinfo_rice_initialhistory,
|
||||
|
@ -673,8 +741,8 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
if (prediction_type == 0)
|
||||
{ /* adaptive fir */
|
||||
predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
|
||||
alac->outputsamples_buffer_a,
|
||||
predictor_decompress_fir_adapt(predicterror_buffer_a,
|
||||
outputsamples_buffer_a,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
predictor_coef_table,
|
||||
|
@ -683,7 +751,7 @@ void decode_frame(alac_file *alac,
|
|||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type);
|
||||
//fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type);
|
||||
/* i think the only other prediction type (or perhaps this is just a
|
||||
* boolean?) runs adaptive fir twice.. like:
|
||||
* predictor_decompress_fir_adapt(predictor_error, tempout, ...)
|
||||
|
@ -704,7 +772,7 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);
|
||||
|
||||
alac->outputsamples_buffer_a[i] = audiobits;
|
||||
outputsamples_buffer_a[i] = audiobits;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -722,7 +790,7 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
audiobits |= readbits(alac, readsamplesize - 16);
|
||||
|
||||
alac->outputsamples_buffer_a[i] = audiobits;
|
||||
outputsamples_buffer_a[i] = audiobits;
|
||||
}
|
||||
}
|
||||
/* wasted_bytes = 0; // unused */
|
||||
|
@ -735,17 +803,16 @@ void decode_frame(alac_file *alac,
|
|||
int i;
|
||||
for (i = 0; i < outputsamples; i++)
|
||||
{
|
||||
int16_t sample = alac->outputsamples_buffer_a[i];
|
||||
if (host_bigendian)
|
||||
_Swap16(sample);
|
||||
((int16_t*)outbuffer)[i * alac->numchannels] = sample;
|
||||
/* Output mono data as stereo */
|
||||
outbuffer[i*2] = outputsamples_buffer_a[i];
|
||||
outbuffer[i*2+1] = outputsamples_buffer_a[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 20:
|
||||
case 24:
|
||||
case 32:
|
||||
fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
|
||||
//fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -788,13 +855,11 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
if (!isnotcompressed)
|
||||
{ /* compressed */
|
||||
int16_t predictor_coef_table_a[32];
|
||||
int predictor_coef_num_a;
|
||||
int prediction_type_a;
|
||||
int prediction_quantitization_a;
|
||||
int ricemodifier_a;
|
||||
|
||||
int16_t predictor_coef_table_b[32];
|
||||
int predictor_coef_num_b;
|
||||
int prediction_type_b;
|
||||
int prediction_quantitization_b;
|
||||
|
@ -834,12 +899,12 @@ void decode_frame(alac_file *alac,
|
|||
/*********************/
|
||||
if (wasted_bytes)
|
||||
{ /* see mono case */
|
||||
fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
|
||||
//fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
|
||||
}
|
||||
|
||||
/* channel 1 */
|
||||
basterdised_rice_decompress(alac,
|
||||
alac->predicterror_buffer_a,
|
||||
predicterror_buffer_a,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
alac->setinfo_rice_initialhistory,
|
||||
|
@ -849,8 +914,8 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
if (prediction_type_a == 0)
|
||||
{ /* adaptive fir */
|
||||
predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
|
||||
alac->outputsamples_buffer_a,
|
||||
predictor_decompress_fir_adapt(predicterror_buffer_a,
|
||||
outputsamples_buffer_a,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
predictor_coef_table_a,
|
||||
|
@ -859,12 +924,12 @@ void decode_frame(alac_file *alac,
|
|||
}
|
||||
else
|
||||
{ /* see mono case */
|
||||
fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a);
|
||||
//fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a);
|
||||
}
|
||||
|
||||
/* channel 2 */
|
||||
basterdised_rice_decompress(alac,
|
||||
alac->predicterror_buffer_b,
|
||||
predicterror_buffer_b,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
alac->setinfo_rice_initialhistory,
|
||||
|
@ -874,8 +939,8 @@ void decode_frame(alac_file *alac,
|
|||
|
||||
if (prediction_type_b == 0)
|
||||
{ /* adaptive fir */
|
||||
predictor_decompress_fir_adapt(alac->predicterror_buffer_b,
|
||||
alac->outputsamples_buffer_b,
|
||||
predictor_decompress_fir_adapt(predicterror_buffer_b,
|
||||
outputsamples_buffer_b,
|
||||
outputsamples,
|
||||
readsamplesize,
|
||||
predictor_coef_table_b,
|
||||
|
@ -884,7 +949,7 @@ void decode_frame(alac_file *alac,
|
|||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b);
|
||||
//fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -902,8 +967,8 @@ void decode_frame(alac_file *alac,
|
|||
audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);
|
||||
audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);
|
||||
|
||||
alac->outputsamples_buffer_a[i] = audiobits_a;
|
||||
alac->outputsamples_buffer_b[i] = audiobits_b;
|
||||
outputsamples_buffer_a[i] = audiobits_a;
|
||||
outputsamples_buffer_b[i] = audiobits_b;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -923,8 +988,8 @@ void decode_frame(alac_file *alac,
|
|||
audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);
|
||||
audiobits_b |= readbits(alac, alac->setinfo_sample_size - 16);
|
||||
|
||||
alac->outputsamples_buffer_a[i] = audiobits_a;
|
||||
alac->outputsamples_buffer_b[i] = audiobits_b;
|
||||
outputsamples_buffer_a[i] = audiobits_a;
|
||||
outputsamples_buffer_b[i] = audiobits_b;
|
||||
}
|
||||
}
|
||||
/* wasted_bytes = 0; */
|
||||
|
@ -936,8 +1001,8 @@ void decode_frame(alac_file *alac,
|
|||
{
|
||||
case 16:
|
||||
{
|
||||
deinterlace_16(alac->outputsamples_buffer_a,
|
||||
alac->outputsamples_buffer_b,
|
||||
deinterlace_16(outputsamples_buffer_a,
|
||||
outputsamples_buffer_b,
|
||||
(int16_t*)outbuffer,
|
||||
alac->numchannels,
|
||||
outputsamples,
|
||||
|
@ -948,7 +1013,7 @@ void decode_frame(alac_file *alac,
|
|||
case 20:
|
||||
case 24:
|
||||
case 32:
|
||||
fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
|
||||
//fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -957,16 +1022,12 @@ void decode_frame(alac_file *alac,
|
|||
break;
|
||||
}
|
||||
}
|
||||
return outbuffer;
|
||||
}
|
||||
|
||||
alac_file *create_alac(int samplesize, int numchannels)
|
||||
void create_alac(int samplesize, int numchannels, alac_file* alac)
|
||||
{
|
||||
alac_file *newfile = malloc(sizeof(alac_file));
|
||||
|
||||
newfile->samplesize = samplesize;
|
||||
newfile->numchannels = numchannels;
|
||||
newfile->bytespersample = (samplesize / 8) * numchannels;
|
||||
|
||||
return newfile;
|
||||
alac->samplesize = samplesize;
|
||||
alac->numchannels = numchannels;
|
||||
alac->bytespersample = (samplesize / 8) * numchannels;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
#ifndef __ALAC__DECOMP_H
|
||||
#define __ALAC__DECOMP_H
|
||||
|
||||
typedef struct alac_file alac_file;
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *input_buffer;
|
||||
int input_buffer_bitaccumulator; /* used so we can do arbitary
|
||||
bit reads */
|
||||
int samplesize;
|
||||
int numchannels;
|
||||
int bytespersample;
|
||||
|
||||
alac_file *create_alac(int samplesize, int numchannels);
|
||||
void decode_frame(alac_file *alac,
|
||||
/* stuff from setinfo */
|
||||
uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
|
||||
uint8_t setinfo_7a; /* 0x00 */
|
||||
uint8_t setinfo_sample_size; /* 0x10 */
|
||||
uint8_t setinfo_rice_historymult; /* 0x28 */
|
||||
uint8_t setinfo_rice_initialhistory; /* 0x0a */
|
||||
uint8_t setinfo_rice_kmodifier; /* 0x0e */
|
||||
uint8_t setinfo_7f; /* 0x02 */
|
||||
uint16_t setinfo_80; /* 0x00ff */
|
||||
uint32_t setinfo_82; /* 0x000020e7 */
|
||||
uint32_t setinfo_86; /* 0x00069fe4 */
|
||||
uint32_t setinfo_8a_rate; /* 0x0000ac44 */
|
||||
/* end setinfo stuff */
|
||||
} alac_file;
|
||||
|
||||
void create_alac(int samplesize, int numchannels, alac_file* alac);
|
||||
int16_t* decode_frame(alac_file *alac,
|
||||
unsigned char *inbuffer,
|
||||
void *outbuffer, int *outputsize);
|
||||
int *outputsize);
|
||||
void alac_set_info(alac_file *alac, char *inputbuffer);
|
||||
|
||||
#endif /* __ALAC__DECOMP_H */
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../codec.h"
|
||||
|
||||
#include "stream.h"
|
||||
#include "demux.h"
|
||||
|
||||
|
@ -56,7 +58,7 @@ static void read_chunk_ftyp(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
size_remaining-=4;
|
||||
if (type != MAKEFOURCC('M','4','A',' '))
|
||||
{
|
||||
fprintf(stderr, "not M4A file\n");
|
||||
//fprintf(stderr, "not M4A file\n");
|
||||
return;
|
||||
}
|
||||
minor_ver = stream_read_uint32(qtmovie->stream);
|
||||
|
@ -151,7 +153,7 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
if (numentries != 1)
|
||||
{
|
||||
fprintf(stderr, "only expecting one entry in sample description atom!\n");
|
||||
//fprintf(stderr, "only expecting one entry in sample description atom!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -173,8 +175,8 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
entry_remaining -= 6;
|
||||
|
||||
version = stream_read_uint16(qtmovie->stream);
|
||||
if (version != 1)
|
||||
fprintf(stderr, "unknown version??\n");
|
||||
// if (version != 1)
|
||||
//fprintf(stderr, "unknown version??\n");
|
||||
entry_remaining -= 2;
|
||||
|
||||
/* revision level */
|
||||
|
@ -245,8 +247,8 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
if (qtmovie->res->format != MAKEFOURCC('a','l','a','c'))
|
||||
{
|
||||
fprintf(stderr, "expecting 'alac' data format, got %c%c%c%c\n",
|
||||
SPLITFOURCC(qtmovie->res->format));
|
||||
// fprintf(stderr, "expecting 'alac' data format, got %c%c%c%c\n",
|
||||
// SPLITFOURCC(qtmovie->res->format));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +284,7 @@ static void read_chunk_stts(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
if (size_remaining)
|
||||
{
|
||||
fprintf(stderr, "ehm, size remianing?\n");
|
||||
//fprintf(stderr, "ehm, size remianing?\n");
|
||||
stream_skip(qtmovie->stream, size_remaining);
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +307,7 @@ static void read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
/* default sample size */
|
||||
if (stream_read_uint32(qtmovie->stream) != 0)
|
||||
{
|
||||
fprintf(stderr, "i was expecting variable samples sizes\n");
|
||||
//fprintf(stderr, "i was expecting variable samples sizes\n");
|
||||
stream_read_uint32(qtmovie->stream);
|
||||
size_remaining -= 4;
|
||||
return;
|
||||
|
@ -326,7 +328,7 @@ static void read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
if (size_remaining)
|
||||
{
|
||||
fprintf(stderr, "ehm, size remianing?\n");
|
||||
//fprintf(stderr, "ehm, size remianing?\n");
|
||||
stream_skip(qtmovie->stream, size_remaining);
|
||||
}
|
||||
}
|
||||
|
@ -343,7 +345,7 @@ static void read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
sub_chunk_len = stream_read_uint32(qtmovie->stream);
|
||||
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
|
||||
{
|
||||
fprintf(stderr, "strange size for chunk inside stbl\n");
|
||||
//fprintf(stderr, "strange size for chunk inside stbl\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -366,8 +368,8 @@ static void read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
stream_skip(qtmovie->stream, sub_chunk_len - 8);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(stbl) unknown chunk id: %c%c%c%c\n",
|
||||
SPLITFOURCC(sub_chunk_id));
|
||||
// fprintf(stderr, "(stbl) unknown chunk id: %c%c%c%c\n",
|
||||
// SPLITFOURCC(sub_chunk_id));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -383,12 +385,12 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
/**** SOUND HEADER CHUNK ****/
|
||||
if (stream_read_uint32(qtmovie->stream) != 16)
|
||||
{
|
||||
fprintf(stderr, "unexpected size in media info\n");
|
||||
//fprintf(stderr, "unexpected size in media info\n");
|
||||
return;
|
||||
}
|
||||
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','m','h','d'))
|
||||
{
|
||||
fprintf(stderr, "not a sound header! can't handle this.\n");
|
||||
//fprintf(stderr, "not a sound header! can't handle this.\n");
|
||||
return;
|
||||
}
|
||||
/* now skip the rest */
|
||||
|
@ -400,7 +402,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
dinf_size = stream_read_uint32(qtmovie->stream);
|
||||
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('d','i','n','f'))
|
||||
{
|
||||
fprintf(stderr, "expected dinf, didn't get it.\n");
|
||||
//fprintf(stderr, "expected dinf, didn't get it.\n");
|
||||
return;
|
||||
}
|
||||
/* skip it */
|
||||
|
@ -413,7 +415,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
stbl_size = stream_read_uint32(qtmovie->stream);
|
||||
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','t','b','l'))
|
||||
{
|
||||
fprintf(stderr, "expected stbl, didn't get it.\n");
|
||||
//fprintf(stderr, "expected stbl, didn't get it.\n");
|
||||
return;
|
||||
}
|
||||
read_chunk_stbl(qtmovie, stbl_size);
|
||||
|
@ -421,7 +423,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
if (size_remaining)
|
||||
{
|
||||
fprintf(stderr, "oops\n");
|
||||
//fprintf(stderr, "oops\n");
|
||||
stream_skip(qtmovie->stream, size_remaining);
|
||||
}
|
||||
}
|
||||
|
@ -438,7 +440,7 @@ static void read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
sub_chunk_len = stream_read_uint32(qtmovie->stream);
|
||||
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
|
||||
{
|
||||
fprintf(stderr, "strange size for chunk inside mdia\n");
|
||||
//fprintf(stderr, "strange size for chunk inside mdia\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -456,8 +458,8 @@ static void read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
read_chunk_minf(qtmovie, sub_chunk_len);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(mdia) unknown chunk id: %c%c%c%c\n",
|
||||
SPLITFOURCC(sub_chunk_id));
|
||||
// fprintf(stderr, "(mdia) unknown chunk id: %c%c%c%c\n",
|
||||
// SPLITFOURCC(sub_chunk_id));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -478,7 +480,7 @@ static void read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
sub_chunk_len = stream_read_uint32(qtmovie->stream);
|
||||
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
|
||||
{
|
||||
fprintf(stderr, "strange size for chunk inside trak\n");
|
||||
//fprintf(stderr, "strange size for chunk inside trak\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -493,8 +495,8 @@ static void read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
read_chunk_mdia(qtmovie, sub_chunk_len);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(trak) unknown chunk id: %c%c%c%c\n",
|
||||
SPLITFOURCC(sub_chunk_id));
|
||||
// fprintf(stderr, "(trak) unknown chunk id: %c%c%c%c\n",
|
||||
// SPLITFOURCC(sub_chunk_id));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -533,7 +535,7 @@ static void read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
sub_chunk_len = stream_read_uint32(qtmovie->stream);
|
||||
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
|
||||
{
|
||||
fprintf(stderr, "strange size for chunk inside moov\n");
|
||||
//fprintf(stderr, "strange size for chunk inside moov\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -551,8 +553,8 @@ static void read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
read_chunk_udta(qtmovie, sub_chunk_len);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(moov) unknown chunk id: %c%c%c%c\n",
|
||||
SPLITFOURCC(sub_chunk_id));
|
||||
// fprintf(stderr, "(moov) unknown chunk id: %c%c%c%c\n",
|
||||
// SPLITFOURCC(sub_chunk_id));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -574,14 +576,11 @@ static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len)
|
|||
|
||||
int qtmovie_read(stream_t *file, demux_res_t *demux_res)
|
||||
{
|
||||
qtmovie_t *qtmovie;
|
||||
|
||||
qtmovie = (qtmovie_t*)malloc(sizeof(qtmovie_t));
|
||||
qtmovie_t qtmovie;
|
||||
|
||||
/* construct the stream */
|
||||
qtmovie->stream = file;
|
||||
|
||||
qtmovie->res = demux_res;
|
||||
qtmovie.stream = file;
|
||||
qtmovie.res = demux_res;
|
||||
|
||||
/* read the chunks */
|
||||
while (1)
|
||||
|
@ -589,26 +588,26 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res)
|
|||
size_t chunk_len;
|
||||
fourcc_t chunk_id;
|
||||
|
||||
chunk_len = stream_read_uint32(qtmovie->stream);
|
||||
if (stream_eof(qtmovie->stream))
|
||||
chunk_len = stream_read_uint32(qtmovie.stream);
|
||||
if (stream_eof(qtmovie.stream))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (chunk_len == 1)
|
||||
{
|
||||
fprintf(stderr, "need 64bit support\n");
|
||||
//fprintf(stderr, "need 64bit support\n");
|
||||
return 0;
|
||||
}
|
||||
chunk_id = stream_read_uint32(qtmovie->stream);
|
||||
chunk_id = stream_read_uint32(qtmovie.stream);
|
||||
|
||||
switch (chunk_id)
|
||||
{
|
||||
case MAKEFOURCC('f','t','y','p'):
|
||||
read_chunk_ftyp(qtmovie, chunk_len);
|
||||
read_chunk_ftyp(&qtmovie, chunk_len);
|
||||
break;
|
||||
case MAKEFOURCC('m','o','o','v'):
|
||||
read_chunk_moov(qtmovie, chunk_len);
|
||||
read_chunk_moov(&qtmovie, chunk_len);
|
||||
break;
|
||||
/* once we hit mdat we stop reading and return.
|
||||
* this is on the assumption that there is no furhter interesting
|
||||
|
@ -617,16 +616,16 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res)
|
|||
* for the decoder. And we don't want to rely on fseek/ftell,
|
||||
* as they may not always be avilable */
|
||||
case MAKEFOURCC('m','d','a','t'):
|
||||
read_chunk_mdat(qtmovie, chunk_len);
|
||||
read_chunk_mdat(&qtmovie, chunk_len);
|
||||
return 1;
|
||||
|
||||
/* these following atoms can be skipped !!!! */
|
||||
case MAKEFOURCC('f','r','e','e'):
|
||||
stream_skip(qtmovie->stream, chunk_len - 8); /* FIXME not 8 */
|
||||
stream_skip(qtmovie.stream, chunk_len - 8); /* FIXME not 8 */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(top) unknown chunk id: %c%c%c%c\n",
|
||||
SPLITFOURCC(chunk_id));
|
||||
// fprintf(stderr, "(top) unknown chunk id: %c%c%c%c\n",
|
||||
// SPLITFOURCC(chunk_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef DEMUX_H
|
||||
#define DEMUX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include "stream.h"
|
||||
|
||||
typedef uint32_t fourcc_t;
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
/* stream.h */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct stream_tTAG stream_t;
|
||||
typedef struct {
|
||||
int eof;
|
||||
} stream_t;
|
||||
|
||||
void stream_read(stream_t *stream, size_t len, void *buf);
|
||||
|
||||
|
@ -22,9 +24,4 @@ void stream_skip(stream_t *stream, size_t skip);
|
|||
|
||||
int stream_eof(stream_t *stream);
|
||||
|
||||
stream_t *stream_create_file(FILE *file,
|
||||
int bigendian);
|
||||
void stream_destroy(stream_t *stream);
|
||||
|
||||
#endif /* STREAM_H */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue