Commit 47b8510a authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ogg: correctly handle chapters.

See http://wiki.xiph.org/Chapter_Extension
parent 22c9b6fe
...@@ -112,6 +112,42 @@ error: ...@@ -112,6 +112,42 @@ error:
return p_attachment; return p_attachment;
} }
typedef struct chapter_entry_t
{
int i_index;
seekpoint_t *p_seekpoint;
} chapter_entry_t;
typedef struct chapters_array_t
{
int i_num;
chapter_entry_t ** pp_chapters;
} chapters_array_t;
static chapter_entry_t * getChapterEntry( int i_index, chapters_array_t *p_array )
{
chapter_entry_t *p_chapter = NULL;
for( int i=0; i<p_array->i_num; i++ )
{
if ( p_array->pp_chapters[i]->i_index == i_index )
{
p_chapter = p_array->pp_chapters[i];
break;
}
}
if ( !p_chapter )
{
p_chapter = malloc( sizeof(chapter_entry_t) );
p_chapter->i_index = i_index;
p_chapter->p_seekpoint = vlc_seekpoint_New();
if ( i_index > p_array->i_num ) i_index = p_array->i_num;
if ( p_array->i_num == 0 ) i_index = 0;
/* FIXME or not.. : won't sort chapters if chapter00 is missing */
TAB_INSERT( p_array->i_num, p_array->pp_chapters, p_chapter, i_index );
}
return p_chapter;
}
void vorbis_ParseComment( vlc_meta_t **pp_meta, void vorbis_ParseComment( vlc_meta_t **pp_meta,
const uint8_t *p_data, int i_data, const uint8_t *p_data, int i_data,
int *i_attachments, input_attachment_t ***attachments, int *i_attachments, input_attachment_t ***attachments,
...@@ -120,7 +156,6 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -120,7 +156,6 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
{ {
int n; int n;
int i_comment; int i_comment;
seekpoint_t *sk = NULL;
if( i_data < 8 ) if( i_data < 8 )
return; return;
...@@ -167,6 +202,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -167,6 +202,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
bool hasEncodedBy = false; bool hasEncodedBy = false;
bool hasTrackTotal = false; bool hasTrackTotal = false;
chapters_array_t chapters_array;
TAB_INIT( chapters_array.i_num, chapters_array.pp_chapters );
for( ; i_comment > 0; i_comment-- ) for( ; i_comment > 0; i_comment-- )
{ {
char *psz_comment; char *psz_comment;
...@@ -259,29 +297,28 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -259,29 +297,28 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
*i_attachments, *attachments, p_attachment ); *i_attachments, *attachments, p_attachment );
} }
} }
else if( !strncasecmp(psz_comment, "chapter", strlen("chapter")) ) else if( !strncmp(psz_comment, "CHAPTER", 7) )
{ {
if( ppp_seekpoint == NULL )
continue;
int i_chapt; int i_chapt;
if( strstr( psz_comment, "name") && sscanf( psz_comment, "chapter%i=", &i_chapt ) == 1 ) chapter_entry_t *p_chapter = NULL;
if( strstr( psz_comment, "NAME=" ) &&
sscanf( psz_comment, "CHAPTER%iNAME=", &i_chapt ) == 1 )
{ {
char *p = strchr( psz_comment, '=' ); char *p = strchr( psz_comment, '=' );
*p++ = '\0'; p_chapter = getChapterEntry( i_chapt, &chapters_array );
sk->psz_name = strdup( p ); if ( ! p_chapter->p_seekpoint->psz_name )
p_chapter->p_seekpoint->psz_name = strdup( ++p );
} }
else if( sscanf( psz_comment, "chapter %i=", &i_chapt ) == 1 ) else if( sscanf( psz_comment, "CHAPTER%i=", &i_chapt ) == 1 )
{ {
int h, m, s, ms; int h, m, s, ms;
char *p = strchr( psz_comment, '=' ); char *p = strchr( psz_comment, '=' );
*p++ = '\0'; if( p && sscanf( ++p, "%d:%d:%d.%d", &h, &m, &s, &ms ) == 4 )
if( sscanf( p, "%d:%d:%d.%d", &h, &m, &s, &ms ) == 4 )
{ {
sk = vlc_seekpoint_New(); p_chapter = getChapterEntry( i_chapt, &chapters_array );
sk->i_time_offset = (((int64_t)h * 3600 + (int64_t)m * 60 + (int64_t)s) * 1000 + ms) * 1000; p_chapter->p_seekpoint->i_time_offset =
TAB_APPEND_CAST( (seekpoint_t**), *i_seekpoint, *ppp_seekpoint, sk ); (((int64_t)h * 3600 + (int64_t)m * 60 + (int64_t)s) * 1000 + ms) * 1000;
} }
} }
} }
...@@ -302,6 +339,14 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -302,6 +339,14 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
free( psz_comment ); free( psz_comment );
} }
#undef RM #undef RM
for ( int i=0; i<chapters_array.i_num; i++ )
{
TAB_APPEND_CAST( (seekpoint_t**), *i_seekpoint, *ppp_seekpoint,
chapters_array.pp_chapters[i]->p_seekpoint );
free(chapters_array.pp_chapters[i]);
}
TAB_CLEAN( chapters_array.i_num, chapters_array.pp_chapters );
} }
const char *FindKateCategoryName( const char *psz_tag ) const char *FindKateCategoryName( const char *psz_tag )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment