Commit 3633449e authored by Laurent Aimar's avatar Laurent Aimar

* mp4: added text track support. (there is a problem with the encoding).

parent e7e6e9df
...@@ -1367,6 +1367,58 @@ static void MP4_FreeBox_sample_vide( MP4_Box_t *p_box ) ...@@ -1367,6 +1367,58 @@ static void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
} }
static int MP4_ReadBox_sample_text( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
{
unsigned int i;
MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
for( i = 0; i < 6 ; i++ )
{
MP4_GET1BYTE( p_box->data.p_sample_text->i_reserved1[i] );
}
MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
MP4_GET4BYTES( p_box->data.p_sample_text->i_justification );
MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[0] );
MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[1] );
MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[2] );
MP4_GET8BYTES( p_box->data.p_sample_text->i_text_box );
MP4_GET8BYTES( p_box->data.p_sample_text->i_reserved2 );
MP4_GET2BYTES( p_box->data.p_sample_text->i_font_number );
MP4_GET2BYTES( p_box->data.p_sample_text->i_font_face );
MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved3 );
MP4_GET2BYTES( p_box->data.p_sample_text->i_foreground_color[0] );
MP4_GET2BYTES( p_box->data.p_sample_text->i_foreground_color[1] );
MP4_GET2BYTES( p_box->data.p_sample_text->i_foreground_color[2] );
MP4_GET1BYTE( i );
p_box->data.p_sample_text->psz_text_name = malloc( i + 1 );
memcpy( p_box->data.p_sample_text->psz_text_name, p_peek, i );
p_box->data.p_sample_text->psz_text_name[i] = '\0';
#ifdef MP4_VERBOSE
msg_Dbg( p_stream->s, "read box: \"text\" in stsd text name=%s",
p_box->data.p_sample_text->psz_text_name );
#endif
MP4_READBOX_EXIT( 1 );
}
#if 0
/* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
{
FREE( p_box->data.p_sample_text->psz_text_name );
}
#endif
static int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box ) static int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
{ {
...@@ -2084,6 +2136,46 @@ static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box ) ...@@ -2084,6 +2136,46 @@ static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
FREE( p_box->data.p_0xa9xxx->psz_text ); FREE( p_box->data.p_0xa9xxx->psz_text );
} }
/* For generic */
static int MP4_ReadBox_default( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
{
if( !p_box->p_father )
{
goto unknown;
}
if( p_box->p_father->i_type == FOURCC_stsd )
{
MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../.." );
MP4_Box_t *p_hdlr;
if( p_mdia == NULL || p_mdia->i_type != FOURCC_mdia ||
(p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
{
goto unknown;
}
switch( p_hdlr->data.p_hdlr->i_handler_type )
{
case FOURCC_soun:
return MP4_ReadBox_sample_soun( p_stream, p_box );
case FOURCC_vide:
return MP4_ReadBox_sample_vide( p_stream, p_box );
case FOURCC_text:
return MP4_ReadBox_sample_text( p_stream, p_box );
default:
msg_Warn( p_stream->s,
"unknown handler type in stsd (uncompletetly loaded)" );
return 1;
}
}
unknown:
msg_Warn( p_stream->s,
"unknown box type %4.4s (uncompletetly loaded)",
(char*)&p_box->i_type );
return 1;
}
/**** ------------------------------------------------------------------- ****/ /**** ------------------------------------------------------------------- ****/
/**** "Higher level" Functions ****/ /**** "Higher level" Functions ****/
/**** ------------------------------------------------------------------- ****/ /**** ------------------------------------------------------------------- ****/
...@@ -2179,6 +2271,7 @@ static struct ...@@ -2179,6 +2271,7 @@ static struct
{ FOURCC_SVQ3, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_SVQ3, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_ZyGo, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_ZyGo, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_DIVX, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_DIVX, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_XVID, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_h263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_h263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_s263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_s263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_cvid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_cvid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
...@@ -2192,8 +2285,10 @@ static struct ...@@ -2192,8 +2285,10 @@ static struct
{ FOURCC_3vid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_3vid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_mjpa, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_mjpa, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_mjpb, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_mjpb, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_mjqt, NULL, NULL }, /* found in mjpa/b */
{ FOURCC_mjht, NULL, NULL }, { FOURCC_mjqt, MP4_ReadBox_default, NULL }, /* found in mjpa/b */
{ FOURCC_mjht, MP4_ReadBox_default, NULL },
{ FOURCC_dvc, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_dvc, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_dvp, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_dvp, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_VP31, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_VP31, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
...@@ -2203,18 +2298,18 @@ static struct ...@@ -2203,18 +2298,18 @@ static struct
{ FOURCC_jpeg, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_jpeg, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_avc1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide }, { FOURCC_avc1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_mp4s, NULL, MP4_FreeBox_Common }, { FOURCC_mp4s, MP4_ReadBox_default, MP4_FreeBox_Common },
/* XXX there is 2 box where we could find this entry stbl and tref*/ /* XXX there is 2 box where we could find this entry stbl and tref*/
{ FOURCC_hint, NULL, MP4_FreeBox_Common }, { FOURCC_hint, MP4_ReadBox_default, MP4_FreeBox_Common },
/* found in tref box */ /* found in tref box */
{ FOURCC_dpnd, NULL, NULL }, { FOURCC_dpnd, MP4_ReadBox_default, NULL },
{ FOURCC_ipir, NULL, NULL }, { FOURCC_ipir, MP4_ReadBox_default, NULL },
{ FOURCC_mpod, NULL, NULL }, { FOURCC_mpod, MP4_ReadBox_default, NULL },
/* found in hnti */ /* found in hnti */
{ FOURCC_rtp, NULL, NULL }, { FOURCC_rtp, MP4_ReadBox_default, NULL },
/* found in rmra */ /* found in rmra */
{ FOURCC_rdrf, MP4_ReadBox_rdrf, MP4_FreeBox_rdrf }, { FOURCC_rdrf, MP4_ReadBox_rdrf, MP4_FreeBox_rdrf },
...@@ -2249,7 +2344,7 @@ static struct ...@@ -2249,7 +2344,7 @@ static struct
{ FOURCC_0xa9src,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx }, { FOURCC_0xa9src,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
/* Last entry */ /* Last entry */
{ 0, NULL, NULL } { 0, MP4_ReadBox_default, NULL }
}; };
...@@ -2286,13 +2381,8 @@ static MP4_Box_t *MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_father ) ...@@ -2286,13 +2381,8 @@ static MP4_Box_t *MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_father )
break; break;
} }
} }
if( MP4_Box_Function[i_index].MP4_ReadBox_function == NULL )
{ if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
msg_Warn( p_stream->s,
"unknown box type %4.4s (uncompletetly loaded)",
(char*)&p_box->i_type );
}
else if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
{ {
free( p_box ); free( p_box );
return NULL; return NULL;
......
...@@ -127,6 +127,7 @@ ...@@ -127,6 +127,7 @@
#define FOURCC_h263 VLC_FOURCC( 'h', '2', '6', '3' ) #define FOURCC_h263 VLC_FOURCC( 'h', '2', '6', '3' )
#define FOURCC_s263 VLC_FOURCC( 's', '2', '6', '3' ) #define FOURCC_s263 VLC_FOURCC( 's', '2', '6', '3' )
#define FOURCC_DIVX VLC_FOURCC( 'D', 'I', 'V', 'X' ) #define FOURCC_DIVX VLC_FOURCC( 'D', 'I', 'V', 'X' )
#define FOURCC_XVID VLC_FOURCC( 'X', 'V', 'I', 'D' )
#define FOURCC_cvid VLC_FOURCC( 'c', 'v', 'i', 'd' ) #define FOURCC_cvid VLC_FOURCC( 'c', 'v', 'i', 'd' )
#define FOURCC_mjpa VLC_FOURCC( 'm', 'j', 'p', 'a' ) #define FOURCC_mjpa VLC_FOURCC( 'm', 'j', 'p', 'a' )
#define FOURCC_mjpb VLC_FOURCC( 'm', 'j', 'q', 't' ) #define FOURCC_mjpb VLC_FOURCC( 'm', 'j', 'q', 't' )
...@@ -168,6 +169,8 @@ ...@@ -168,6 +169,8 @@
#define FOURCC_name VLC_FOURCC( 'n', 'a', 'm', 'e' ) #define FOURCC_name VLC_FOURCC( 'n', 'a', 'm', 'e' )
#define FOURCC_priv VLC_FOURCC( 'p', 'r', 'i', 'v' ) #define FOURCC_priv VLC_FOURCC( 'p', 'r', 'i', 'v' )
#define FOURCC_text VLC_FOURCC( 't', 'e', 'x', 't' )
#define FOURCC_0xa9nam VLC_FOURCC( 0xa9, 'n', 'a', 'm' ) #define FOURCC_0xa9nam VLC_FOURCC( 0xa9, 'n', 'a', 'm' )
#define FOURCC_0xa9aut VLC_FOURCC( 0xa9, 'a', 'u', 't' ) #define FOURCC_0xa9aut VLC_FOURCC( 0xa9, 'a', 'u', 't' )
#define FOURCC_0xa9swr VLC_FOURCC( 0xa9, 's', 'w', 'r' ) #define FOURCC_0xa9swr VLC_FOURCC( 0xa9, 's', 'w', 'r' )
...@@ -447,6 +450,25 @@ typedef struct MP4_Box_data_sample_vide_s ...@@ -447,6 +450,25 @@ typedef struct MP4_Box_data_sample_vide_s
} MP4_Box_data_sample_vide_t; } MP4_Box_data_sample_vide_t;
typedef struct
{
uint8_t i_reserved1[6];
uint16_t i_data_reference_index;
uint32_t i_display_flags;
uint32_t i_justification;
uint16_t i_background_color[3];
uint64_t i_text_box;
uint64_t i_reserved2;
uint16_t i_font_number;
uint16_t i_font_face;
uint16_t i_reserved3;
uint16_t i_foreground_color[3];
char *psz_text_name;
} MP4_Box_data_sample_text_t;
typedef struct MP4_Box_data_sample_hint_s typedef struct MP4_Box_data_sample_hint_s
{ {
uint8_t i_reserved1[6]; uint8_t i_reserved1[6];
...@@ -785,6 +807,7 @@ typedef union MP4_Box_data_s ...@@ -785,6 +807,7 @@ typedef union MP4_Box_data_s
MP4_Box_data_stsd_t *p_stsd; MP4_Box_data_stsd_t *p_stsd;
MP4_Box_data_sample_vide_t *p_sample_vide; MP4_Box_data_sample_vide_t *p_sample_vide;
MP4_Box_data_sample_soun_t *p_sample_soun; MP4_Box_data_sample_soun_t *p_sample_soun;
MP4_Box_data_sample_text_t *p_sample_text;
MP4_Box_data_sample_hint_t *p_sample_hint; MP4_Box_data_sample_hint_t *p_sample_hint;
MP4_Box_data_esds_t *p_esds; MP4_Box_data_esds_t *p_esds;
......
...@@ -450,6 +450,10 @@ static int Open( vlc_object_t * p_this ) ...@@ -450,6 +450,10 @@ static int Open( vlc_object_t * p_this )
case( AUDIO_ES ): case( AUDIO_ES ):
psz_cat = "audio"; psz_cat = "audio";
break; break;
case( SPU_ES ):
psz_cat = "subtitle";
break;
default: default:
psz_cat = "unknown"; psz_cat = "unknown";
break; break;
...@@ -580,6 +584,23 @@ static int Demux( demux_t *p_demux ) ...@@ -580,6 +584,23 @@ static int Demux( demux_t *p_demux )
(uint32_t*)p_block->p_buffer, (uint32_t*)p_block->p_buffer,
p_block->i_buffer ); p_block->i_buffer );
} }
else if( tk->fmt.i_cat == SPU_ES && p_block->i_buffer >= 2 )
{
uint16_t i_size = GetWBE( p_block->p_buffer );
if( i_size + 2 <= p_block->i_buffer )
{
/* remove the length field, and append a '\0' */
memmove( &p_block->p_buffer[0], &p_block->p_buffer[2], i_size );
p_block->p_buffer[i_size] = '\0';
p_block->i_buffer = i_size + 1;
}
else
{
/* Invalid */
p_block->i_buffer = 0;
}
}
p_block->i_dts = MP4_TrackGetPTS( p_demux, tk ) + 1; p_block->i_dts = MP4_TrackGetPTS( p_demux, tk ) + 1;
p_block->i_pts = tk->fmt.i_cat == VIDEO_ES ? 0 : p_block->i_dts + 1; p_block->i_pts = tk->fmt.i_cat == VIDEO_ES ? 0 : p_block->i_dts + 1;
...@@ -1084,6 +1105,11 @@ static int TrackCreateES ( demux_t *p_demux, ...@@ -1084,6 +1105,11 @@ static int TrackCreateES ( demux_t *p_demux,
case( VLC_FOURCC( 's', '2', '6', '3' ) ): case( VLC_FOURCC( 's', '2', '6', '3' ) ):
p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' ); p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
break; break;
case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
p_track->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
break;
default: default:
p_track->fmt.i_codec = p_sample->i_type; p_track->fmt.i_codec = p_sample->i_type;
break; break;
...@@ -1559,6 +1585,10 @@ static void MP4_TrackCreate( demux_t *p_demux, ...@@ -1559,6 +1585,10 @@ static void MP4_TrackCreate( demux_t *p_demux,
p_track->fmt.i_cat = VIDEO_ES; p_track->fmt.i_cat = VIDEO_ES;
break; break;
case( FOURCC_text ):
p_track->fmt.i_cat = SPU_ES;
break;
default: default:
return; return;
} }
......
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