mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-09 23:53:28 -04:00
Most of the churn here occurs because 'filesize' is one of the redefined filesystem functions, but some of the structs used by the native FS code also include a 'filesize' member variable which gets renamed by the macro in some but not all source files. It's easier to rename 'filesize()' to 'ffilesize()' rather than try to clean up the macro mess or renaming the struct members. There is weirdness with root_realpath() which now breaks on native builds because it was assumed to be unprefixed there. dir_get_info() was unprefixed everywhere but this just seems inconsistent; make it follow the FS_PREFIX() convention too. Change-Id: Ic3700c6234ea45f32679c1a8429d70fdb8f4088a
608 lines
19 KiB
C
608 lines
19 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
*
|
|
* Copyright (C) 2008 Dave Chapman
|
|
* Copyright (C) 2009 Mohamed Tarek
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "rm.h"
|
|
#ifdef ROCKBOX
|
|
#include "codeclib.h"
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include "inttypes.h"
|
|
#include <sys/stat.h>
|
|
|
|
int ffilesize(int fd)
|
|
{
|
|
struct stat buf;
|
|
|
|
if (fstat(fd,&buf) == -1) {
|
|
return -1;
|
|
} else {
|
|
return (int)buf.st_size;
|
|
}
|
|
}
|
|
|
|
static int read_uint8(int fd, uint8_t* buf)
|
|
{
|
|
unsigned char tmp[1];
|
|
int res;
|
|
|
|
res=read(fd, tmp, 1);
|
|
*buf = tmp[0];
|
|
return res;
|
|
}
|
|
|
|
static int read_uint16be(int fd, uint16_t* buf)
|
|
{
|
|
unsigned char tmp[2];
|
|
int res;
|
|
|
|
res=read(fd, tmp, 2);
|
|
*buf = (tmp[0] << 8) | tmp[1];
|
|
return res;
|
|
}
|
|
|
|
static int read_uint32be(int fd, uint32_t* buf)
|
|
{
|
|
unsigned char tmp[4];
|
|
int res;
|
|
|
|
res=read(fd, tmp, 4);
|
|
*buf = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];
|
|
return res;
|
|
}
|
|
|
|
|
|
static void print_cook_extradata(RMContext *rmctx) {
|
|
|
|
DEBUGF(" cook_version = 0x%08x\n", rm_get_uint32be(rmctx->codec_extradata));
|
|
DEBUGF(" samples_per_frame_per_channel = %d\n", rm_get_uint16be(&rmctx->codec_extradata[4]));
|
|
DEBUGF(" number_of_subbands_in_freq_domain = %d\n", rm_get_uint16be(&rmctx->codec_extradata[6]));
|
|
if(rmctx->extradata_size == 16) {
|
|
DEBUGF(" joint_stereo_subband_start = %d\n",rm_get_uint16be(&rmctx->codec_extradata[12]));
|
|
DEBUGF(" joint_stereo_vlc_bits = %d\n", rm_get_uint16be(&rmctx->codec_extradata[14]));
|
|
}
|
|
}
|
|
|
|
|
|
struct real_object_t
|
|
{
|
|
uint32_t fourcc;
|
|
uint32_t size;
|
|
uint16_t version;
|
|
};
|
|
|
|
#define FOURCC(a,b,c,d) (((a)<<24) | ((b) << 16) | ((c) << 8) | (d))
|
|
|
|
static int real_read_object_header(int fd, struct real_object_t* obj)
|
|
{
|
|
int n;
|
|
|
|
if ((n = read_uint32be(fd, &obj->fourcc)) <= 0) return n;
|
|
if ((n = read_uint32be(fd, &obj->size)) <= 0) return n;
|
|
if ((n = read_uint16be(fd, &obj->version)) <= 0) return n;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static char* fourcc2str(uint32_t f)
|
|
{
|
|
static char res[5];
|
|
|
|
res[0] = (f & 0xff000000) >> 24;
|
|
res[1] = (f & 0xff0000) >> 16;
|
|
res[2] = (f & 0xff00) >> 8;
|
|
res[3] = (f & 0xff);
|
|
res[4] = 0;
|
|
|
|
return res;
|
|
}
|
|
|
|
static int read_str(int fd, char* buf)
|
|
{
|
|
uint8_t len;
|
|
int res;
|
|
|
|
res = read(fd, &len, 1);
|
|
res = read(fd, buf, len);
|
|
buf[len]=0;
|
|
|
|
return len+1;
|
|
}
|
|
|
|
static int real_read_audio_stream_info(int fd, RMContext *rmctx)
|
|
{
|
|
int skipped = 0;
|
|
uint32_t version;
|
|
struct real_object_t obj;
|
|
memset(&obj,0,sizeof(obj));
|
|
uint32_t header_size;
|
|
uint16_t flavor;
|
|
uint32_t coded_framesize;
|
|
uint32_t unknown1;
|
|
uint32_t unknown2;
|
|
uint32_t unknown3;
|
|
uint16_t unknown4;
|
|
uint16_t unknown5;
|
|
uint16_t unknown6;
|
|
uint16_t unknown7;
|
|
uint32_t unknown8;
|
|
uint8_t interleaver_id_length;
|
|
uint32_t interleaver_id;
|
|
uint8_t fourcc_length;
|
|
uint32_t fourcc = 0;
|
|
uint8_t unknown9;
|
|
uint16_t unknown10;
|
|
uint8_t unknown11;
|
|
|
|
read_uint32be(fd, &version);
|
|
skipped += 4;
|
|
|
|
DEBUGF(" version=0x%04x\n",((version >> 16) & 0xff));
|
|
if (((version >> 16) & 0xff) == 3) {
|
|
/* Very old version */
|
|
} else {
|
|
real_read_object_header(fd, &obj);
|
|
skipped += 10;
|
|
read_uint32be(fd, &header_size);
|
|
skipped += 4;
|
|
/* obj.size will be filled with an unknown value, replaced with header_size */
|
|
DEBUGF(" Object: %s, size: %d bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version);
|
|
|
|
read_uint16be(fd, &flavor);
|
|
read_uint32be(fd, &coded_framesize);
|
|
read_uint32be(fd, &unknown1);
|
|
read_uint32be(fd, &unknown2);
|
|
read_uint32be(fd, &unknown3);
|
|
read_uint16be(fd, &rmctx->sub_packet_h);
|
|
read_uint16be(fd, &rmctx->block_align);
|
|
read_uint16be(fd, &rmctx->sub_packet_size);
|
|
read_uint16be(fd, &unknown4);
|
|
skipped += 26;
|
|
if (((version >> 16) & 0xff) == 5)
|
|
{
|
|
read_uint16be(fd, &unknown5);
|
|
read_uint16be(fd, &unknown6);
|
|
read_uint16be(fd, &unknown7);
|
|
skipped += 6;
|
|
}
|
|
read_uint16be(fd, &rmctx->sample_rate);
|
|
read_uint32be(fd, &unknown8);
|
|
read_uint16be(fd, &rmctx->nb_channels);
|
|
skipped += 8;
|
|
if (((version >> 16) & 0xff) == 4)
|
|
{
|
|
read_uint8(fd, &interleaver_id_length);
|
|
read_uint32be(fd, &interleaver_id);
|
|
read_uint8(fd, &fourcc_length);
|
|
read_uint32be(fd, &fourcc);
|
|
skipped += 10;
|
|
}
|
|
if (((version >> 16) & 0xff) == 5)
|
|
{
|
|
read_uint32be(fd, &interleaver_id);
|
|
read_uint32be(fd, &fourcc);
|
|
skipped += 8;
|
|
}
|
|
read_uint8(fd,&unknown9);
|
|
read_uint16be(fd,&unknown10);
|
|
skipped += 3;
|
|
if (((version >> 16) & 0xff) == 5)
|
|
{
|
|
read_uint8(fd, &unknown11);
|
|
skipped += 1;
|
|
}
|
|
|
|
switch(fourcc) {
|
|
case FOURCC('c','o','o','k'):
|
|
rmctx->codec_type = CODEC_COOK;
|
|
read_uint32be(fd, &rmctx->extradata_size);
|
|
skipped += 4;
|
|
read(fd, rmctx->codec_extradata, rmctx->extradata_size);
|
|
skipped += rmctx->extradata_size;
|
|
break;
|
|
|
|
case FOURCC('a','t','r','c'):
|
|
rmctx->codec_type = CODEC_ATRAC;
|
|
read_uint32be(fd, &rmctx->extradata_size);
|
|
skipped += 4;
|
|
read(fd, rmctx->codec_extradata, rmctx->extradata_size);
|
|
skipped += rmctx->extradata_size;
|
|
break;
|
|
|
|
case FOURCC('r','a','a','c'):
|
|
case FOURCC('r','a','c','p'):
|
|
rmctx->codec_type = CODEC_AAC;
|
|
read_uint32be(fd, &rmctx->extradata_size);
|
|
skipped += 4;
|
|
read(fd, rmctx->codec_extradata, rmctx->extradata_size);
|
|
skipped += rmctx->extradata_size;
|
|
break;
|
|
|
|
case FOURCC('d','n','e','t'):
|
|
rmctx->codec_type = CODEC_AC3;
|
|
break;
|
|
|
|
default: /* Not a supported codec */
|
|
return -1;
|
|
}
|
|
|
|
|
|
DEBUGF(" flavor = %d\n",flavor);
|
|
DEBUGF(" coded_frame_size = %d\n",coded_framesize);
|
|
DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h);
|
|
DEBUGF(" frame_size = %d\n",rmctx->block_align);
|
|
DEBUGF(" sub_packet_size = %d\n",rmctx->sub_packet_size);
|
|
DEBUGF(" sample_rate= %d\n",rmctx->sample_rate);
|
|
DEBUGF(" channels= %d\n",rmctx->nb_channels);
|
|
DEBUGF(" fourcc = %s\n",fourcc2str(fourcc));
|
|
DEBUGF(" codec_extra_data_length = %d\n",rmctx->extradata_size);
|
|
if(rmctx->codec_type == CODEC_COOK) {
|
|
DEBUGF(" cook_extradata :\n");
|
|
print_cook_extradata(rmctx);
|
|
}
|
|
|
|
}
|
|
|
|
return skipped;
|
|
}
|
|
|
|
int real_parse_header(int fd, RMContext *rmctx)
|
|
{
|
|
struct real_object_t obj;
|
|
memset(&obj,0,sizeof(obj));
|
|
int res;
|
|
int skipped;
|
|
off_t curpos;
|
|
|
|
uint32_t unknown1;
|
|
uint32_t unknown2;
|
|
|
|
uint32_t max_bitrate;
|
|
uint32_t avg_bitrate = 0;
|
|
uint32_t max_packet_size;
|
|
uint32_t avg_packet_size;
|
|
uint32_t packet_count;
|
|
uint32_t duration;
|
|
uint32_t preroll;
|
|
uint32_t index_offset;
|
|
uint16_t num_streams;
|
|
uint16_t flags = 0;
|
|
|
|
uint16_t stream_id;
|
|
uint32_t start_time;
|
|
char desc[256];
|
|
char mimetype[256];
|
|
uint32_t codec_data_size;
|
|
uint32_t v;
|
|
|
|
char title[256];
|
|
char author[256];
|
|
char copyright[256];
|
|
char comment[256];
|
|
|
|
uint32_t next_data_off;
|
|
uint8_t header_end;
|
|
|
|
curpos = lseek(fd, 0, SEEK_SET);
|
|
res = real_read_object_header(fd, &obj);
|
|
|
|
if (obj.fourcc == FOURCC('.','r','a',0xfd))
|
|
{
|
|
/* Very old .ra format - not yet supported */
|
|
return -1;
|
|
}
|
|
else if (obj.fourcc != FOURCC('.','R','M','F'))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
read_uint32be(fd, &unknown1);
|
|
read_uint32be(fd, &unknown2);
|
|
|
|
DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
|
|
DEBUGF(" unknown1=%d (0x%08x)\n",unknown1,unknown1);
|
|
DEBUGF(" unknown2=%d (0x%08x)\n",unknown2,unknown2);
|
|
|
|
res = real_read_object_header(fd, &obj);
|
|
header_end = 0;
|
|
while(res)
|
|
{
|
|
DEBUGF("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos);
|
|
skipped = 10;
|
|
if(obj.fourcc == FOURCC('I','N','D','X'))
|
|
break;
|
|
switch (obj.fourcc)
|
|
{
|
|
case FOURCC('P','R','O','P'): /* File properties */
|
|
read_uint32be(fd, &max_bitrate);
|
|
read_uint32be(fd, &rmctx->bit_rate); /*avg bitrate*/
|
|
read_uint32be(fd, &max_packet_size);
|
|
read_uint32be(fd, &avg_packet_size);
|
|
read_uint32be(fd, &packet_count);
|
|
read_uint32be(fd, &rmctx->duration);
|
|
read_uint32be(fd, &preroll);
|
|
read_uint32be(fd, &index_offset);
|
|
read_uint32be(fd, &rmctx->data_offset);
|
|
read_uint16be(fd, &num_streams);
|
|
read_uint16be(fd, &rmctx->flags);
|
|
skipped += 40;
|
|
|
|
DEBUGF(" max_bitrate = %d\n",max_bitrate);
|
|
DEBUGF(" avg_bitrate = %d\n",avg_bitrate);
|
|
DEBUGF(" max_packet_size = %d\n",max_packet_size);
|
|
DEBUGF(" avg_packet_size = %d\n",avg_packet_size);
|
|
DEBUGF(" packet_count = %d\n",packet_count);
|
|
DEBUGF(" duration = %d\n",rmctx->duration);
|
|
DEBUGF(" preroll = %d\n",preroll);
|
|
DEBUGF(" index_offset = %d\n",index_offset);
|
|
DEBUGF(" data_offset = %d\n",rmctx->data_offset);
|
|
DEBUGF(" num_streams = %d\n",num_streams);
|
|
DEBUGF(" flags=0x%04x\n",flags);
|
|
break;
|
|
|
|
case FOURCC('C','O','N','T'):
|
|
/* Four strings - Title, Author, Copyright, Comment */
|
|
skipped += read_str(fd,title);
|
|
skipped += read_str(fd,author);
|
|
skipped += read_str(fd,copyright);
|
|
skipped += read_str(fd,comment);
|
|
|
|
DEBUGF(" title=\"%s\"\n",title);
|
|
DEBUGF(" author=\"%s\"\n",author);
|
|
DEBUGF(" copyright=\"%s\"\n",copyright);
|
|
DEBUGF(" comment=\"%s\"\n",comment);
|
|
break;
|
|
|
|
case FOURCC('M','D','P','R'): /* Media properties */
|
|
read_uint16be(fd,&stream_id);
|
|
skipped += 2;
|
|
read_uint32be(fd,&max_bitrate);
|
|
skipped += 4;
|
|
read_uint32be(fd,&avg_bitrate);
|
|
skipped += 4;
|
|
read_uint32be(fd,&max_packet_size);
|
|
skipped += 4;
|
|
read_uint32be(fd,&avg_packet_size);
|
|
skipped += 4;
|
|
read_uint32be(fd,&start_time);
|
|
skipped += 4;
|
|
read_uint32be(fd,&preroll);
|
|
skipped += 4;
|
|
read_uint32be(fd,&duration);
|
|
skipped += 4;
|
|
skipped += read_str(fd,desc);
|
|
skipped += read_str(fd,mimetype);
|
|
read_uint32be(fd,&codec_data_size);
|
|
skipped += 4;
|
|
//From ffmpeg: codec_pos = url_ftell(pb);
|
|
read_uint32be(fd,&v);
|
|
skipped += 4;
|
|
|
|
DEBUGF(" stream_id = 0x%04x\n",stream_id);
|
|
DEBUGF(" max_bitrate = %d\n",max_bitrate);
|
|
DEBUGF(" avg_bitrate = %d\n",avg_bitrate);
|
|
DEBUGF(" max_packet_size = %d\n",max_packet_size);
|
|
DEBUGF(" avg_packet_size = %d\n",avg_packet_size);
|
|
DEBUGF(" start_time = %d\n",start_time);
|
|
DEBUGF(" preroll = %d\n",preroll);
|
|
DEBUGF(" duration = %d\n",duration);
|
|
DEBUGF(" desc=\"%s\"\n",desc);
|
|
DEBUGF(" mimetype=\"%s\"\n",mimetype);
|
|
DEBUGF(" codec_data_size = %d\n",codec_data_size);
|
|
DEBUGF(" v=\"%s\"\n", fourcc2str(v));
|
|
|
|
if (v == FOURCC('.','r','a',0xfd))
|
|
{
|
|
skipped += real_read_audio_stream_info(fd, rmctx);
|
|
}
|
|
|
|
break;
|
|
|
|
case FOURCC('D','A','T','A'):
|
|
|
|
read_uint32be(fd,&rmctx->nb_packets);
|
|
skipped += 4;
|
|
read_uint32be(fd,&next_data_off);
|
|
skipped += 4;
|
|
if (!rmctx->nb_packets && (rmctx->flags & 4))
|
|
rmctx->nb_packets = 3600 * 25;
|
|
|
|
/***
|
|
* nb_packets correction :
|
|
* in some samples, number of packets may not exactly form
|
|
* an integer number of scrambling units. This is corrected
|
|
* by constructing a partially filled unit out of the few
|
|
* remaining samples at the end of decoding.
|
|
***/
|
|
if(rmctx->nb_packets % rmctx->sub_packet_h)
|
|
rmctx->nb_packets += rmctx->sub_packet_h - (rmctx->nb_packets % rmctx->sub_packet_h);
|
|
|
|
DEBUGF(" data_nb_packets = %d\n",rmctx->nb_packets);
|
|
DEBUGF(" next DATA offset = %d\n",next_data_off);
|
|
header_end = 1;
|
|
break;
|
|
}
|
|
if(header_end) break;
|
|
curpos = lseek(fd, obj.size - skipped, SEEK_CUR);
|
|
res = real_read_object_header(fd, &obj);
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt)
|
|
{
|
|
uint8_t unknown,packet_group;
|
|
uint16_t x;
|
|
uint16_t sps = rmctx->sub_packet_size;
|
|
uint16_t h = rmctx->sub_packet_h;
|
|
uint16_t y = rmctx->sub_packet_cnt;
|
|
uint16_t w = rmctx->audio_framesize;
|
|
int res;
|
|
do
|
|
{
|
|
y = rmctx->sub_packet_cnt;
|
|
read_uint16be(fd,&pkt->version);
|
|
read_uint16be(fd,&pkt->length);
|
|
read_uint16be(fd,&pkt->stream_number);
|
|
read_uint32be(fd,&pkt->timestamp);
|
|
DEBUGF(" version = %d\n"
|
|
" length = %d\n"
|
|
" stream = %d\n"
|
|
" timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);
|
|
|
|
if(pkt->version == 0)
|
|
{
|
|
read_uint8(fd,&packet_group);
|
|
read_uint8(fd,&pkt->flags);
|
|
}
|
|
if(pkt->version == 1)
|
|
read_uint8(fd,&unknown);
|
|
|
|
if (pkt->flags & 2) /* keyframe */
|
|
y = rmctx->sub_packet_cnt = 0;
|
|
if (!y) /* if keyframe update playback elapsed time */
|
|
rmctx->audiotimestamp = pkt->timestamp;
|
|
|
|
for(x = 0 ; x < w/sps; x++)
|
|
{
|
|
res = read(fd,pkt->data+(sps*(h*x+((h+1)/2)*(y&1)+(y>>1))), sps);
|
|
}
|
|
rmctx->audio_pkt_cnt++;
|
|
}while(++(rmctx->sub_packet_cnt) < h);
|
|
|
|
}
|
|
#endif /*TEST*/
|
|
|
|
void rm_ac3_swap_bytes(uint8_t *buf, int bufsize)
|
|
{
|
|
uint8_t *bufptr;
|
|
for (bufptr = buf; bufptr < buf + bufsize - 1; bufptr += 2)
|
|
{
|
|
bufptr[0] ^= bufptr[1];
|
|
bufptr[1] ^= bufptr[0];
|
|
bufptr[0] ^= bufptr[1];
|
|
}
|
|
}
|
|
|
|
int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
|
|
{
|
|
int consumed = 0;
|
|
int headerlen;
|
|
/* rockbox: comment 'set but unused' variables
|
|
uint8_t unknown;
|
|
*/
|
|
uint16_t x;
|
|
uint16_t sps = rmctx->sub_packet_size;
|
|
uint16_t h = rmctx->sub_packet_h;
|
|
uint16_t y = 0;
|
|
uint16_t w = rmctx->audio_framesize;
|
|
|
|
rmctx->sub_packet_cnt = 0;
|
|
rmctx->audio_pkt_cnt = 0;
|
|
|
|
do
|
|
{
|
|
y = rmctx->sub_packet_cnt;
|
|
pkt->version = rm_get_uint16be(*src);
|
|
|
|
/* Simple error checking */
|
|
if(pkt->version != 0 && pkt->version != 1)
|
|
{
|
|
DEBUGF("parsing packets failed\n");
|
|
return -1;
|
|
}
|
|
|
|
headerlen = PACKET_HEADER_SIZE + (pkt->version ? 1 : 0);
|
|
pkt->length = rm_get_uint16be(*src+2);
|
|
pkt->stream_number = rm_get_uint16be(*src+4);
|
|
pkt->timestamp = rm_get_uint32be(*src+6);
|
|
/*DEBUGF(" version = %d\n"
|
|
" length = %d\n"
|
|
" stream = %d\n"
|
|
" timestamp= %d\n\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);*/
|
|
/* unknown =*/ rm_get_uint8(*src+10);
|
|
pkt->flags = rm_get_uint8(*src+11);
|
|
|
|
if(pkt->version == 1)
|
|
/* unknown = */ rm_get_uint8(*src+12);
|
|
|
|
if (pkt->flags & 2) { /* keyframe */
|
|
if (y)
|
|
return consumed;
|
|
y = 0;
|
|
}
|
|
if (!y)
|
|
rmctx->audiotimestamp = pkt->timestamp;
|
|
|
|
/* Skip packet header */
|
|
advance_buffer(src, headerlen);
|
|
consumed += headerlen;
|
|
if (rmctx->codec_type == CODEC_COOK || rmctx->codec_type == CODEC_ATRAC) {
|
|
for(x = 0 ; x < w/sps; x++)
|
|
{
|
|
pkt->frames[h*x+((h+1)/2)*(y&1)+(y>>1)] = *src;
|
|
advance_buffer(src,sps);
|
|
consumed += sps;
|
|
}
|
|
}
|
|
else if (rmctx->codec_type == CODEC_AAC) {
|
|
rmctx->sub_packet_cnt = (rm_get_uint16be(*src) & 0xf0) >> 4;
|
|
advance_buffer(src, 2);
|
|
consumed += 2;
|
|
if (rmctx->sub_packet_cnt) {
|
|
for(x = 0; x < rmctx->sub_packet_cnt; x++) {
|
|
rmctx->sub_packet_lengths[x] = rm_get_uint16be(*src);
|
|
advance_buffer(src, 2);
|
|
consumed += 2;
|
|
}
|
|
rmctx->audio_pkt_cnt = rmctx->sub_packet_cnt;
|
|
}
|
|
break;
|
|
}
|
|
|
|
else if (rmctx->codec_type == CODEC_AC3) {
|
|
/* The byte order of the data is reversed from standard AC3 */
|
|
rm_ac3_swap_bytes(*src, pkt->length - headerlen);
|
|
break;
|
|
}
|
|
else return -1; /* invalid codec type */
|
|
|
|
rmctx->audio_pkt_cnt++;
|
|
}while(++(rmctx->sub_packet_cnt) < h);
|
|
|
|
return consumed;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void dump_rm_context(RMContext *rmctx)
|
|
{
|
|
DEBUGF("block_align = %u\n", rmctx->block_align);
|
|
DEBUGF("nb_channels = %u\n", rmctx->nb_channels);
|
|
DEBUGF("sample_rate = %u\n", rmctx->sample_rate);
|
|
DEBUGF("bit_rate = %lu\n", (unsigned long) rmctx->bit_rate );
|
|
}
|
|
#endif
|