@ -242,6 +242,36 @@ static void vorbis_cleanup(AVFormatContext *s, int idx)
av_freep ( & priv - > packet [ i ] ) ;
}
static int vorbis_update_metadata ( AVFormatContext * s , int idx )
{
struct ogg * ogg = s - > priv_data ;
struct ogg_stream * os = ogg - > streams + idx ;
AVStream * st = s - > streams [ idx ] ;
int ret ;
if ( os - > psize < = 8 )
return 0 ;
/* New metadata packet; release old data. */
av_dict_free ( & st - > metadata ) ;
ret = ff_vorbis_comment ( s , & st - > metadata , os - > buf + os - > pstart + 7 ,
os - > psize - 8 ) ;
if ( ret < 0 )
return ret ;
/* Update the metadata if possible. */
av_freep ( & os - > new_metadata ) ;
if ( st - > metadata ) {
os - > new_metadata = av_packet_pack_dictionary ( st - > metadata , & os - > new_metadata_size ) ;
/* Send an empty dictionary to indicate that metadata has been cleared. */
} else {
os - > new_metadata = av_malloc ( 1 ) ;
os - > new_metadata_size = 0 ;
}
return ret ;
}
static int vorbis_header ( AVFormatContext * s , int idx )
{
struct ogg * ogg = s - > priv_data ;
@ -317,9 +347,7 @@ static int vorbis_header(AVFormatContext *s, int idx)
avpriv_set_pts_info ( st , 64 , 1 , srate ) ;
}
} else if ( os - > buf [ os - > pstart ] = = 3 ) {
if ( os - > psize > 8 & &
ff_vorbis_comment ( s , & st - > metadata , os - > buf + os - > pstart + 7 ,
os - > psize - 8 ) > = 0 ) {
if ( vorbis_update_metadata ( s , idx ) > = 0 ) {
// drop all metadata we parsed and which is not required by libvorbis
unsigned new_len = 7 + 4 + AV_RL32 ( priv - > packet [ 1 ] + 7 ) + 4 + 1 ;
if ( new_len > = 16 & & new_len < os - > psize ) {
@ -350,7 +378,7 @@ static int vorbis_packet(AVFormatContext *s, int idx)
struct ogg * ogg = s - > priv_data ;
struct ogg_stream * os = ogg - > streams + idx ;
struct oggvorbis_private * priv = os - > private ;
int duration ;
int duration , flags = 0 ;
/* first packet handling
* here we parse the duration of each packet in the first page and compare
@ -364,19 +392,25 @@ static int vorbis_packet(AVFormatContext *s, int idx)
avpriv_vorbis_parse_reset ( & priv - > vp ) ;
duration = 0 ;
seg = os - > segp ;
d = avpriv_vorbis_parse_frame ( & priv - > vp , last_pkt , 1 ) ;
d = avpriv_vorbis_parse_frame_flags ( & priv - > vp , last_pkt , 1 , & flags ) ;
if ( d < 0 ) {
os - > pflags | = AV_PKT_FLAG_CORRUPT ;
return 0 ;
} else if ( flags & VORBIS_FLAG_COMMENT ) {
vorbis_update_metadata ( s , idx ) ;
flags = 0 ;
}
duration + = d ;
last_pkt = next_pkt = next_pkt + os - > psize ;
for ( ; seg < os - > nsegs ; seg + + ) {
if ( os - > segments [ seg ] < 255 ) {
int d = avpriv_vorbis_parse_frame ( & priv - > vp , last_pkt , 1 ) ;
int d = avpriv_vorbis_parse_frame_flags ( & priv - > vp , last_pkt , 1 , & flags ) ;
if ( d < 0 ) {
duration = os - > granule ;
break ;
} else if ( flags & VORBIS_FLAG_COMMENT ) {
vorbis_update_metadata ( s , idx ) ;
flags = 0 ;
}
duration + = d ;
last_pkt = next_pkt + os - > segments [ seg ] ;
@ -396,10 +430,13 @@ static int vorbis_packet(AVFormatContext *s, int idx)
/* parse packet duration */
if ( os - > psize > 0 ) {
duration = avpriv_vorbis_parse_frame ( & priv - > vp , os - > buf + os - > pstart , 1 ) ;
duration = avpriv_vorbis_parse_frame_flags ( & priv - > vp , os - > buf + os - > pstart , 1 , & flags ) ;
if ( duration < 0 ) {
os - > pflags | = AV_PKT_FLAG_CORRUPT ;
return 0 ;
} else if ( flags & VORBIS_FLAG_COMMENT ) {
vorbis_update_metadata ( s , idx ) ;
flags = 0 ;
}
os - > pduration = duration ;
}