@ -39,7 +39,7 @@
# include "vorbiscomment.h"
# include "vorbiscomment.h"
# include "replaygain.h"
# include "replaygain.h"
static int ogm_chapter ( AVFormatContext * as , uint8_t * key , uint8_t * val )
static int ogm_chapter ( AVFormatContext * as , const uint8_t * key , const uint8_t * val )
{
{
int i , cnum , h , m , s , ms , keylen = strlen ( key ) ;
int i , cnum , h , m , s , ms , keylen = strlen ( key ) ;
AVChapter * chapter = NULL ;
AVChapter * chapter = NULL ;
@ -54,7 +54,6 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
avpriv_new_chapter ( as , cnum , ( AVRational ) { 1 , 1000 } ,
avpriv_new_chapter ( as , cnum , ( AVRational ) { 1 , 1000 } ,
ms + 1000 * ( s + 60 * ( m + 60 * h ) ) ,
ms + 1000 * ( s + 60 * ( m + 60 * h ) ) ,
AV_NOPTS_VALUE , NULL ) ;
AV_NOPTS_VALUE , NULL ) ;
av_free ( val ) ;
} else if ( ! av_strcasecmp ( key + keylen - 4 , " NAME " ) ) {
} else if ( ! av_strcasecmp ( key + keylen - 4 , " NAME " ) ) {
for ( i = 0 ; i < as - > nb_chapters ; i + + )
for ( i = 0 ; i < as - > nb_chapters ; i + + )
if ( as - > chapters [ i ] - > id = = cnum ) {
if ( as - > chapters [ i ] - > id = = cnum ) {
@ -64,11 +63,10 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
if ( ! chapter )
if ( ! chapter )
return 0 ;
return 0 ;
av_dict_set ( & chapter - > metadata , " title " , val , AV_DICT_DONT_STRDUP_VAL ) ;
av_dict_set ( & chapter - > metadata , " title " , val , 0 ) ;
} else
} else
return 0 ;
return 0 ;
av_free ( key ) ;
return 1 ;
return 1 ;
}
}
@ -84,13 +82,18 @@ int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
return updates ;
return updates ;
}
}
/**
* This function temporarily modifies the ( const qualified ) input buffer
* and reverts its changes before return . The input buffer needs to have
* at least one byte of padding .
*/
static int vorbis_parse_single_comment ( AVFormatContext * as , AVDictionary * * m ,
static int vorbis_parse_single_comment ( AVFormatContext * as , AVDictionary * * m ,
const uint8_t * buf , uint32_t size ,
const uint8_t * buf , uint32_t size ,
int * updates , int parse_picture )
int * updates , int parse_picture )
{
{
const char * t = buf , * v = memchr ( t , ' = ' , size ) ;
char * t = ( char * ) buf , * v = memchr ( t , ' = ' , size ) ;
char * tt , * ct ;
int tl , vl ;
int tl , vl ;
char backup ;
if ( ! v )
if ( ! v )
return 0 ;
return 0 ;
@ -102,19 +105,10 @@ static int vorbis_parse_single_comment(AVFormatContext *as, AVDictionary **m,
if ( ! tl | | ! vl )
if ( ! tl | | ! vl )
return 0 ;
return 0 ;
tt = av_malloc ( tl + 1 ) ;
t [ tl ] = 0 ;
ct = av_malloc ( vl + 1 ) ;
if ( ! tt | | ! ct ) {
av_freep ( & tt ) ;
av_freep ( & ct ) ;
return AVERROR ( ENOMEM ) ;
}
memcpy ( tt , t , tl ) ;
tt [ tl ] = 0 ;
memcpy ( ct , v , vl ) ;
backup = v [ vl ] ;
ct [ vl ] = 0 ;
v [ vl ] = 0 ;
/* The format in which the pictures are stored is the FLAC format.
/* The format in which the pictures are stored is the FLAC format.
* Xiph says : " The binary FLAC picture structure is base64 encoded
* Xiph says : " The binary FLAC picture structure is base64 encoded
@ -122,35 +116,31 @@ static int vorbis_parse_single_comment(AVFormatContext *as, AVDictionary **m,
* ' METADATA_BLOCK_PICTURE ' . This is the preferred and
* ' METADATA_BLOCK_PICTURE ' . This is the preferred and
* recommended way of embedding cover art within VorbisComments . "
* recommended way of embedding cover art within VorbisComments . "
*/
*/
if ( ! av_strcasecmp ( tt , " METADATA_BLOCK_PICTURE " ) & & parse_picture ) {
if ( ! av_strcasecmp ( t , " METADATA_BLOCK_PICTURE " ) & & parse_picture ) {
int ret , len = AV_BASE64_DECODE_SIZE ( vl ) ;
int ret , len = AV_BASE64_DECODE_SIZE ( vl ) ;
uint8_t * pict = av_malloc ( len ) ;
uint8_t * pict = av_malloc ( len ) ;
if ( ! pict ) {
if ( ! pict ) {
av_log ( as , AV_LOG_WARNING , " out-of-memory error. Skipping cover art block. \n " ) ;
av_log ( as , AV_LOG_WARNING , " out-of-memory error. Skipping cover art block. \n " ) ;
av_freep ( & tt ) ;
goto end ;
av_freep ( & ct ) ;
return 0 ;
}
}
ret = av_base64_decode ( pict , ct , len ) ;
ret = av_base64_decode ( pict , v , len ) ;
av_freep ( & tt ) ;
av_freep ( & ct ) ;
if ( ret > 0 )
if ( ret > 0 )
ret = ff_flac_parse_picture ( as , pict , ret , 0 ) ;
ret = ff_flac_parse_picture ( as , pict , ret , 0 ) ;
av_freep ( & pict ) ;
av_freep ( & pict ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
av_log ( as , AV_LOG_WARNING , " Failed to parse cover art block. \n " ) ;
av_log ( as , AV_LOG_WARNING , " Failed to parse cover art block. \n " ) ;
return 0 ;
goto end ;
}
}
} else if ( ! ogm_chapter ( as , tt , ct ) ) {
} else if ( ! ogm_chapter ( as , t , v ) ) {
( * updates ) + + ;
( * updates ) + + ;
if ( av_dict_get ( * m , tt , NULL , 0 ) ) {
if ( av_dict_get ( * m , t , NULL , 0 ) )
av_dict_set ( m , tt , " ; " , AV_DICT_APPEND ) ;
av_dict_set ( m , t , " ; " , AV_DICT_APPEND ) ;
}
av_dict_set ( m , t , v , AV_DICT_APPEND ) ;
av_dict_set ( m , tt , ct ,
AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL |
AV_DICT_APPEND ) ;
}
}
end :
t [ tl ] = ' = ' ;
v [ vl ] = backup ;
return 0 ;
return 0 ;
}
}