summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohamed Tarek <mt@rockbox.org>2009-07-06 22:40:45 +0000
committerMohamed Tarek <mt@rockbox.org>2009-07-06 22:40:45 +0000
commite184ef1027ba8f41aca65dbae2af05662b23c722 (patch)
treeb7b108acf795d52e0c4f9f841906b02d1df3f773
parent03fe562a95a2b4fe4b3e316d3877140c3b4c822f (diff)
downloadrockbox-e184ef1027ba8f41aca65dbae2af05662b23c722.tar.gz
rockbox-e184ef1027ba8f41aca65dbae2af05662b23c722.zip
Adding support for rm playback. Only cook codec is supported for now and no seeking.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21695 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/SOURCES1
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/codecs.make4
-rw-r--r--apps/codecs/cook.c144
-rw-r--r--apps/codecs/libcook/Makefile.test4
-rw-r--r--apps/codecs/libcook/SOURCES3
-rw-r--r--apps/codecs/libcook/bitstream.c85
-rw-r--r--apps/codecs/libcook/bitstream.h21
-rw-r--r--apps/codecs/libcook/bswap.h173
-rw-r--r--apps/codecs/libcook/cook.c15
-rw-r--r--apps/codecs/libcook/cook.h4
-rw-r--r--apps/codecs/libcook/cook_fixpoint.h53
-rw-r--r--apps/codecs/libcook/cookdata_fixpoint.h6
-rw-r--r--apps/codecs/libcook/libcook.make18
-rw-r--r--apps/codecs/libcook/main.c25
-rw-r--r--apps/codecs/librm/rm.c250
-rw-r--r--apps/codecs/librm/rm.h32
-rw-r--r--apps/filetypes.c2
-rw-r--r--apps/metadata.c11
-rw-r--r--apps/metadata.h1
-rw-r--r--apps/metadata/metadata_parsers.h1
-rw-r--r--apps/metadata/rm.c420
22 files changed, 957 insertions, 317 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index f3acef1739..8166dbe4e2 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -167,6 +167,7 @@ metadata/wave.c
167metadata/wavpack.c 167metadata/wavpack.c
168metadata/a52.c 168metadata/a52.c
169metadata/asap.c 169metadata/asap.c
170metadata/rm.c
170#endif 171#endif
171#ifdef HAVE_TAGCACHE 172#ifdef HAVE_TAGCACHE
172tagcache.c 173tagcache.c
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 4e4f994a2a..44a8498fa9 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -9,6 +9,7 @@ wavpack.c
9#ifndef RB_PROFILE 9#ifndef RB_PROFILE
10alac.c 10alac.c
11#endif 11#endif
12cook.c
12mpc.c 13mpc.c
13wma.c 14wma.c
14sid.c 15sid.c
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make
index 7b56ced575..a8c0085cb4 100644
--- a/apps/codecs/codecs.make
+++ b/apps/codecs/codecs.make
@@ -33,6 +33,7 @@ include $(APPSDIR)/codecs/libspeex/libspeex.make
33include $(APPSDIR)/codecs/libtremor/libtremor.make 33include $(APPSDIR)/codecs/libtremor/libtremor.make
34include $(APPSDIR)/codecs/libwavpack/libwavpack.make 34include $(APPSDIR)/codecs/libwavpack/libwavpack.make
35include $(APPSDIR)/codecs/libwma/libwma.make 35include $(APPSDIR)/codecs/libwma/libwma.make
36include $(APPSDIR)/codecs/libcook/libcook.make
36 37
37# compile flags for codecs 38# compile flags for codecs
38CODECFLAGS = $(CFLAGS) -I$(APPSDIR)/codecs -I$(APPSDIR)/codecs/lib \ 39CODECFLAGS = $(CFLAGS) -I$(APPSDIR)/codecs -I$(APPSDIR)/codecs/lib \
@@ -47,7 +48,7 @@ CODEC_CRT0 := $(CODECDIR)/codec_crt0.o
47 48
48CODECLIBS := $(DEMACLIB) $(A52LIB) $(ALACLIB) $(ASAPLIB) \ 49CODECLIBS := $(DEMACLIB) $(A52LIB) $(ALACLIB) $(ASAPLIB) \
49 $(FAADLIB) $(FFMPEGFLACLIB) $(M4ALIB) $(MADLIB) $(MUSEPACKLIB) \ 50 $(FAADLIB) $(FFMPEGFLACLIB) $(M4ALIB) $(MADLIB) $(MUSEPACKLIB) \
50 $(SPCLIB) $(SPEEXLIB) $(TREMORLIB) $(WAVPACKLIB) $(WMALIB) \ 51 $(SPCLIB) $(SPEEXLIB) $(TREMORLIB) $(WAVPACKLIB) $(WMALIB) $(COOKLIB) \
51 $(CODECLIB) 52 $(CODECLIB)
52 53
53$(CODECS): $(CODEC_CRT0) $(CODECLINK_LDS) 54$(CODECS): $(CODEC_CRT0) $(CODECLINK_LDS)
@@ -73,6 +74,7 @@ $(CODECDIR)/ape.codec : $(CODECDIR)/libdemac.a
73$(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a 74$(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a
74$(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a 75$(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a
75$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a 76$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a
77$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a
76 78
77$(CODECS): $(CODECLIB) # this must be last in codec dependency list 79$(CODECS): $(CODECLIB) # this must be last in codec dependency list
78 80
diff --git a/apps/codecs/cook.c b/apps/codecs/cook.c
new file mode 100644
index 0000000000..7b4b8e7461
--- /dev/null
+++ b/apps/codecs/cook.c
@@ -0,0 +1,144 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * Copyright (C) 2009 Mohamed Tarek
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <string.h>
21
22#include "logf.h"
23#include "codeclib.h"
24#include "inttypes.h"
25#include "libcook/cook.h"
26
27#define DATA_HEADER_SIZE 18 /* size of DATA chunk header in a rm file */
28
29CODEC_HEADER
30
31RMContext rmctx;
32RMPacket pkt;
33COOKContext q;
34
35static void init_rm(RMContext *rmctx)
36{
37 memcpy(rmctx, ci->id3->id3v2buf, sizeof(RMContext));
38}
39
40/* this is the codec entry point */
41enum codec_status codec_main(void)
42{
43 static size_t buff_size;
44 int datasize, res, consumed,i;
45 uint8_t *bit_buffer;
46 int16_t outbuf[2048] __attribute__((aligned(32)));
47 uint16_t fs,sps,h;
48 uint32_t packet_count;
49 int scrambling_unit_size;
50
51next_track:
52 if (codec_init()) {
53 DEBUGF("codec init failed\n");
54 return CODEC_ERROR;
55 }
56 while (!*ci->taginfo_ready && !ci->stop_codec)
57 ci->sleep(1);
58
59 codec_set_replaygain(ci->id3);
60 ci->memset(&rmctx,0,sizeof(RMContext));
61 ci->memset(&pkt,0,sizeof(RMPacket));
62 ci->memset(&q,0,sizeof(COOKContext));
63
64 init_rm(&rmctx);
65
66 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
67 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
68 ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
69 STEREO_MONO : STEREO_INTERLEAVED);
70
71 packet_count = rmctx.nb_packets;
72 rmctx.audio_framesize = rmctx.block_align;
73 rmctx.block_align = rmctx.sub_packet_size;
74 fs = rmctx.audio_framesize;
75 sps= rmctx.block_align;
76 h = rmctx.sub_packet_h;
77 scrambling_unit_size = h*fs;
78
79 res =cook_decode_init(&rmctx, &q);
80 if(res < 0) {
81 DEBUGF("failed to initialize cook decoder\n");
82 return CODEC_ERROR;
83 }
84
85 ci->set_elapsed(0);
86 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
87
88 /* The main decoder loop */
89 while (1)
90 {
91 /*if (ci->seek_time) {
92
93 ci->set_elapsed(ci->seek_time);
94 n = ci->seek_time/10;
95 memset(buf,0,BUF_SIZE);
96 ci->seek_complete();
97 }*/
98
99 while(packet_count)
100 {
101 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
102 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
103 if(consumed < 0) {
104 DEBUGF("rm_get_packet failed\n");
105 return CODEC_ERROR;
106 }
107 /*DEBUGF(" version = %d\n"
108 " length = %d\n"
109 " stream = %d\n"
110 " timestamp= %d\n",pkt.version,pkt.length,pkt.stream_number,pkt.timestamp);*/
111
112 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
113 {
114 ci->yield();
115 if (ci->stop_codec || ci->new_track)
116 goto done;
117
118 res = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.frames[i], rmctx.block_align);
119 rmctx.frame_number++;
120
121 /* skip the first two frames; no valid audio */
122 if(rmctx.frame_number < 3) continue;
123
124 if(res != rmctx.block_align) {
125 DEBUGF("codec error\n");
126 return CODEC_ERROR;
127 }
128
129 ci->pcmbuf_insert(outbuf, NULL, rmctx.samples_pf_pc / rmctx.nb_channels);
130 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
131 }
132 packet_count -= rmctx.audio_pkt_cnt;
133 rmctx.audio_pkt_cnt = 0;
134 ci->advance_buffer(consumed);
135 }
136 goto done;
137
138 }
139 done :
140 if (ci->request_next_track())
141 goto next_track;
142
143 return CODEC_OK;
144}
diff --git a/apps/codecs/libcook/Makefile.test b/apps/codecs/libcook/Makefile.test
index 493ab8f623..c8a3236935 100644
--- a/apps/codecs/libcook/Makefile.test
+++ b/apps/codecs/libcook/Makefile.test
@@ -1,4 +1,4 @@
1CFLAGS = -Wall -O3 1CFLAGS = -Wall -O3 -DTEST -D"DEBUGF=printf"
2OBJS = main.o bitstream.o cook.o ../librm/rm.o 2OBJS = main.o bitstream.o cook.o ../librm/rm.o
3cooktest: $(OBJS) 3cooktest: $(OBJS)
4 gcc -o cooktest $(OBJS) 4 gcc -o cooktest $(OBJS)
@@ -7,4 +7,4 @@ cooktest: $(OBJS)
7 $(CC) $(CFLAGS) -c -o $@ $< 7 $(CC) $(CFLAGS) -c -o $@ $<
8 8
9clean: 9clean:
10 rm -f cooktest $(OBJS) *~ 10 rm -f cooktest $(OBJS) *~ output.wav
diff --git a/apps/codecs/libcook/SOURCES b/apps/codecs/libcook/SOURCES
new file mode 100644
index 0000000000..7b2cd967ea
--- /dev/null
+++ b/apps/codecs/libcook/SOURCES
@@ -0,0 +1,3 @@
1cook.c
2bitstream.c
3../librm/rm.c
diff --git a/apps/codecs/libcook/bitstream.c b/apps/codecs/libcook/bitstream.c
index 4bc706ffb7..1375134b21 100644
--- a/apps/codecs/libcook/bitstream.c
+++ b/apps/codecs/libcook/bitstream.c
@@ -22,13 +22,13 @@
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */ 23 */
24 24
25/**
26 * @file libavcodec/bitstream.c
27 * bitstream api.
28 */
29
30#include "bitstream.h" 25#include "bitstream.h"
31 26
27#ifdef ROCKBOX
28#undef DEBUGF
29#define DEBUGF(...)
30#endif
31
32const uint8_t ff_log2_run[32]={ 32const uint8_t ff_log2_run[32]={
33 0, 0, 0, 0, 1, 1, 1, 1, 33 0, 0, 0, 0, 1, 1, 1, 1,
34 2, 2, 2, 2, 3, 3, 3, 3, 34 2, 2, 2, 2, 3, 3, 3, 3,
@@ -46,24 +46,6 @@ const uint8_t ff_log2_run[32]={
46 * and should correctly use static arrays 46 * and should correctly use static arrays
47 */ 47 */
48 48
49#if 0
50attribute_deprecated av_alloc_size(2)
51static void *ff_realloc_static(void *ptr, unsigned int size);
52
53static void *ff_realloc_static(void *ptr, unsigned int size)
54{
55 return av_realloc(ptr, size);
56}
57
58void align_put_bits(PutBitContext *s)
59{
60#ifdef ALT_BITSTREAM_WRITER
61 put_bits(s,( - s->index) & 7,0);
62#else
63 put_bits(s,s->bit_left & 7,0);
64#endif
65}
66#endif
67 49
68void ff_put_string(PutBitContext * pbc, const char *s, int put_zero) 50void ff_put_string(PutBitContext * pbc, const char *s, int put_zero)
69{ 51{
@@ -75,30 +57,6 @@ void ff_put_string(PutBitContext * pbc, const char *s, int put_zero)
75 put_bits(pbc, 8, 0); 57 put_bits(pbc, 8, 0);
76} 58}
77 59
78#if 0
79void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length)
80{
81 const uint16_t *srcw= (const uint16_t*)src;
82 int words= length>>4;
83 int bits= length&15;
84 int i;
85
86 if(length==0) return;
87
88 if(CONFIG_SMALL || words < 16 || put_bits_count(pb)&7){
89 for(i=0; i<words; i++) put_bits(pb, 16, AV_RB16(&srcw[i]));
90 }else{
91 for(i=0; put_bits_count(pb)&31; i++)
92 put_bits(pb, 8, src[i]);
93 flush_put_bits(pb);
94 memcpy(pbBufPtr(pb), src+i, 2*words-i);
95 skip_put_bytes(pb, 2*words-i);
96 }
97
98 put_bits(pb, bits, AV_RB16(&srcw[words])>>(16-bits));
99}
100#endif
101
102/* VLC decoding */ 60/* VLC decoding */
103 61
104//#define DEBUG_VLC 62//#define DEBUG_VLC
@@ -127,8 +85,7 @@ static int alloc_table(VLC *vlc, int size, int use_static)
127 vlc->table_size += size; 85 vlc->table_size += size;
128 if (vlc->table_size > vlc->table_allocated) { 86 if (vlc->table_size > vlc->table_allocated) {
129 if(use_static>1){ 87 if(use_static>1){
130 printf("init_vlc() used with too little memory : table_size > allocated_memory\n"); 88 DEBUGF("init_vlc() used with too little memory : table_size > allocated_memory\n");
131 abort(); //cant do anything, init_vlc() is used with too little memory
132 } 89 }
133 90
134 if (!vlc->table) 91 if (!vlc->table)
@@ -151,7 +108,7 @@ static int build_table(VLC *vlc, int table_nb_bits,
151 table_size = 1 << table_nb_bits; 108 table_size = 1 << table_nb_bits;
152 table_index = alloc_table(vlc, table_size, flags & (INIT_VLC_USE_STATIC|INIT_VLC_USE_NEW_STATIC)); 109 table_index = alloc_table(vlc, table_size, flags & (INIT_VLC_USE_STATIC|INIT_VLC_USE_NEW_STATIC));
153#ifdef DEBUG_VLC 110#ifdef DEBUG_VLC
154 printf("new table index=%d size=%d code_prefix=%x n=%d\n", 111 DEBUGF("new table index=%d size=%d code_prefix=%x n=%d\n",
155 table_index, table_size, code_prefix, n_prefix); 112 table_index, table_size, code_prefix, n_prefix);
156#endif 113#endif
157 if (table_index < 0) 114 if (table_index < 0)
@@ -175,15 +132,15 @@ static int build_table(VLC *vlc, int table_nb_bits,
175 else 132 else
176 GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size); 133 GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size);
177#if defined(DEBUG_VLC) && 0 134#if defined(DEBUG_VLC) && 0
178 printf("i=%d n=%d code=0x%x\n", i, n, code); 135 DEBUGF("i=%d n=%d code=0x%x\n", i, n, code);
179#endif 136#endif
180 /* if code matches the prefix, it is in the table */ 137 /* if code matches the prefix, it is in the table */
181 n -= n_prefix; 138 n -= n_prefix;
182 if(flags & INIT_VLC_LE) 139 if(flags & INIT_VLC_LE)
183 code_prefix2= code & (n_prefix>=32 ? 0xffffffff : (1 << n_prefix)-1); 140 code_prefix2= code & (n_prefix>=32 ? (int)0xffffffff : (1 << n_prefix)-1);
184 else 141 else
185 code_prefix2= code >> n; 142 code_prefix2= code >> n;
186 if (n > 0 && code_prefix2 == code_prefix) { 143 if (n > 0 && code_prefix2 == (int)code_prefix) {
187 if (n <= table_nb_bits) { 144 if (n <= table_nb_bits) {
188 /* no need to add another table */ 145 /* no need to add another table */
189 j = (code << (table_nb_bits - n)) & (table_size - 1); 146 j = (code << (table_nb_bits - n)) & (table_size - 1);
@@ -192,11 +149,11 @@ static int build_table(VLC *vlc, int table_nb_bits,
192 if(flags & INIT_VLC_LE) 149 if(flags & INIT_VLC_LE)
193 j = (code >> n_prefix) + (k<<n); 150 j = (code >> n_prefix) + (k<<n);
194#ifdef DEBUG_VLC 151#ifdef DEBUG_VLC
195 printf("%4x: code=%d n=%d\n", 152 DEBUGF("%4x: code=%d n=%d\n",
196 j, i, n); 153 j, i, n);
197#endif 154#endif
198 if (table[j][1] /*bits*/ != 0) { 155 if (table[j][1] /*bits*/ != 0) {
199 printf("incorrect codes\n"); 156 DEBUGF("incorrect codes\n");
200 return -1; 157 return -1;
201 } 158 }
202 table[j][1] = n; //bits 159 table[j][1] = n; //bits
@@ -207,7 +164,7 @@ static int build_table(VLC *vlc, int table_nb_bits,
207 n -= table_nb_bits; 164 n -= table_nb_bits;
208 j = (code >> ((flags & INIT_VLC_LE) ? n_prefix : n)) & ((1 << table_nb_bits) - 1); 165 j = (code >> ((flags & INIT_VLC_LE) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
209#ifdef DEBUG_VLC 166#ifdef DEBUG_VLC
210 printf("%4x: n=%d (subtable)\n", 167 DEBUGF("%4x: n=%d (subtable)\n",
211 j, n); 168 j, n);
212#endif 169#endif
213 /* compute table size */ 170 /* compute table size */
@@ -282,7 +239,7 @@ int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
282 if(vlc->table_size && vlc->table_size == vlc->table_allocated){ 239 if(vlc->table_size && vlc->table_size == vlc->table_allocated){
283 return 0; 240 return 0;
284 }else if(vlc->table_size){ 241 }else if(vlc->table_size){
285 abort(); // fatal error, we are called on a partially initialized table 242 return -1; // fatal error, we are called on a partially initialized table
286 } 243 }
287 }else if(!(flags & INIT_VLC_USE_STATIC)) { 244 }else if(!(flags & INIT_VLC_USE_STATIC)) {
288 vlc->table = NULL; 245 vlc->table = NULL;
@@ -296,7 +253,7 @@ int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
296 } 253 }
297 254
298#ifdef DEBUG_VLC 255#ifdef DEBUG_VLC
299 printf("build table nb_codes=%d\n", nb_codes); 256 DEBUGF("build table nb_codes=%d\n", nb_codes);
300#endif 257#endif
301 258
302 if (build_table(vlc, nb_bits, nb_codes, 259 if (build_table(vlc, nb_bits, nb_codes,
@@ -304,20 +261,16 @@ int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
304 codes, codes_wrap, codes_size, 261 codes, codes_wrap, codes_size,
305 symbols, symbols_wrap, symbols_size, 262 symbols, symbols_wrap, symbols_size,
306 0, 0, flags) < 0) { 263 0, 0, flags) < 0) {
307 free(&vlc->table); 264 //free(&vlc->table);
308 return -1; 265 return -1;
309 } 266 }
310 /* Changed the following condition to be true if table_size > table_allocated. * 267 /* Changed the following condition to be true if table_size > table_allocated. *
311 * This would be more sensible for static tables since we want warnings for * 268 * This would be more sensible for static tables since we want warnings for *
312 * memory shortages only. */ 269 * memory shortages only. */
270#ifdef TEST
313 if((flags & INIT_VLC_USE_NEW_STATIC) && vlc->table_size > vlc->table_allocated) 271 if((flags & INIT_VLC_USE_NEW_STATIC) && vlc->table_size > vlc->table_allocated)
314 printf("needed %d had %d\n", vlc->table_size, vlc->table_allocated); 272 DEBUGF("needed %d had %d\n", vlc->table_size, vlc->table_allocated);
273#endif
315 return 0; 274 return 0;
316} 275}
317 276
318
319void free_vlc(VLC *vlc)
320{
321 free(&vlc->table);
322}
323
diff --git a/apps/codecs/libcook/bitstream.h b/apps/codecs/libcook/bitstream.h
index 085d0a1566..9be8e65690 100644
--- a/apps/codecs/libcook/bitstream.h
+++ b/apps/codecs/libcook/bitstream.h
@@ -18,15 +18,10 @@
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */ 19 */
20 20
21/** 21#ifndef BITSTREAM_H
22 * @file libavcodec/bitstream.h 22#define BITSTREAM_H
23 * bitstream api header.
24 */
25 23
26#ifndef AVCODEC_BITSTREAM_H 24#include <inttypes.h>
27#define AVCODEC_BITSTREAM_H
28
29#include <stdint.h>
30#include <stdlib.h> 25#include <stdlib.h>
31#include <assert.h> 26#include <assert.h>
32#include <string.h> 27#include <string.h>
@@ -51,7 +46,7 @@
51//#define ALT_BITSTREAM_WRITER 46//#define ALT_BITSTREAM_WRITER
52//#define ALIGNED_BITSTREAM_WRITER 47//#define ALIGNED_BITSTREAM_WRITER
53#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER) 48#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER)
54# if ARCH_ARM 49# if defined(ARCH_ARM)
55# define A32_BITSTREAM_READER 50# define A32_BITSTREAM_READER
56# else 51# else
57# define ALT_BITSTREAM_READER 52# define ALT_BITSTREAM_READER
@@ -62,7 +57,7 @@
62 57
63extern const uint8_t ff_reverse[256]; 58extern const uint8_t ff_reverse[256];
64 59
65#if ARCH_X86 60#if defined(ARCH_X86)
66// avoid +32 for shift optimization (gcc should do that ...) 61// avoid +32 for shift optimization (gcc should do that ...)
67static inline int32_t NEG_SSR32( int32_t a, int8_t s){ 62static inline int32_t NEG_SSR32( int32_t a, int8_t s){
68 __asm__ ("sarl %1, %0\n\t" 63 __asm__ ("sarl %1, %0\n\t"
@@ -226,7 +221,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value)
226 } else { 221 } else {
227 bit_buf<<=bit_left; 222 bit_buf<<=bit_left;
228 bit_buf |= value >> (n - bit_left); 223 bit_buf |= value >> (n - bit_left);
229#if !HAVE_FAST_UNALIGNED 224#if !defined(HAVE_FAST_UNALIGNED)
230 if (3 & (intptr_t) s->buf_ptr) { 225 if (3 & (intptr_t) s->buf_ptr) {
231 AV_WB32(s->buf_ptr, bit_buf); 226 AV_WB32(s->buf_ptr, bit_buf);
232 } else 227 } else
@@ -736,6 +731,7 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n){
736 } 731 }
737} 732}
738 733
734#if 0
739static inline int check_marker(GetBitContext *s, const char *msg) 735static inline int check_marker(GetBitContext *s, const char *msg)
740{ 736{
741 int bit= get_bits1(s); 737 int bit= get_bits1(s);
@@ -744,6 +740,7 @@ static inline int check_marker(GetBitContext *s, const char *msg)
744 740
745 return bit; 741 return bit;
746} 742}
743#endif
747 744
748/** 745/**
749 * init GetBitContext. 746 * init GetBitContext.
@@ -963,4 +960,4 @@ static inline int decode210(GetBitContext *gb){
963 return 2 - get_bits1(gb); 960 return 2 - get_bits1(gb);
964} 961}
965 962
966#endif /* AVCODEC_BITSTREAM_H */ 963#endif /* BITSTREAM_H */
diff --git a/apps/codecs/libcook/bswap.h b/apps/codecs/libcook/bswap.h
index 443cd1c3f9..b083d10ed0 100644
--- a/apps/codecs/libcook/bswap.h
+++ b/apps/codecs/libcook/bswap.h
@@ -1,86 +1,137 @@
1/*
2 * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/** 1/**
22 * @file libavutil/bswap.h 2 * @file bswap.h
23 * byte swapping routines 3 * byte swap.
24 */ 4 */
25 5
26#ifndef AVUTIL_BSWAP_H 6#ifndef __BSWAP_H__
27#define AVUTIL_BSWAP_H 7#define __BSWAP_H__
28 8
29#include <stdint.h> 9#ifdef HAVE_BYTESWAP_H
30//#include "ffmpeg_config.h" 10#include <byteswap.h>
31//#include "common.h" 11#else
32
33#if ARCH_ARM
34# include "arm/bswap.h"
35#elif ARCH_BFIN
36# include "bfin/bswap.h"
37#elif ARCH_SH4
38# include "sh4/bswap.h"
39#elif ARCH_X86
40# include "x86/bswap.h"
41#endif
42 12
43#ifndef bswap_16 13#ifdef ROCKBOX
44static inline uint16_t bswap_16(uint16_t x) 14#include "codecs.h"
15
16/* rockbox' optimised inline functions */
17#define bswap_16(x) swap16(x)
18#define bswap_32(x) swap32(x)
19
20static inline uint64_t ByteSwap64(uint64_t x)
45{ 21{
46 x= (x>>8) | (x<<8); 22 union {
47 return x; 23 uint64_t ll;
24 struct {
25 uint32_t l,h;
26 } l;
27 } r;
28 r.l.l = bswap_32 (x);
29 r.l.h = bswap_32 (x>>32);
30 return r.ll;
48} 31}
49#endif 32#define bswap_64(x) ByteSwap64(x)
50 33
51#ifndef bswap_32 34#elif defined(ARCH_X86)
52static inline uint32_t bswap_32(uint32_t x) 35static inline unsigned short ByteSwap16(unsigned short x)
53{ 36{
54 x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); 37 __asm("xchgb %b0,%h0" :
55 x= (x>>16) | (x<<16); 38 "=q" (x) :
39 "0" (x));
56 return x; 40 return x;
57} 41}
42#define bswap_16(x) ByteSwap16(x)
43
44static inline unsigned int ByteSwap32(unsigned int x)
45{
46#if __CPU__ > 386
47 __asm("bswap %0":
48 "=r" (x) :
49#else
50 __asm("xchgb %b0,%h0\n"
51 " rorl $16,%0\n"
52 " xchgb %b0,%h0":
53 "=q" (x) :
58#endif 54#endif
55 "0" (x));
56 return x;
57}
58#define bswap_32(x) ByteSwap32(x)
59 59
60#ifndef bswap_64 60static inline unsigned long long int ByteSwap64(unsigned long long int x)
61static inline uint64_t bswap_64(uint64_t x)
62{ 61{
63#if 0 62 register union { __extension__ uint64_t __ll;
64 x= ((x<< 8)&0xFF00FF00FF00FF00ULL) | ((x>> 8)&0x00FF00FF00FF00FFULL); 63 uint32_t __l[2]; } __x;
65 x= ((x<<16)&0xFFFF0000FFFF0000ULL) | ((x>>16)&0x0000FFFF0000FFFFULL); 64 asm("xchgl %0,%1":
66 return (x>>32) | (x<<32); 65 "=r"(__x.__l[0]),"=r"(__x.__l[1]):
66 "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32))));
67 return __x.__ll;
68}
69#define bswap_64(x) ByteSwap64(x)
70
71#elif defined(ARCH_SH4)
72
73static inline uint16_t ByteSwap16(uint16_t x) {
74 __asm__("swap.b %0,%0":"=r"(x):"0"(x));
75 return x;
76}
77
78static inline uint32_t ByteSwap32(uint32_t x) {
79 __asm__(
80 "swap.b %0,%0\n"
81 "swap.w %0,%0\n"
82 "swap.b %0,%0\n"
83 :"=r"(x):"0"(x));
84 return x;
85}
86
87#define bswap_16(x) ByteSwap16(x)
88#define bswap_32(x) ByteSwap32(x)
89
90static inline uint64_t ByteSwap64(uint64_t x)
91{
92 union {
93 uint64_t ll;
94 struct {
95 uint32_t l,h;
96 } l;
97 } r;
98 r.l.l = bswap_32 (x);
99 r.l.h = bswap_32 (x>>32);
100 return r.ll;
101}
102#define bswap_64(x) ByteSwap64(x)
103
67#else 104#else
68 union { 105
106#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8)
107
108
109// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc.
110#define bswap_32(x) \
111 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
112 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
113
114static inline uint64_t ByteSwap64(uint64_t x)
115{
116 union {
69 uint64_t ll; 117 uint64_t ll;
70 uint32_t l[2]; 118 uint32_t l[2];
71 } w, r; 119 } w, r;
72 w.ll = x; 120 w.ll = x;
73 r.l[0] = bswap_32 (w.l[1]); 121 r.l[0] = bswap_32 (w.l[1]);
74 r.l[1] = bswap_32 (w.l[0]); 122 r.l[1] = bswap_32 (w.l[0]);
75 return r.ll; 123 return r.ll;
76#endif
77} 124}
78#endif 125#define bswap_64(x) ByteSwap64(x)
126
127#endif /* !ARCH_X86 */
128
129#endif /* !HAVE_BYTESWAP_H */
79 130
80// be2me ... big-endian to machine-endian 131// be2me ... BigEndian to MachineEndian
81// le2me ... little-endian to machine-endian 132// le2me ... LittleEndian to MachineEndian
82 133
83#ifdef WORDS_BIGENDIAN 134#ifdef ROCKBOX_BIG_ENDIAN
84#define be2me_16(x) (x) 135#define be2me_16(x) (x)
85#define be2me_32(x) (x) 136#define be2me_32(x) (x)
86#define be2me_64(x) (x) 137#define be2me_64(x) (x)
@@ -96,4 +147,4 @@ static inline uint64_t bswap_64(uint64_t x)
96#define le2me_64(x) (x) 147#define le2me_64(x) (x)
97#endif 148#endif
98 149
99#endif /* AVUTIL_BSWAP_H */ 150#endif /* __BSWAP_H__ */
diff --git a/apps/codecs/libcook/cook.c b/apps/codecs/libcook/cook.c
index 8caa3992bd..ba5fbab6a1 100644
--- a/apps/codecs/libcook/cook.c
+++ b/apps/codecs/libcook/cook.c
@@ -21,7 +21,7 @@
21 */ 21 */
22 22
23/** 23/**
24 * @file libavcodec/cook.c 24 * @file cook.c
25 * Cook compatible decoder. Bastardization of the G.722.1 standard. 25 * Cook compatible decoder. Bastardization of the G.722.1 standard.
26 * This decoder handles RealNetworks, RealAudio G2 data. 26 * This decoder handles RealNetworks, RealAudio G2 data.
27 * Cook is identified by the codec name cook in RM files. 27 * Cook is identified by the codec name cook in RM files.
@@ -60,16 +60,15 @@
60#define SUBBAND_SIZE 20 60#define SUBBAND_SIZE 20
61#define MAX_SUBPACKETS 5 61#define MAX_SUBPACKETS 5
62//#define COOKDEBUG 62//#define COOKDEBUG
63#if 0 63#ifndef COOKDEBUG
64#define DEBUGF(message,args ...) printf 64#undef DEBUGF
65#else
66#define DEBUGF(...) 65#define DEBUGF(...)
67#endif 66#endif
68 67
69/** 68/**
70 * Random bit stream generator. 69 * Random bit stream generator.
71 */ 70 */
72static int inline cook_random(COOKContext *q) 71static inline int cook_random(COOKContext *q)
73{ 72{
74 q->random_state = 73 q->random_state =
75 q->random_state * 214013 + 2531011; /* typical RNG numbers */ 74 q->random_state * 214013 + 2531011; /* typical RNG numbers */
@@ -200,7 +199,7 @@ static void decode_gain_info(GetBitContext *gb, int *gaininfo)
200 i = 0; 199 i = 0;
201 while (n--) { 200 while (n--) {
202 int index = get_bits(gb, 3); 201 int index = get_bits(gb, 3);
203 int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; 202 int gain = get_bits1(gb) ? (int)get_bits(gb, 4) - 7 : -1;
204 203
205 while (i <= index) gaininfo[i++] = gain; 204 while (i <= index) gaininfo[i++] = gain;
206 } 205 }
@@ -789,7 +788,7 @@ int cook_decode_init(RMContext *rmctx, COOKContext *q)
789 return -1; 788 return -1;
790 789
791 790
792 if(q->block_align >= UINT_MAX/2) 791 if(rmctx->block_align >= UINT16_MAX/2)
793 return -1; 792 return -1;
794 793
795 q->gains1.now = q->gain_1; 794 q->gains1.now = q->gain_1;
diff --git a/apps/codecs/libcook/cook.h b/apps/codecs/libcook/cook.h
index ca982076ec..03d6d3254c 100644
--- a/apps/codecs/libcook/cook.h
+++ b/apps/codecs/libcook/cook.h
@@ -22,7 +22,7 @@
22#ifndef _COOK_H 22#ifndef _COOK_H
23#define _COOK_H 23#define _COOK_H
24 24
25#include <stdint.h> 25#include <inttypes.h>
26#include "bitstream.h" 26#include "bitstream.h"
27#include "../librm/rm.h" 27#include "../librm/rm.h"
28#include "cookdata_fixpoint.h" 28#include "cookdata_fixpoint.h"
@@ -99,4 +99,4 @@ int cook_decode_init(RMContext *rmctx, COOKContext *q);
99int cook_decode_frame(RMContext *rmctx,COOKContext *q, 99int cook_decode_frame(RMContext *rmctx,COOKContext *q,
100 int16_t *outbuffer, int *data_size, 100 int16_t *outbuffer, int *data_size,
101 const uint8_t *inbuffer, int buf_size); 101 const uint8_t *inbuffer, int buf_size);
102#endif 102#endif /*_COOK_H */
diff --git a/apps/codecs/libcook/cook_fixpoint.h b/apps/codecs/libcook/cook_fixpoint.h
index 0f12b1340a..e416bc4ef5 100644
--- a/apps/codecs/libcook/cook_fixpoint.h
+++ b/apps/codecs/libcook/cook_fixpoint.h
@@ -54,29 +54,6 @@ static const FIXPU* cplscales[5] = {
54}; 54};
55 55
56/** 56/**
57 * Initialise fixed point implementation.
58 * Nothing to do for fixed point.
59 *
60 * @param q pointer to the COOKContext
61 */
62static inline int init_cook_math(COOKContext *q)
63{
64 return 0;
65}
66
67/**
68 * Free resources used by floating point implementation.
69 * Nothing to do for fixed point.
70 *
71 * @param q pointer to the COOKContext
72 */
73static inline void free_cook_math(COOKContext *q)
74{
75 return;
76}
77
78
79/**
80 * Fixed point multiply by power of two. 57 * Fixed point multiply by power of two.
81 * 58 *
82 * @param x fix point value 59 * @param x fix point value
@@ -167,7 +144,7 @@ static void scalar_dequant_math(COOKContext *q, int index,
167 } 144 }
168} 145}
169 146
170 147#ifdef TEST
171/** 148/**
172 * The modulated lapped transform, this takes transform coefficients 149 * The modulated lapped transform, this takes transform coefficients
173 * and transforms them into timedomain samples. 150 * and transforms them into timedomain samples.
@@ -205,7 +182,35 @@ static inline void imlt_math(COOKContext *q, FIXP *in)
205 q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j]); 182 q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j]);
206 } while (++i < n); 183 } while (++i < n);
207} 184}
185#else
186#include <codecs/lib/codeclib.h>
187
188static inline void imlt_math(COOKContext *q, FIXP *in)
189{
190 const int n = q->samples_per_channel;
191 const int step = 4 << (10 - av_log2(n));
192 int i = 0, j = step>>1;
193
194 mdct_backward(2 * n, in, q->mono_mdct_output);
208 195
196 do {
197 FIXP tmp = q->mono_mdct_output[i];
198
199 q->mono_mdct_output[i] =
200 fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j]);
201 q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j+1]);
202 j += step;
203 } while (++i < n/2);
204 do {
205 FIXP tmp = q->mono_mdct_output[i];
206
207 j -= step;
208 q->mono_mdct_output[i] =
209 fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j+1]);
210 q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j]);
211 } while (++i < n);
212}
213#endif
209 214
210/** 215/**
211 * Perform buffer overlapping. 216 * Perform buffer overlapping.
diff --git a/apps/codecs/libcook/cookdata_fixpoint.h b/apps/codecs/libcook/cookdata_fixpoint.h
index b394c46a27..7a9440c664 100644
--- a/apps/codecs/libcook/cookdata_fixpoint.h
+++ b/apps/codecs/libcook/cookdata_fixpoint.h
@@ -26,7 +26,7 @@
26 * fixed point data types and constants 26 * fixed point data types and constants
27 */ 27 */
28 28
29#include <stdint.h> 29#include <inttypes.h>
30typedef int32_t FIXP; /* Fixed point variable type */ 30typedef int32_t FIXP; /* Fixed point variable type */
31typedef uint16_t FIXPU; /* Fixed point fraction 0<=x<1 */ 31typedef uint16_t FIXPU; /* Fixed point fraction 0<=x<1 */
32 32
@@ -39,11 +39,11 @@ typedef FIXP REAL_T;
39typedef struct { 39typedef struct {
40} realvars_t; 40} realvars_t;
41 41
42 42#ifdef TEST
43#define cPI1_8 0xec83 /* 1pi/8 2^16 */ 43#define cPI1_8 0xec83 /* 1pi/8 2^16 */
44#define cPI2_8 0xb505 /* 2pi/8 2^16 */ 44#define cPI2_8 0xb505 /* 2pi/8 2^16 */
45#define cPI3_8 0x61f8 /* 3pi/8 2^16 */ 45#define cPI3_8 0x61f8 /* 3pi/8 2^16 */
46 46#endif
47static const FIXPU sincos_lookup[2050] = { 47static const FIXPU sincos_lookup[2050] = {
48 /* x_i = 2^16 sin(i 2pi/8192), 2^16 cos(i 2pi/8192); i=0..1024 */ 48 /* x_i = 2^16 sin(i 2pi/8192), 2^16 cos(i 2pi/8192); i=0..1024 */
49 0x0000, 0xffff, 0x0032, 0xffff, 0x0065, 0xffff, 0x0097, 0xffff, 49 0x0000, 0xffff, 0x0032, 0xffff, 0x0065, 0xffff, 0x0097, 0xffff,
diff --git a/apps/codecs/libcook/libcook.make b/apps/codecs/libcook/libcook.make
new file mode 100644
index 0000000000..07836913d7
--- /dev/null
+++ b/apps/codecs/libcook/libcook.make
@@ -0,0 +1,18 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id:$
8#
9
10# libcook
11COOKLIB := $(CODECDIR)/libcook.a
12COOKLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libcook/SOURCES)
13COOKLIB_OBJ := $(call c2obj, $(COOKLIB_SRC))
14OTHER_SRC += $(COOKLIB_SRC)
15
16$(COOKLIB): $(COOKLIB_OBJ)
17 $(SILENT)$(shell rm -f $@)
18 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null \ No newline at end of file
diff --git a/apps/codecs/libcook/main.c b/apps/codecs/libcook/main.c
index 87f65845e8..fd20f98871 100644
--- a/apps/codecs/libcook/main.c
+++ b/apps/codecs/libcook/main.c
@@ -29,13 +29,6 @@
29#include "cook.h" 29#include "cook.h"
30 30
31//#define DUMP_RAW_FRAMES 31//#define DUMP_RAW_FRAMES
32#ifndef DEBUGF
33# if 0
34# define DEBUGF(message,args ...) printf
35# else
36# define DEBUGF(...)
37# endif
38#endif
39 32
40#define DATA_HEADER_SIZE 18 /* size of DATA chunk header in a rm file */ 33#define DATA_HEADER_SIZE 18 /* size of DATA chunk header in a rm file */
41static unsigned char wav_header[44]={ 34static unsigned char wav_header[44]={
@@ -151,8 +144,8 @@ int main(int argc, char *argv[])
151 144
152 /* copy the input rm file to a memory buffer */ 145 /* copy the input rm file to a memory buffer */
153 uint8_t * filebuf = (uint8_t *)calloc((int)filesize(fd),sizeof(uint8_t)); 146 uint8_t * filebuf = (uint8_t *)calloc((int)filesize(fd),sizeof(uint8_t));
154 read(fd,filebuf,filesize(fd)); 147 res = read(fd,filebuf,filesize(fd));
155 148
156 fd_dec = open_wav("output.wav"); 149 fd_dec = open_wav("output.wav");
157 if (fd_dec < 0) { 150 if (fd_dec < 0) {
158 DEBUGF("Error creating output file\n"); 151 DEBUGF("Error creating output file\n");
@@ -166,27 +159,25 @@ int main(int argc, char *argv[])
166 sps= rmctx.block_align; 159 sps= rmctx.block_align;
167 h = rmctx.sub_packet_h; 160 h = rmctx.sub_packet_h;
168 cook_decode_init(&rmctx,&q); 161 cook_decode_init(&rmctx,&q);
169 DEBUGF("nb_frames = %d\n",nb_frames); 162
170
171 /* change the buffer pointer to point at the first audio frame */ 163 /* change the buffer pointer to point at the first audio frame */
172 advance_buffer(&filebuf, rmctx.data_offset+ DATA_HEADER_SIZE); 164 advance_buffer(&filebuf, rmctx.data_offset+ DATA_HEADER_SIZE);
173 while(packet_count) 165 while(packet_count)
174 { 166 {
175 rm_get_packet_membuf(&filebuf, &rmctx, &pkt); 167 rm_get_packet(&filebuf, &rmctx, &pkt);
176 DEBUGF("total frames = %d packet count = %d output counter = %d \n",rmctx.audio_pkt_cnt*(fs/sps), packet_count,rmctx.audio_pkt_cnt); 168 //DEBUGF("total frames = %d packet count = %d output counter = %d \n",rmctx.audio_pkt_cnt*(fs/sps), packet_count,rmctx.audio_pkt_cnt);
177 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) 169 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
178 { 170 {
179 /* output raw audio frames that are sent to the decoder into separate files */ 171 /* output raw audio frames that are sent to the decoder into separate files */
180 #ifdef DUMP_RAW_FRAMES 172#ifdef DUMP_RAW_FRAMES
181 snprintf(filename,sizeof(filename),"dump%d.raw",++x); 173 snprintf(filename,sizeof(filename),"dump%d.raw",++x);
182 fd_out = open(filename,O_WRONLY|O_CREAT|O_APPEND); 174 fd_out = open(filename,O_WRONLY|O_CREAT|O_APPEND);
183 write(fd_out,pkt.frames[i],sps); 175 write(fd_out,pkt.frames[i],sps);
184 close(fd_out); 176 close(fd_out);
185 #endif 177#endif
186
187 nb_frames = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.frames[i] , rmctx.block_align); 178 nb_frames = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.frames[i] , rmctx.block_align);
188 rmctx.frame_number++; 179 rmctx.frame_number++;
189 write(fd_dec,outbuf,datasize); 180 res = write(fd_dec,outbuf,datasize);
190 } 181 }
191 packet_count -= rmctx.audio_pkt_cnt; 182 packet_count -= rmctx.audio_pkt_cnt;
192 rmctx.audio_pkt_cnt = 0; 183 rmctx.audio_pkt_cnt = 0;
diff --git a/apps/codecs/librm/rm.c b/apps/codecs/librm/rm.c
index 86c4378d56..4f7ebe9bef 100644
--- a/apps/codecs/librm/rm.c
+++ b/apps/codecs/librm/rm.c
@@ -21,28 +21,34 @@
21 ****************************************************************************/ 21 ****************************************************************************/
22#include <stdio.h> 22#include <stdio.h>
23#include <string.h> 23#include <string.h>
24#include <stdint.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <unistd.h>
29 24
30#include "rm.h" 25#include "rm.h"
26#ifdef ROCKBOX
27#include "codeclib.h"
28#endif
31 29
30void advance_buffer(uint8_t **buf, int val)
31{
32 *buf += val;
33}
32 34
33#if 0
34#define DEBUG
35#define DEBUGF printf
36#else
37#define DEBUGF(...)
38#endif
39
40/* Some Rockbox-like functions (these should be implemented in metadata_common.[ch] */
41static uint8_t get_uint8(uint8_t *buf) 35static uint8_t get_uint8(uint8_t *buf)
42{ 36{
43 return (uint8_t)buf[0]; 37 return (uint8_t)buf[0];
44} 38}
45 39
40#ifdef ROCKBOX_BIG_ENDIAN
41static uint16_t get_uint16be(uint8_t *buf)
42{
43 return (uint16_t)((buf[1] << 8)|buf[0]);
44}
45
46static uint32_t get_uint32be(uint8_t *buf)
47{
48 return (uint32_t)((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]);
49}
50
51#else
46static uint16_t get_uint16be(uint8_t *buf) 52static uint16_t get_uint16be(uint8_t *buf)
47{ 53{
48 return (uint16_t)((buf[0] << 8)|buf[1]); 54 return (uint16_t)((buf[0] << 8)|buf[1]);
@@ -52,6 +58,24 @@ static uint32_t get_uint32be(uint8_t *buf)
52{ 58{
53 return (uint32_t)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); 59 return (uint32_t)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
54} 60}
61#endif /* ROCKBOX_BIG_ENDIAN */
62
63#ifdef TEST
64#include <fcntl.h>
65#include <unistd.h>
66#include <sys/types.h>
67#include <sys/stat.h>
68
69int filesize(int fd)
70{
71 struct stat buf;
72
73 if (fstat(fd,&buf) == -1) {
74 return -1;
75 } else {
76 return (int)buf.st_size;
77 }
78}
55 79
56static int read_uint8(int fd, uint8_t* buf) 80static int read_uint8(int fd, uint8_t* buf)
57{ 81{
@@ -83,23 +107,9 @@ static int read_uint32be(int fd, uint32_t* buf)
83 return res; 107 return res;
84} 108}
85 109
86off_t filesize(int fd)
87{
88 struct stat buf;
89 110
90 if (fstat(fd,&buf) == -1) {
91 return -1;
92 } else {
93 return buf.st_size;
94 }
95}
96 111
97void advance_buffer(uint8_t **buf, int val) 112static int read_cook_extradata(int fd, RMContext *rmctx) {
98{
99 *buf += val;
100}
101
102int read_cook_extradata(int fd, RMContext *rmctx) {
103 read_uint32be(fd, &rmctx->cook_version); 113 read_uint32be(fd, &rmctx->cook_version);
104 read_uint16be(fd, &rmctx->samples_pf_pc); 114 read_uint16be(fd, &rmctx->samples_pf_pc);
105 read_uint16be(fd, &rmctx->nb_subbands); 115 read_uint16be(fd, &rmctx->nb_subbands);
@@ -111,14 +121,14 @@ int read_cook_extradata(int fd, RMContext *rmctx) {
111 return rmctx->extradata_size; /* for 'skipped' */ 121 return rmctx->extradata_size; /* for 'skipped' */
112} 122}
113 123
114void print_cook_extradata(RMContext *rmctx) { 124static void print_cook_extradata(RMContext *rmctx) {
115 125
116 printf(" cook_version = 0x%08x\n", rmctx->cook_version); 126 DEBUGF(" cook_version = 0x%08x\n", rmctx->cook_version);
117 printf(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc); 127 DEBUGF(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc);
118 printf(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands); 128 DEBUGF(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands);
119 if(rmctx->extradata_size == 16) { 129 if(rmctx->extradata_size == 16) {
120 printf(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start); 130 DEBUGF(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start);
121 printf(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits); 131 DEBUGF(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits);
122 } 132 }
123} 133}
124 134
@@ -196,7 +206,7 @@ static int real_read_audio_stream_info(int fd, RMContext *rmctx)
196 read_uint32be(fd, &version); 206 read_uint32be(fd, &version);
197 skipped += 4; 207 skipped += 4;
198 208
199 printf(" version=0x%04x\n",((version >> 16) & 0xff)); 209 DEBUGF(" version=0x%04x\n",((version >> 16) & 0xff));
200 if (((version >> 16) & 0xff) == 3) { 210 if (((version >> 16) & 0xff) == 3) {
201 /* Very old version */ 211 /* Very old version */
202 } else { 212 } else {
@@ -205,7 +215,7 @@ static int real_read_audio_stream_info(int fd, RMContext *rmctx)
205 read_uint32be(fd, &header_size); 215 read_uint32be(fd, &header_size);
206 skipped += 4; 216 skipped += 4;
207 /* obj.size will be filled with an unknown value, replaced with header_size */ 217 /* obj.size will be filled with an unknown value, replaced with header_size */
208 printf(" Object: %s, size: %d bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version); 218 DEBUGF(" Object: %s, size: %d bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version);
209 219
210 read_uint16be(fd, &flavor); 220 read_uint16be(fd, &flavor);
211 read_uint32be(fd, &coded_framesize); 221 read_uint32be(fd, &coded_framesize);
@@ -253,20 +263,22 @@ static int real_read_audio_stream_info(int fd, RMContext *rmctx)
253 263
254 read_uint32be(fd, &rmctx->extradata_size); 264 read_uint32be(fd, &rmctx->extradata_size);
255 skipped += 4; 265 skipped += 4;
256 if(!strncmp(fourcc2str(fourcc),"cook",4)) 266 if(!strncmp(fourcc2str(fourcc),"cook",4)){
257 skipped += read_cook_extradata(fd, rmctx); 267 skipped += read_cook_extradata(fd, rmctx);
268 rmctx->codec_type = cook;
269 }
258 270
259 271
260 printf(" flavor = %d\n",flavor); 272 DEBUGF(" flavor = %d\n",flavor);
261 printf(" coded_frame_size = %d\n",coded_framesize); 273 DEBUGF(" coded_frame_size = %d\n",coded_framesize);
262 printf(" sub_packet_h = %d\n",rmctx->sub_packet_h); 274 DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h);
263 printf(" frame_size = %d\n",rmctx->block_align); 275 DEBUGF(" frame_size = %d\n",rmctx->block_align);
264 printf(" sub_packet_size = %d\n",rmctx->sub_packet_size); 276 DEBUGF(" sub_packet_size = %d\n",rmctx->sub_packet_size);
265 printf(" sample_rate= %d\n",rmctx->sample_rate); 277 DEBUGF(" sample_rate= %d\n",rmctx->sample_rate);
266 printf(" channels= %d\n",rmctx->nb_channels); 278 DEBUGF(" channels= %d\n",rmctx->nb_channels);
267 printf(" fourcc = %s\n",fourcc2str(fourcc)); 279 DEBUGF(" fourcc = %s\n",fourcc2str(fourcc));
268 printf(" codec_extra_data_length = %d\n",rmctx->extradata_size); 280 DEBUGF(" codec_extra_data_length = %d\n",rmctx->extradata_size);
269 printf(" codec_extradata :\n"); 281 DEBUGF(" codec_extradata :\n");
270 print_cook_extradata(rmctx); 282 print_cook_extradata(rmctx);
271 283
272 } 284 }
@@ -327,18 +339,18 @@ int real_parse_header(int fd, RMContext *rmctx)
327 read_uint32be(fd, &unknown1); 339 read_uint32be(fd, &unknown1);
328 read_uint32be(fd, &unknown2); 340 read_uint32be(fd, &unknown2);
329 341
330 printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos); 342 DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
331 printf(" unknown1=%d (0x%08x)\n",unknown1,unknown1); 343 DEBUGF(" unknown1=%d (0x%08x)\n",unknown1,unknown1);
332 printf(" unknown2=%d (0x%08x)\n",unknown2,unknown2); 344 DEBUGF(" unknown2=%d (0x%08x)\n",unknown2,unknown2);
333 345
334 res = real_read_object_header(fd, &obj); 346 res = real_read_object_header(fd, &obj);
335 header_end = 0; 347 header_end = 0;
336 while(res) 348 while(res)
337 { 349 {
338 printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos); 350 DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
339 skipped = 10; 351 skipped = 10;
340 if(obj.fourcc == FOURCC('I','N','D','X')) 352 if(obj.fourcc == FOURCC('I','N','D','X'))
341 break; 353 break;
342 switch (obj.fourcc) 354 switch (obj.fourcc)
343 { 355 {
344 case FOURCC('P','R','O','P'): /* File properties */ 356 case FOURCC('P','R','O','P'): /* File properties */
@@ -347,7 +359,7 @@ int real_parse_header(int fd, RMContext *rmctx)
347 read_uint32be(fd, &max_packet_size); 359 read_uint32be(fd, &max_packet_size);
348 read_uint32be(fd, &avg_packet_size); 360 read_uint32be(fd, &avg_packet_size);
349 read_uint32be(fd, &packet_count); 361 read_uint32be(fd, &packet_count);
350 read_uint32be(fd, &duration); 362 read_uint32be(fd, &rmctx->duration);
351 read_uint32be(fd, &preroll); 363 read_uint32be(fd, &preroll);
352 read_uint32be(fd, &index_offset); 364 read_uint32be(fd, &index_offset);
353 read_uint32be(fd, &rmctx->data_offset); 365 read_uint32be(fd, &rmctx->data_offset);
@@ -355,17 +367,17 @@ int real_parse_header(int fd, RMContext *rmctx)
355 read_uint16be(fd, &rmctx->flags); 367 read_uint16be(fd, &rmctx->flags);
356 skipped += 40; 368 skipped += 40;
357 369
358 printf(" max_bitrate = %d\n",max_bitrate); 370 DEBUGF(" max_bitrate = %d\n",max_bitrate);
359 printf(" avg_bitrate = %d\n",avg_bitrate); 371 DEBUGF(" avg_bitrate = %d\n",avg_bitrate);
360 printf(" max_packet_size = %d\n",max_packet_size); 372 DEBUGF(" max_packet_size = %d\n",max_packet_size);
361 printf(" avg_packet_size = %d\n",avg_packet_size); 373 DEBUGF(" avg_packet_size = %d\n",avg_packet_size);
362 printf(" packet_count = %d\n",packet_count); 374 DEBUGF(" packet_count = %d\n",packet_count);
363 printf(" duration = %d\n",duration); 375 DEBUGF(" duration = %d\n",rmctx->duration);
364 printf(" preroll = %d\n",preroll); 376 DEBUGF(" preroll = %d\n",preroll);
365 printf(" index_offset = %d\n",index_offset); 377 DEBUGF(" index_offset = %d\n",index_offset);
366 printf(" data_offset = %d\n",rmctx->data_offset); 378 DEBUGF(" data_offset = %d\n",rmctx->data_offset);
367 printf(" num_streams = %d\n",num_streams); 379 DEBUGF(" num_streams = %d\n",num_streams);
368 printf(" flags=0x%04x\n",flags); 380 DEBUGF(" flags=0x%04x\n",flags);
369 break; 381 break;
370 382
371 case FOURCC('C','O','N','T'): 383 case FOURCC('C','O','N','T'):
@@ -375,10 +387,10 @@ int real_parse_header(int fd, RMContext *rmctx)
375 skipped += read_str(fd,copyright); 387 skipped += read_str(fd,copyright);
376 skipped += read_str(fd,comment); 388 skipped += read_str(fd,comment);
377 389
378 printf(" title=\"%s\"\n",title); 390 DEBUGF(" title=\"%s\"\n",title);
379 printf(" author=\"%s\"\n",author); 391 DEBUGF(" author=\"%s\"\n",author);
380 printf(" copyright=\"%s\"\n",copyright); 392 DEBUGF(" copyright=\"%s\"\n",copyright);
381 printf(" comment=\"%s\"\n",comment); 393 DEBUGF(" comment=\"%s\"\n",comment);
382 break; 394 break;
383 395
384 case FOURCC('M','D','P','R'): /* Media properties */ 396 case FOURCC('M','D','P','R'): /* Media properties */
@@ -406,18 +418,18 @@ int real_parse_header(int fd, RMContext *rmctx)
406 read_uint32be(fd,&v); 418 read_uint32be(fd,&v);
407 skipped += 4; 419 skipped += 4;
408 420
409 printf(" stream_id = 0x%04x\n",stream_id); 421 DEBUGF(" stream_id = 0x%04x\n",stream_id);
410 printf(" max_bitrate = %d\n",max_bitrate); 422 DEBUGF(" max_bitrate = %d\n",max_bitrate);
411 printf(" avg_bitrate = %d\n",avg_bitrate); 423 DEBUGF(" avg_bitrate = %d\n",avg_bitrate);
412 printf(" max_packet_size = %d\n",max_packet_size); 424 DEBUGF(" max_packet_size = %d\n",max_packet_size);
413 printf(" avg_packet_size = %d\n",avg_packet_size); 425 DEBUGF(" avg_packet_size = %d\n",avg_packet_size);
414 printf(" start_time = %d\n",start_time); 426 DEBUGF(" start_time = %d\n",start_time);
415 printf(" preroll = %d\n",preroll); 427 DEBUGF(" preroll = %d\n",preroll);
416 printf(" duration = %d\n",duration); 428 DEBUGF(" duration = %d\n",duration);
417 printf(" desc=\"%s\"\n",desc); 429 DEBUGF(" desc=\"%s\"\n",desc);
418 printf(" mimetype=\"%s\"\n",mimetype); 430 DEBUGF(" mimetype=\"%s\"\n",mimetype);
419 printf(" codec_data_size = %d\n",codec_data_size); 431 DEBUGF(" codec_data_size = %d\n",codec_data_size);
420 printf(" v=\"%s\"\n", fourcc2str(v)); 432 DEBUGF(" v=\"%s\"\n", fourcc2str(v));
421 433
422 if (v == FOURCC('.','r','a',0xfd)) 434 if (v == FOURCC('.','r','a',0xfd))
423 { 435 {
@@ -428,10 +440,10 @@ int real_parse_header(int fd, RMContext *rmctx)
428 440
429 case FOURCC('D','A','T','A'): 441 case FOURCC('D','A','T','A'):
430 442
431 read_uint32be(fd,&rmctx->nb_packets); 443 read_uint32be(fd,&rmctx->nb_packets);
432 skipped += 4; 444 skipped += 4;
433 read_uint32be(fd,&next_data_off); 445 read_uint32be(fd,&next_data_off);
434 skipped += 4; 446 skipped += 4;
435 if (!rmctx->nb_packets && (rmctx->flags & 4)) 447 if (!rmctx->nb_packets && (rmctx->flags & 4))
436 rmctx->nb_packets = 3600 * 25; 448 rmctx->nb_packets = 3600 * 25;
437 449
@@ -445,8 +457,8 @@ int real_parse_header(int fd, RMContext *rmctx)
445 if(rmctx->nb_packets % rmctx->sub_packet_h) 457 if(rmctx->nb_packets % rmctx->sub_packet_h)
446 rmctx->nb_packets += rmctx->sub_packet_h - (rmctx->nb_packets % rmctx->sub_packet_h); 458 rmctx->nb_packets += rmctx->sub_packet_h - (rmctx->nb_packets % rmctx->sub_packet_h);
447 459
448 printf(" data_nb_packets = %d\n",rmctx->nb_packets); 460 DEBUGF(" data_nb_packets = %d\n",rmctx->nb_packets);
449 printf(" next DATA offset = %d\n",next_data_off); 461 DEBUGF(" next DATA offset = %d\n",next_data_off);
450 header_end = 1; 462 header_end = 1;
451 break; 463 break;
452 } 464 }
@@ -459,7 +471,7 @@ int real_parse_header(int fd, RMContext *rmctx)
459 return 0; 471 return 0;
460} 472}
461 473
462void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt) 474void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt)
463{ 475{
464 uint8_t unknown,packet_group; 476 uint8_t unknown,packet_group;
465 uint16_t x, place; 477 uint16_t x, place;
@@ -467,10 +479,19 @@ void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt)
467 uint16_t h = rmctx->sub_packet_h; 479 uint16_t h = rmctx->sub_packet_h;
468 uint16_t y = rmctx->sub_packet_cnt; 480 uint16_t y = rmctx->sub_packet_cnt;
469 uint16_t w = rmctx->audio_framesize; 481 uint16_t w = rmctx->audio_framesize;
482 int res;
470 do 483 do
471 { 484 {
472 y = rmctx->sub_packet_cnt; 485 y = rmctx->sub_packet_cnt;
473 read_uint16be(fd,&pkt->version); 486 read_uint16be(fd,&pkt->version);
487
488 /* Simple error checking */
489 if(pkt->version != 0 && pkt->version != 1)
490 {
491 DEBUGF("parsing packets failed\n");
492 return -1;
493 }
494
474 read_uint16be(fd,&pkt->length); 495 read_uint16be(fd,&pkt->length);
475 read_uint16be(fd,&pkt->stream_number); 496 read_uint16be(fd,&pkt->stream_number);
476 read_uint32be(fd,&pkt->timestamp); 497 read_uint32be(fd,&pkt->timestamp);
@@ -495,22 +516,17 @@ void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt)
495 516
496 for(x = 0 ; x < w/sps; x++) 517 for(x = 0 ; x < w/sps; x++)
497 { 518 {
498 place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1)); 519 res = read(fd,pkt->data+(sps*(h*x+((h+1)/2)*(y&1)+(y>>1))), sps);
499 read(fd,pkt->data+place, sps);
500 //DEBUGF("place = %d data[place] = %d\n",place,pkt->data[place]);
501 } 520 }
502 rmctx->audio_pkt_cnt++; 521 rmctx->audio_pkt_cnt++;
503 }while(++(rmctx->sub_packet_cnt) < h); 522 }while(++(rmctx->sub_packet_cnt) < h);
504 523
505 //return pkt->data;
506} 524}
525#endif /*TEST*/
507 526
508/** 527int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
509 * Another version of rm_get_packet which reads from a memory buffer
510 * instead of readind from a file descriptor.
511 **/
512void rm_get_packet_membuf(uint8_t **filebuf,RMContext *rmctx, RMPacket *pkt)
513{ 528{
529 int consumed = 0;
514 uint8_t unknown; 530 uint8_t unknown;
515 uint16_t x, place; 531 uint16_t x, place;
516 uint16_t sps = rmctx->sub_packet_size; 532 uint16_t sps = rmctx->sub_packet_size;
@@ -520,36 +536,46 @@ void rm_get_packet_membuf(uint8_t **filebuf,RMContext *rmctx, RMPacket *pkt)
520 do 536 do
521 { 537 {
522 y = rmctx->sub_packet_cnt; 538 y = rmctx->sub_packet_cnt;
523 pkt->version = get_uint16be(*filebuf); 539 pkt->version = get_uint16be(*src);
524 pkt->length = get_uint16be(*filebuf+2); 540
525 pkt->stream_number = get_uint16be(*filebuf+4); 541 /* Simple error checking */
526 pkt->timestamp = get_uint32be(*filebuf+6); 542 if(pkt->version != 0 && pkt->version != 1)
527 DEBUGF(" version = %d\n" 543 {
544 DEBUGF("parsing packets failed\n");
545 return -1;
546 }
547
548 pkt->length = get_uint16be(*src+2);
549 pkt->stream_number = get_uint16be(*src+4);
550 pkt->timestamp = get_uint32be(*src+6);
551 /*DEBUGF(" version = %d\n"
528 " length = %d\n" 552 " length = %d\n"
529 " stream = %d\n" 553 " stream = %d\n"
530 " timestamp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp); 554 " timestamp= %d\n\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);*/
531 555 unknown = get_uint8(*src+10);
532 unknown = get_uint8(*filebuf+10); 556 pkt->flags = get_uint8(*src+11);
533 pkt->flags = get_uint8(*filebuf+11);
534 557
535 if(pkt->version == 1) 558 if(pkt->version == 1)
536 unknown = get_uint8(*filebuf+10); 559 unknown = get_uint8(*src+10);
537 560
538 if (pkt->flags & 2) /* keyframe */ 561 if (pkt->flags & 2) /* keyframe */
539 y = rmctx->sub_packet_cnt = 0; 562 y = rmctx->sub_packet_cnt = 0;
540 if (!y) /* if keyframe update playback elapsed time */ 563 if (!y)
541 rmctx->audiotimestamp = pkt->timestamp; 564 rmctx->audiotimestamp = pkt->timestamp;
542 565
543 advance_buffer(filebuf,12); 566 advance_buffer(src,12);
544 567 consumed += 12;
545 for(x = 0 ; x < w/sps; x++) 568 for(x = 0 ; x < w/sps; x++)
546 { 569 {
547 place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1)); 570 place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1));
548 pkt->frames[place/sps] = *filebuf; 571 pkt->frames[place/sps] = *src;
549 advance_buffer(filebuf,sps); 572 advance_buffer(src,sps);
573 consumed += sps;
550 } 574 }
551 rmctx->audio_pkt_cnt++; 575 rmctx->audio_pkt_cnt++;
552 }while(++(rmctx->sub_packet_cnt) < h); 576 }while(++(rmctx->sub_packet_cnt) < h);
577
578return consumed;
553} 579}
554 580
555#ifdef DEBUG 581#ifdef DEBUG
diff --git a/apps/codecs/librm/rm.h b/apps/codecs/librm/rm.h
index bdd03f3db2..a0c386e824 100644
--- a/apps/codecs/librm/rm.h
+++ b/apps/codecs/librm/rm.h
@@ -22,17 +22,21 @@
22#define _RM_H 22#define _RM_H
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdint.h> 25#include <inttypes.h>
26 26
27enum codecs{cook};
27typedef struct rm_packet 28typedef struct rm_packet
28{ 29{
29 uint8_t data[30000]; /* Reordered data. No malloc, hence the size */
30 uint8_t *frames[100]; /* Pointers to ordered audio frames in buffer */ 30 uint8_t *frames[100]; /* Pointers to ordered audio frames in buffer */
31 uint16_t version; 31 uint16_t version;
32 uint16_t length; 32 uint16_t length;
33 uint32_t timestamp; 33 uint32_t timestamp;
34 uint16_t stream_number; 34 uint16_t stream_number;
35 uint8_t flags; 35 uint8_t flags;
36
37#ifdef TEST
38 uint8_t data[30000]; /* Reordered data. No malloc, hence the size */
39#endif
36}RMPacket; 40}RMPacket;
37 41
38typedef struct rm_context 42typedef struct rm_context
@@ -46,6 +50,7 @@ typedef struct rm_context
46 50
47 /* Stream Variables */ 51 /* Stream Variables */
48 uint32_t data_offset; 52 uint32_t data_offset;
53 uint32_t duration;
49 uint32_t audiotimestamp; /* Audio packet timestamp*/ 54 uint32_t audiotimestamp; /* Audio packet timestamp*/
50 uint16_t sub_packet_cnt; /* Subpacket counter, used while reading */ 55 uint16_t sub_packet_cnt; /* Subpacket counter, used while reading */
51 uint16_t sub_packet_size, sub_packet_h, coded_framesize; /* Descrambling parameters from container */ 56 uint16_t sub_packet_size, sub_packet_h, coded_framesize; /* Descrambling parameters from container */
@@ -53,6 +58,7 @@ typedef struct rm_context
53 uint16_t sub_packet_lengths[16]; /* Length of each subpacket */ 58 uint16_t sub_packet_lengths[16]; /* Length of each subpacket */
54 59
55 /* Codec Context */ 60 /* Codec Context */
61 enum codecs codec_type;
56 uint16_t block_align; 62 uint16_t block_align;
57 uint32_t nb_packets; 63 uint32_t nb_packets;
58 int frame_number; 64 int frame_number;
@@ -66,18 +72,26 @@ typedef struct rm_context
66 uint32_t cook_version; 72 uint32_t cook_version;
67 uint16_t samples_pf_pc; /* samples per frame per channel */ 73 uint16_t samples_pf_pc; /* samples per frame per channel */
68 uint16_t nb_subbands; /* number of subbands in the frequency domain */ 74 uint16_t nb_subbands; /* number of subbands in the frequency domain */
69 /* extra 8 bytes for stereo data */ 75 /* extra 8 bytes for joint-stereo data */
70 uint32_t unused; 76 uint32_t unused;
71 uint16_t js_subband_start; /* joint stereo subband start */ 77 uint16_t js_subband_start; /* joint stereo subband start */
72 uint16_t js_vlc_bits; 78 uint16_t js_vlc_bits;
73 79
74} RMContext; 80} RMContext;
75 81
76int open_wav(char* filename);
77void close_wav(int fd, RMContext *rmctx);
78int real_parse_header(int fd, RMContext *rmctx); 82int real_parse_header(int fd, RMContext *rmctx);
79void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt); 83
80void rm_get_packet_membuf(uint8_t **filebuf,RMContext *rmctx, RMPacket *pkt); 84/* Get a (sub_packet_h*frames_per_packet) number of audio frames from a memory buffer */
81off_t filesize(int fd); 85int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt);
86
87#ifdef TEST
88
89int filesize(int fd);
82void advance_buffer(uint8_t **buf, int val); 90void advance_buffer(uint8_t **buf, int val);
83#endif 91
92/* Get a (sub_packet_h*frames_per_packet) number of audio frames from a file descriptor */
93void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt);
94
95#endif /* TEST */
96
97#endif /* _RM_H */
diff --git a/apps/filetypes.c b/apps/filetypes.c
index 680ca57727..1772cac7ee 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -83,6 +83,8 @@ static const struct filetype inbuilt_filetypes[] = {
83 { "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 83 { "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
84 { "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 84 { "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
85 { "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 85 { "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
86 { "rm", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
87 { "ra", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
86#endif 88#endif
87 { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 89 { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
88 { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 90 { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
diff --git a/apps/metadata.c b/apps/metadata.c
index 0892fc65fd..6003e1977e 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -115,6 +115,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
115 /* Amiga SAP File */ 115 /* Amiga SAP File */
116 [AFMT_SAP] = 116 [AFMT_SAP] =
117 AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ), 117 AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ),
118 /* Cook in RM/RA */
119 [AFMT_COOK] =
120 AFMT_ENTRY("Cook", "cook", NULL, "rm\0ra\0" ),
118#endif 121#endif
119}; 122};
120 123
@@ -372,6 +375,14 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
372 id3->filesize = filesize(fd); 375 id3->filesize = filesize(fd);
373 id3->genre_string = id3_get_num_genre(36); 376 id3->genre_string = id3_get_num_genre(36);
374 break; 377 break;
378
379 case AFMT_COOK:
380 if (!get_rm_metadata(fd, id3))
381 {
382 DEBUGF("get_rm_metadata error\n");
383 return false;
384 }
385 break;
375 386
376#endif /* CONFIG_CODEC == SWCODEC */ 387#endif /* CONFIG_CODEC == SWCODEC */
377 388
diff --git a/apps/metadata.h b/apps/metadata.h
index 55a5907731..6c0201781a 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -61,6 +61,7 @@ enum
61 AFMT_WMA, /* WMAV1/V2 in ASF */ 61 AFMT_WMA, /* WMAV1/V2 in ASF */
62 AFMT_MOD, /* Amiga MOD File Format */ 62 AFMT_MOD, /* Amiga MOD File Format */
63 AFMT_SAP, /* Amiga 8Bit SAP Format */ 63 AFMT_SAP, /* Amiga 8Bit SAP Format */
64 AFMT_COOK, /* Cook in RM/RA */
64#endif 65#endif
65 66
66 /* add new formats at any index above this line to have a sensible order - 67 /* add new formats at any index above this line to have a sensible order -
diff --git a/apps/metadata/metadata_parsers.h b/apps/metadata/metadata_parsers.h
index 1521f1301d..760d9a0da3 100644
--- a/apps/metadata/metadata_parsers.h
+++ b/apps/metadata/metadata_parsers.h
@@ -39,3 +39,4 @@ bool get_wavpack_metadata(int fd, struct mp3entry* id3);
39bool get_a52_metadata(int fd, struct mp3entry* id3); 39bool get_a52_metadata(int fd, struct mp3entry* id3);
40bool get_asf_metadata(int fd, struct mp3entry* id3); 40bool get_asf_metadata(int fd, struct mp3entry* id3);
41bool get_asap_metadata(int fd, struct mp3entry* id3); 41bool get_asap_metadata(int fd, struct mp3entry* id3);
42bool get_rm_metadata(int fd, struct mp3entry* id3);
diff --git a/apps/metadata/rm.c b/apps/metadata/rm.c
new file mode 100644
index 0000000000..4fefdeb00d
--- /dev/null
+++ b/apps/metadata/rm.c
@@ -0,0 +1,420 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
9 *
10 * Copyright (C) 2009 Mohamed Tarek
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <inttypes.h>
26
27#include <codecs/librm/rm.h>
28#include "system.h"
29#include "metadata.h"
30#include "metadata_common.h"
31#include "metadata_parsers.h"
32#include "logf.h"
33
34//#define DEBUG_RM
35#ifndef DEBUG_RM
36#undef DEBUGF
37#define DEBUGF(...)
38#endif
39
40static inline int read_cook_extradata(int fd, RMContext *rmctx) {
41 read_uint32be(fd, &rmctx->cook_version);
42 read_uint16be(fd, &rmctx->samples_pf_pc);
43 read_uint16be(fd, &rmctx->nb_subbands);
44 if(rmctx->extradata_size == 16) {
45 lseek(fd, sizeof(uint32_t), SEEK_CUR); /* reserved */
46 read_uint16be(fd, &rmctx->js_subband_start);
47 read_uint16be(fd, &rmctx->js_vlc_bits);
48 }
49 return rmctx->extradata_size; /* for 'skipped' */
50}
51
52static inline void print_cook_extradata(RMContext *rmctx) {
53
54 DEBUGF(" cook_version = 0x%08lx\n", rmctx->cook_version);
55 DEBUGF(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc);
56 DEBUGF(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands);
57 if(rmctx->extradata_size == 16) {
58 DEBUGF(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start);
59 DEBUGF(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits);
60 }
61}
62
63
64struct real_object_t
65{
66 uint32_t fourcc;
67 uint32_t size;
68 uint16_t version;
69};
70
71#define FOURCC(a,b,c,d) (((a)<<24) | ((b) << 16) | ((c) << 8) | (d))
72
73static int real_read_object_header(int fd, struct real_object_t* obj)
74{
75 int n;
76
77 if ((n = read_uint32be(fd, &obj->fourcc)) <= 0) return n;
78 if ((n = read_uint32be(fd, &obj->size)) <= 0) return n;
79 if ((n = read_uint16be(fd, &obj->version)) <= 0) return n;
80
81 return 1;
82}
83
84#if (defined(SIMULATOR) && defined(DEBUG_RM))
85static char* fourcc2str(uint32_t f)
86{
87 static char res[5];
88
89 res[0] = (f & 0xff000000) >> 24;
90 res[1] = (f & 0xff0000) >> 16;
91 res[2] = (f & 0xff00) >> 8;
92 res[3] = (f & 0xff);
93 res[4] = 0;
94
95 return res;
96}
97#endif
98
99static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
100{
101 int skipped = 0;
102 uint32_t version;
103 struct real_object_t obj;
104#ifdef SIMULATOR
105 uint32_t header_size;
106 uint16_t flavor;
107 uint32_t coded_framesize;
108 uint8_t interleaver_id_length;
109 uint8_t fourcc_length;
110#endif
111 uint32_t interleaver_id;
112 uint32_t fourcc = 0;
113
114 memset(&obj,0,sizeof(obj));
115 read_uint32be(fd, &version);
116 skipped += 4;
117
118 DEBUGF(" version=0x%04lx\n",((version >> 16) & 0xff));
119 if (((version >> 16) & 0xff) == 3) {
120 /* Very old version */
121 } else {
122#ifdef SIMULATOR
123 real_read_object_header(fd, &obj);
124 read_uint32be(fd, &header_size);
125 /* obj.size will be filled with an unknown value, replaced with header_size */
126 DEBUGF(" Object: %s, size: %ld bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version);
127
128 read_uint16be(fd, &flavor);
129 read_uint32be(fd, &coded_framesize);
130#else
131 lseek(fd, 20, SEEK_CUR);
132#endif
133 lseek(fd, 12, SEEK_CUR); /* unknown */
134 read_uint16be(fd, &rmctx->sub_packet_h);
135 read_uint16be(fd, &rmctx->block_align);
136 read_uint16be(fd, &rmctx->sub_packet_size);
137 lseek(fd, 2, SEEK_CUR); /* unknown */
138 skipped += 40;
139 if (((version >> 16) & 0xff) == 5)
140 {
141 lseek(fd, 6, SEEK_CUR); /* unknown */
142 skipped += 6;
143 }
144 read_uint16be(fd, &rmctx->sample_rate);
145 lseek(fd, 4, SEEK_CUR); /* unknown */
146 read_uint16be(fd, &rmctx->nb_channels);
147 skipped += 8;
148 if (((version >> 16) & 0xff) == 4)
149 {
150#ifdef SIMULATOR
151 read_uint8(fd, &interleaver_id_length);
152 read_uint32be(fd, &interleaver_id);
153 read_uint8(fd, &fourcc_length);
154#else
155 lseek(fd, 6, SEEK_CUR);
156#endif
157 read_uint32be(fd, &fourcc);
158 skipped += 10;
159 }
160 if (((version >> 16) & 0xff) == 5)
161 {
162 read_uint32be(fd, &interleaver_id);
163 read_uint32be(fd, &fourcc);
164 skipped += 8;
165 }
166 lseek(fd, 3, SEEK_CUR); /* unknown */
167 skipped += 3;
168 if (((version >> 16) & 0xff) == 5)
169 {
170 lseek(fd, 1, SEEK_CUR); /* unknown */
171 skipped += 1;
172 }
173
174 read_uint32be(fd, &rmctx->extradata_size);
175 skipped += 4;
176 /*if(!strncmp(fourcc2str(fourcc),"cook",4)){
177 skipped += read_cook_extradata(fd, rmctx);
178 rmctx->codec_type = cook;
179 }*/
180 switch(fourcc) {
181 case FOURCC('c','o','o','k'):
182 skipped += read_cook_extradata(fd, rmctx);
183 rmctx->codec_type = cook;
184 break;
185
186 default: /* Not a supported codec */
187 return -1;
188 }
189
190 DEBUGF(" flavor = %d\n",flavor);
191 DEBUGF(" coded_frame_size = %ld\n",coded_framesize);
192 DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h);
193 DEBUGF(" frame_size = %d\n",rmctx->block_align);
194 DEBUGF(" sub_packet_size = %d\n",rmctx->sub_packet_size);
195 DEBUGF(" sample_rate= %d\n",rmctx->sample_rate);
196 DEBUGF(" channels= %d\n",rmctx->nb_channels);
197 DEBUGF(" fourcc = %s\n",fourcc2str(fourcc));
198 DEBUGF(" codec_extra_data_length = %ld\n",rmctx->extradata_size);
199 DEBUGF(" codec_extradata :\n");
200 print_cook_extradata(rmctx);
201
202 }
203
204 return skipped;
205}
206
207static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
208{
209 struct real_object_t obj;
210 int res;
211 int skipped;
212 off_t curpos;
213 uint8_t len; /* Holds a string_length, which is then passed to read_string() */
214
215#ifdef SIMULATOR
216 uint32_t avg_bitrate = 0;
217 uint32_t max_packet_size;
218 uint32_t avg_packet_size;
219 uint32_t packet_count;
220 uint32_t duration;
221 uint32_t preroll;
222 uint32_t index_offset;
223 uint16_t stream_id;
224 uint32_t start_time;
225 uint32_t codec_data_size;
226#endif
227 uint32_t v;
228 uint32_t max_bitrate;
229 uint16_t num_streams;
230 uint32_t next_data_off;
231 uint8_t header_end;
232
233 memset(&obj,0,sizeof(obj));
234 curpos = lseek(fd, 0, SEEK_SET);
235 res = real_read_object_header(fd, &obj);
236
237 if (obj.fourcc == FOURCC('.','r','a',0xfd))
238 {
239 /* Very old .ra format - not yet supported */
240 return -1;
241 }
242 else if (obj.fourcc != FOURCC('.','R','M','F'))
243 {
244 return -1;
245 }
246
247 lseek(fd, 8, SEEK_CUR); /* unknown */
248
249 DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
250
251 res = real_read_object_header(fd, &obj);
252 header_end = 0;
253 while(res)
254 {
255 DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
256 skipped = 10;
257 if(obj.fourcc == FOURCC('I','N','D','X'))
258 break;
259 switch (obj.fourcc)
260 {
261 case FOURCC('P','R','O','P'): /* File properties */
262 read_uint32be(fd, &max_bitrate);
263 read_uint32be(fd, &rmctx->bit_rate); /*avg bitrate*/
264#ifdef SIMULATOR
265 read_uint32be(fd, &max_packet_size);
266 read_uint32be(fd, &avg_packet_size);
267 read_uint32be(fd, &packet_count);
268#else
269 lseek(fd, 3*sizeof(uint32_t), SEEK_CUR);
270#endif
271 read_uint32be(fd, &rmctx->duration);
272#ifdef SIMULATOR
273 read_uint32be(fd, &preroll);
274 read_uint32be(fd, &index_offset);
275#else
276 lseek(fd, 2*sizeof(uint32_t), SEEK_CUR);
277#endif
278 read_uint32be(fd, &rmctx->data_offset);
279 read_uint16be(fd, &num_streams);
280 read_uint16be(fd, &rmctx->flags);
281 skipped += 40;
282
283 DEBUGF(" max_bitrate = %ld\n",max_bitrate);
284 DEBUGF(" avg_bitrate = %ld\n",rmctx->bit_Rate);
285 DEBUGF(" max_packet_size = %ld\n",max_packet_size);
286 DEBUGF(" avg_packet_size = %ld\n",avg_packet_size);
287 DEBUGF(" packet_count = %ld\n",packet_count);
288 DEBUGF(" duration = %ld\n",rmctx->duration);
289 DEBUGF(" preroll = %ld\n",preroll);
290 DEBUGF(" index_offset = %ld\n",index_offset);
291 DEBUGF(" data_offset = %ld\n",rmctx->data_offset);
292 DEBUGF(" num_streams = %d\n",num_streams);
293 DEBUGF(" flags=0x%04x\n",rmctx->flags);
294 break;
295
296 case FOURCC('C','O','N','T'):
297 /* Four strings - Title, Author, Copyright, Comment */
298 read_uint8(fd,&len);
299 skipped += (int)read_string(fd, id3->id3v1buf[0], sizeof(id3->id3v1buf[0]), '\0', len);
300 read_uint8(fd,&len);
301 skipped += (int)read_string(fd, id3->id3v1buf[1], sizeof(id3->id3v1buf[1]), '\0', len);
302 read_uint8(fd,&len);
303 skipped += (int)read_string(fd, id3->id3v1buf[2], sizeof(id3->id3v1buf[2]), '\0', len);
304 read_uint8(fd,&len);
305 skipped += (int)read_string(fd, id3->id3v1buf[3], sizeof(id3->id3v1buf[3]), '\0', len);
306 skipped += 4;
307
308 DEBUGF(" title=\"%s\"\n",id3->id3v1buf[0]);
309 DEBUGF(" author=\"%s\"\n",id3->id3v1buf[1]);
310 DEBUGF(" copyright=\"%s\"\n",id3->id3v1buf[2]);
311 DEBUGF(" comment=\"%s\"\n",id3->id3v1buf[3]);
312 break;
313
314 case FOURCC('M','D','P','R'): /* Media properties */
315#ifdef SIMULATOR
316 read_uint16be(fd,&stream_id);
317 read_uint32be(fd,&max_bitrate);
318 read_uint32be(fd,&avg_bitrate);
319 read_uint32be(fd,&max_packet_size);
320 read_uint32be(fd,&avg_packet_size);
321 read_uint32be(fd,&start_time);
322 read_uint32be(fd,&preroll);
323 read_uint32be(fd,&duration);
324#else
325 lseek(fd, 30, SEEK_CUR);
326#endif
327 skipped += 30;
328 read_uint8(fd,&len);
329 skipped += 1;
330 lseek(fd, len, SEEK_CUR); /* desc */
331 skipped += len;
332 read_uint8(fd,&len);
333 skipped += 1;
334#ifdef SIMULATOR
335 lseek(fd, len, SEEK_CUR); /* mimetype */
336 read_uint32be(fd,&codec_data_size);
337#else
338 lseek(fd, len + 4, SEEK_CUR);
339#endif
340 skipped += len + 4;
341 //From ffmpeg: codec_pos = url_ftell(pb);
342 read_uint32be(fd,&v);
343 skipped += 4;
344
345 DEBUGF(" stream_id = 0x%04x\n",stream_id);
346 DEBUGF(" max_bitrate = %ld\n",max_bitrate);
347 DEBUGF(" avg_bitrate = %ld\n",avg_bitrate);
348 DEBUGF(" max_packet_size = %ld\n",max_packet_size);
349 DEBUGF(" avg_packet_size = %ld\n",avg_packet_size);
350 DEBUGF(" start_time = %ld\n",start_time);
351 DEBUGF(" preroll = %ld\n",preroll);
352 DEBUGF(" duration = %ld\n",duration);
353 DEBUGF(" codec_data_size = %ld\n",codec_data_size);
354 DEBUGF(" v=\"%s\"\n", fourcc2str(v));
355
356 if (v == FOURCC('.','r','a',0xfd))
357 {
358 skipped += real_read_audio_stream_info(fd, rmctx);
359 if(skipped < 0)
360 return -1;
361 }
362
363 break;
364
365 case FOURCC('D','A','T','A'):
366 read_uint32be(fd,&rmctx->nb_packets);
367 skipped += 4;
368 read_uint32be(fd,&next_data_off);
369 skipped += 4;
370
371 /***
372 * nb_packets correction :
373 * in some samples, number of packets may not exactly form
374 * an integer number of scrambling units. This is corrected
375 * by constructing a partially filled unit out of the few
376 * remaining samples at the end of decoding.
377 ***/
378 if(rmctx->nb_packets % rmctx->sub_packet_h)
379 rmctx->nb_packets += rmctx->sub_packet_h - (rmctx->nb_packets % rmctx->sub_packet_h);
380
381 DEBUGF(" data_nb_packets = %ld\n",rmctx->nb_packets);
382 DEBUGF(" next DATA offset = %ld\n",next_data_off);
383 header_end = 1;
384 break;
385 }
386 if(header_end) break;
387 curpos = lseek(fd, obj.size - skipped, SEEK_CUR);
388 res = real_read_object_header(fd, &obj);
389 }
390
391
392 return 0;
393}
394
395
396bool get_rm_metadata(int fd, struct mp3entry* id3)
397{
398 RMContext *rmctx = (RMContext*)id3->id3v2buf;
399 memset(rmctx,0,sizeof(RMContext));
400 if(rm_parse_header(fd, rmctx, id3) < 0)
401 return false;
402
403 /* Copy tags */
404 id3->title = id3->id3v1buf[0];
405 id3->artist = id3->id3v1buf[1];
406 id3->comment = id3->id3v1buf[3];
407
408 /*switch(rmctx->codec_type)
409 {
410 case cook:
411 id3->codectype = AFMT_COOK;
412 break;
413 }*/
414
415 id3->bitrate = rmctx->bit_rate / 1000;
416 id3->frequency = rmctx->sample_rate;
417 id3->length = rmctx->duration;
418 id3->filesize = filesize(fd);
419 return true;
420}