1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-25 04:38:01 +00:00

Move audio packets reordering from codec interface to demuxers for real

files (old and new format), pass only real extradata to the codec
Enable cook codec from lavc, prefer lavc codecs for 14_4 and 28_8
formats. Disable internal 28_8, it's broken now and will be removed soon


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@17150 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
rtognimp 2005-12-09 16:25:37 +00:00
parent c5561f6bf1
commit bda32bc73a
4 changed files with 199 additions and 205 deletions

View File

@ -2100,11 +2100,32 @@ audiocodec qtmace6
driver qtaudio driver qtaudio
dll "QuickTime.qts" dll "QuickTime.qts"
audiocodec ffra144
info "FFmpeg RealAudio 1.0"
status working
format 0x345F3431 ; "14_4"
driver ffmpeg
dll "real_144"
audiocodec ffra288
info "FFmpeg RealAudio 2.0"
status working
format 0x385F3832 ; "28_8"
driver ffmpeg
dll "real_288"
audiocodec ffcook
info "FFmpeg COOK audio decoder"
status working
format 0x6B6F6F63 ; "cook"
driver ffmpeg
dll "cook"
audiocodec mpra1428 audiocodec mpra1428
info "RealAudio 1.0 / 2.0 native decoder" info "RealAudio 1.0 / 2.0 native decoder"
status working status working
format 0x345F3431 ; "14_4" format 0x345F3431 ; "14_4"
format 0x385F3832 ; "28_8" ; format 0x385F3832 ; "28_8" ; broken after demuxer changes
driver ra1428 driver ra1428
audiocodec ra144 audiocodec ra144
@ -2376,20 +2397,6 @@ audiocodec ffmac6
driver ffmpeg driver ffmpeg
dll "mace6" dll "mace6"
audiocodec ffra144
info "FFmpeg RealAudio 1.0"
status untested
format 0x345F3431 ; "14_4"
driver ffmpeg
dll "real_144"
audiocodec ffra288
info "FFmpeg RealAudio 2.0"
status crashing
format 0x385F3832 ; "28_8"
driver ffmpeg
dll "real_288"
audiocodec ffsonic audiocodec ffsonic
info "FFmpeg Sonic" info "FFmpeg Sonic"
status untested status untested

View File

@ -291,10 +291,10 @@ static int preinit(sh_audio_t *sh){
sh->wf->wBitsPerSample, sh->wf->wBitsPerSample,
sh->wf->nChannels, sh->wf->nChannels,
100, // quality 100, // quality
((short*)(sh->wf+1))[0], // subpacket size sh->wf->nBlockAlign, // subpacket size
((short*)(sh->wf+1))[3], // coded frame size sh->wf->nBlockAlign, // coded frame size
((short*)(sh->wf+1))[4], // codec data length sh->wf->cbSize, // codec data length
((char*)(sh->wf+1))+10 // extras (char*)(sh->wf+1) // extras
}; };
#ifdef USE_WIN32DLL #ifdef USE_WIN32DLL
wra_init_t winit_data={ wra_init_t winit_data={
@ -302,10 +302,10 @@ static int preinit(sh_audio_t *sh){
sh->wf->wBitsPerSample, sh->wf->wBitsPerSample,
sh->wf->nChannels, sh->wf->nChannels,
100, // quality 100, // quality
((short*)(sh->wf+1))[0], // subpacket size sh->wf->nBlockAlign, // subpacket size
((short*)(sh->wf+1))[3], // coded frame size sh->wf->nBlockAlign, // coded frame size
((short*)(sh->wf+1))[4], // codec data length sh->wf->cbSize, // codec data length
((char*)(sh->wf+1))+10 // extras (char*)(sh->wf+1) // extras
}; };
#endif #endif
#ifdef USE_WIN32DLL #ifdef USE_WIN32DLL
@ -336,42 +336,35 @@ static int preinit(sh_audio_t *sh){
raSetPwd(sh->context,"Ardubancel Quazanga"); // set password... lol. raSetPwd(sh->context,"Ardubancel Quazanga"); // set password... lol.
} }
if (sh->format == mmioFOURCC('s','i','p','r')) {
short flavor;
if (sh->wf->nAvgBytesPerSec > 1531)
flavor = 3;
else if (sh->wf->nAvgBytesPerSec > 937)
flavor = 1;
else if (sh->wf->nAvgBytesPerSec > 719)
flavor = 0;
else
flavor = 2;
mp_msg(MSGT_DECAUDIO,MSGL_V,"Got sipr flavor %d from bitrate %d\n",flavor, sh->wf->nAvgBytesPerSec);
#ifdef USE_WIN32DLL #ifdef USE_WIN32DLL
if (dll_type == 1) if (dll_type == 1)
result=wraSetFlavor(sh->context,((short*)(sh->wf+1))[2]); result=wraSetFlavor(sh->context,flavor);
else else
#endif #endif
result=raSetFlavor(sh->context,((short*)(sh->wf+1))[2]); result=raSetFlavor(sh->context,flavor);
if(result){ if(result){
mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder flavor setup failed, error code: 0x%X\n",result); mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder flavor setup failed, error code: 0x%X\n",result);
return 0; return 0;
} }
} // sipr flavor
#ifdef USE_WIN32DLL sh->i_bps=sh->wf->nAvgBytesPerSec;
if (dll_type == 1)
prop=wraGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0,&len);
else
#endif
prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0,&len);
mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Audio codec: [%d] %s\n",((short*)(sh->wf+1))[2],prop);
#ifdef USE_WIN32DLL
if (dll_type == 1)
prop=wraGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],1,&len);
else
#endif
prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],1,&len);
if(prop){
sh->i_bps=((*((int*)prop))+4)/8;
mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Audio bitrate: %5.3f kbit/s (%d bps) \n",(*((int*)prop))*0.001f,sh->i_bps);
} else
sh->i_bps=12000; // dunno :((( [12000 seems to be OK for crash.rmvb too]
// prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0x13,&len);
// mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Samples/block?: %d \n",(*((int*)prop)));
sh->audio_out_minsize=128000; // no idea how to get... :( sh->audio_out_minsize=128000; // no idea how to get... :(
sh->audio_in_minsize=((short*)(sh->wf+1))[1]*sh->wf->nBlockAlign; sh->audio_in_minsize = sh->wf->nBlockAlign;
return 1; // return values: 1=OK 0=ERROR return 1; // return values: 1=OK 0=ERROR
} }
@ -413,83 +406,16 @@ static void uninit(sh_audio_t *sh){
rv_handle = NULL; rv_handle = NULL;
} }
static unsigned char sipr_swaps[38][2]={
{0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
{13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
{25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
{42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
{77,80} };
static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){ static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){
int result; int result;
int len=-1; int len=-1;
int sps=((short*)(sh->wf+1))[0];
int w=sh->wf->nBlockAlign; // 5
int h=((short*)(sh->wf+1))[1];
int cfs=((short*)(sh->wf+1))[3];
// printf("bs=%d sps=%d w=%d h=%d \n",sh->wf->nBlockAlign,sps,w,h);
#if 1
if(sh->a_in_buffer_len<=0){
if (sh->ds->eof) return 0;
// fill the buffer!
if (sh->format == mmioFOURCC('1','4','_','4')) {
demux_read_data(sh->ds, sh->a_in_buffer, sh->wf->nBlockAlign);
sh->a_in_buffer_size=
sh->a_in_buffer_len=sh->wf->nBlockAlign;
} else
if (sh->format == mmioFOURCC('2','8','_','8')) {
int i,j;
for (j = 0; j < h; j++)
for (i = 0; i < h/2; i++)
demux_read_data(sh->ds, sh->a_in_buffer+i*2*w+j*cfs, cfs);
sh->a_in_buffer_size=
sh->a_in_buffer_len=sh->wf->nBlockAlign*h;
} else
if((sh->format == mmioFOURCC('s','i','p','r')) || !sps){ // is !sps really needed? (cook with sipr matrix?)
// 'sipr' way
int j,n;
int bs=h*w*2/96; // nibbles per subpacket
unsigned char *p=sh->a_in_buffer;
demux_read_data(sh->ds, p, h*w);
for(n=0;n<38;n++){
int i=bs*sipr_swaps[n][0];
int o=bs*sipr_swaps[n][1];
// swap nibbles of block 'i' with 'o' TODO: optimize
for(j=0;j<bs;j++){
int x=(i&1) ? (p[(i>>1)]>>4) : (p[(i>>1)]&15);
int y=(o&1) ? (p[(o>>1)]>>4) : (p[(o>>1)]&15);
if(o&1) p[(o>>1)]=(p[(o>>1)]&0x0F)|(x<<4);
else p[(o>>1)]=(p[(o>>1)]&0xF0)|x;
if(i&1) p[(i>>1)]=(p[(i>>1)]&0x0F)|(y<<4);
else p[(i>>1)]=(p[(i>>1)]&0xF0)|y;
++i;++o;
}
}
sh->a_in_buffer_size=
sh->a_in_buffer_len=w*h;
} else {
// 'cook' way
int x,y;
w/=sps;
for(y=0;y<h;y++)
for(x=0;x<w;x++){
demux_read_data(sh->ds, sh->a_in_buffer+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
}
sh->a_in_buffer_size=
sh->a_in_buffer_len=w*h*sps;
}
}
#else
if(sh->a_in_buffer_len<=0){ if(sh->a_in_buffer_len<=0){
// fill the buffer! // fill the buffer!
demux_read_data(sh->ds, sh->a_in_buffer, sh->wf->nBlockAlign); demux_read_data(sh->ds, sh->a_in_buffer, sh->wf->nBlockAlign);
sh->a_in_buffer_size= sh->a_in_buffer_size=
sh->a_in_buffer_len=sh->wf->nBlockAlign; sh->a_in_buffer_len=sh->wf->nBlockAlign;
} }
#endif
#ifdef USE_WIN32DLL #ifdef USE_WIN32DLL
if (dll_type == 1) if (dll_type == 1)

View File

@ -38,6 +38,13 @@ Video codecs: (supported by RealPlayer8 for Linux)
#define MAX_STREAMS 32 #define MAX_STREAMS 32
static unsigned char sipr_swaps[38][2]={
{0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
{13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
{25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
{42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
{77,80} };
typedef struct { typedef struct {
int timestamp; int timestamp;
int offset; int offset;
@ -92,6 +99,18 @@ typedef struct {
int a_bitrate; ///< Audio bitrate int a_bitrate; ///< Audio bitrate
int v_bitrate; ///< Video bitrate int v_bitrate; ///< Video bitrate
int stream_switch; ///< Flag used to switch audio/video demuxing int stream_switch; ///< Flag used to switch audio/video demuxing
/**
* Used to reorder audio data
*/
int sub_packet_size[MAX_STREAMS]; ///< sub packet size, per stream
int sub_packet_h[MAX_STREAMS]; ///< number of coded frames per block
int coded_framesize[MAX_STREAMS]; ///< coded frame size, per stream
int audiopk_size[MAX_STREAMS]; ///< audio packet size
unsigned char *audio_buf; ///< place to store reordered audio data
int audio_timestamp; ///< timestamp for all audio packets in a block
int sub_packet_cnt; ///< number of subpacket already received
int audio_filepos; ///< file position of first audio packet in block
} real_priv_t; } real_priv_t;
/* originally from FFmpeg */ /* originally from FFmpeg */
@ -531,6 +550,8 @@ static int demux_real_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds)
int version; int version;
int reserved; int reserved;
demux_packet_t *dp; demux_packet_t *dp;
int x, sps, cfs, sph, spc, w;
int audioreorder_getnextpk = 0;
while(1){ while(1){
@ -622,6 +643,11 @@ got_audio:
ds=demuxer->audio; ds=demuxer->audio;
mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is audio (id: %d)\n", stream_id); mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is audio (id: %d)\n", stream_id);
if (flags & 2) {
priv->sub_packet_cnt = 0;
audioreorder_getnextpk = 0;
}
// parse audio chunk: // parse audio chunk:
{ {
#ifdef CRACK_MATRIX #ifdef CRACK_MATRIX
@ -649,8 +675,79 @@ got_audio:
free(sub_packet_lengths); free(sub_packet_lengths);
return 1; return 1;
} }
if ((((sh_audio_t*)ds->sh)->format == mmioFOURCC('2', '8', '_', '8')) ||
(((sh_audio_t*)ds->sh)->format == mmioFOURCC('c', 'o', 'o', 'k')) ||
(((sh_audio_t*)ds->sh)->format == mmioFOURCC('a', 't', 'r', 'c')) ||
(((sh_audio_t*)ds->sh)->format == mmioFOURCC('s', 'i', 'p', 'r'))) {
sps = priv->sub_packet_size[stream_id];
sph = priv->sub_packet_h[stream_id];
cfs = priv->coded_framesize[stream_id];
w = priv->audiopk_size[stream_id];
spc = priv->sub_packet_cnt;
switch (((sh_audio_t*)ds->sh)->format) {
case mmioFOURCC('2', '8', '_', '8'):
for (x = 0; x < sph / 2; x++)
stream_read(demuxer->stream, priv->audio_buf + x * 2 * w + spc * cfs, cfs);
break;
case mmioFOURCC('c', 'o', 'o', 'k'):
case mmioFOURCC('a', 't', 'r', 'c'):
for (x = 0; x < w / sps; x++)
stream_read(demuxer->stream, priv->audio_buf + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) +
(spc >> 1)), sps);
break;
case mmioFOURCC('s', 'i', 'p', 'r'):
stream_read(demuxer->stream, priv->audio_buf + spc * w, w);
if (spc == sph - 1) {
int n;
int bs = sph * w * 2 / 96; // nibbles per subpacket
// Perform reordering
for(n=0; n < 38; n++) {
int j;
int i = bs * sipr_swaps[n][0];
int o = bs * sipr_swaps[n][1];
// swap nibbles of block 'i' with 'o' TODO: optimize
for(j = 0;j < bs; j++) {
int x = (i & 1) ? (priv->audio_buf[i >> 1] >> 4) : (priv->audio_buf[i >> 1] & 0x0F);
int y = (o & 1) ? (priv->audio_buf[o >> 1] >> 4) : (priv->audio_buf[o >> 1] & 0x0F);
if(o & 1)
priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0x0F) | (x << 4);
else
priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0xF0) | x;
if(i & 1)
priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0x0F) | (y << 4);
else
priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0xF0) | y;
++i; ++o;
}
}
}
break;
}
priv->audio_need_keyframe = 0;
priv->audio_timestamp = timestamp / 1000.0f;
priv->a_pts = timestamp; // All packets in a block have the same timestamp
if (priv->sub_packet_cnt == 0)
priv->audio_filepos = demuxer->filepos;
if (++(priv->sub_packet_cnt) < sph)
audioreorder_getnextpk = 1;
else {
int apk_usize = ((WAVEFORMATEX*)((sh_audio_t*)ds->sh)->wf)->nBlockAlign;
audioreorder_getnextpk = 0;
priv->sub_packet_cnt = 0;
// Release all the audio packets
for (x = 0; x < sph*w/apk_usize; x++) {
dp = new_demux_packet(apk_usize);
memcpy(dp->buffer, priv->audio_buf + x * apk_usize, apk_usize);
dp->pts = x ? 0 : priv->audio_timestamp;
dp->pos = priv->audio_filepos; // all equal
dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe
ds_add_packet(ds, dp);
}
}
} else { // Not a codec that require reordering
dp = new_demux_packet(len); dp = new_demux_packet(len);
stream_read(demuxer->stream, dp->buffer, len); stream_read(demuxer->stream, dp->buffer, len);
#ifdef CRACK_MATRIX #ifdef CRACK_MATRIX
mp_msg(MSGT_DEMUX, MSGL_V,"*** audio block len=%d\n",len); mp_msg(MSGT_DEMUX, MSGL_V,"*** audio block len=%d\n",len);
{ // HACK - used for reverse engineering the descrambling matrix { // HACK - used for reverse engineering the descrambling matrix
@ -691,6 +788,8 @@ got_audio:
dp->pos = demuxer->filepos; dp->pos = demuxer->filepos;
dp->flags = (flags & 0x2) ? 0x10 : 0; dp->flags = (flags & 0x2) ? 0x10 : 0;
ds_add_packet(ds, dp); ds_add_packet(ds, dp);
} // codec_id check, codec default case
} }
// we will not use audio index if we use -idx and have a video // we will not use audio index if we use -idx and have a video
if(!demuxer->video->sh && index_mode == 2 && (unsigned)demuxer->audio->id < MAX_STREAMS) if(!demuxer->video->sh && index_mode == 2 && (unsigned)demuxer->audio->id < MAX_STREAMS)
@ -706,6 +805,10 @@ got_audio:
priv->stream_switch = 1; priv->stream_switch = 1;
} }
// If we're reordering audio packets and we need more data get it
if (audioreorder_getnextpk)
continue;
return 1; return 1;
} }
@ -933,6 +1036,7 @@ if(stream_id<256){
demuxer->audio->id=stream_id; demuxer->audio->id=stream_id;
sh->ds=demuxer->audio; sh->ds=demuxer->audio;
demuxer->audio->sh=sh; demuxer->audio->sh=sh;
priv->audio_buf = malloc(priv->sub_packet_h[demuxer->audio->id] * priv->audiopk_size[demuxer->audio->id]);
mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM audio ID = %d\n",stream_id); mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM audio ID = %d\n",stream_id);
goto got_audio; goto got_audio;
} }
@ -1260,30 +1364,11 @@ static demuxer_t* demux_open_real(demuxer_t* demuxer)
sh->wf->nChannels = sh->channels; sh->wf->nChannels = sh->channels;
sh->wf->wBitsPerSample = sh->samplesize*8; sh->wf->wBitsPerSample = sh->samplesize*8;
sh->wf->nSamplesPerSec = sh->samplerate; sh->wf->nSamplesPerSec = sh->samplerate;
sh->wf->nAvgBytesPerSec = bitrate; sh->wf->nAvgBytesPerSec = bitrate/8;
sh->wf->nBlockAlign = frame_size; sh->wf->nBlockAlign = frame_size;
sh->wf->cbSize = 0; sh->wf->cbSize = 0;
sh->format = MKTAG(buf[0], buf[1], buf[2], buf[3]); sh->format = MKTAG(buf[0], buf[1], buf[2], buf[3]);
#if 0
switch (sh->format){
case MKTAG('d', 'n', 'e', 't'):
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET (AC3 with low-bitrate extension)\n");
break;
case MKTAG('s', 'i', 'p', 'r'):
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: SiproLab's ACELP.net\n");
break;
case MKTAG('c', 'o', 'o', 'k'):
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Real's GeneralCooker (?) (RealAudio G2?) (unsupported)\n");
break;
case MKTAG('a', 't', 'r', 'c'):
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Sony ATRAC3 (RealAudio 8) (unsupported)\n");
break;
default:
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%s)\n", buf);
}
#endif
switch (sh->format) switch (sh->format)
{ {
case MKTAG('d', 'n', 'e', 't'): case MKTAG('d', 'n', 'e', 't'):
@ -1291,74 +1376,40 @@ static demuxer_t* demux_open_real(demuxer_t* demuxer)
// sh->format = 0x2000; // sh->format = 0x2000;
break; break;
case MKTAG('1', '4', '_', '4'): case MKTAG('1', '4', '_', '4'):
sh->wf->cbSize = 10; sh->wf->nBlockAlign = 0x14;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);
((short*)(sh->wf+1))[0]=0;
((short*)(sh->wf+1))[1]=240;
((short*)(sh->wf+1))[2]=0;
((short*)(sh->wf+1))[3]=0x14;
((short*)(sh->wf+1))[4]=0;
break; break;
case MKTAG('2', '8', '_', '8'): case MKTAG('2', '8', '_', '8'):
sh->wf->cbSize = 10; sh->wf->nBlockAlign = coded_frame_size;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); priv->sub_packet_size[stream_id] = sub_packet_size;
((short*)(sh->wf+1))[0]=sub_packet_size; priv->sub_packet_h[stream_id] = sub_packet_h;
((short*)(sh->wf+1))[1]=sub_packet_h; priv->coded_framesize[stream_id] = coded_frame_size;
((short*)(sh->wf+1))[2]=flavor; priv->audiopk_size[stream_id] = frame_size;
((short*)(sh->wf+1))[3]=coded_frame_size;
((short*)(sh->wf+1))[4]=0;
break; break;
case MKTAG('s', 'i', 'p', 'r'): case MKTAG('s', 'i', 'p', 'r'):
#if 0
sh->format = 0x130;
/* for buggy directshow loader */
sh->wf->cbSize = 4;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);
sh->wf->wBitsPerSample = 0;
sh->wf->nAvgBytesPerSec = 1055;
sh->wf->nBlockAlign = 19;
// sh->wf->nBlockAlign = frame_size / 288;
buf[0] = 30;
buf[1] = 1;
buf[2] = 1;
buf[3] = 0;
memcpy((sh->wf+18), (char *)&buf[0], 4);
// sh->wf[sizeof(WAVEFORMATEX)+1] = 30;
// sh->wf[sizeof(WAVEFORMATEX)+2] = 1;
// sh->wf[sizeof(WAVEFORMATEX)+3] = 1;
// sh->wf[sizeof(WAVEFORMATEX)+4] = 0;
break;
#endif
case MKTAG('a', 't', 'r', 'c'): case MKTAG('a', 't', 'r', 'c'):
#if 0
sh->format = 0x270;
/* 14 bytes extra header needed ! */
sh->wf->cbSize = 14;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);
sh->wf->nAvgBytesPerSec = 16537; // 8268
sh->wf->nBlockAlign = 384; // 192
sh->wf->wBitsPerSample = 0; /* from AVI created by VirtualDub */
break;
#endif
case MKTAG('c', 'o', 'o', 'k'): case MKTAG('c', 'o', 'o', 'k'):
// realaudio codec plugins - common: // realaudio codec plugins - common:
// sh->wf->cbSize = 4+2+24;
stream_skip(demuxer->stream,3); // Skip 3 unknown bytes stream_skip(demuxer->stream,3); // Skip 3 unknown bytes
if (version==5) if (version==5)
stream_skip(demuxer->stream,1); // Skip 1 additional unknown byte stream_skip(demuxer->stream,1); // Skip 1 additional unknown byte
codecdata_length=stream_read_dword(demuxer->stream); codecdata_length=stream_read_dword(demuxer->stream);
sh->wf->cbSize = 10+codecdata_length; sh->wf->cbSize = codecdata_length;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);
((short*)(sh->wf+1))[0]=sub_packet_size; stream_read(demuxer->stream, ((char*)(sh->wf+1)), codecdata_length); // extras
((short*)(sh->wf+1))[1]=sub_packet_h; if ((sh->format == MKTAG('a', 't', 'r', 'c')) ||
((short*)(sh->wf+1))[2]=flavor; (sh->format == MKTAG('c', 'o', 'o', 'k')))
((short*)(sh->wf+1))[3]=coded_frame_size; sh->wf->nBlockAlign = sub_packet_size;
((short*)(sh->wf+1))[4]=codecdata_length; else
// stream_read(demuxer->stream, ((char*)(sh->wf+1))+6, 24); // extras sh->wf->nBlockAlign = coded_frame_size;
stream_read(demuxer->stream, ((char*)(sh->wf+1))+10, codecdata_length); // extras
priv->sub_packet_size[stream_id] = sub_packet_size;
priv->sub_packet_h[stream_id] = sub_packet_h;
priv->coded_framesize[stream_id] = coded_frame_size;
priv->audiopk_size[stream_id] = frame_size;
break; break;
case MKTAG('r', 'a', 'a', 'c'): case MKTAG('r', 'a', 'a', 'c'):
case MKTAG('r', 'a', 'c', 'p'): case MKTAG('r', 'a', 'c', 'p'):
/* This is just AAC. The two or five bytes of */ /* This is just AAC. The two or five bytes of */
@ -1397,6 +1448,7 @@ static demuxer_t* demux_open_real(demuxer_t* demuxer)
demuxer->audio->id=stream_id; demuxer->audio->id=stream_id;
sh->ds=demuxer->audio; sh->ds=demuxer->audio;
demuxer->audio->sh=sh; demuxer->audio->sh=sh;
priv->audio_buf = malloc(priv->sub_packet_h[demuxer->audio->id] * priv->audiopk_size[demuxer->audio->id]);
} }
++a_streams; ++a_streams;

View File

@ -36,6 +36,7 @@ typedef struct {
unsigned short frame_size; unsigned short frame_size;
unsigned short sub_packet_size; unsigned short sub_packet_size;
char genr[4]; char genr[4];
char * audio_buf;
} ra_priv_t; } ra_priv_t;
@ -68,6 +69,7 @@ static int demux_ra_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds)
sh_audio_t *sh = ds->sh; sh_audio_t *sh = ds->sh;
WAVEFORMATEX *wf = sh->wf; WAVEFORMATEX *wf = sh->wf;
demux_packet_t *dp; demux_packet_t *dp;
int x, y;
if (demuxer->stream->eof) if (demuxer->stream->eof)
return 0; return 0;
@ -75,6 +77,21 @@ static int demux_ra_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds)
len = wf->nBlockAlign; len = wf->nBlockAlign;
demuxer->filepos = stream_tell(demuxer->stream); demuxer->filepos = stream_tell(demuxer->stream);
if (sh->format == FOURCC_288) {
for (y = 0; y < ra_priv->sub_packet_h; y++)
for (x = 0; x < ra_priv->sub_packet_h / 2; x++)
stream_read(demuxer->stream, ra_priv->audio_buf + x * 2 *ra_priv->frame_size +
y * ra_priv->coded_framesize, ra_priv->coded_framesize);
// Release all the audio packets
for (x = 0; x < ra_priv->sub_packet_h * ra_priv->frame_size / len; x++) {
dp = new_demux_packet(len);
memcpy(dp->buffer, ra_priv->audio_buf + x * len, len);
dp->pts = x ? 0 : demuxer->filepos / ra_priv->data_size;
dp->pos = demuxer->filepos; // all equal
dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe
ds_add_packet(ds, dp);
}
} else {
dp = new_demux_packet(len); dp = new_demux_packet(len);
stream_read(demuxer->stream, dp->buffer, len); stream_read(demuxer->stream, dp->buffer, len);
@ -82,6 +99,7 @@ static int demux_ra_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds)
dp->pos = demuxer->filepos; dp->pos = demuxer->filepos;
dp->flags = 0; dp->flags = 0;
ds_add_packet(ds, dp); ds_add_packet(ds, dp);
}
return 1; return 1;
} }
@ -234,23 +252,12 @@ static demuxer_t* demux_open_ra(demuxer_t* demuxer)
switch (sh->format) { switch (sh->format) {
case FOURCC_144: case FOURCC_144:
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 14_4\n"); mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 14_4\n");
sh->wf->cbSize = 10/*+codecdata_length*/; sh->wf->nBlockAlign = 0x14;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);
((short*)(sh->wf+1))[0]=0;
((short*)(sh->wf+1))[1]=240;
((short*)(sh->wf+1))[2]=0;
((short*)(sh->wf+1))[3]=0x14;
((short*)(sh->wf+1))[4]=0;
break; break;
case FOURCC_288: case FOURCC_288:
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 28_8\n"); mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 28_8\n");
sh->wf->cbSize = 10/*+codecdata_length*/; sh->wf->nBlockAlign = ra_priv->coded_framesize;
sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); ra_priv->audio_buf = malloc(ra_priv->sub_packet_h * ra_priv->frame_size);
((short*)(sh->wf+1))[0]=0;
((short*)(sh->wf+1))[1]=ra_priv->sub_packet_h;
((short*)(sh->wf+1))[2]=ra_priv->codec_flavor;
((short*)(sh->wf+1))[3]=ra_priv->coded_framesize;
((short*)(sh->wf+1))[4]=0;
break; break;
case FOURCC_DNET: case FOURCC_DNET:
mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET -> AC3\n"); mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET -> AC3\n");
@ -276,9 +283,11 @@ static void demux_close_ra(demuxer_t *demuxer)
{ {
ra_priv_t* ra_priv = demuxer->priv; ra_priv_t* ra_priv = demuxer->priv;
if (ra_priv) if (ra_priv) {
if (ra_priv->audio_buf)
free (ra_priv->audio_buf);
free(ra_priv); free(ra_priv);
}
return; return;
} }