25 typedef struct da_priv
{
30 extern void free_sh_audio(sh_audio_t
* sh
);
31 extern void resync_audio_stream(sh_audio_t
*sh_audio
);
32 extern void print_wave_header(WAVEFORMATEX
*h
);
36 int demux_audio_open(demuxer_t
* demuxer
) {
39 uint8_t hdr
[HDR_SIZE
];
40 int st_pos
= 0,frmt
= 0, n
= 0, pos
= 0, step
, mp3_freq
,mp3_chans
;
43 assert(demuxer
!= NULL
);
44 assert(demuxer
->stream
!= NULL
);
49 while(n
< 5 && ! s
->eof
) {
50 st_pos
= stream_tell(s
);
53 stream_read(s
,&hdr
[pos
],HDR_SIZE
-pos
);
57 if( hdr
[0] == 'R' && hdr
[1] == 'I' && hdr
[2] == 'F' && hdr
[3] == 'F' ) {
64 if(hdr
[0] != 'W' || hdr
[1] != 'A' || hdr
[2] != 'V' || hdr
[3] != 'E' )
67 // We found wav header. Now we can have 'fmt ' or a mp3 header
70 } else if( hdr
[0] == 'I' && hdr
[1] == 'D' && hdr
[2] == '3' && (hdr
[3] >= 2)) {
74 len
= (hdr
[0]<<21) | (hdr
[1]<<14) | (hdr
[2]<<7) | hdr
[3];
77 } else if( hdr
[0] == 'f' && hdr
[1] == 'm' && hdr
[2] == 't' && hdr
[3] == ' ' ) {
80 } else if((n
= mp_get_mp3_header(hdr
,&mp3_chans
,&mp3_freq
)) > 0) {
83 } else if( hdr
[0] == 'f' && hdr
[1] == 'L' && hdr
[2] == 'a' && hdr
[3] == 'C' ) {
88 // Add here some other audio format detection
90 memmove(hdr
,&hdr
[step
],HDR_SIZE
-step
);
97 sh_audio
= new_sh_audio(demuxer
,0);
101 sh_audio
->format
= 0x55;
102 demuxer
->movi_start
= st_pos
-HDR_SIZE
+n
;
103 sh_audio
->audio
.dwSampleSize
= 0;
104 sh_audio
->audio
.dwScale
= 1152;
105 sh_audio
->audio
.dwRate
= mp3_freq
;
106 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
107 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
108 sh_audio
->wf
->nChannels
= mp3_chans
;
109 sh_audio
->wf
->nSamplesPerSec
= mp3_freq
;
110 sh_audio
->wf
->nBlockAlign
= 1152;
111 sh_audio
->wf
->wBitsPerSample
= 16;
112 sh_audio
->wf
->cbSize
= 0;
113 for(n
= 0; n
< 5 ; n
++) {
114 pos
= mp_decode_mp3_header(hdr
);
117 stream_skip(s
,pos
-4);
120 stream_read(s
,hdr
,4);
126 stream_seek(s
,s
->end_pos
-128);
127 stream_read(s
,tag
,3);
129 if(strcmp(tag
,"TAG"))
130 demuxer
->movi_end
= s
->end_pos
;
134 demuxer
->movi_end
= stream_tell(s
)-3;
135 stream_read(s
,buf
,30);
137 demux_info_add(demuxer
,"Title",buf
);
138 stream_read(s
,buf
,30);
140 demux_info_add(demuxer
,"Artist",buf
);
141 stream_read(s
,buf
,30);
143 demux_info_add(demuxer
,"Album",buf
);
144 stream_read(s
,buf
,4);
146 demux_info_add(demuxer
,"Year",buf
);
147 stream_read(s
,buf
,30);
149 demux_info_add(demuxer
,"Comment",buf
);
150 if(buf
[28] == 0 && buf
[29] != 0) {
151 uint8_t trk
= (uint8_t)buf
[29];
152 sprintf(buf
,"%d",trk
);
153 demux_info_add(demuxer
,"Track",buf
);
155 g
= stream_read_char(s
);
156 demux_info_add(demuxer
,"Genre",genres
[g
]);
161 unsigned int chunk_type
;
162 unsigned int chunk_size
;
165 l
= stream_read_dword_le(s
);
167 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"[demux_audio] Bad wav header length: too short (%d)!!!\n",l
);
168 free_sh_audio(sh_audio
);
171 sh_audio
->wf
= w
= (WAVEFORMATEX
*)malloc(l
);
172 w
->wFormatTag
= sh_audio
->format
= stream_read_word_le(s
);
173 w
->nChannels
= sh_audio
->channels
= stream_read_word_le(s
);
174 w
->nSamplesPerSec
= sh_audio
->samplerate
= stream_read_dword_le(s
);
175 w
->nAvgBytesPerSec
= stream_read_dword_le(s
);
176 w
->nBlockAlign
= stream_read_word_le(s
);
177 w
->wBitsPerSample
= sh_audio
->samplesize
= stream_read_word_le(s
);
181 w
->cbSize
= stream_read_word_le(s
);
185 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"[demux_audio] truncated extradata (%d < %d)\n",
187 stream_read(s
,(char*)((char*)(w
)+sizeof(WAVEFORMATEX
)),l
);
190 stream_read(s
,(char*)((char*)(w
)+sizeof(WAVEFORMATEX
)),w
->cbSize
);
196 if(verbose
>0) print_wave_header(w
);
201 chunk_type
= stream_read_fourcc(demuxer
->stream
);
202 chunk_size
= stream_read_dword_le(demuxer
->stream
);
203 if (chunk_type
!= mmioFOURCC('d', 'a', 't', 'a'))
204 stream_skip(demuxer
->stream
, chunk_size
);
205 } while (chunk_type
!= mmioFOURCC('d', 'a', 't', 'a'));
206 demuxer
->movi_start
= stream_tell(s
);
207 demuxer
->movi_end
= s
->end_pos
;
208 // printf("wav: %X .. %X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);
211 sh_audio
->format
= mmioFOURCC('f', 'L', 'a', 'C');
212 demuxer
->movi_start
= stream_tell(s
);
213 demuxer
->movi_end
= s
->end_pos
;
217 priv
= (da_priv_t
*)malloc(sizeof(da_priv_t
));
220 demuxer
->priv
= priv
;
221 demuxer
->audio
->id
= 0;
222 demuxer
->audio
->sh
= sh_audio
;
223 sh_audio
->ds
= demuxer
->audio
;
224 sh_audio
->samplerate
= sh_audio
->audio
.dwRate
;
226 if(stream_tell(s
) != demuxer
->movi_start
)
227 stream_seek(s
,demuxer
->movi_start
);
229 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_audio: audio data 0x%X - 0x%X \n",demuxer
->movi_start
,demuxer
->movi_end
);
235 int demux_audio_fill_buffer(demux_stream_t
*ds
) {
236 sh_audio_t
* sh_audio
;
242 assert(ds
->sh
!= NULL
);
243 assert(ds
->demuxer
!= NULL
);
250 if(s
->eof
|| (demux
->movi_end
&& stream_tell(s
) >= demux
->movi_end
) )
255 while(! s
->eof
|| (demux
->movi_end
&& stream_tell(s
) >= demux
->movi_end
) ) {
258 stream_read(s
,hdr
,4);
259 len
= mp_decode_mp3_header(hdr
);
264 if(s
->eof
|| (demux
->movi_end
&& stream_tell(s
) >= demux
->movi_end
) )
266 dp
= new_demux_packet(len
);
267 memcpy(dp
->buffer
,hdr
,4);
268 stream_read(s
,dp
->buffer
+ 4,len
-4);
269 priv
->last_pts
= priv
->last_pts
< 0 ? 0 : priv
->last_pts
+ 1152/(float)sh_audio
->samplerate
;
270 ds
->pts
= priv
->last_pts
- (ds_tell_pts(demux
->audio
)-sh_audio
->a_in_buffer_len
)/(float)sh_audio
->i_bps
;
271 ds_add_packet(ds
,dp
);
276 int l
= sh_audio
->wf
->nAvgBytesPerSec
;
277 demux_packet_t
* dp
= new_demux_packet(l
);
278 l
= stream_read(s
,dp
->buffer
,l
);
279 resize_demux_packet(dp
, l
);
280 priv
->last_pts
= priv
->last_pts
< 0 ? 0 : priv
->last_pts
+ l
/(float)sh_audio
->i_bps
;
281 ds
->pts
= priv
->last_pts
- (ds_tell_pts(demux
->audio
)-sh_audio
->a_in_buffer_len
)/(float)sh_audio
->i_bps
;
282 ds_add_packet(ds
,dp
);
287 demux_packet_t
* dp
= new_demux_packet(l
);
288 l
= stream_read(s
,dp
->buffer
,l
);
289 resize_demux_packet(dp
, l
);
290 priv
->last_pts
= priv
->last_pts
< 0 ? 0 : priv
->last_pts
+ l
/(float)sh_audio
->i_bps
;
291 ds
->pts
= priv
->last_pts
- (ds_tell_pts(demux
->audio
)-sh_audio
->a_in_buffer_len
)/(float)sh_audio
->i_bps
;
292 ds_add_packet(ds
,dp
);
296 printf("Audio demuxer : unknown format %d\n",priv
->frmt
);
303 static void high_res_mp3_seek(demuxer_t
*demuxer
,float time
) {
306 da_priv_t
* priv
= demuxer
->priv
;
307 sh_audio_t
* sh
= (sh_audio_t
*)demuxer
->audio
->sh
;
309 nf
= time
*sh
->samplerate
/1152;
311 stream_read(demuxer
->stream
,hdr
,4);
312 len
= mp_decode_mp3_header(hdr
);
314 stream_skip(demuxer
->stream
,-3);
317 stream_skip(demuxer
->stream
,len
-4);
318 priv
->last_pts
+= 1152/(float)sh
->samplerate
;
323 void demux_audio_seek(demuxer_t
*demuxer
,float rel_seek_secs
,int flags
){
324 sh_audio_t
* sh_audio
;
330 if(!(sh_audio
= demuxer
->audio
->sh
))
333 priv
= demuxer
->priv
;
335 if(priv
->frmt
== MP3
&& hr_mp3_seek
&& !(flags
& 2)) {
336 len
= (flags
& 1) ? rel_seek_secs
- priv
->last_pts
: rel_seek_secs
;
338 stream_seek(s
,demuxer
->movi_start
);
339 len
= priv
->last_pts
+ len
;
343 high_res_mp3_seek(demuxer
,len
);
344 sh_audio
->delay
= priv
->last_pts
- (ds_tell_pts(demuxer
->audio
)-sh_audio
->a_in_buffer_len
)/(float)sh_audio
->i_bps
;
345 resync_audio_stream(sh_audio
);
349 base
= flags
&1 ? demuxer
->movi_start
: stream_tell(s
);
351 pos
= base
+ ((demuxer
->movi_end
- demuxer
->movi_start
)*rel_seek_secs
);
353 pos
= base
+ (rel_seek_secs
*sh_audio
->i_bps
);
355 if(demuxer
->movi_end
&& pos
>= demuxer
->movi_end
) {
356 pos
= demuxer
->movi_end
;
357 //sh_audio->delay = (stream_tell(s) - demuxer->movi_start)/(float)sh_audio->i_bps;
359 } else if(pos
< demuxer
->movi_start
)
360 pos
= demuxer
->movi_start
;
362 priv
->last_pts
= (pos
-demuxer
->movi_start
)/(float)sh_audio
->i_bps
;
363 sh_audio
->delay
= priv
->last_pts
- (ds_tell_pts(demuxer
->audio
)-sh_audio
->a_in_buffer_len
)/(float)sh_audio
->i_bps
;
367 pos
-= (pos
% (sh_audio
->channels
* sh_audio
->samplesize
) );
368 // We need to decrease the pts by one step to make it the "last one"
369 priv
->last_pts
-= sh_audio
->wf
->nAvgBytesPerSec
/(float)sh_audio
->i_bps
;
375 resync_audio_stream(sh_audio
);
379 void demux_close_audio(demuxer_t
* demuxer
) {
380 da_priv_t
* priv
= demuxer
->priv
;
387 int demux_audio_control(demuxer_t
*demuxer
,int cmd
, void *arg
){
388 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
389 int audio_length
= demuxer
->movi_end
/ sh_audio
->i_bps
;
390 da_priv_t
* priv
= demuxer
->priv
;
393 case DEMUXER_CTRL_GET_TIME_LENGTH
:
394 if (audio_length
<=0) return DEMUXER_CTRL_DONTKNOW
;
395 *((unsigned long *)arg
)=(unsigned long)audio_length
;
396 return DEMUXER_CTRL_GUESS
;
398 case DEMUXER_CTRL_GET_PERCENT_POS
:
400 return DEMUXER_CTRL_DONTKNOW
;
401 *((int *)arg
)=(int)( (priv
->last_pts
*100) / audio_length
);
402 return DEMUXER_CTRL_OK
;
405 return DEMUXER_CTRL_NOTIMPL
;