summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2009-05-09 01:21:49 +0000
committerDave Chapman <dave@dchapman.com>2009-05-09 01:21:49 +0000
commit67695617a13e9f37f17e3718b03046f6d748a9e1 (patch)
tree7e8a8b5fb8d4222e3286f3300bcf12ad439424b0
parent69db01e72f2de91d35703919bfc9d0700df83e85 (diff)
downloadrockbox-67695617a13e9f37f17e3718b03046f6d748a9e1.tar.gz
rockbox-67695617a13e9f37f17e3718b03046f6d748a9e1.zip
The first part of Mohamed Tarek's Google Summer of Code work to implement RealAudio support in Rockbox. This is a self-contained Cook decoder using the original ffmpeg (still floating point) decoder and a new RM parser started by me in 2008 and continued by MT over the past few months. This is the equivalent of libcook.patch1 from FS#10182, but with further cleaning by both MT and me to minimise the differences to the original ffmpeg files. See README.rockbox for more details.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20883 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/libcook/Makefile.test10
-rw-r--r--apps/codecs/libcook/README.rockbox40
-rw-r--r--apps/codecs/libcook/avcodec.h3
-rw-r--r--apps/codecs/libcook/bitstream.c2
-rw-r--r--apps/codecs/libcook/bitstream.h4
-rw-r--r--apps/codecs/libcook/cook.c264
-rw-r--r--apps/codecs/libcook/dsputil.h10
-rw-r--r--apps/codecs/libcook/ffmpeg_config.h14
-rw-r--r--apps/codecs/libcook/libavutil/avutil.h8
-rw-r--r--apps/codecs/libcook/libavutil/bswap.h2
-rw-r--r--apps/codecs/libcook/libavutil/common.h6
-rw-r--r--apps/codecs/libcook/libavutil/internal.h12
-rw-r--r--apps/codecs/libcook/libavutil/intreadwrite.h2
-rw-r--r--apps/codecs/libcook/libavutil/mem.c1
-rw-r--r--apps/codecs/libcook/rm2wav.c584
-rw-r--r--apps/codecs/libcook/rm2wav.h74
16 files changed, 925 insertions, 111 deletions
diff --git a/apps/codecs/libcook/Makefile.test b/apps/codecs/libcook/Makefile.test
new file mode 100644
index 0000000000..98ee7ffcb4
--- /dev/null
+++ b/apps/codecs/libcook/Makefile.test
@@ -0,0 +1,10 @@
1CFLAGS = -Wall -O3
2OBJS = bitstream.o cook.o fft.o libavutil/log.o mdct.o libavutil/mem.o libavutil/lfg.o libavutil/md5.o rm2wav.o
3cooktest: $(OBJS)
4 gcc -o cooktest $(OBJS) -lm
5
6.c.o :
7 $(CC) $(CFLAGS) -c -o $@ $<
8
9clean:
10 rm -f cooktest $(OBJS) *~
diff --git a/apps/codecs/libcook/README.rockbox b/apps/codecs/libcook/README.rockbox
new file mode 100644
index 0000000000..9447b96be5
--- /dev/null
+++ b/apps/codecs/libcook/README.rockbox
@@ -0,0 +1,40 @@
1Library: libcook
2Imported by : Mohamed Tarek
3
4These files comprise a rm parser and a cook decoder based on the decoder
5from ffmpeg.
6
7LICENSING INFORMATION
8
9ffmpeg is licensed under the Lesser GNU General Public License and the
10file cook.c is Copyright 2003 Sascha Sommer and 2005 Benjamin Larsson.
11
12IMPORT DETAILS
13
14The decoder is based on ffmpeg-svn r18079.
15
16The file libavcodec/cook.c was modified to remove all ffmpeg-specific
17code and to use the current rm parser.
18
19In initializing random_state in COOKContext, ffmpeg used a random_seed()
20function that was weird in the way it gets the random number. So it was
21decided to not use this function at all,and the value was initialized to 1,
22because according to Benjamin Larsson random_seed() could just be
23replaced by any value.
24
25The current files contain lots of code which is either not needed by
26the decoder or totally disabled (#if 0 .. #endif) to enable
27compiling. This was during the isolation of the decoder from ffmpeg,
28the intention was to take as few files as possible to be able to
29compile cook.c and the related files outside ffmpeg.
30
31The decoder still uses floating point and relies on dynamic allocations
32in some parts of it. It's still not ready to be ported to rockbox.
33
34TESTING
35
36The test program should compile in any Unix-like environment using the
37command "make -f Makefile.test".
38
39Running "./cooktest file.rm" will decode the audio data to a WAV file
40called "output.wav" in the current directory.
diff --git a/apps/codecs/libcook/avcodec.h b/apps/codecs/libcook/avcodec.h
index a520340162..08eb800d4b 100644
--- a/apps/codecs/libcook/avcodec.h
+++ b/apps/codecs/libcook/avcodec.h
@@ -406,6 +406,7 @@ enum SampleFormat {
406#define FF_MIN_BUFFER_SIZE 16384 406#define FF_MIN_BUFFER_SIZE 16384
407 407
408 408
409#if 0/* MT : DELETE THIS LINE.*/
409/** 410/**
410 * motion estimation type. 411 * motion estimation type.
411 */ 412 */
@@ -3429,4 +3430,6 @@ void av_register_hwaccel(AVHWAccel *hwaccel);
3429 */ 3430 */
3430AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel); 3431AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel);
3431 3432
3433#endif/* MT : DELETE THIS LINE.*/
3434
3432#endif /* AVCODEC_AVCODEC_H */ 3435#endif /* AVCODEC_AVCODEC_H */
diff --git a/apps/codecs/libcook/bitstream.c b/apps/codecs/libcook/bitstream.c
index 6781fe6cb0..f32e88fdbf 100644
--- a/apps/codecs/libcook/bitstream.c
+++ b/apps/codecs/libcook/bitstream.c
@@ -73,6 +73,7 @@ void ff_put_string(PutBitContext * pbc, const char *s, int put_zero)
73 put_bits(pbc, 8, 0); 73 put_bits(pbc, 8, 0);
74} 74}
75 75
76#if 0
76void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length) 77void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length)
77{ 78{
78 const uint16_t *srcw= (const uint16_t*)src; 79 const uint16_t *srcw= (const uint16_t*)src;
@@ -94,6 +95,7 @@ void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length)
94 95
95 put_bits(pb, bits, AV_RB16(&srcw[words])>>(16-bits)); 96 put_bits(pb, bits, AV_RB16(&srcw[words])>>(16-bits));
96} 97}
98#endif
97 99
98/* VLC decoding */ 100/* VLC decoding */
99 101
diff --git a/apps/codecs/libcook/bitstream.h b/apps/codecs/libcook/bitstream.h
index 3670285904..e3e3d77595 100644
--- a/apps/codecs/libcook/bitstream.h
+++ b/apps/codecs/libcook/bitstream.h
@@ -33,7 +33,7 @@
33#include "libavutil/common.h" 33#include "libavutil/common.h"
34#include "libavutil/intreadwrite.h" 34#include "libavutil/intreadwrite.h"
35#include "libavutil/log.h" 35#include "libavutil/log.h"
36#include "mathops.h" 36//#include "mathops.h"
37 37
38#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER) 38#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER)
39# define ALT_BITSTREAM_READER 39# define ALT_BITSTREAM_READER
@@ -707,12 +707,14 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n){
707 } 707 }
708} 708}
709 709
710#if 0
710/** 711/**
711 * reads 0-32 bits as a signed integer. 712 * reads 0-32 bits as a signed integer.
712 */ 713 */
713static inline int get_sbits_long(GetBitContext *s, int n) { 714static inline int get_sbits_long(GetBitContext *s, int n) {
714 return sign_extend(get_bits_long(s, n), n); 715 return sign_extend(get_bits_long(s, n), n);
715} 716}
717#endif
716 718
717/** 719/**
718 * shows 0-32 bits. 720 * shows 0-32 bits.
diff --git a/apps/codecs/libcook/cook.c b/apps/codecs/libcook/cook.c
index cee69fe14a..856004f31b 100644
--- a/apps/codecs/libcook/cook.c
+++ b/apps/codecs/libcook/cook.c
@@ -45,15 +45,30 @@
45#include <math.h> 45#include <math.h>
46#include <stddef.h> 46#include <stddef.h>
47#include <stdio.h> 47#include <stdio.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
48 52
49#include "libavutil/lfg.h" 53#include "libavutil/lfg.h"
50#include "libavutil/random_seed.h"
51#include "avcodec.h"
52#include "bitstream.h" 54#include "bitstream.h"
53#include "dsputil.h" 55#include "dsputil.h"
54#include "bytestream.h" 56#include "bytestream.h"
55 57
56#include "cookdata.h" 58#include "cookdata.h"
59#include "rm2wav.h"
60
61/* The following table is taken from libavutil/mathematics.c */
62const uint8_t ff_log2_tab[256]={
63 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
64 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
65 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
66 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
67 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
68 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
69 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
70 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
71};
57 72
58/* the different Cook versions */ 73/* the different Cook versions */
59#define MONO 0x1000001 74#define MONO 0x1000001
@@ -64,6 +79,8 @@
64#define SUBBAND_SIZE 20 79#define SUBBAND_SIZE 20
65#define MAX_SUBPACKETS 5 80#define MAX_SUBPACKETS 5
66//#define COOKDEBUG 81//#define COOKDEBUG
82//#define DUMP_RAW_FRAMES
83#define DEBUGF(message,args ...) av_log(NULL,AV_LOG_ERROR,message,## args)
67 84
68typedef struct { 85typedef struct {
69 int *now; 86 int *now;
@@ -93,8 +110,10 @@ typedef struct cook {
93 110
94 void (* saturate_output) (struct cook *q, int chan, int16_t *out); 111 void (* saturate_output) (struct cook *q, int chan, int16_t *out);
95 112
96 AVCodecContext* avctx;
97 GetBitContext gb; 113 GetBitContext gb;
114 int frame_number;
115 int block_align;
116 int extradata_size;
98 /* stream data */ 117 /* stream data */
99 int nb_channels; 118 int nb_channels;
100 int joint_stereo; 119 int joint_stereo;
@@ -112,7 +131,6 @@ typedef struct cook {
112 int cookversion; 131 int cookversion;
113 /* states */ 132 /* states */
114 AVLFG random_state; 133 AVLFG random_state;
115
116 /* transform data */ 134 /* transform data */
117 MDCTContext mdct_ctx; 135 MDCTContext mdct_ctx;
118 float* mlt_window; 136 float* mlt_window;
@@ -138,7 +156,7 @@ typedef struct cook {
138 /* data buffers */ 156 /* data buffers */
139 157
140 uint8_t* decoded_bytes_buffer; 158 uint8_t* decoded_bytes_buffer;
141 DECLARE_ALIGNED_16(float,mono_mdct_output[2048]); 159 float mono_mdct_output[2048] __attribute__ ((aligned(16))); //DECLARE_ALIGNED_16(float,mono_mdct_output[2048]);
142 float mono_previous_buffer1[1024]; 160 float mono_previous_buffer1[1024];
143 float mono_previous_buffer2[1024]; 161 float mono_previous_buffer2[1024];
144 float decode_buffer_1[1024]; 162 float decode_buffer_1[1024];
@@ -214,7 +232,7 @@ static av_cold int init_cook_vlc_tables(COOKContext *q) {
214 envelope_quant_index_huffbits[i], 1, 1, 232 envelope_quant_index_huffbits[i], 1, 1,
215 envelope_quant_index_huffcodes[i], 2, 2, 0); 233 envelope_quant_index_huffcodes[i], 2, 2, 0);
216 } 234 }
217 av_log(q->avctx,AV_LOG_DEBUG,"sqvh VLC init\n"); 235 av_log(NULL,AV_LOG_DEBUG,"sqvh VLC init\n");
218 for (i=0 ; i<7 ; i++) { 236 for (i=0 ; i<7 ; i++) {
219 result |= init_vlc (&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], 237 result |= init_vlc (&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i],
220 cvh_huffbits[i], 1, 1, 238 cvh_huffbits[i], 1, 1,
@@ -225,10 +243,10 @@ static av_cold int init_cook_vlc_tables(COOKContext *q) {
225 result |= init_vlc (&q->ccpl, 6, (1<<q->js_vlc_bits)-1, 243 result |= init_vlc (&q->ccpl, 6, (1<<q->js_vlc_bits)-1,
226 ccpl_huffbits[q->js_vlc_bits-2], 1, 1, 244 ccpl_huffbits[q->js_vlc_bits-2], 1, 1,
227 ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0); 245 ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0);
228 av_log(q->avctx,AV_LOG_DEBUG,"Joint-stereo VLC used.\n"); 246 av_log(NULL,AV_LOG_DEBUG,"Joint-stereo VLC used.\n");
229 } 247 }
230 248
231 av_log(q->avctx,AV_LOG_DEBUG,"VLC tables initialized.\n"); 249 av_log(NULL,AV_LOG_ERROR,"VLC tables initialized. Result = %d\n",result);
232 return result; 250 return result;
233} 251}
234 252
@@ -249,8 +267,8 @@ static av_cold int init_cook_mlt(COOKContext *q) {
249 av_free(q->mlt_window); 267 av_free(q->mlt_window);
250 return -1; 268 return -1;
251 } 269 }
252 av_log(q->avctx,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n", 270 av_log(NULL,AV_LOG_ERROR,"MDCT initialized, order = %d. mlt_window = %d\n",
253 av_log2(mlt_size)+1); 271 av_log2(mlt_size)+1,sizeof(q->mlt_window)*mlt_size);
254 272
255 return 0; 273 return 0;
256} 274}
@@ -317,11 +335,11 @@ static inline int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes)
317 * Cook uninit 335 * Cook uninit
318 */ 336 */
319 337
320static av_cold int cook_decode_close(AVCodecContext *avctx) 338static av_cold int cook_decode_close(COOKContext *q)
321{ 339{
322 int i; 340 int i;
323 COOKContext *q = avctx->priv_data; 341 //COOKContext *q = avctx->priv_data;
324 av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n"); 342 av_log(NULL,AV_LOG_ERROR, "Deallocating memory.\n");
325 343
326 /* Free allocated memory buffers. */ 344 /* Free allocated memory buffers. */
327 av_free(q->mlt_window); 345 av_free(q->mlt_window);
@@ -341,7 +359,7 @@ static av_cold int cook_decode_close(AVCodecContext *avctx)
341 free_vlc(&q->ccpl); 359 free_vlc(&q->ccpl);
342 } 360 }
343 361
344 av_log(avctx,AV_LOG_DEBUG,"Memory deallocated.\n"); 362 av_log(NULL,AV_LOG_ERROR,"Memory deallocated.\n");
345 363
346 return 0; 364 return 0;
347} 365}
@@ -864,6 +882,8 @@ static void joint_decode(COOKContext *q, float* mlt_buffer1,
864 * @param gain_ptr array of current/prev gain pointers 882 * @param gain_ptr array of current/prev gain pointers
865 */ 883 */
866 884
885#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
886
867static inline void 887static inline void
868decode_bytes_and_gain(COOKContext *q, const uint8_t *inbuffer, 888decode_bytes_and_gain(COOKContext *q, const uint8_t *inbuffer,
869 cook_gains *gains_ptr) 889 cook_gains *gains_ptr)
@@ -938,9 +958,9 @@ static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer,
938 int sub_packet_size, int16_t *outbuffer) { 958 int sub_packet_size, int16_t *outbuffer) {
939 /* packet dump */ 959 /* packet dump */
940// for (i=0 ; i<sub_packet_size ; i++) { 960// for (i=0 ; i<sub_packet_size ; i++) {
941// av_log(q->avctx, AV_LOG_ERROR, "%02x", inbuffer[i]); 961// av_log(NULL, AV_LOG_ERROR, "%02x", inbuffer[i]);
942// } 962// }
943// av_log(q->avctx, AV_LOG_ERROR, "\n"); 963// av_log(NULL, AV_LOG_ERROR, "\n");
944 964
945 decode_bytes_and_gain(q, inbuffer, &q->gains1); 965 decode_bytes_and_gain(q, inbuffer, &q->gains1);
946 966
@@ -974,37 +994,37 @@ static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer,
974/** 994/**
975 * Cook frame decoding 995 * Cook frame decoding
976 * 996 *
977 * @param avctx pointer to the AVCodecContext 997 * @param rmctx pointer to the RMContext
978 */ 998 */
979 999
980static int cook_decode_frame(AVCodecContext *avctx, 1000static int cook_decode_frame(RMContext *rmctx,COOKContext *q,
981 void *data, int *data_size, 1001 int16_t *outbuffer, int *data_size,
982 const uint8_t *buf, int buf_size) { 1002 const uint8_t *inbuffer, int buf_size) {
983 COOKContext *q = avctx->priv_data; 1003 //COOKContext *q = avctx->priv_data;
1004 //COOKContext *q;
984 1005
985 if (buf_size < avctx->block_align) 1006 if (buf_size < rmctx->block_align)
986 return buf_size; 1007 return buf_size;
987 1008
988 *data_size = decode_subpacket(q, buf, avctx->block_align, data); 1009 *data_size = decode_subpacket(q, inbuffer, rmctx->block_align, outbuffer);
989 1010
990 /* Discard the first two frames: no valid audio. */ 1011 /* Discard the first two frames: no valid audio. */
991 if (avctx->frame_number < 2) *data_size = 0; 1012 if (rmctx->frame_number < 2) *data_size = 0;
992 1013
993 return avctx->block_align; 1014 return rmctx->block_align;
994} 1015}
995 1016
996#ifdef COOKDEBUG 1017#ifdef COOKDEBUG
997static void dump_cook_context(COOKContext *q) 1018static void dump_cook_context(COOKContext *q)
998{ 1019{
999 //int i=0; 1020 //int i=0;
1000#define PRINT(a,b) av_log(q->avctx,AV_LOG_ERROR," %s = %d\n", a, b); 1021#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b);
1001 av_log(q->avctx,AV_LOG_ERROR,"COOKextradata\n"); 1022 av_log(NULL,AV_LOG_ERROR,"COOKextradata\n");
1002 av_log(q->avctx,AV_LOG_ERROR,"cookversion=%x\n",q->cookversion); 1023 av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",q->cookversion);
1003 if (q->cookversion > STEREO) { 1024 if (q->cookversion > STEREO) {
1004 PRINT("js_subband_start",q->js_subband_start); 1025 PRINT("js_subband_start",q->js_subband_start);
1005 PRINT("js_vlc_bits",q->js_vlc_bits); 1026 PRINT("js_vlc_bits",q->js_vlc_bits);
1006 } 1027 }
1007 av_log(q->avctx,AV_LOG_ERROR,"COOKContext\n");
1008 PRINT("nb_channels",q->nb_channels); 1028 PRINT("nb_channels",q->nb_channels);
1009 PRINT("bit_rate",q->bit_rate); 1029 PRINT("bit_rate",q->bit_rate);
1010 PRINT("sample_rate",q->sample_rate); 1030 PRINT("sample_rate",q->sample_rate);
@@ -1031,76 +1051,60 @@ static av_cold int cook_count_channels(unsigned int mask){
1031 1051
1032/** 1052/**
1033 * Cook initialization 1053 * Cook initialization
1034 *
1035 * @param avctx pointer to the AVCodecContext
1036 */ 1054 */
1037 1055
1038static av_cold int cook_decode_init(AVCodecContext *avctx) 1056static av_cold int cook_decode_init(RMContext *rmctx, COOKContext *q)
1039{ 1057{
1040 COOKContext *q = avctx->priv_data; 1058 /* cook extradata */
1041 const uint8_t *edata_ptr = avctx->extradata; 1059 q->cookversion = rmctx->cook_version;
1042 q->avctx = avctx; 1060 q->samples_per_frame = rmctx->samples_pf_pc;
1043 1061 q->subbands = rmctx->nb_subbands;
1044 /* Take care of the codec specific extradata. */ 1062 q->extradata_size = rmctx->extradata_size;
1045 if (avctx->extradata_size <= 0) { 1063 if (q->extradata_size >= 16){
1046 av_log(avctx,AV_LOG_ERROR,"Necessary extradata missing!\n"); 1064 q->js_subband_start = rmctx->js_subband_start;
1047 return -1; 1065 q->js_vlc_bits = rmctx->js_vlc_bits;
1048 } else {
1049 /* 8 for mono, 16 for stereo, ? for multichannel
1050 Swap to right endianness so we don't need to care later on. */
1051 av_log(avctx,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size);
1052 if (avctx->extradata_size >= 8){
1053 q->cookversion = bytestream_get_be32(&edata_ptr);
1054 q->samples_per_frame = bytestream_get_be16(&edata_ptr);
1055 q->subbands = bytestream_get_be16(&edata_ptr);
1056 }
1057 if (avctx->extradata_size >= 16){
1058 bytestream_get_be32(&edata_ptr); //Unknown unused
1059 q->js_subband_start = bytestream_get_be16(&edata_ptr);
1060 q->js_vlc_bits = bytestream_get_be16(&edata_ptr);
1061 }
1062 } 1066 }
1063 1067
1064 /* Take data from the AVCodecContext (RM container). */ 1068 /* Take data from the RMContext (RM container). */
1065 q->sample_rate = avctx->sample_rate; 1069 q->sample_rate = rmctx->sample_rate;
1066 q->nb_channels = avctx->channels; 1070 q->nb_channels = rmctx->nb_channels;
1067 q->bit_rate = avctx->bit_rate; 1071 q->bit_rate = rmctx->bit_rate;
1068 1072
1069 /* Initialize RNG. */ 1073 /* Initialize RNG. */
1070 av_lfg_init(&q->random_state, ff_random_get_seed()); 1074 av_lfg_init(&q->random_state, 1);
1071 1075
1072 /* Initialize extradata related variables. */ 1076 /* Initialize extradata related variables. */
1073 q->samples_per_channel = q->samples_per_frame / q->nb_channels; 1077 q->samples_per_channel = q->samples_per_frame / q->nb_channels;
1074 q->bits_per_subpacket = avctx->block_align * 8; 1078 q->bits_per_subpacket = rmctx->block_align * 8;
1075 1079
1076 /* Initialize default data states. */ 1080 /* Initialize default data states. */
1077 q->log2_numvector_size = 5; 1081 q->log2_numvector_size = 5;
1078 q->total_subbands = q->subbands; 1082 q->total_subbands = q->subbands;
1079 1083
1080 /* Initialize version-dependent variables */ 1084 /* Initialize version-dependent variables */
1081 av_log(avctx,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion); 1085 av_log(NULL,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion);
1082 q->joint_stereo = 0; 1086 q->joint_stereo = 0;
1083 switch (q->cookversion) { 1087 switch (q->cookversion) {
1084 case MONO: 1088 case MONO:
1085 if (q->nb_channels != 1) { 1089 if (q->nb_channels != 1) {
1086 av_log(avctx,AV_LOG_ERROR,"Container channels != 1, report sample!\n"); 1090 av_log(NULL,AV_LOG_ERROR,"Container channels != 1, report sample!\n");
1087 return -1; 1091 return -1;
1088 } 1092 }
1089 av_log(avctx,AV_LOG_DEBUG,"MONO\n"); 1093 av_log(NULL,AV_LOG_DEBUG,"MONO\n");
1090 break; 1094 break;
1091 case STEREO: 1095 case STEREO:
1092 if (q->nb_channels != 1) { 1096 if (q->nb_channels != 1) {
1093 q->bits_per_subpacket = q->bits_per_subpacket/2; 1097 q->bits_per_subpacket = q->bits_per_subpacket/2;
1094 } 1098 }
1095 av_log(avctx,AV_LOG_DEBUG,"STEREO\n"); 1099 av_log(NULL,AV_LOG_DEBUG,"STEREO\n");
1096 break; 1100 break;
1097 case JOINT_STEREO: 1101 case JOINT_STEREO:
1098 if (q->nb_channels != 2) { 1102 if (q->nb_channels != 2) {
1099 av_log(avctx,AV_LOG_ERROR,"Container channels != 2, report sample!\n"); 1103 av_log(NULL,AV_LOG_ERROR,"Container channels != 2, report sample!\n");
1100 return -1; 1104 return -1;
1101 } 1105 }
1102 av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n"); 1106 av_log(NULL,AV_LOG_ERROR,"JOINT_STEREO\n");
1103 if (avctx->extradata_size >= 16){ 1107 if (q->extradata_size >= 16){
1104 q->total_subbands = q->subbands + q->js_subband_start; 1108 q->total_subbands = q->subbands + q->js_subband_start;
1105 q->joint_stereo = 1; 1109 q->joint_stereo = 1;
1106 } 1110 }
@@ -1112,11 +1116,11 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
1112 } 1116 }
1113 break; 1117 break;
1114 case MC_COOK: 1118 case MC_COOK:
1115 av_log(avctx,AV_LOG_ERROR,"MC_COOK not supported!\n"); 1119 av_log(NULL,AV_LOG_ERROR,"MC_COOK not supported!\n");
1116 return -1; 1120 return -1;
1117 break; 1121 break;
1118 default: 1122 default:
1119 av_log(avctx,AV_LOG_ERROR,"Unknown Cook version, report sample!\n"); 1123 av_log(NULL,AV_LOG_ERROR,"Unknown Cook version, report sample!\n");
1120 return -1; 1124 return -1;
1121 break; 1125 break;
1122 } 1126 }
@@ -1133,22 +1137,24 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
1133 return -1; 1137 return -1;
1134 1138
1135 1139
1136 if(avctx->block_align >= UINT_MAX/2) 1140 if(q->block_align >= UINT_MAX/2)
1137 return -1; 1141 return -1;
1138 1142
1139 /* Pad the databuffer with: 1143 /* Pad the databuffer with:
1140 DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), 1144 DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(),
1141 FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ 1145 INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */
1146
1147#define INPUT_BUFFER_PADDING_SIZE 8
1142 if (q->nb_channels==2 && q->joint_stereo==0) { 1148 if (q->nb_channels==2 && q->joint_stereo==0) {
1143 q->decoded_bytes_buffer = 1149 q->decoded_bytes_buffer =
1144 av_mallocz(avctx->block_align/2 1150 av_mallocz(rmctx->block_align/2
1145 + DECODE_BYTES_PAD2(avctx->block_align/2) 1151 + DECODE_BYTES_PAD2(q->block_align/2)
1146 + FF_INPUT_BUFFER_PADDING_SIZE); 1152 + INPUT_BUFFER_PADDING_SIZE);
1147 } else { 1153 } else {
1148 q->decoded_bytes_buffer = 1154 q->decoded_bytes_buffer =
1149 av_mallocz(avctx->block_align 1155 av_mallocz(rmctx->block_align
1150 + DECODE_BYTES_PAD1(avctx->block_align) 1156 + DECODE_BYTES_PAD1(q->block_align)
1151 + FF_INPUT_BUFFER_PADDING_SIZE); 1157 + INPUT_BUFFER_PADDING_SIZE);
1152 } 1158 }
1153 if (q->decoded_bytes_buffer == NULL) 1159 if (q->decoded_bytes_buffer == NULL)
1154 return -1; 1160 return -1;
@@ -1173,25 +1179,23 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
1173 1179
1174 /* Try to catch some obviously faulty streams, othervise it might be exploitable */ 1180 /* Try to catch some obviously faulty streams, othervise it might be exploitable */
1175 if (q->total_subbands > 53) { 1181 if (q->total_subbands > 53) {
1176 av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); 1182 av_log(NULL,AV_LOG_ERROR,"total_subbands > 53, report sample!\n");
1177 return -1; 1183 return -1;
1178 } 1184 }
1179 if (q->subbands > 50) { 1185 if (q->subbands > 50) {
1180 av_log(avctx,AV_LOG_ERROR,"subbands > 50, report sample!\n"); 1186 av_log(NULL,AV_LOG_ERROR,"subbands > 50, report sample!\n");
1181 return -1; 1187 return -1;
1182 } 1188 }
1183 if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) { 1189 if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) {
1184 } else { 1190 } else {
1185 av_log(avctx,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel); 1191 av_log(NULL,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel);
1186 return -1; 1192 return -1;
1187 } 1193 }
1188 if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) { 1194 if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) {
1189 av_log(avctx,AV_LOG_ERROR,"q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits); 1195 av_log(NULL,AV_LOG_ERROR,"q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits);
1190 return -1; 1196 return -1;
1191 } 1197 }
1192 1198
1193 avctx->sample_fmt = SAMPLE_FMT_S16;
1194 avctx->channel_layout = (avctx->channels==2) ? CH_LAYOUT_STEREO : CH_LAYOUT_MONO;
1195 1199
1196#ifdef COOKDEBUG 1200#ifdef COOKDEBUG
1197 dump_cook_context(q); 1201 dump_cook_context(q);
@@ -1200,14 +1204,86 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
1200} 1204}
1201 1205
1202 1206
1203AVCodec cook_decoder = 1207int main(int argc, char *argv[])
1204{ 1208{
1205 .name = "cook", 1209 int fd, fd_dec;
1206 .type = CODEC_TYPE_AUDIO, 1210 int res, datasize,x,i;
1207 .id = CODEC_ID_COOK, 1211 int nb_frames = 0;
1208 .priv_data_size = sizeof(COOKContext), 1212#ifdef DUMP_RAW_FRAMES
1209 .init = cook_decode_init, 1213 char filename[15];
1210 .close = cook_decode_close, 1214 int fd_out;
1211 .decode = cook_decode_frame, 1215#endif
1212 .long_name = NULL_IF_CONFIG_SMALL("COOK"), 1216 int16_t outbuf[2048];
1213}; 1217 uint8_t inbuf[1024];
1218 uint16_t fs,sps,h;
1219 uint32_t packet_count;
1220 COOKContext q;
1221 RMContext rmctx;
1222 RMPacket pkt;
1223
1224 memset(&q,0,sizeof(COOKContext));
1225 memset(&rmctx,0,sizeof(RMContext));
1226 memset(&pkt,0,sizeof(RMPacket));
1227
1228 if (argc != 2) {
1229 av_log(NULL,AV_LOG_ERROR,"Incorrect number of arguments\n");
1230 return -1;
1231 }
1232
1233 fd = open(argv[1],O_RDONLY);
1234 if (fd < 0) {
1235 av_log(NULL,AV_LOG_ERROR,"Error opening file %s\n", argv[1]);
1236 return -1;
1237 }
1238
1239 fd_dec = open_wav("output.wav");
1240 if (fd_dec < 0) {
1241 av_log(NULL,AV_LOG_ERROR,"Error creating output file\n");
1242 return -1;
1243 }
1244 res = real_parse_header(fd, &rmctx);
1245 packet_count = rmctx.nb_packets;
1246 rmctx.audio_framesize = rmctx.block_align;
1247 rmctx.block_align = rmctx.sub_packet_size;
1248 fs = rmctx.audio_framesize;
1249 sps= rmctx.block_align;
1250 h = rmctx.sub_packet_h;
1251 cook_decode_init(&rmctx,&q);
1252 av_log(NULL,AV_LOG_ERROR,"nb_frames = %d\n",nb_frames);
1253 x = 0;
1254 if(packet_count % h)
1255 {
1256 packet_count += h - (packet_count % h);
1257 rmctx.nb_packets = packet_count;
1258 }
1259 while(packet_count)
1260 {
1261
1262 memset(pkt.data,0,sizeof(pkt.data));
1263 rm_get_packet(fd, &rmctx, &pkt);
1264 DEBUGF("total frames = %d packet count = %d output counter = %d \n",rmctx.audio_pkt_cnt*(fs/sps), packet_count,rmctx.audio_pkt_cnt);
1265 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
1266 {
1267 /* output raw audio frames that are sent to the decoder into separate files */
1268 #ifdef DUMP_RAW_FRAMES
1269 snprintf(filename,sizeof(filename),"dump%d.raw",++x);
1270 fd_out = open(filename,O_WRONLY|O_CREAT|O_APPEND);
1271 write(fd_out,pkt.data+i*sps,sps);
1272 close(fd_out);
1273 #endif
1274
1275 memcpy(inbuf,pkt.data+i*sps,sps);
1276 nb_frames = cook_decode_frame(&rmctx,&q, outbuf, &datasize, inbuf , rmctx.block_align);
1277 rmctx.frame_number++;
1278 write(fd_dec,outbuf,datasize);
1279 }
1280 packet_count -= rmctx.audio_pkt_cnt;
1281 rmctx.audio_pkt_cnt = 0;
1282 }
1283 cook_decode_close(&q);
1284 close_wav(fd_dec,&rmctx);
1285 close(fd);
1286
1287
1288 return 0;
1289}
diff --git a/apps/codecs/libcook/dsputil.h b/apps/codecs/libcook/dsputil.h
index e9c2bfc77e..4573c17a62 100644
--- a/apps/codecs/libcook/dsputil.h
+++ b/apps/codecs/libcook/dsputil.h
@@ -36,6 +36,7 @@
36 36
37//#define DEBUG 37//#define DEBUG
38/* dct code */ 38/* dct code */
39#if 0 /*MT : DELETE THIS LINE.*/
39typedef short DCTELEM; 40typedef short DCTELEM;
40typedef int DWTELEM; 41typedef int DWTELEM;
41typedef short IDWTELEM; 42typedef short IDWTELEM;
@@ -590,8 +591,10 @@ void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx);
590void dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx); 591void dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx);
591void dsputil_init_vis(DSPContext* c, AVCodecContext *avctx); 592void dsputil_init_vis(DSPContext* c, AVCodecContext *avctx);
592 593
594#endif /*MT : DELETE THIS LINE ONLY. */
593#define DECLARE_ALIGNED_16(t, v) DECLARE_ALIGNED(16, t, v) 595#define DECLARE_ALIGNED_16(t, v) DECLARE_ALIGNED(16, t, v)
594 596
597#if 0 /*MT : DELETE THIS LINE ONLY. */
595#if HAVE_MMX 598#if HAVE_MMX
596 599
597#undef emms_c 600#undef emms_c
@@ -644,10 +647,12 @@ extern int mm_flags;
644 647
645#endif 648#endif
646 649
650#endif /* MT : DELETE THIS LINE ONLY */
647#ifndef DECLARE_ALIGNED_8 651#ifndef DECLARE_ALIGNED_8
648# define DECLARE_ALIGNED_8(t, v) DECLARE_ALIGNED(8, t, v) 652# define DECLARE_ALIGNED_8(t, v) DECLARE_ALIGNED(8, t, v)
649#endif 653#endif
650 654
655#if 0 /* MT : DELETE THIS LINE ONLY */
651#ifndef STRIDE_ALIGN 656#ifndef STRIDE_ALIGN
652# define STRIDE_ALIGN 8 657# define STRIDE_ALIGN 8
653#endif 658#endif
@@ -657,6 +662,7 @@ void get_psnr(uint8_t *orig_image[3], uint8_t *coded_image[3],
657 int orig_linesize[3], int coded_linesize, 662 int orig_linesize[3], int coded_linesize,
658 AVCodecContext *avctx); 663 AVCodecContext *avctx);
659 664
665#endif /*MT : DELETE THIS LINE.*/
660/* FFT computation */ 666/* FFT computation */
661 667
662/* NOTE: soon integer code will be added, so you must use the 668/* NOTE: soon integer code will be added, so you must use the
@@ -715,6 +721,7 @@ static inline void ff_fft_calc(FFTContext *s, FFTComplex *z)
715} 721}
716void ff_fft_end(FFTContext *s); 722void ff_fft_end(FFTContext *s);
717 723
724#endif /*MT : DELETE THIS LINE.*/
718/* MDCT computation */ 725/* MDCT computation */
719 726
720typedef struct MDCTContext { 727typedef struct MDCTContext {
@@ -735,6 +742,7 @@ static inline void ff_imdct_half(MDCTContext *s, FFTSample *output, const FFTSam
735 s->fft.imdct_half(s, output, input); 742 s->fft.imdct_half(s, output, input);
736} 743}
737 744
745#if 0 /* MT : DELETE THIS LINE. */
738/** 746/**
739 * Generate a Kaiser-Bessel Derived Window. 747 * Generate a Kaiser-Bessel Derived Window.
740 * @param window pointer to half window 748 * @param window pointer to half window
@@ -742,6 +750,7 @@ static inline void ff_imdct_half(MDCTContext *s, FFTSample *output, const FFTSam
742 * @param n size of half window 750 * @param n size of half window
743 */ 751 */
744void ff_kbd_window_init(float *window, float alpha, int n); 752void ff_kbd_window_init(float *window, float alpha, int n);
753#endif /* MT : DELETE THIS LINE.*/
745 754
746/** 755/**
747 * Generate a sine window. 756 * Generate a sine window.
@@ -769,6 +778,7 @@ void ff_imdct_half_sse(MDCTContext *s, FFTSample *output, const FFTSample *input
769void ff_mdct_calc(MDCTContext *s, FFTSample *out, const FFTSample *input); 778void ff_mdct_calc(MDCTContext *s, FFTSample *out, const FFTSample *input);
770void ff_mdct_end(MDCTContext *s); 779void ff_mdct_end(MDCTContext *s);
771 780
781#if 0 /* MT : DELETE THIS LINE.*/
772/* Real Discrete Fourier Transform */ 782/* Real Discrete Fourier Transform */
773 783
774enum RDFTransformType { 784enum RDFTransformType {
diff --git a/apps/codecs/libcook/ffmpeg_config.h b/apps/codecs/libcook/ffmpeg_config.h
new file mode 100644
index 0000000000..707e14df52
--- /dev/null
+++ b/apps/codecs/libcook/ffmpeg_config.h
@@ -0,0 +1,14 @@
1/* Automatically generated by configure - do not modify */
2#ifndef _FFMPEG_CONFIG_H
3#define _FFMPEG_CONFIG_H
4// CHECK THIS : #include "codecs.h"
5
6#ifdef CPU_ARM
7#define CONFIG_ALIGN 1
8#endif
9
10#ifdef ROCKBOX_BIG_ENDIAN
11#define WORDS_BIGENDIAN
12#endif
13
14#endif
diff --git a/apps/codecs/libcook/libavutil/avutil.h b/apps/codecs/libcook/libavutil/avutil.h
index c57e69f10c..c07e44d660 100644
--- a/apps/codecs/libcook/libavutil/avutil.h
+++ b/apps/codecs/libcook/libavutil/avutil.h
@@ -54,10 +54,10 @@
54unsigned avutil_version(void); 54unsigned avutil_version(void);
55 55
56#include "common.h" 56#include "common.h"
57#include "mathematics.h" 57//#include "mathematics.h"
58#include "rational.h" 58//#include "rational.h"
59#include "intfloat_readwrite.h" 59//#include "intfloat_readwrite.h"
60#include "log.h" 60#include "log.h"
61#include "pixfmt.h" 61//#include "pixfmt.h"
62 62
63#endif /* AVUTIL_AVUTIL_H */ 63#endif /* AVUTIL_AVUTIL_H */
diff --git a/apps/codecs/libcook/libavutil/bswap.h b/apps/codecs/libcook/libavutil/bswap.h
index cf68c43c72..9175cb24a5 100644
--- a/apps/codecs/libcook/libavutil/bswap.h
+++ b/apps/codecs/libcook/libavutil/bswap.h
@@ -27,7 +27,7 @@
27#define AVUTIL_BSWAP_H 27#define AVUTIL_BSWAP_H
28 28
29#include <stdint.h> 29#include <stdint.h>
30#include "config.h" 30//#include "ffmpeg_config.h"
31#include "common.h" 31#include "common.h"
32 32
33#if ARCH_ARM 33#if ARCH_ARM
diff --git a/apps/codecs/libcook/libavutil/common.h b/apps/codecs/libcook/libavutil/common.h
index 15eaf9849d..949f093d35 100644
--- a/apps/codecs/libcook/libavutil/common.h
+++ b/apps/codecs/libcook/libavutil/common.h
@@ -278,9 +278,9 @@ static inline av_const float av_clipf(float a, float amin, float amax)
278 278
279#include "mem.h" 279#include "mem.h"
280 280
281#ifdef HAVE_AV_CONFIG_H 281//#ifdef HAVE_AV_CONFIG_H
282# include "config.h" 282//# include "ffmpeg_config.h"
283# include "internal.h" 283# include "internal.h"
284#endif /* HAVE_AV_CONFIG_H */ 284//#endif /* HAVE_AV_CONFIG_H */
285 285
286#endif /* AVUTIL_COMMON_H */ 286#endif /* AVUTIL_COMMON_H */
diff --git a/apps/codecs/libcook/libavutil/internal.h b/apps/codecs/libcook/libavutil/internal.h
index 4191aa8e52..f8f9418a76 100644
--- a/apps/codecs/libcook/libavutil/internal.h
+++ b/apps/codecs/libcook/libavutil/internal.h
@@ -34,10 +34,10 @@
34#include <stdint.h> 34#include <stdint.h>
35#include <stddef.h> 35#include <stddef.h>
36#include <assert.h> 36#include <assert.h>
37#include "config.h" 37//#include "ffmpeg_config.h"
38#include "common.h" 38#include "common.h"
39#include "mem.h" 39#include "mem.h"
40#include "timer.h" 40//#include "timer.h"
41 41
42#ifndef attribute_align_arg 42#ifndef attribute_align_arg
43#if (!defined(__ICC) || __ICC > 1100) && AV_GCC_VERSION_AT_LEAST(4,2) 43#if (!defined(__ICC) || __ICC > 1100) && AV_GCC_VERSION_AT_LEAST(4,2)
@@ -223,10 +223,10 @@ if((y)<(x)){\
223#define realloc please_use_av_realloc 223#define realloc please_use_av_realloc
224#undef time 224#undef time
225#define time time_is_forbidden_due_to_security_issues 225#define time time_is_forbidden_due_to_security_issues
226#undef rand 226//#undef rand
227#define rand rand_is_forbidden_due_to_state_trashing_use_av_random 227//#define rand rand_is_forbidden_due_to_state_trashing_use_av_random
228#undef srand 228//#undef srand
229#define srand srand_is_forbidden_due_to_state_trashing_use_av_random_init 229//#define srand srand_is_forbidden_due_to_state_trashing_use_av_random_init
230#undef random 230#undef random
231#define random random_is_forbidden_due_to_state_trashing_use_av_random 231#define random random_is_forbidden_due_to_state_trashing_use_av_random
232#undef sprintf 232#undef sprintf
diff --git a/apps/codecs/libcook/libavutil/intreadwrite.h b/apps/codecs/libcook/libavutil/intreadwrite.h
index 7c5909ea51..d27a50061e 100644
--- a/apps/codecs/libcook/libavutil/intreadwrite.h
+++ b/apps/codecs/libcook/libavutil/intreadwrite.h
@@ -20,7 +20,7 @@
20#define AVUTIL_INTREADWRITE_H 20#define AVUTIL_INTREADWRITE_H
21 21
22#include <stdint.h> 22#include <stdint.h>
23#include "config.h" 23//#include "ffmpeg_config.h"
24#include "bswap.h" 24#include "bswap.h"
25 25
26#ifdef __GNUC__ 26#ifdef __GNUC__
diff --git a/apps/codecs/libcook/libavutil/mem.c b/apps/codecs/libcook/libavutil/mem.c
index 741450b53f..7307df2384 100644
--- a/apps/codecs/libcook/libavutil/mem.c
+++ b/apps/codecs/libcook/libavutil/mem.c
@@ -24,7 +24,6 @@
24 * default memory allocator for libavutil 24 * default memory allocator for libavutil
25 */ 25 */
26 26
27#include "config.h"
28 27
29#include <limits.h> 28#include <limits.h>
30#include <stdlib.h> 29#include <stdlib.h>
diff --git a/apps/codecs/libcook/rm2wav.c b/apps/codecs/libcook/rm2wav.c
new file mode 100644
index 0000000000..4ef1ec4f66
--- /dev/null
+++ b/apps/codecs/libcook/rm2wav.c
@@ -0,0 +1,584 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Dave Chapman
11 * Copyright (C) 2009 Mohamed Tarek
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include <stdio.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
30#include "rm2wav.h"
31
32#define MAX_PATH 260
33#define PKT_HEADER_SIZE 12
34#define RAW_AUDIO_DATA packet_length-PKT_HEADER_SIZE
35
36
37#if 0
38#define DEBUG
39#define DEBUGF printf
40#else
41#define DEBUGF(...)
42#endif
43
44/* ASF codec IDs */
45#define CODEC_ID_WMAV1 0x160
46#define CODEC_ID_WMAV2 0x161
47
48static unsigned char wav_header[44]={
49 'R','I','F','F',// 0 - ChunkID
50 0,0,0,0, // 4 - ChunkSize (filesize-8)
51 'W','A','V','E',// 8 - Format
52 'f','m','t',' ',// 12 - SubChunkID
53 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
54 1,0, // 20 - AudioFormat (1=Uncompressed)
55 2,0, // 22 - NumChannels
56 0,0,0,0, // 24 - SampleRate in Hz
57 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
58 4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
59 16,0, // 34 - BitsPerSample
60 'd','a','t','a',// 36 - Subchunk2ID
61 0,0,0,0 // 40 - Subchunk2Size
62};
63
64int open_wav(char* filename) {
65 int fd,res;
66
67 fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR|S_IWUSR);
68 if (fd >= 0) {
69 res = write(fd,wav_header,sizeof(wav_header));
70 }
71
72 return(fd);
73}
74
75void close_wav(int fd, RMContext *rmctx) {
76 int x,res;
77 int filesize;
78 int bytes_per_sample = 2;
79 int samples_per_frame = rmctx->samples_pf_pc;
80 int nb_channels = rmctx->nb_channels;
81 int sample_rate = rmctx->sample_rate;
82 int nb_frames = rmctx->audio_framesize/rmctx->block_align * rmctx->nb_packets - 2; // first 2 frames have no valid audio; skipped in output
83
84 filesize= samples_per_frame*bytes_per_sample*nb_frames +44;
85 printf("Filesize = %d\n",filesize);
86
87 // ChunkSize
88 x=filesize-8;
89 wav_header[4]=(x&0xff);
90 wav_header[5]=(x&0xff00)>>8;
91 wav_header[6]=(x&0xff0000)>>16;
92 wav_header[7]=(x&0xff000000)>>24;
93
94 // Number of channels
95 wav_header[22]=nb_channels;
96
97 // Samplerate
98 wav_header[24]=sample_rate&0xff;
99 wav_header[25]=(sample_rate&0xff00)>>8;
100 wav_header[26]=(sample_rate&0xff0000)>>16;
101 wav_header[27]=(sample_rate&0xff000000)>>24;
102
103 // ByteRate
104 x=sample_rate*bytes_per_sample*nb_channels;
105 wav_header[28]=(x&0xff);
106 wav_header[29]=(x&0xff00)>>8;
107 wav_header[30]=(x&0xff0000)>>16;
108 wav_header[31]=(x&0xff000000)>>24;
109
110 // BlockAlign
111 wav_header[32]=rmctx->block_align;//2*rmctx->nb_channels;
112
113 // Bits per sample
114 wav_header[34]=16;
115
116 // Subchunk2Size
117 x=filesize-44;
118 wav_header[40]=(x&0xff);
119 wav_header[41]=(x&0xff00)>>8;
120 wav_header[42]=(x&0xff0000)>>16;
121 wav_header[43]=(x&0xff000000)>>24;
122
123 lseek(fd,0,SEEK_SET);
124 res = write(fd,wav_header,sizeof(wav_header));
125 close(fd);
126}
127
128/* Some Rockbox-like functions (these should be implemented in metadata_common.[ch] */
129struct cook_extradata {
130 uint32_t cook_version;
131 uint16_t samples_pf_pc; /* samples per frame per channel */
132 uint16_t nb_subbands; /* number of subbands in the frequency domain */
133
134 /* extra 8 bytes for stereo data */
135 uint32_t unused;
136 uint16_t js_subband_start; /* joint stereo subband start */
137 uint16_t js_vlc_bits;
138};
139
140static int read_uint8(int fd, uint8_t* buf)
141{
142 unsigned char tmp[1];
143 int res;
144
145 res=read(fd, tmp, 1);
146 *buf = tmp[0];
147 return res;
148}
149
150static int read_uint16be(int fd, uint16_t* buf)
151{
152 unsigned char tmp[2];
153 int res;
154
155 res=read(fd, tmp, 2);
156 *buf = (tmp[0] << 8) | tmp[1];
157 return res;
158}
159
160static int read_uint32be(int fd, uint32_t* buf)
161{
162 unsigned char tmp[4];
163 int res;
164
165 res=read(fd, tmp, 4);
166 *buf = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];
167 return res;
168}
169
170off_t filesize(int fd)
171{
172 struct stat buf;
173
174 if (fstat(fd,&buf) == -1) {
175 return -1;
176 } else {
177 return buf.st_size;
178 }
179}
180
181int read_cook_extradata(int fd, RMContext *rmctx) {
182 read_uint32be(fd, &rmctx->cook_version);
183 read_uint16be(fd, &rmctx->samples_pf_pc);
184 read_uint16be(fd, &rmctx->nb_subbands);
185 if(rmctx->extradata_size == 16) {
186 read_uint32be(fd, &rmctx->unused);
187 read_uint16be(fd, &rmctx->js_subband_start);
188 read_uint16be(fd, &rmctx->js_vlc_bits);
189 }
190 return rmctx->extradata_size; /* for 'skipped' */
191}
192
193void print_cook_extradata(RMContext *rmctx) {
194
195 printf(" cook_version = 0x%08x\n", rmctx->cook_version);
196 printf(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc);
197 printf(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands);
198 if(rmctx->extradata_size == 16) {
199 printf(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start);
200 printf(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits);
201 }
202}
203
204
205struct real_object_t
206{
207 uint32_t fourcc;
208 uint32_t size;
209 uint16_t version;
210};
211
212#define FOURCC(a,b,c,d) (((a)<<24) | ((b) << 16) | ((c) << 8) | (d))
213
214static int real_read_object_header(int fd, struct real_object_t* obj)
215{
216 int n;
217
218 if ((n = read_uint32be(fd, &obj->fourcc)) <= 0) return n;
219 if ((n = read_uint32be(fd, &obj->size)) <= 0) return n;
220 if ((n = read_uint16be(fd, &obj->version)) <= 0) return n;
221
222 return 1;
223}
224
225static char* fourcc2str(uint32_t f)
226{
227 static char res[5];
228
229 res[0] = (f & 0xff000000) >> 24;
230 res[1] = (f & 0xff0000) >> 16;
231 res[2] = (f & 0xff00) >> 8;
232 res[3] = (f & 0xff);
233 res[4] = 0;
234
235 return res;
236}
237
238static int read_str(int fd, char* buf)
239{
240 uint8_t len;
241 int res;
242
243 res = read(fd, &len, 1);
244 res = read(fd, buf, len);
245 buf[len]=0;
246
247 return len+1;
248}
249
250static int real_read_audio_stream_info(int fd, RMContext *rmctx)
251{
252 int skipped = 0;
253 uint32_t version;
254 struct real_object_t obj;
255 memset(&obj,0,sizeof(obj));
256 uint32_t header_size;
257 uint16_t flavor;
258 uint32_t coded_framesize;
259 uint32_t unknown1;
260 uint32_t unknown2;
261 uint32_t unknown3;
262 uint16_t unknown4;
263 uint16_t unknown5;
264 uint16_t unknown6;
265 uint16_t unknown7;
266 uint32_t unknown8;
267 uint8_t interleaver_id_length;
268 uint32_t interleaver_id;
269 uint8_t fourcc_length;
270 uint32_t fourcc = 0;
271 uint8_t unknown9;
272 uint16_t unknown10;
273 uint8_t unknown11;
274
275 read_uint32be(fd, &version);
276 skipped += 4;
277
278 printf(" version=0x%04x\n",((version >> 16) & 0xff));
279 if (((version >> 16) & 0xff) == 3) {
280 /* Very old version */
281 } else {
282 real_read_object_header(fd, &obj);
283 skipped += 10;
284 read_uint32be(fd, &header_size);
285 skipped += 4;
286 /* obj.size will be filled with an unknown value, replaced with header_size */
287 printf(" Object: %s, size: %d bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version);
288
289 read_uint16be(fd, &flavor);
290 read_uint32be(fd, &coded_framesize);
291 read_uint32be(fd, &unknown1);
292 read_uint32be(fd, &unknown2);
293 read_uint32be(fd, &unknown3);
294 read_uint16be(fd, &rmctx->sub_packet_h);
295 read_uint16be(fd, &rmctx->block_align);
296 read_uint16be(fd, &rmctx->sub_packet_size);
297 read_uint16be(fd, &unknown4);
298 skipped += 26;
299 if (((version >> 16) & 0xff) == 5)
300 {
301 read_uint16be(fd, &unknown5);
302 read_uint16be(fd, &unknown6);
303 read_uint16be(fd, &unknown7);
304 skipped += 6;
305 }
306 read_uint16be(fd, &rmctx->sample_rate);
307 read_uint32be(fd, &unknown8);
308 read_uint16be(fd, &rmctx->nb_channels);
309 skipped += 8;
310 if (((version >> 16) & 0xff) == 4)
311 {
312 read_uint8(fd, &interleaver_id_length);
313 read_uint32be(fd, &interleaver_id);
314 read_uint8(fd, &fourcc_length);
315 read_uint32be(fd, &fourcc);
316 skipped += 10;
317 }
318 if (((version >> 16) & 0xff) == 5)
319 {
320 read_uint32be(fd, &interleaver_id);
321 read_uint32be(fd, &fourcc);
322 skipped += 8;
323 }
324 read_uint8(fd,&unknown9);
325 read_uint16be(fd,&unknown10);
326 skipped += 3;
327 if (((version >> 16) & 0xff) == 5)
328 {
329 read_uint8(fd, &unknown11);
330 skipped += 1;
331 }
332
333 read_uint32be(fd, &rmctx->extradata_size);
334 skipped += 4;
335 if(!strncmp(fourcc2str(fourcc),"cook",4))
336 skipped += read_cook_extradata(fd, rmctx);
337
338
339 printf(" flavor = %d\n",flavor);
340 printf(" coded_frame_size = %d\n",coded_framesize);
341 printf(" sub_packet_h = %d\n",rmctx->sub_packet_h);
342 printf(" frame_size = %d\n",rmctx->block_align);
343 printf(" sub_packet_size = %d\n",rmctx->sub_packet_size);
344 printf(" sample_rate= %d\n",rmctx->sample_rate);
345 printf(" channels= %d\n",rmctx->nb_channels);
346 printf(" fourcc = %s\n",fourcc2str(fourcc));
347 printf(" codec_extra_data_length = %d\n",rmctx->extradata_size);
348 printf(" codec_extradata :\n");
349 print_cook_extradata(rmctx);
350
351 }
352
353 return skipped;
354}
355
356int real_parse_header(int fd, RMContext *rmctx)
357{
358 struct real_object_t obj;
359 memset(&obj,0,sizeof(obj));
360 int res;
361 int skipped;
362 off_t curpos;
363
364 uint32_t unknown1;
365 uint32_t unknown2;
366
367 uint32_t max_bitrate;
368 uint32_t avg_bitrate = 0;
369 uint32_t max_packet_size;
370 uint32_t avg_packet_size;
371 uint32_t packet_count;
372 uint32_t duration;
373 uint32_t preroll;
374 uint32_t index_offset;
375 uint32_t data_offset;
376 uint16_t num_streams;
377 uint16_t flags = 0;
378
379 uint16_t stream_id;
380 uint32_t start_time;
381 char desc[256];
382 char mimetype[256];
383 uint32_t codec_data_size;
384 uint32_t v;
385
386 char title[256];
387 char author[256];
388 char copyright[256];
389 char comment[256];
390
391 uint32_t next_data_off;
392 uint8_t header_end;
393
394 curpos = lseek(fd, 0, SEEK_SET);
395 res = real_read_object_header(fd, &obj);
396
397 if (obj.fourcc == FOURCC('.','r','a',0xfd))
398 {
399 /* Very old .ra format - not yet supported */
400 return -1;
401 }
402 else if (obj.fourcc != FOURCC('.','R','M','F'))
403 {
404 return -1;
405 }
406
407 read_uint32be(fd, &unknown1);
408 read_uint32be(fd, &unknown2);
409
410 printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
411 printf(" unknown1=%d (0x%08x)\n",unknown1,unknown1);
412 printf(" unknown2=%d (0x%08x)\n",unknown2,unknown2);
413
414 res = real_read_object_header(fd, &obj);
415 header_end = 0;
416 while(res)
417 {
418 printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
419 skipped = 10;
420 if(obj.fourcc == FOURCC('I','N','D','X'))
421 break;
422 switch (obj.fourcc)
423 {
424 case FOURCC('P','R','O','P'): /* File properties */
425 read_uint32be(fd, &max_bitrate);
426 read_uint32be(fd, &rmctx->bit_rate); /*avg bitrate*/
427 read_uint32be(fd, &max_packet_size);
428 read_uint32be(fd, &avg_packet_size);
429 read_uint32be(fd, &packet_count);
430 read_uint32be(fd, &duration);
431 read_uint32be(fd, &preroll);
432 read_uint32be(fd, &index_offset);
433 read_uint32be(fd, &data_offset);
434 read_uint16be(fd, &num_streams);
435 read_uint16be(fd, &rmctx->flags);
436 skipped += 40;
437
438 printf(" max_bitrate = %d\n",max_bitrate);
439 printf(" avg_bitrate = %d\n",avg_bitrate);
440 printf(" max_packet_size = %d\n",max_packet_size);
441 printf(" avg_packet_size = %d\n",avg_packet_size);
442 printf(" packet_count = %d\n",packet_count);
443 printf(" duration = %d\n",duration);
444 printf(" preroll = %d\n",preroll);
445 printf(" index_offset = %d\n",index_offset);
446 printf(" data_offset = %d\n",data_offset);
447 printf(" num_streams = %d\n",num_streams);
448 printf(" flags=0x%04x\n",flags);
449 break;
450
451 case FOURCC('C','O','N','T'):
452 /* Four strings - Title, Author, Copyright, Comment */
453 skipped += read_str(fd,title);
454 skipped += read_str(fd,author);
455 skipped += read_str(fd,copyright);
456 skipped += read_str(fd,comment);
457
458 printf(" title=\"%s\"\n",title);
459 printf(" author=\"%s\"\n",author);
460 printf(" copyright=\"%s\"\n",copyright);
461 printf(" comment=\"%s\"\n",comment);
462 break;
463
464 case FOURCC('M','D','P','R'): /* Media properties */
465 read_uint16be(fd,&stream_id);
466 skipped += 2;
467 read_uint32be(fd,&max_bitrate);
468 skipped += 4;
469 read_uint32be(fd,&avg_bitrate);
470 skipped += 4;
471 read_uint32be(fd,&max_packet_size);
472 skipped += 4;
473 read_uint32be(fd,&avg_packet_size);
474 skipped += 4;
475 read_uint32be(fd,&start_time);
476 skipped += 4;
477 read_uint32be(fd,&preroll);
478 skipped += 4;
479 read_uint32be(fd,&duration);
480 skipped += 4;
481 skipped += read_str(fd,desc);
482 skipped += read_str(fd,mimetype);
483 read_uint32be(fd,&codec_data_size);
484 skipped += 4;
485 //From ffmpeg: codec_pos = url_ftell(pb);
486 read_uint32be(fd,&v);
487 skipped += 4;
488
489 printf(" stream_id = 0x%04x\n",stream_id);
490 printf(" max_bitrate = %d\n",max_bitrate);
491 printf(" avg_bitrate = %d\n",avg_bitrate);
492 printf(" max_packet_size = %d\n",max_packet_size);
493 printf(" avg_packet_size = %d\n",avg_packet_size);
494 printf(" start_time = %d\n",start_time);
495 printf(" preroll = %d\n",preroll);
496 printf(" duration = %d\n",duration);
497 printf(" desc=\"%s\"\n",desc);
498 printf(" mimetype=\"%s\"\n",mimetype);
499 printf(" codec_data_size = %d\n",codec_data_size);
500 printf(" v=\"%s\"\n", fourcc2str(v));
501
502 if (v == FOURCC('.','r','a',0xfd))
503 {
504 skipped += real_read_audio_stream_info(fd, rmctx);
505 }
506
507 break;
508
509 case FOURCC('D','A','T','A'):
510
511 read_uint32be(fd,&rmctx->nb_packets);
512 skipped += 4;
513 read_uint32be(fd,&next_data_off);
514 skipped += 4;
515 if (!rmctx->nb_packets && (rmctx->flags & 4))
516 rmctx->nb_packets = 3600 * 25;
517 printf(" data_nb_packets = %d\n",rmctx->nb_packets);
518 printf(" next DATA offset = %d\n",next_data_off);
519 header_end = 1;
520 break;
521 }
522 if(header_end) break;
523 curpos = lseek(fd, obj.size - skipped, SEEK_CUR);
524 res = real_read_object_header(fd, &obj);
525 }
526
527
528 return 0;
529}
530
531void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt)
532{
533 uint8_t unknown,packet_group;
534 uint16_t x, place;
535 uint16_t sps = rmctx->sub_packet_size;
536 uint16_t h = rmctx->sub_packet_h;
537 uint16_t y = rmctx->sub_packet_cnt;
538 uint16_t w = rmctx->audio_framesize;
539 do
540 {
541 y = rmctx->sub_packet_cnt;
542 read_uint16be(fd,&pkt->version);
543 read_uint16be(fd,&pkt->length);
544 read_uint16be(fd,&pkt->stream_number);
545 read_uint32be(fd,&pkt->timestamp);
546 DEBUGF(" version = %d\n"
547 " length = %d\n"
548 " stream = %d\n"
549 " timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);
550
551 //getchar();
552 if(pkt->version == 0)
553 {
554 read_uint8(fd,&packet_group);
555 read_uint8(fd,&pkt->flags);
556 }
557 if(pkt->version == 1)
558 read_uint8(fd,&unknown);
559
560 if (pkt->flags & 2) /* keyframe */
561 y = rmctx->sub_packet_cnt = 0;
562 if (!y) /* if keyframe update playback elapsed time */
563 rmctx->audiotimestamp = pkt->timestamp;
564
565 for(x = 0 ; x < w/sps; x++)
566 {
567 place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1));
568 read(fd,pkt->data+place, sps);
569 //DEBUGF("place = %d data[place] = %d\n",place,pkt->data[place]);
570 }
571 rmctx->audio_pkt_cnt++;
572 }while(++(rmctx->sub_packet_cnt) < h);
573
574 //return pkt->data;
575}
576#ifdef DEBUG
577void dump_rm_context(RMContext *rmctx)
578{
579 DEBUGF("block_align = %d\n", rmctx->block_align);
580 DEBUGF("nb_channels = %d\n", rmctx->nb_channels);
581 DEBUGF("sample_rate = %d\n", rmctx->sample_rate);
582 DEBUGF("bit_rate = %d\n", rmctx->bit_rate );
583}
584#endif
diff --git a/apps/codecs/libcook/rm2wav.h b/apps/codecs/libcook/rm2wav.h
new file mode 100644
index 0000000000..09b20c7fa6
--- /dev/null
+++ b/apps/codecs/libcook/rm2wav.h
@@ -0,0 +1,74 @@
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 <stdint.h>
23
24typedef struct rm_packet
25{
26 uint8_t data[30000]; /* Reordered data. No malloc, hence the size */
27 uint16_t version;
28 uint16_t length;
29 uint32_t timestamp;
30 uint16_t stream_number;
31 uint8_t flags;
32}RMPacket;
33
34typedef struct rm_context
35{
36 /* Demux Context */
37 int old_format;
38 int current_stream;
39 int remaining_len;
40 int audio_stream_num; /*< Stream number for audio packets*/
41 int audio_pkt_cnt; /* Output packet counter*/
42
43 /* Stream Variables */
44 uint32_t audiotimestamp; /* Audio packet timestamp*/
45 uint16_t sub_packet_cnt; /* Subpacket counter, used while reading */
46 uint16_t sub_packet_size, sub_packet_h, coded_framesize; /* Descrambling parameters from container */
47 uint16_t audio_framesize; /* Audio frame size from container */
48 uint16_t sub_packet_lengths[16]; /* Length of each subpacket */
49
50 /* Codec Context */
51 uint16_t block_align;
52 uint32_t nb_packets;
53 int frame_number;
54 uint32_t extradata_size;
55 uint16_t sample_rate;
56 uint16_t nb_channels;
57 uint32_t bit_rate;
58 uint16_t flags;
59
60 /*cook extradata*/
61 uint32_t cook_version;
62 uint16_t samples_pf_pc; /* samples per frame per channel */
63 uint16_t nb_subbands; /* number of subbands in the frequency domain */
64 /* extra 8 bytes for stereo data */
65 uint32_t unused;
66 uint16_t js_subband_start; /* joint stereo subband start */
67 uint16_t js_vlc_bits;
68
69} RMContext;
70
71int open_wav(char* filename);
72void close_wav(int fd, RMContext *rmctx);
73int real_parse_header(int fd, RMContext *rmctx);
74void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt);