8 #include "stream/stream.h"
13 #include "libavutil/intreadwrite.h"
24 typedef struct da_priv
{
29 //! rather arbitrary value for maximum length of wav-format headers
30 #define MAX_WAVHDR_LEN (1 * 1024 * 1024)
32 //! how many valid frames in a row we need before accepting as valid MP3
33 #define MIN_MP3_HDRS 12
35 //! Used to describe a potential (chain of) MP3 headers we found
36 typedef struct mp3_hdr
{
37 off_t frame_pos
; // start of first frame in this "chain" of headers
38 off_t next_frame_pos
; // here we expect the next header with same parameters
44 int cons_hdrs
; // if this reaches MIN_MP3_HDRS we accept as MP3 file
48 extern void print_wave_header(WAVEFORMATEX
*h
, int verbose_level
);
53 * \brief free a list of MP3 header descriptions
54 * \param list pointer to the head-of-list pointer
56 static void free_mp3_hdrs(mp3_hdr_t
**list
) {
66 * \brief add another potential MP3 header to our list
67 * If it fits into an existing chain this one is expanded otherwise
68 * a new one is created.
69 * All entries that expected a MP3 header before the current position
71 * The list is expected to be and will be kept sorted by next_frame_pos
72 * and when those are equal by frame_pos.
73 * \param list pointer to the head-of-list pointer
74 * \param st_pos stream position where the described header starts
75 * \param mp3_chans number of channels as specified by the header (*)
76 * \param mp3_freq sampling frequency as specified by the header (*)
77 * \param mpa_spf frame size as specified by the header
78 * \param mpa_layer layer type ("version") as specified by the header (*)
79 * \param mpa_br bitrate as specified by the header
80 * \param mp3_flen length of the frame as specified by the header
81 * \return If non-null the current file is accepted as MP3 and the
82 * mp3_hdr struct describing the valid chain is returned. Must be
83 * freed independent of the list.
85 * parameters marked by (*) must be the same for all headers in the same chain
87 static mp3_hdr_t
*add_mp3_hdr(mp3_hdr_t
**list
, off_t st_pos
,
88 int mp3_chans
, int mp3_freq
, int mpa_spf
,
89 int mpa_layer
, int mpa_br
, int mp3_flen
) {
92 while (*list
&& (*list
)->next_frame_pos
<= st_pos
) {
93 if (((*list
)->next_frame_pos
< st_pos
) || ((*list
)->mp3_chans
!= mp3_chans
)
94 || ((*list
)->mp3_freq
!= mp3_freq
) || ((*list
)->mpa_layer
!= mpa_layer
) ) {
100 (*list
)->cons_hdrs
++;
101 (*list
)->next_frame_pos
= st_pos
+ mp3_flen
;
102 (*list
)->mpa_spf
= mpa_spf
;
103 (*list
)->mpa_br
= mpa_br
;
104 if ((*list
)->cons_hdrs
>= MIN_MP3_HDRS
) {
105 // copy the valid entry, so that the list can be easily freed
106 tmp
= malloc(sizeof(mp3_hdr_t
));
107 memcpy(tmp
, *list
, sizeof(mp3_hdr_t
));
112 list
= &((*list
)->next
);
115 if (!in_list
) { // does not belong into an existing chain, insert
116 // find right position to insert to keep sorting
117 while (*list
&& (*list
)->next_frame_pos
<= st_pos
+ mp3_flen
)
118 list
= &((*list
)->next
);
119 tmp
= malloc(sizeof(mp3_hdr_t
));
120 tmp
->frame_pos
= st_pos
;
121 tmp
->next_frame_pos
= st_pos
+ mp3_flen
;
122 tmp
->mp3_chans
= mp3_chans
;
123 tmp
->mp3_freq
= mp3_freq
;
124 tmp
->mpa_spf
= mpa_spf
;
125 tmp
->mpa_layer
= mpa_layer
;
126 tmp
->mpa_br
= mpa_br
;
134 #define FLAC_SIGNATURE_SIZE 4
135 #define FLAC_STREAMINFO_SIZE 34
136 #define FLAC_SEEKPOINT_SIZE 18
148 get_flac_metadata (demuxer_t
* demuxer
)
151 unsigned int blk_len
;
161 /* file is qualified; skip over the signature bytes in the stream */
164 /* loop through the metadata blocks; use a do-while construct since there
165 * will always be 1 metadata block */
169 r
= stream_read (s
, (char *) preamble
, FLAC_SIGNATURE_SIZE
);
170 if (r
!= FLAC_SIGNATURE_SIZE
)
173 blk_len
= (preamble
[1] << 16) | (preamble
[2] << 8) | (preamble
[3] << 0);
175 switch (preamble
[0] & 0x7F)
177 case FLAC_STREAMINFO
:
179 if (blk_len
!= FLAC_STREAMINFO_SIZE
)
182 stream_skip (s
, FLAC_STREAMINFO_SIZE
);
187 stream_skip (s
, blk_len
);
190 case FLAC_APPLICATION
:
191 stream_skip (s
, blk_len
);
196 int seekpoint_count
, i
;
198 seekpoint_count
= blk_len
/ FLAC_SEEKPOINT_SIZE
;
199 for (i
= 0; i
< seekpoint_count
; i
++)
200 if (stream_skip (s
, FLAC_SEEKPOINT_SIZE
) != 1)
205 case FLAC_VORBIS_COMMENT
:
207 /* For a description of the format please have a look at */
208 /* http://www.xiph.org/vorbis/doc/v-comment.html */
210 uint32_t length
, comment_list_len
;
211 char comments
[blk_len
];
212 uint8_t *ptr
= comments
;
217 if (stream_read (s
, comments
, blk_len
) == blk_len
)
219 length
= AV_RL32(ptr
);
222 comment_list_len
= AV_RL32(ptr
);
226 for (; cn
< comment_list_len
; cn
++)
228 length
= AV_RL32(ptr
);
235 if (!strncasecmp ("TITLE=", comment
, 6) && (length
- 6 > 0))
236 demux_info_add (demuxer
, "Title", comment
+ 6);
237 else if (!strncasecmp ("ARTIST=", comment
, 7) && (length
- 7 > 0))
238 demux_info_add (demuxer
, "Artist", comment
+ 7);
239 else if (!strncasecmp ("ALBUM=", comment
, 6) && (length
- 6 > 0))
240 demux_info_add (demuxer
, "Album", comment
+ 6);
241 else if (!strncasecmp ("DATE=", comment
, 5) && (length
- 5 > 0))
242 demux_info_add (demuxer
, "Year", comment
+ 5);
243 else if (!strncasecmp ("GENRE=", comment
, 6) && (length
- 6 > 0))
244 demux_info_add (demuxer
, "Genre", comment
+ 6);
245 else if (!strncasecmp ("Comment=", comment
, 8) && (length
- 8 > 0))
246 demux_info_add (demuxer
, "Comment", comment
+ 8);
247 else if (!strncasecmp ("TRACKNUMBER=", comment
, 12)
248 && (length
- 12 > 0))
252 sprintf (buf
, "%d", atoi (comment
+ 12));
253 demux_info_add(demuxer
, "Track", buf
);
264 stream_skip (s
, blk_len
);
268 /* 6-127 are presently reserved */
269 stream_skip (s
, blk_len
);
272 } while ((preamble
[0] & 0x80) == 0);
275 static int demux_audio_open(demuxer_t
* demuxer
) {
277 sh_audio_t
* sh_audio
;
278 uint8_t hdr
[HDR_SIZE
];
279 int frmt
= 0, n
= 0, step
;
280 off_t st_pos
= 0, next_frame_pos
= 0;
281 // mp3_hdrs list is sorted first by next_frame_pos and then by frame_pos
282 mp3_hdr_t
*mp3_hdrs
= NULL
, *mp3_found
= NULL
;
287 stream_read(s
, hdr
, HDR_SIZE
);
288 while(n
< 30000 && !s
->eof
) {
289 int mp3_freq
, mp3_chans
, mp3_flen
, mpa_layer
, mpa_spf
, mpa_br
;
290 st_pos
= stream_tell(s
) - HDR_SIZE
;
293 if( hdr
[0] == 'R' && hdr
[1] == 'I' && hdr
[2] == 'F' && hdr
[3] == 'F' ) {
297 stream_read(s
,hdr
,4);
300 if(hdr
[0] != 'W' || hdr
[1] != 'A' || hdr
[2] != 'V' || hdr
[3] != 'E' )
303 // We found wav header. Now we can have 'fmt ' or a mp3 header
306 } else if( hdr
[0] == 'I' && hdr
[1] == 'D' && hdr
[2] == '3' && (hdr
[3] >= 2)) {
309 stream_read(s
,hdr
,4);
310 len
= (hdr
[0]<<21) | (hdr
[1]<<14) | (hdr
[2]<<7) | hdr
[3];
313 } else if( hdr
[0] == 'f' && hdr
[1] == 'm' && hdr
[2] == 't' && hdr
[3] == ' ' ) {
316 } else if((mp3_flen
= mp_get_mp3_header(hdr
, &mp3_chans
, &mp3_freq
,
317 &mpa_spf
, &mpa_layer
, &mpa_br
)) > 0) {
318 mp3_found
= add_mp3_hdr(&mp3_hdrs
, st_pos
, mp3_chans
, mp3_freq
,
319 mpa_spf
, mpa_layer
, mpa_br
, mp3_flen
);
324 } else if( hdr
[0] == 'f' && hdr
[1] == 'L' && hdr
[2] == 'a' && hdr
[3] == 'C' ) {
328 // Add here some other audio format detection
330 memmove(hdr
,&hdr
[step
],HDR_SIZE
-step
);
331 stream_read(s
, &hdr
[HDR_SIZE
- step
], step
);
335 free_mp3_hdrs(&mp3_hdrs
);
340 sh_audio
= new_sh_audio(demuxer
,0);
344 sh_audio
->format
= (mp3_found
->mpa_layer
< 3 ? 0x50 : 0x55);
345 demuxer
->movi_start
= mp3_found
->frame_pos
;
346 next_frame_pos
= mp3_found
->next_frame_pos
;
347 sh_audio
->audio
.dwSampleSize
= 0;
348 sh_audio
->audio
.dwScale
= mp3_found
->mpa_spf
;
349 sh_audio
->audio
.dwRate
= mp3_found
->mp3_freq
;
350 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
351 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
352 sh_audio
->wf
->nChannels
= mp3_found
->mp3_chans
;
353 sh_audio
->wf
->nSamplesPerSec
= mp3_found
->mp3_freq
;
354 sh_audio
->wf
->nAvgBytesPerSec
= mp3_found
->mpa_br
* (1000 / 8);
355 sh_audio
->wf
->nBlockAlign
= mp3_found
->mpa_spf
;
356 sh_audio
->wf
->wBitsPerSample
= 16;
357 sh_audio
->wf
->cbSize
= 0;
358 sh_audio
->i_bps
= sh_audio
->wf
->nAvgBytesPerSec
;
363 stream_seek(s
,s
->end_pos
-128);
364 stream_read(s
,tag
,3);
366 if(strcmp(tag
,"TAG"))
367 demuxer
->movi_end
= s
->end_pos
;
371 demuxer
->movi_end
= stream_tell(s
)-3;
372 stream_read(s
,buf
,30);
374 demux_info_add(demuxer
,"Title",buf
);
375 stream_read(s
,buf
,30);
377 demux_info_add(demuxer
,"Artist",buf
);
378 stream_read(s
,buf
,30);
380 demux_info_add(demuxer
,"Album",buf
);
381 stream_read(s
,buf
,4);
383 demux_info_add(demuxer
,"Year",buf
);
384 stream_read(s
,buf
,30);
386 demux_info_add(demuxer
,"Comment",buf
);
387 if(buf
[28] == 0 && buf
[29] != 0) {
388 uint8_t trk
= (uint8_t)buf
[29];
389 sprintf(buf
,"%d",trk
);
390 demux_info_add(demuxer
,"Track",buf
);
392 g
= stream_read_char(s
);
393 demux_info_add(demuxer
,"Genre",genres
[g
]);
398 unsigned int chunk_type
;
399 unsigned int chunk_size
;
402 l
= stream_read_dword_le(s
);
404 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"[demux_audio] Bad wav header length: too short (%d)!!!\n",l
);
407 if(l
> MAX_WAVHDR_LEN
) {
408 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"[demux_audio] Bad wav header length: too long (%d)!!!\n",l
);
411 sh_audio
->wf
= w
= malloc(l
> sizeof(WAVEFORMATEX
) ? l
: sizeof(WAVEFORMATEX
));
412 w
->wFormatTag
= sh_audio
->format
= stream_read_word_le(s
);
413 w
->nChannels
= sh_audio
->channels
= stream_read_word_le(s
);
414 w
->nSamplesPerSec
= sh_audio
->samplerate
= stream_read_dword_le(s
);
415 w
->nAvgBytesPerSec
= stream_read_dword_le(s
);
416 w
->nBlockAlign
= stream_read_word_le(s
);
417 w
->wBitsPerSample
= stream_read_word_le(s
);
418 sh_audio
->samplesize
= (w
->wBitsPerSample
+ 7) / 8;
420 sh_audio
->i_bps
= sh_audio
->wf
->nAvgBytesPerSec
;
423 w
->cbSize
= stream_read_word_le(s
);
427 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"[demux_audio] truncated extradata (%d < %d)\n",
429 stream_read(s
,(char*)((char*)(w
)+sizeof(WAVEFORMATEX
)),l
);
432 stream_read(s
,(char*)((char*)(w
)+sizeof(WAVEFORMATEX
)),w
->cbSize
);
438 if( mp_msg_test(MSGT_DEMUX
,MSGL_V
) ) print_wave_header(w
, MSGL_V
);
443 chunk_type
= stream_read_fourcc(demuxer
->stream
);
444 chunk_size
= stream_read_dword_le(demuxer
->stream
);
445 if (chunk_type
!= mmioFOURCC('d', 'a', 't', 'a'))
446 stream_skip(demuxer
->stream
, chunk_size
);
447 } while (!s
->eof
&& chunk_type
!= mmioFOURCC('d', 'a', 't', 'a'));
448 demuxer
->movi_start
= stream_tell(s
);
449 demuxer
->movi_end
= chunk_size
? demuxer
->movi_start
+ chunk_size
: s
->end_pos
;
450 // printf("wav: %X .. %X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);
451 // Check if it contains dts audio
452 if((w
->wFormatTag
== 0x01) && (w
->nChannels
== 2) && (w
->nSamplesPerSec
== 44100)) {
453 unsigned char buf
[16384]; // vlc uses 16384*4 (4 dts frames)
455 stream_read(s
, buf
, sizeof(buf
));
456 for (i
= 0; i
< sizeof(buf
) - 5; i
+= 2) {
458 if((buf
[i
] == 0xff) && (buf
[i
+1] == 0x1f) && (buf
[i
+2] == 0x00) &&
459 (buf
[i
+3] == 0xe8) && ((buf
[i
+4] & 0xfe) == 0xf0) && (buf
[i
+5] == 0x07)) {
460 sh_audio
->format
= 0x2001;
461 mp_msg(MSGT_DEMUX
,MSGL_V
,"[demux_audio] DTS audio in wav, 14 bit, LE\n");
465 if((buf
[i
] == 0x1f) && (buf
[i
+1] == 0xff) && (buf
[i
+2] == 0xe8) &&
466 (buf
[i
+3] == 0x00) && (buf
[i
+4] == 0x07) && ((buf
[i
+5] & 0xfe) == 0xf0)) {
467 sh_audio
->format
= 0x2001;
468 mp_msg(MSGT_DEMUX
,MSGL_V
,"[demux_audio] DTS audio in wav, 14 bit, BE\n");
472 if((buf
[i
] == 0x7f) && (buf
[i
+1] == 0xfe) && (buf
[i
+2] == 0x80) &&
473 (buf
[i
+3] == 0x01)) {
474 sh_audio
->format
= 0x2001;
475 mp_msg(MSGT_DEMUX
,MSGL_V
,"[demux_audio] DTS audio in wav, 16 bit, BE\n");
479 if((buf
[i
] == 0xfe) && (buf
[i
+1] == 0x7f) && (buf
[i
+2] == 0x01) &&
480 (buf
[i
+3] == 0x80)) {
481 sh_audio
->format
= 0x2001;
482 mp_msg(MSGT_DEMUX
,MSGL_V
,"[demux_audio] DTS audio in wav, 16 bit, LE\n");
486 if (sh_audio
->format
== 0x2001)
487 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"[demux_audio] DTS sync offset = %u\n", i
);
490 stream_seek(s
,demuxer
->movi_start
);
493 sh_audio
->format
= mmioFOURCC('f', 'L', 'a', 'C');
494 demuxer
->movi_start
= stream_tell(s
) - 4;
495 demuxer
->movi_end
= s
->end_pos
;
496 if (demuxer
->movi_end
> demuxer
->movi_start
) {
497 // try to find out approx. bitrate
498 int64_t size
= demuxer
->movi_end
- demuxer
->movi_start
;
499 int64_t num_samples
= 0;
502 stream_read(s
, (char *)&srate
, 3);
503 srate
= be2me_32(srate
) >> 12;
504 stream_read(s
, (char *)&num_samples
, 5);
505 num_samples
= (be2me_64(num_samples
) >> 24) & 0xfffffffffULL
;
506 if (num_samples
&& srate
)
507 sh_audio
->i_bps
= size
* srate
/ num_samples
;
509 if (sh_audio
->i_bps
< 1) // guess value to prevent crash
510 sh_audio
->i_bps
= 64 * 1024;
511 get_flac_metadata (demuxer
);
515 priv
= malloc(sizeof(da_priv_t
));
518 demuxer
->priv
= priv
;
519 demuxer
->audio
->id
= 0;
520 demuxer
->audio
->sh
= sh_audio
;
521 sh_audio
->ds
= demuxer
->audio
;
522 sh_audio
->samplerate
= sh_audio
->audio
.dwRate
;
524 if(stream_tell(s
) != demuxer
->movi_start
)
526 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_audio: seeking from 0x%X to start pos 0x%X\n",
527 (int)stream_tell(s
), (int)demuxer
->movi_start
);
528 stream_seek(s
,demuxer
->movi_start
);
529 if (stream_tell(s
) != demuxer
->movi_start
) {
530 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_audio: seeking failed, now at 0x%X!\n",
531 (int)stream_tell(s
));
532 if (next_frame_pos
) {
533 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_audio: seeking to 0x%X instead\n",
534 (int)next_frame_pos
);
535 stream_seek(s
, next_frame_pos
);
540 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_audio: audio data 0x%X - 0x%X \n",(int)demuxer
->movi_start
,(int)demuxer
->movi_end
);
542 return DEMUXER_TYPE_AUDIO
;
546 static int demux_audio_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
) {
549 sh_audio_t
* sh_audio
= ds
->sh
;
550 demuxer_t
* demux
= ds
->demuxer
;
551 da_priv_t
* priv
= demux
->priv
;
552 double this_pts
= priv
->next_pts
;
553 stream_t
* s
= demux
->stream
;
562 stream_read(s
,hdr
,4);
565 l
= mp_decode_mp3_header(hdr
);
567 if (demux
->movi_end
&& stream_tell(s
) >= demux
->movi_end
)
568 return 0; // might be ID3 tag, i.e. EOF
571 dp
= new_demux_packet(l
);
572 memcpy(dp
->buffer
,hdr
,4);
573 if (stream_read(s
,dp
->buffer
+ 4,l
-4) != l
-4)
575 free_demux_packet(dp
);
578 priv
->next_pts
+= sh_audio
->audio
.dwScale
/(double)sh_audio
->samplerate
;
583 unsigned align
= sh_audio
->wf
->nBlockAlign
;
584 l
= sh_audio
->wf
->nAvgBytesPerSec
;
585 if (demux
->movi_end
&& l
> demux
->movi_end
- stream_tell(s
)) {
586 // do not read beyond end, there might be junk after data chunk
587 l
= demux
->movi_end
- stream_tell(s
);
588 if (l
<= 0) return 0;
591 l
= (l
+ align
- 1) / align
* align
;
592 dp
= new_demux_packet(l
);
593 l
= stream_read(s
,dp
->buffer
,l
);
594 priv
->next_pts
+= l
/(double)sh_audio
->i_bps
;
599 dp
= new_demux_packet(l
);
600 l
= stream_read(s
,dp
->buffer
,l
);
601 /* FLAC is not a constant-bitrate codec. These values will be wrong. */
602 priv
->next_pts
+= l
/(double)sh_audio
->i_bps
;
606 mp_msg(MSGT_DEMUXER
,MSGL_WARN
,MSGTR_MPDEMUX_AUDIO_UnknownFormat
,priv
->frmt
);
610 resize_demux_packet(dp
, l
);
612 ds_add_packet(ds
, dp
);
616 static void high_res_mp3_seek(demuxer_t
*demuxer
,float time
) {
619 da_priv_t
* priv
= demuxer
->priv
;
620 sh_audio_t
* sh
= (sh_audio_t
*)demuxer
->audio
->sh
;
622 nf
= time
*sh
->samplerate
/sh
->audio
.dwScale
;
624 stream_read(demuxer
->stream
,hdr
,4);
625 len
= mp_decode_mp3_header(hdr
);
627 stream_skip(demuxer
->stream
,-3);
630 stream_skip(demuxer
->stream
,len
-4);
631 priv
->next_pts
+= sh
->audio
.dwScale
/(double)sh
->samplerate
;
636 static void demux_audio_seek(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
){
637 sh_audio_t
* sh_audio
;
643 if(!(sh_audio
= demuxer
->audio
->sh
))
646 priv
= demuxer
->priv
;
648 if(priv
->frmt
== MP3
&& hr_mp3_seek
&& !(flags
& 2)) {
649 len
= (flags
& 1) ? rel_seek_secs
- priv
->next_pts
: rel_seek_secs
;
651 stream_seek(s
,demuxer
->movi_start
);
652 len
= priv
->next_pts
+ len
;
656 high_res_mp3_seek(demuxer
,len
);
660 base
= flags
&1 ? demuxer
->movi_start
: stream_tell(s
);
662 pos
= base
+ ((demuxer
->movi_end
- demuxer
->movi_start
)*rel_seek_secs
);
664 pos
= base
+ (rel_seek_secs
*sh_audio
->i_bps
);
666 if(demuxer
->movi_end
&& pos
>= demuxer
->movi_end
) {
667 pos
= demuxer
->movi_end
;
668 } else if(pos
< demuxer
->movi_start
)
669 pos
= demuxer
->movi_start
;
671 priv
->next_pts
= (pos
-demuxer
->movi_start
)/(double)sh_audio
->i_bps
;
675 pos
-= (pos
- demuxer
->movi_start
) %
676 (sh_audio
->wf
->nBlockAlign
? sh_audio
->wf
->nBlockAlign
:
677 (sh_audio
->channels
* sh_audio
->samplesize
));
684 static void demux_close_audio(demuxer_t
* demuxer
) {
685 da_priv_t
* priv
= demuxer
->priv
;
692 static int demux_audio_control(demuxer_t
*demuxer
,int cmd
, void *arg
){
693 sh_audio_t
*sh_audio
=demuxer
->audio
->sh
;
694 int audio_length
= demuxer
->movi_end
/ sh_audio
->i_bps
;
695 da_priv_t
* priv
= demuxer
->priv
;
698 case DEMUXER_CTRL_GET_TIME_LENGTH
:
699 if (audio_length
<=0) return DEMUXER_CTRL_DONTKNOW
;
700 *((double *)arg
)=(double)audio_length
;
701 return DEMUXER_CTRL_GUESS
;
703 case DEMUXER_CTRL_GET_PERCENT_POS
:
705 return DEMUXER_CTRL_DONTKNOW
;
706 *((int *)arg
)=(int)( (priv
->next_pts
*100) / audio_length
);
707 return DEMUXER_CTRL_OK
;
710 return DEMUXER_CTRL_NOTIMPL
;
715 const demuxer_desc_t demuxer_desc_audio
= {
722 0, // unsafe autodetect
724 demux_audio_fill_buffer
,