forked from len0rd/rockbox
FS#10466: Introduce a real malloc for tremor.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22528 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
260ed99139
commit
3fad1523c7
12 changed files with 427 additions and 91 deletions
|
|
@ -14,6 +14,9 @@ OTHER_SRC += $(CODECS_SRC)
|
||||||
CODECS := $(CODECS_SRC:.c=.codec)
|
CODECS := $(CODECS_SRC:.c=.codec)
|
||||||
CODECS := $(subst $(ROOTDIR),$(BUILDDIR),$(CODECS))
|
CODECS := $(subst $(ROOTDIR),$(BUILDDIR),$(CODECS))
|
||||||
|
|
||||||
|
# TLSF memory allocator library
|
||||||
|
include $(APPSDIR)/codecs/lib/tlsf/libtlsf.make
|
||||||
|
|
||||||
# the codec helper library
|
# the codec helper library
|
||||||
include $(APPSDIR)/codecs/lib/libcodec.make
|
include $(APPSDIR)/codecs/lib/libcodec.make
|
||||||
OTHER_INC += -I$(APPSDIR)/codecs/lib
|
OTHER_INC += -I$(APPSDIR)/codecs/lib
|
||||||
|
|
@ -66,7 +69,7 @@ $(CODECDIR)/spc.codec : $(CODECDIR)/libspc.a
|
||||||
$(CODECDIR)/mpa.codec : $(CODECDIR)/libmad.a
|
$(CODECDIR)/mpa.codec : $(CODECDIR)/libmad.a
|
||||||
$(CODECDIR)/a52.codec : $(CODECDIR)/liba52.a
|
$(CODECDIR)/a52.codec : $(CODECDIR)/liba52.a
|
||||||
$(CODECDIR)/flac.codec : $(CODECDIR)/libffmpegFLAC.a
|
$(CODECDIR)/flac.codec : $(CODECDIR)/libffmpegFLAC.a
|
||||||
$(CODECDIR)/vorbis.codec : $(CODECDIR)/libtremor.a
|
$(CODECDIR)/vorbis.codec : $(CODECDIR)/libtremor.a $(TLSFLIB)
|
||||||
$(CODECDIR)/speex.codec : $(CODECDIR)/libspeex.a
|
$(CODECDIR)/speex.codec : $(CODECDIR)/libspeex.a
|
||||||
$(CODECDIR)/mpc.codec : $(CODECDIR)/libmusepack.a
|
$(CODECDIR)/mpc.codec : $(CODECDIR)/libmusepack.a
|
||||||
$(CODECDIR)/wavpack.codec : $(CODECDIR)/libwavpack.a
|
$(CODECDIR)/wavpack.codec : $(CODECDIR)/libwavpack.a
|
||||||
|
|
|
||||||
23
apps/codecs/lib/tlsf/COPYING
Normal file
23
apps/codecs/lib/tlsf/COPYING
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
LICENSE INFORMATION
|
||||||
|
|
||||||
|
TLSF is released as LGPL and GPL. A copy of both licences can be found in this
|
||||||
|
directoy. For the GPL licence, the following exception applies.
|
||||||
|
|
||||||
|
|
||||||
|
TLSF is free software; you can redistribute it and/or modify it under terms of
|
||||||
|
the GNU General Public License as published by the Free Software Foundation;
|
||||||
|
either version 2, or (at your option) any later version. TLSF is distributed
|
||||||
|
in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||||
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||||
|
the GNU General Public License for more details. You should have received a
|
||||||
|
copy of the GNU General Public License along with TLSF; see file COPYING. If
|
||||||
|
not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
|
||||||
|
USA.
|
||||||
|
|
||||||
|
As a special exception, including TLSF header files in a file, or linking with
|
||||||
|
other files objects to produce an executable application, is merely considered
|
||||||
|
normal use of the library, and does *not* fall under the heading of "derived
|
||||||
|
work". Therfore does not by itself cause the resulting executable application
|
||||||
|
to be covered by the GNU General Public License. This exception does not
|
||||||
|
however invalidate any other reasons why the executable file might be covered
|
||||||
|
by the GNU Public License.
|
||||||
119
apps/codecs/lib/tlsf/Changelog
Normal file
119
apps/codecs/lib/tlsf/Changelog
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
Version History
|
||||||
|
---------------
|
||||||
|
-v2.4.4 (October 13 2008)
|
||||||
|
* Corrected minor syntactic bug on statistic gathering code.
|
||||||
|
Reported by Tim Cussins and P. Mantegazza.
|
||||||
|
|
||||||
|
-v2.4.3 (July 30 2008)
|
||||||
|
* Minor fixes to compile with the greenhills compiler.
|
||||||
|
Reported by "Kaya, Sinan SEA" <sinan.kaya@siemens.com>
|
||||||
|
* Small change in the license in order to include TLSF in the RTEMS
|
||||||
|
project.
|
||||||
|
|
||||||
|
-v2.4.2 (May 16 2008) (Herman ten Brugge)
|
||||||
|
* Memory usage statistics added again, with cleaner and more compacted
|
||||||
|
code.
|
||||||
|
|
||||||
|
-v2.4.1 (April 30 2008)
|
||||||
|
* Fixed a bug in the tlsf_realloc function: init the pool automatically
|
||||||
|
on the first call.
|
||||||
|
Reported by: Alejandro Mery <amery@geeks.cl>
|
||||||
|
|
||||||
|
-v2.4 (Feb 19 2008)
|
||||||
|
* "rtl_*" functions renamed to "tlsf_*".
|
||||||
|
* Added the add_new_area function to insert new memory areas to an
|
||||||
|
existing memory pool.
|
||||||
|
* A single TLSF pool can manage non-contiguous memory areas.
|
||||||
|
* Support for mmap and sbrk added.
|
||||||
|
* The init_memory_pool is not longer needed when used on a system
|
||||||
|
with mmap or sbrk.
|
||||||
|
* Removed the get_used_size counting.The same functionality can be
|
||||||
|
implemented outside the TLSF code.
|
||||||
|
|
||||||
|
-v2.3.2 (Sep 27 2007)
|
||||||
|
* Minor cosmetic code improvements.
|
||||||
|
|
||||||
|
-v2.3.1 (Jul 30 2007)
|
||||||
|
* Fixed some minor bugs in the version 2.3. Herman ten Brugge
|
||||||
|
<hermantenbrugge@home.nl>
|
||||||
|
|
||||||
|
-v2.3 (Jul 28 2007) Released a new version with all the contributions
|
||||||
|
received from Herman ten Brugge <hermantenbrugge@home.nl>
|
||||||
|
(This is his summary of changes in the TLSF's code):
|
||||||
|
* Add 64 bit support. It now runs on x86_64 and solaris64.
|
||||||
|
* I also tested this on vxworks/32 and solaris/32 and i386/32
|
||||||
|
processors.
|
||||||
|
* Remove assembly code. I could not measure any performance difference
|
||||||
|
on my core2 processor. This also makes the code more portable.
|
||||||
|
* Moved defines/typedefs from tlsf.h to tlsf.c
|
||||||
|
* Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to
|
||||||
|
(sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact
|
||||||
|
that the minumum size is still sizeof (bhdr_t).
|
||||||
|
* Changed all C++ comment style to C style. (// -> /* ... *./)
|
||||||
|
* Used ls_bit instead of ffs and ms_bit instead of fls. I did this to
|
||||||
|
avoid confusion with the standard ffs function which returns
|
||||||
|
different values.
|
||||||
|
* Created set_bit/clear_bit fuctions because they are not present
|
||||||
|
on x86_64.
|
||||||
|
* Added locking support + extra file target.h to show how to use it.
|
||||||
|
* Added get_used_size function
|
||||||
|
* Added rtl_realloc and rtl_calloc function
|
||||||
|
* Implemented realloc clever support.
|
||||||
|
* Added some test code in the example directory.
|
||||||
|
|
||||||
|
-- Thank you very much for your help Herman!
|
||||||
|
|
||||||
|
-v2.2.1 (Oct 23 2006)
|
||||||
|
* Support for ARMv5 implemented by Adam Scislowicz
|
||||||
|
<proteuskor@gmail.com>. Thank you for your contribution.
|
||||||
|
|
||||||
|
- v2.2.0 (Jun 30 2006) Miguel Masmano & Ismael Ripoll.
|
||||||
|
|
||||||
|
* Blocks smaller than 128 bytes are stored on a single
|
||||||
|
segregated list. The already existing bits maps and data
|
||||||
|
structures are used.
|
||||||
|
* Minor code speed-up improvements.
|
||||||
|
* Worst case response time both on malloc and free improved.
|
||||||
|
* External fragmantation also improved!.
|
||||||
|
* Segragared lists are AGAIN sorted by LIFO order. Version
|
||||||
|
2.1b was proven to be no better than 2.1.
|
||||||
|
|
||||||
|
- v2.1b: Allocation policy has been always a LIFO Good-Fit, that
|
||||||
|
is, between several free blocks in the same range, TLSF will
|
||||||
|
always allocate the most recently released. In this version of
|
||||||
|
TLSF, we have implemented a FIFO Good-Fit. However,
|
||||||
|
fragmentation doesn't seems to be altered so is it worth it?.
|
||||||
|
|
||||||
|
- v2.1: Realloc and calloc included again in TLSF 2.0.
|
||||||
|
|
||||||
|
- v2.0: In this version, TLSF has been programmed from scratch.
|
||||||
|
Now the allocator is provided as an unique file. Realloc and
|
||||||
|
calloc are not longer implemented.
|
||||||
|
|
||||||
|
|
||||||
|
- v1.4: Created the section "Version History". Studied real
|
||||||
|
behaviour of actual applications (regular applications tend
|
||||||
|
to require small memory blocks (less than 16 bytes) whereas
|
||||||
|
TLSF is optimised to be used with blocks larger than 16
|
||||||
|
bytes: Added special lists to deal with blocks smaller than
|
||||||
|
16 bytes.
|
||||||
|
|
||||||
|
|
||||||
|
- v1.3: Change of concept, now the main TLSF structure is created
|
||||||
|
inside of the beginning of the block instead of being an
|
||||||
|
static structure, allowing multiple TLSFs working at the
|
||||||
|
same time. Now, TLSF uses specific processor instructions to
|
||||||
|
deal with bitmaps. TLSF sanity functions added to find TLSF
|
||||||
|
overflows. The TLSF code will not be RTLinux-oriented any
|
||||||
|
more.
|
||||||
|
|
||||||
|
- v1.1 ... v1.2: Many little bugs fixed, code cleaned and splitted
|
||||||
|
in several files because of cosmetic requirements.
|
||||||
|
Starting from TLSF v1.1, MaRTE OS
|
||||||
|
(http://marte.unican.es) uses the TLSF allocator
|
||||||
|
as its default memory allocator.
|
||||||
|
|
||||||
|
- v0.1 ... v1.0: First implementations were created for testing and
|
||||||
|
research purposes. Basically TLSF is implemented to
|
||||||
|
be used by RTLinux-GPL (www.rtlinux-gpl.org), so
|
||||||
|
it is RTLinux-oriented.
|
||||||
163
apps/codecs/lib/tlsf/README
Normal file
163
apps/codecs/lib/tlsf/README
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
|
||||||
|
TLSF Memory Storage allocator implementation.
|
||||||
|
Version 2.4 Feb 2008
|
||||||
|
|
||||||
|
Authors: Miguel Masmano, Ismael Ripoll & Alfons Crespo.
|
||||||
|
Copyright UPVLC, OCERA Consortium.
|
||||||
|
|
||||||
|
TLSF is released in the GPL/LGPL licence. The exact terms of the licence
|
||||||
|
are described in the COPYING file.
|
||||||
|
|
||||||
|
This component provides basic memory allocation functions:
|
||||||
|
malloc and free, as defined in the standard "C" library.
|
||||||
|
|
||||||
|
This allocator was designed to provide real-time performance, that is:
|
||||||
|
1.- Bounded time malloc and free.
|
||||||
|
2.- Fast response time.
|
||||||
|
3.- Efficient memory management, that is low fragmentation.
|
||||||
|
|
||||||
|
|
||||||
|
The worst response time for both malloc and free is O(1).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
How to use it:
|
||||||
|
|
||||||
|
This code is prepared to be used as a stand-alone code that can be
|
||||||
|
linked with a regular application or it can be compiled to be a Linux
|
||||||
|
module (which required the BigPhysicalArea patch). Initially the
|
||||||
|
module was designed to work jointly with RTLinux-GPL, but it can be
|
||||||
|
used as a stand alone Linux module.
|
||||||
|
|
||||||
|
When compiled as a regular linux process the API is:
|
||||||
|
|
||||||
|
Initialisation and destruction functions
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
init_memory_pool may be called before any request or release call:
|
||||||
|
|
||||||
|
- size_t init_memory_pool(size_t, void *);
|
||||||
|
- void destroy_memory_pool(void *);
|
||||||
|
|
||||||
|
Request and release functions
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
As can be seen, there are two functions for each traditional memory
|
||||||
|
allocation function (malloc, free, realloc, and calloc). One with the
|
||||||
|
prefix "tlsf_" and the other with the suffix "_ex".
|
||||||
|
|
||||||
|
The versions with the prefix "tlsf_" provides the expected behaviour,
|
||||||
|
that is, allocating/releasing memory from the default memory pool. The
|
||||||
|
default memory pool is the last pool initialised by the
|
||||||
|
init_memory_pool function.
|
||||||
|
|
||||||
|
On the other hand, the functions with the prefix "_ex" enable the use of several memory pools.
|
||||||
|
|
||||||
|
- void *tlsf_malloc(size_t);
|
||||||
|
- void *malloc_ex(size_t, void *);
|
||||||
|
|
||||||
|
- void tlsf_free(void *ptr);
|
||||||
|
- void free_ex(void *, void *);
|
||||||
|
|
||||||
|
- void *tlsf_realloc(void *ptr, size_t size);
|
||||||
|
- void *realloc_ex(void *, size_t, void *);
|
||||||
|
|
||||||
|
- void *tlsf_calloc(size_t nelem, size_t elem_size);
|
||||||
|
- void *calloc_ex(size_t, size_t, void *);
|
||||||
|
|
||||||
|
EXAMPLE OF USE:
|
||||||
|
|
||||||
|
char memory_pool[1024*1024];
|
||||||
|
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
init_memory_pool(1024*1024, memory_pool);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ptr1=malloc_ex(100, memory_pool);
|
||||||
|
ptr2=tlsf_malloc(100); // This function will use memory_pool
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
tlsf_free(ptr2);
|
||||||
|
free_ex(ptr1, memory_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
Growing the memory pool
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Starting from the version 2.4, the function add_new_area adds an
|
||||||
|
memory area to an existing memory pool.
|
||||||
|
|
||||||
|
- size_t add_new_area(void *, size_t, void *);
|
||||||
|
|
||||||
|
This feature is pretty useful when an existing memory pool is running
|
||||||
|
low and we want to add more free memory to it.
|
||||||
|
EXAMPLE OF USE:
|
||||||
|
|
||||||
|
char memory_pool[1024*1024];
|
||||||
|
char memory_pool2[1024*1024];
|
||||||
|
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
init_memory_pool(1024*1024, memory_pool);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ptr[0]=malloc_ex(1024*256 memory_pool);
|
||||||
|
ptr[1]=malloc_ex(1024*512, memory_pool);
|
||||||
|
add_new_area(memory_pool2, 1024*1024, memory_pool);
|
||||||
|
// Now we have an extra free memory area of 1Mb
|
||||||
|
// The next malloc may not fail
|
||||||
|
ptr[2]=malloc_ex(1024*512, memory_pool);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SBRK and MMAP support
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The version 2.4 can use the functions SBRK and MMAP to _automatically_
|
||||||
|
growing the memory pool, before running out of memory.
|
||||||
|
|
||||||
|
So, when this feature is enabled, unless the operating system were out
|
||||||
|
of memory, a malloc operation would not fail due to an "out-of-memory"
|
||||||
|
error.
|
||||||
|
|
||||||
|
To enable this support, compile tlsf.c with the FLAGS -DUSE_MMAP=1 or
|
||||||
|
-DUSE_SBRK=1 depending on whether you want to use "mmap" or "sbrk" or both.
|
||||||
|
|
||||||
|
** By default (default Makefile) this feature is enabled.
|
||||||
|
|
||||||
|
EXAMPLE OF USE:
|
||||||
|
|
||||||
|
gcc -o tlsf.o -O2 -Wall -DUSE_MMAP=1 -DUSE_SBRK=1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
If the sbrk/mmap support is enabled and we are _only_ going to use one
|
||||||
|
memory pool, it is not necessary to call init_memory_pool
|
||||||
|
|
||||||
|
EXAMPLE OF USE (with MMAP/SBRK support enabled):
|
||||||
|
|
||||||
|
{
|
||||||
|
...
|
||||||
|
|
||||||
|
ptr2=tlsf_malloc(100); // This function will use memory_pool
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
tlsf_free(ptr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This work has been supported by the followin projects:
|
||||||
|
EUROPEAN: IST-2001-35102(OCERA) http://www.ocera.org.
|
||||||
|
SPANISH: TIN2005-08665-C3-03
|
||||||
3
apps/codecs/lib/tlsf/SOURCES
Normal file
3
apps/codecs/lib/tlsf/SOURCES
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#if CONFIG_CODEC == SWCODEC /* software codec platforms */
|
||||||
|
src/tlsf.c
|
||||||
|
#endif
|
||||||
9
apps/codecs/lib/tlsf/TODO
Normal file
9
apps/codecs/lib/tlsf/TODO
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
To do list
|
||||||
|
==========
|
||||||
|
|
||||||
|
* Add mmap/sbrk support (DONE - V2.4).
|
||||||
|
|
||||||
|
* TLSF rounds-up request size to the head of a free list.
|
||||||
|
It has been shown to be a good policy for small blocks (<2048).
|
||||||
|
But for larger blocks this policy may cause excesive fragmentation.
|
||||||
|
A deeper analisys should be done.
|
||||||
28
apps/codecs/lib/tlsf/libtlsf.make
Normal file
28
apps/codecs/lib/tlsf/libtlsf.make
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# __________ __ ___.
|
||||||
|
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
# \/ \/ \/ \/ \/
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
|
||||||
|
TLSFLIB := $(CODECDIR)/libtlsf.a
|
||||||
|
TLSFLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/lib/tlsf/SOURCES)
|
||||||
|
TLSFLIB_OBJ := $(call c2obj, $(TLSFLIB_SRC))
|
||||||
|
OTHER_SRC += $(TLSFLIB_SRC)
|
||||||
|
|
||||||
|
$(TLSFLIB): $(TLSFLIB_OBJ)
|
||||||
|
$(SILENT)$(shell rm -f $@)
|
||||||
|
$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
|
||||||
|
|
||||||
|
TLSFLIBFLAGS = $(CODECFLAGS) -ffunction-sections
|
||||||
|
|
||||||
|
ifdef SIMVER
|
||||||
|
TLSFLIBFLAGS += -DTLSF_STATISTIC=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(CODECDIR)/lib/tlsf/src/%.o: $(APPSDIR)/codecs/lib/tlsf/src/%.c
|
||||||
|
$(SILENT)mkdir -p $(dir $@)
|
||||||
|
$(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) \
|
||||||
|
-I$(dir $<) $(TLSFLIBFLAGS) -c $< -o $@
|
||||||
|
|
@ -283,7 +283,7 @@ void vorbis_dsp_clear(vorbis_dsp_state *v){
|
||||||
codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
|
codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
|
||||||
private_state *b=(private_state *)v->backend_state;
|
private_state *b=(private_state *)v->backend_state;
|
||||||
|
|
||||||
if(NULL == v->iram_double_pcm)
|
if(NULL == v->iram_double_pcm && vi != NULL)
|
||||||
{
|
{
|
||||||
/* pcm buffer came from oggmalloc rather than iram */
|
/* pcm buffer came from oggmalloc rather than iram */
|
||||||
for(i=0;i<vi->channels;i++)
|
for(i=0;i<vi->channels;i++)
|
||||||
|
|
|
||||||
|
|
@ -1,85 +1,63 @@
|
||||||
#include "os_types.h"
|
#include "os_types.h"
|
||||||
|
#include "../lib/tlsf/src/tlsf.h"
|
||||||
|
|
||||||
#if defined(CPU_ARM) || defined(CPU_COLDFIRE)
|
#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS)
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
extern jmp_buf rb_jump_buf;
|
extern jmp_buf rb_jump_buf;
|
||||||
|
#define LONGJMP(x) longjmp(rb_jump_buf, x)
|
||||||
|
#elif defined(SIMULATOR)
|
||||||
|
#define LONGJMP(x) do { DEBUGF("Vorbis: allocation failed!\n"); return NULL; } while (false)
|
||||||
|
#else
|
||||||
|
#define LONGJMP(x) return NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static size_t tmp_ptr;
|
|
||||||
|
|
||||||
void ogg_malloc_init(void)
|
void ogg_malloc_init(void)
|
||||||
{
|
{
|
||||||
mallocbuf = ci->codec_get_buffer(&bufsize);
|
size_t bufsize;
|
||||||
tmp_ptr = bufsize & ~3;
|
void* buf = ci->codec_get_buffer(&bufsize);
|
||||||
mem_ptr = 0;
|
init_memory_pool(bufsize, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ogg_malloc_destroy()
|
||||||
|
{
|
||||||
|
size_t bufsize;
|
||||||
|
void* buf = ci->codec_get_buffer(&bufsize);
|
||||||
|
destroy_memory_pool(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ogg_malloc(size_t size)
|
void *ogg_malloc(size_t size)
|
||||||
{
|
{
|
||||||
void* x;
|
void* x = tlsf_malloc(size);
|
||||||
|
|
||||||
size = (size + 3) & ~3;
|
if (x == NULL)
|
||||||
|
LONGJMP(1);
|
||||||
if (mem_ptr + size > tmp_ptr)
|
|
||||||
#if defined(CPU_ARM) || defined(CPU_COLDFIRE)
|
|
||||||
longjmp(rb_jump_buf, 1);
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
x = &mallocbuf[mem_ptr];
|
|
||||||
mem_ptr += size; /* Keep memory 32-bit aligned */
|
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ogg_tmpmalloc(size_t size)
|
|
||||||
{
|
|
||||||
size = (size + 3) & ~3;
|
|
||||||
|
|
||||||
if (mem_ptr + size > tmp_ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
tmp_ptr -= size;
|
|
||||||
return &mallocbuf[tmp_ptr];
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ogg_calloc(size_t nmemb, size_t size)
|
void *ogg_calloc(size_t nmemb, size_t size)
|
||||||
{
|
{
|
||||||
void *x;
|
void *x = tlsf_calloc(nmemb, size);
|
||||||
x = ogg_malloc(nmemb * size);
|
|
||||||
if (x == NULL)
|
|
||||||
return NULL;
|
|
||||||
ci->memset(x, 0, nmemb * size);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ogg_tmpcalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *x;
|
|
||||||
x = ogg_tmpmalloc(nmemb * size);
|
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
return NULL;
|
LONGJMP(1);
|
||||||
ci->memset(x, 0, nmemb * size);
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ogg_realloc(void *ptr, size_t size)
|
void *ogg_realloc(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
void *x;
|
void *x = tlsf_realloc(ptr, size);
|
||||||
(void)ptr;
|
|
||||||
x = ogg_malloc(size);
|
if (x == NULL)
|
||||||
|
LONGJMP(1);
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
long ogg_tmpmalloc_pos(void)
|
void ogg_free(void* ptr)
|
||||||
{
|
{
|
||||||
return tmp_ptr;
|
tlsf_free(ptr);
|
||||||
}
|
|
||||||
|
|
||||||
void ogg_tmpmalloc_free(long pos)
|
|
||||||
{
|
|
||||||
tmp_ptr = pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate IRAM buffer */
|
/* Allocate IRAM buffer */
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,14 @@
|
||||||
#define _ogg_malloc ogg_malloc
|
#define _ogg_malloc ogg_malloc
|
||||||
#define _ogg_calloc ogg_calloc
|
#define _ogg_calloc ogg_calloc
|
||||||
#define _ogg_realloc ogg_realloc
|
#define _ogg_realloc ogg_realloc
|
||||||
#define _ogg_free(x) do { } while(0)
|
#define _ogg_free ogg_free
|
||||||
|
|
||||||
void ogg_malloc_init(void);
|
void ogg_malloc_init(void);
|
||||||
|
void ogg_malloc_destroy(void);
|
||||||
void *ogg_malloc(size_t size);
|
void *ogg_malloc(size_t size);
|
||||||
void *ogg_tmpmalloc(size_t size);
|
|
||||||
void *ogg_calloc(size_t nmemb, size_t size);
|
void *ogg_calloc(size_t nmemb, size_t size);
|
||||||
void *ogg_tmpcalloc(size_t nmemb, size_t size);
|
|
||||||
void *ogg_realloc(void *ptr, size_t size);
|
void *ogg_realloc(void *ptr, size_t size);
|
||||||
long ogg_tmpmalloc_pos(void);
|
void ogg_free(void *ptr);
|
||||||
void ogg_tmpmalloc_free(long pos);
|
|
||||||
void iram_malloc_init(void);
|
void iram_malloc_init(void);
|
||||||
void *iram_malloc(size_t size);
|
void *iram_malloc(size_t size);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ static ogg_int32_t _float32_unpack(long val,int *point){
|
||||||
static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
|
static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
|
||||||
long i,j,count=0;
|
long i,j,count=0;
|
||||||
ogg_uint32_t marker[33];
|
ogg_uint32_t marker[33];
|
||||||
ogg_uint32_t *r=(ogg_uint32_t *)ogg_tmpmalloc((sparsecount?sparsecount:n)*sizeof(*r));
|
ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
|
||||||
memset(marker,0,sizeof(marker));
|
memset(marker,0,sizeof(marker));
|
||||||
|
|
||||||
for(i=0;i<n;i++){
|
for(i=0;i<n;i++){
|
||||||
|
|
@ -87,7 +87,7 @@ static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
|
||||||
/* update ourself */
|
/* update ourself */
|
||||||
if(length<32 && (entry>>length)){
|
if(length<32 && (entry>>length)){
|
||||||
/* error condition; the lengths must specify an overpopulated tree */
|
/* error condition; the lengths must specify an overpopulated tree */
|
||||||
/* _ogg_free(r); */
|
_ogg_free(r);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
r[count++]=entry;
|
r[count++]=entry;
|
||||||
|
|
@ -188,9 +188,8 @@ static ogg_int32_t *_book_unquantize(const static_codebook *b,int n,
|
||||||
ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint);
|
ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint);
|
||||||
ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint);
|
ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint);
|
||||||
ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r));
|
ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r));
|
||||||
int *rp=(int *)ogg_tmpcalloc(n*b->dim,sizeof(*rp));
|
int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp));
|
||||||
|
|
||||||
memset(rp, 0, n*b->dim*sizeof(*rp));
|
|
||||||
*maxpoint=minpoint;
|
*maxpoint=minpoint;
|
||||||
|
|
||||||
/* maptype 1 and 2 both use a quantized value vector, but
|
/* maptype 1 and 2 both use a quantized value vector, but
|
||||||
|
|
@ -277,7 +276,7 @@ static ogg_int32_t *_book_unquantize(const static_codebook *b,int n,
|
||||||
if(rp[j]<*maxpoint)
|
if(rp[j]<*maxpoint)
|
||||||
r[j]>>=*maxpoint-rp[j];
|
r[j]>>=*maxpoint-rp[j];
|
||||||
|
|
||||||
/* _ogg_free(rp); */
|
_ogg_free(rp);
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
@ -325,7 +324,6 @@ static int sort32a(const void *a,const void *b){
|
||||||
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
int i,j,n=0,tabn;
|
int i,j,n=0,tabn;
|
||||||
int *sortindex;
|
int *sortindex;
|
||||||
long pos = ogg_tmpmalloc_pos();
|
|
||||||
memset(c,0,sizeof(*c));
|
memset(c,0,sizeof(*c));
|
||||||
|
|
||||||
/* count actually used entries */
|
/* count actually used entries */
|
||||||
|
|
@ -350,9 +348,13 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
|
|
||||||
/* perform sort */
|
/* perform sort */
|
||||||
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
|
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
|
||||||
ogg_uint32_t **codep=(ogg_uint32_t **)ogg_tmpmalloc(sizeof(*codep)*n);
|
ogg_uint32_t **codep=(ogg_uint32_t **)_ogg_malloc(sizeof(*codep)*n);
|
||||||
|
|
||||||
if(codes==NULL||codep==NULL)goto err_out;
|
if(codes==NULL||codep==NULL){
|
||||||
|
_ogg_free(codep);
|
||||||
|
_ogg_free(codes);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
for(i=0;i<n;i++){
|
for(i=0;i<n;i++){
|
||||||
codes[i]=bitreverse(codes[i]);
|
codes[i]=bitreverse(codes[i]);
|
||||||
|
|
@ -361,7 +363,7 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
|
|
||||||
qsort(codep,n,sizeof(*codep),sort32a);
|
qsort(codep,n,sizeof(*codep),sort32a);
|
||||||
|
|
||||||
sortindex=(int *)ogg_tmpmalloc(n*sizeof(*sortindex));
|
sortindex=(int *)_ogg_malloc(n*sizeof(*sortindex));
|
||||||
c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist));
|
c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist));
|
||||||
/* the index is a reverse index */
|
/* the index is a reverse index */
|
||||||
for(i=0;i<n;i++){
|
for(i=0;i<n;i++){
|
||||||
|
|
@ -371,7 +373,8 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
|
|
||||||
for(i=0;i<n;i++)
|
for(i=0;i<n;i++)
|
||||||
c->codelist[sortindex[i]]=codes[i];
|
c->codelist[sortindex[i]]=codes[i];
|
||||||
/* _ogg_free(codes); */
|
_ogg_free(codep);
|
||||||
|
_ogg_free(codes);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -387,6 +390,7 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
if(s->lengthlist[i]>0)
|
if(s->lengthlist[i]>0)
|
||||||
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
|
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
|
||||||
|
|
||||||
|
_ogg_free(sortindex);
|
||||||
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
|
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
|
||||||
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
|
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
|
||||||
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
|
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
|
||||||
|
|
@ -434,10 +438,8 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ogg_tmpmalloc_free(pos);
|
|
||||||
return(0);
|
return(0);
|
||||||
err_out:
|
err_out:
|
||||||
ogg_tmpmalloc_free(pos);
|
|
||||||
vorbis_book_clear(c);
|
vorbis_book_clear(c);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,13 @@
|
||||||
#include "codeclib.h"
|
#include "codeclib.h"
|
||||||
#include "libtremor/ivorbisfile.h"
|
#include "libtremor/ivorbisfile.h"
|
||||||
#include "libtremor/ogg.h"
|
#include "libtremor/ogg.h"
|
||||||
|
#ifdef SIMULATOR
|
||||||
|
#include "lib/tlsf/src/tlsf.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
CODEC_HEADER
|
CODEC_HEADER
|
||||||
|
|
||||||
#if defined(CPU_ARM) || defined(CPU_COLDFIRE)
|
#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS)
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
jmp_buf rb_jump_buf;
|
jmp_buf rb_jump_buf;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -76,8 +79,7 @@ static long tell_handler(void *datasource)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This sets the DSP parameters based on the current logical bitstream
|
/* This sets the DSP parameters based on the current logical bitstream
|
||||||
* (sampling rate, number of channels, etc). It also tries to guess
|
* (sampling rate, number of channels, etc).
|
||||||
* reasonable buffer parameters based on the current quality setting.
|
|
||||||
*/
|
*/
|
||||||
static bool vorbis_set_codec_parameters(OggVorbis_File *vf)
|
static bool vorbis_set_codec_parameters(OggVorbis_File *vf)
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +88,6 @@ static bool vorbis_set_codec_parameters(OggVorbis_File *vf)
|
||||||
vi = ov_info(vf, -1);
|
vi = ov_info(vf, -1);
|
||||||
|
|
||||||
if (vi == NULL) {
|
if (vi == NULL) {
|
||||||
//ci->splash(HZ*2, "Vorbis Error");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,27 +121,23 @@ enum codec_status codec_main(void)
|
||||||
ogg_int64_t vf_pcmlengths[2];
|
ogg_int64_t vf_pcmlengths[2];
|
||||||
|
|
||||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
|
ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
|
||||||
/* Note: These are sane defaults for these values. Perhaps
|
|
||||||
* they should be set differently based on quality setting
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(CPU_ARM) || defined(CPU_COLDFIRE)
|
if (codec_init()) {
|
||||||
if (setjmp(rb_jump_buf) != 0)
|
error = CODEC_ERROR;
|
||||||
{
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ogg_malloc_init();
|
||||||
|
|
||||||
|
#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS)
|
||||||
|
if (setjmp(rb_jump_buf) != 0) {
|
||||||
/* malloc failed; skip to next track */
|
/* malloc failed; skip to next track */
|
||||||
error = CODEC_ERROR;
|
error = CODEC_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We need to flush reserver memory every track load. */
|
|
||||||
next_track:
|
next_track:
|
||||||
if (codec_init()) {
|
|
||||||
error = CODEC_ERROR;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
ogg_malloc_init();
|
|
||||||
|
|
||||||
while (!*ci->taginfo_ready && !ci->stop_codec)
|
while (!*ci->taginfo_ready && !ci->stop_codec)
|
||||||
ci->sleep(1);
|
ci->sleep(1);
|
||||||
|
|
||||||
|
|
@ -166,6 +163,10 @@ next_track:
|
||||||
* get here.
|
* get here.
|
||||||
*/
|
*/
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
ogg_free(vf.offsets);
|
||||||
|
ogg_free(vf.dataoffsets);
|
||||||
|
ogg_free(vf.serialnos);
|
||||||
|
|
||||||
vf.offsets = vf_offsets;
|
vf.offsets = vf_offsets;
|
||||||
vf.dataoffsets = &vf_dataoffsets;
|
vf.dataoffsets = &vf_dataoffsets;
|
||||||
vf.serialnos = &vf_serialnos;
|
vf.serialnos = &vf_serialnos;
|
||||||
|
|
@ -183,7 +184,7 @@ next_track:
|
||||||
vf.ready_state = OPENED;
|
vf.ready_state = OPENED;
|
||||||
vf.links = 1;
|
vf.links = 1;
|
||||||
} else {
|
} else {
|
||||||
//ci->logf("ov_open: %d", error);
|
DEBUGF("Vorbis: ov_open failed: %d", error);
|
||||||
error = CODEC_ERROR;
|
error = CODEC_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +226,7 @@ next_track:
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
eof = 1;
|
eof = 1;
|
||||||
} else if (n < 0) {
|
} else if (n < 0) {
|
||||||
DEBUGF("Error decoding frame\n");
|
DEBUGF("Vorbis: Error decoding frame\n");
|
||||||
} else {
|
} else {
|
||||||
ci->pcmbuf_insert(pcm[0], pcm[1], n);
|
ci->pcmbuf_insert(pcm[0], pcm[1], n);
|
||||||
ci->set_offset(ov_raw_tell(&vf));
|
ci->set_offset(ov_raw_tell(&vf));
|
||||||
|
|
@ -235,6 +236,15 @@ next_track:
|
||||||
error = CODEC_OK;
|
error = CODEC_OK;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
#if 0 /* defined(SIMULATOR) */
|
||||||
|
{
|
||||||
|
size_t bufsize;
|
||||||
|
void* buf = ci->codec_get_buffer(&bufsize);
|
||||||
|
|
||||||
|
DEBUGF("Vorbis: Memory max: %u\n", get_max_size(buf));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ci->request_next_track()) {
|
if (ci->request_next_track()) {
|
||||||
/* Clean things up for the next track */
|
/* Clean things up for the next track */
|
||||||
vf.dataoffsets = NULL;
|
vf.dataoffsets = NULL;
|
||||||
|
|
@ -246,6 +256,6 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
ogg_malloc_destroy();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue