mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-23 09:59:54 +00:00
id3: Remember id3v2 Header Info. Do Call mpeg_decode() Twice.
This commit is contained in:
parent
b00db8b15c
commit
f97fa5e6ba
@ -1136,6 +1136,10 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
byte_count += count ;
|
||||
break ;
|
||||
|
||||
case '!' : /* Clear buffer, forcing re-read. */
|
||||
psf->header.end = psf->header.indx = 0 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
|
||||
psf->error = SFE_INTERNAL ;
|
||||
|
@ -296,6 +296,12 @@ typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
|
||||
|
||||
typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ;
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t offset ;
|
||||
sf_count_t len ;
|
||||
unsigned minor_version ;
|
||||
} ID3V2_HEADER_INFO ;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
typedef wchar_t sfwchar_t ;
|
||||
#else
|
||||
@ -516,6 +522,8 @@ typedef struct sf_private_tag
|
||||
int (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
int cpu_flags ;
|
||||
|
||||
ID3V2_HEADER_INFO id3_header ;
|
||||
} SF_PRIVATE ;
|
||||
|
||||
|
||||
|
24
src/id3.c
24
src/id3.c
@ -63,31 +63,39 @@ id3_lookup_v1_genre (int UNUSED (number))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
id3_skip (SF_PRIVATE * psf)
|
||||
{ unsigned char buf [10] ;
|
||||
int offset ;
|
||||
|
||||
memset (buf, 0, sizeof (buf)) ;
|
||||
psf_binheader_readf (psf, "pb", 0, buf, 10) ;
|
||||
|
||||
if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3')
|
||||
{ int offset = buf [6] & 0x7f ;
|
||||
{ psf->id3_header.minor_version = buf [3] ;
|
||||
offset = buf [6] & 0x7f ;
|
||||
offset = (offset << 7) | (buf [7] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [8] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [9] & 0x7f) ;
|
||||
|
||||
psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ;
|
||||
/*
|
||||
** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten
|
||||
** bytes of header magic and offset, NOT the total ID3v2 header len.
|
||||
*/
|
||||
psf->id3_header.len = offset + 10 ;
|
||||
psf->id3_header.offset = psf->fileoffset ;
|
||||
|
||||
psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n",
|
||||
psf->id3_header.minor_version, psf->id3_header.len) ;
|
||||
|
||||
/* Never want to jump backwards in a file. */
|
||||
if (offset < 0)
|
||||
return 0 ;
|
||||
|
||||
/* Calculate new file offset and position ourselves there. */
|
||||
offset += 10 ;
|
||||
if (psf->fileoffset + offset < psf->filelength)
|
||||
{ psf_binheader_readf (psf, "p", offset) ;
|
||||
psf->fileoffset += offset ;
|
||||
/* Position ourselves at the new file offset. */
|
||||
if (psf->fileoffset + psf->id3_header.len < psf->filelength)
|
||||
{ psf_binheader_readf (psf, "p!", psf->id3_header.len) ;
|
||||
psf->fileoffset += psf->id3_header.len ;
|
||||
return 1 ;
|
||||
} ;
|
||||
} ;
|
||||
|
@ -526,17 +526,6 @@ mpeg_decoder_init (SF_PRIVATE *psf)
|
||||
if (! (psf->file.mode & SFM_READ))
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
/*
|
||||
** Check to see if we have already successfully opened the file when we
|
||||
** guessed it was an MP3 based on seeing an ID3 header.
|
||||
*/
|
||||
if (psf->codec_data != NULL &&
|
||||
(SF_CODEC (psf->sf.format) == SF_FORMAT_MPEG_LAYER_I
|
||||
|| SF_CODEC (psf->sf.format) == SF_FORMAT_MPEG_LAYER_II
|
||||
|| SF_CODEC (psf->sf.format) == SF_FORMAT_MPEG_LAYER_III)
|
||||
&& ((MPEG_DEC_PRIVATE *) psf->codec_data)->unique_id == psf->unique_id)
|
||||
return 0 ;
|
||||
|
||||
/*
|
||||
** *** FIXME - Threading issues ***
|
||||
**
|
||||
@ -580,15 +569,31 @@ mpeg_decoder_init (SF_PRIVATE *psf)
|
||||
#endif
|
||||
|
||||
psf->dataoffset = 0 ;
|
||||
|
||||
/*
|
||||
** Need to pass the first MPEG frame to libmpg123, but that frame was read
|
||||
** into psf->binheader in order that we could identify the stream.
|
||||
*/
|
||||
if (psf->is_pipe)
|
||||
{ // Need to read data in the binheader buffer. Avoid a file seek.
|
||||
{ /*
|
||||
** Can't seek, so setup our libmpg123 io callbacks to read the binheader
|
||||
** buffer first.
|
||||
*/
|
||||
psf_binheader_readf (psf, "p", 0) ;
|
||||
pmp3d->header_remaining = psf_binheader_readf (psf, NULL) ;
|
||||
|
||||
/* Tell libmpg123 we can't seek the file. */
|
||||
mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_NO_PEEK_END, 1.0) ;
|
||||
}
|
||||
else
|
||||
{ /*
|
||||
** libmpg123 can parse the ID3v2 header. Undo the embedded file offset if the
|
||||
** enclosing file data is the ID3v2 header.
|
||||
*/
|
||||
if (psf->id3_header.len > 0 && psf->id3_header.len + psf->id3_header.offset == psf->fileoffset)
|
||||
psf->fileoffset = psf->id3_header.offset ;
|
||||
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
} ;
|
||||
|
||||
error = mpg123_open_handle (pmp3d->pmh, psf) ;
|
||||
if (error != MPG123_OK)
|
||||
|
@ -967,7 +967,6 @@ sf_format_check (const SF_INFO *info)
|
||||
return 0 ;
|
||||
if (endian != SF_ENDIAN_FILE)
|
||||
return 0 ;
|
||||
/* TODO */
|
||||
if (subformat == SF_FORMAT_MPEG_LAYER_I || subformat == SF_FORMAT_MPEG_LAYER_II || subformat == SF_FORMAT_MPEG_LAYER_III)
|
||||
return 1 ;
|
||||
break ;
|
||||
@ -2881,16 +2880,6 @@ retry:
|
||||
if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 2) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 3)
|
||||
|| buffer [0] == MAKE_MARKER ('I', 'D', '3', 4))
|
||||
{ psf_log_printf (psf, "Found 'ID3' marker.\n") ;
|
||||
|
||||
/* Guess MP3, try and open it as such. Allows libmpg123 to parse the ID3v2 headers */
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if (mpeg_open (psf) == 0)
|
||||
return SF_FORMAT_MPEG | ((~SF_FORMAT_TYPEMASK) & psf->sf.format) ;
|
||||
else if (psf->codec_close)
|
||||
psf->codec_close (psf) ;
|
||||
} ;
|
||||
|
||||
/* Otherwise, seek to after the ID3 header */
|
||||
if (id3_skip (psf))
|
||||
goto retry ;
|
||||
return 0 ;
|
||||
|
Loading…
Reference in New Issue
Block a user