return MP4_ReadBoxContainerChildren( p_stream, p_container, 0 );
}
+static void MP4_BoxOffsetUp( MP4_Box_t *p_box, uint64_t i_offset )
+{
+ while(p_box)
+ {
+ p_box->i_pos += i_offset;
+ MP4_BoxOffsetUp( p_box->p_first, i_offset );
+ p_box = p_box->p_next;
+ }
+}
+
+/* Reads within an already read/in memory box (containers without having to seek) */
+static int MP4_ReadBoxContainerRawInBox( stream_t *p_stream, MP4_Box_t *p_container,
+ uint8_t *p_buffer, uint64_t i_size, uint64_t i_offset )
+{
+ stream_t *p_substream = stream_MemoryNew( p_stream, p_buffer, i_size, true );
+ if( !p_substream )
+ return 0;
+ MP4_Box_t *p_last = (p_container) ? p_container->p_last : NULL;
+ MP4_ReadBoxContainerRaw( p_substream, p_container );
+ stream_Delete( p_substream );
+ /* do pos fixup */
+ if( p_container )
+ {
+ MP4_Box_t *p_box = p_last ? p_last : p_container->p_first;
+ MP4_BoxOffsetUp(p_box, i_offset);
+ }
+
+ return 1;
+}
+
static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
{
if( p_container->i_size &&
FREENULL( p_box->data.p_urn->psz_location );
}
-
-static int MP4_ReadBox_dref( stream_t *p_stream, MP4_Box_t *p_box )
+static int MP4_ReadBox_LtdContainer( stream_t *p_stream, MP4_Box_t *p_box )
{
- MP4_READBOX_ENTER( MP4_Box_data_dref_t );
+ MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_lcont_t, 16 );
+ if( i_read < 8 )
+ MP4_READBOX_EXIT( 0 );
- MP4_GETVERSIONFLAGS( p_box->data.p_dref );
+ MP4_GETVERSIONFLAGS( p_box->data.p_lcont );
+ if( p_box->data.p_lcont->i_version != 0 )
+ MP4_READBOX_EXIT( 0 );
+ MP4_GET4BYTES( p_box->data.p_lcont->i_entry_count );
- MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
+ uint32_t i_entry = 0;
+ i_read = p_box->i_size - 16;
+ while (i_read > 8 && i_entry < p_box->data.p_lcont->i_entry_count )
+ {
+ MP4_Box_t *p_childbox = MP4_ReadBox( p_stream, p_box );
+ if( !p_childbox )
+ break;
+ MP4_BoxAddChild( p_box, p_childbox );
+ i_entry++;
+ i_read -= p_childbox->i_size;
+ }
- stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 8 );
- MP4_ReadBoxContainerRaw( p_stream, p_box );
+ if (i_entry != p_box->data.p_lcont->i_entry_count)
+ p_box->data.p_lcont->i_entry_count = i_entry;
#ifdef MP4_VERBOSE
- msg_Dbg( p_stream, "read box: \"dref\" entry-count %d",
- p_box->data.p_dref->i_entry_count );
+ msg_Dbg( p_stream, "read box: \"%4.4s\" entry-count %d", (char *)&p_box->i_type,
+ p_box->data.p_lcont->i_entry_count );
#endif
+
+ if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
+ MP4_READBOX_EXIT( 0 );
+
MP4_READBOX_EXIT( 1 );
}
p_box->data.p_sample_soun->i_qt_version,
p_box->data.p_sample_soun->i_compressionid );
#endif
-
+ /* @36 bytes */
if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
{
/* SoundDescriptionV1 */
p_box->data.p_sample_soun->i_bytes_per_frame,
p_box->data.p_sample_soun->i_bytes_per_sample );
#endif
-
- if ( MP4_Seek(p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 44) )
- MP4_READBOX_EXIT( 0 );
+ /* @52 bytes */
}
else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
{
p_box->data.p_sample_soun->i_constbytesperaudiopacket,
p_box->data.p_sample_soun->i_constLPCMframesperaudiopacket );
#endif
-
+ /* @72 bytes */
i_extoffset = VLC_CLIP( i_extoffset, i_read, p_box->i_size );
- if ( MP4_Seek( p_stream, p_box->i_pos + i_extoffset ) )
- MP4_READBOX_EXIT( 0 );
+ p_peek += i_extoffset;
+ i_read -= i_extoffset;
}
else
{
msg_Dbg( p_stream, "read box: \"soun\" V0 or qt1/2 (rest=%"PRId64")",
i_read );
#endif
- if ( MP4_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 28 ) )
- MP4_READBOX_EXIT( 0 );
+ /* @36 bytes */
}
if( p_box->i_type == ATOM_drms )
}
/* Loads extensions */
- MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds/wave/... */
+ MP4_ReadBoxContainerRawInBox( p_stream, p_box, p_peek, i_read,
+ p_box->i_pos + p_peek - p_buff ); /* esds/wave/... */
#ifdef MP4_VERBOSE
msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
- if ( MP4_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 78 ) )
- MP4_READBOX_EXIT( 0 );
-
if( p_box->i_type == ATOM_drmi )
{
msg_Warn( p_stream, "DRM protected streams are not supported." );
MP4_READBOX_EXIT( 0 );
}
- MP4_ReadBoxContainerRaw( p_stream, p_box );
+ if( i_actually_read > 78 && p_peek - p_buff > 78 )
+ {
+ MP4_ReadBoxContainerRawInBox( p_stream, p_box, p_peek, i_read,
+ p_box->i_pos + p_peek - p_buff );
+ }
#ifdef MP4_VERBOSE
msg_Dbg( p_stream, "read box: \"vide\" in stsd %dx%d depth %d",
}
#endif
-
-static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
-{
-
- MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
-
- MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
-
- MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
-
- stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 8 );
-
- MP4_ReadBoxContainerRaw( p_stream, p_box );
-
-#ifdef MP4_VERBOSE
- msg_Dbg( p_stream, "read box: \"stsd\" entry-count %d",
- p_box->data.p_stsd->i_entry_count );
-
-#endif
- MP4_READBOX_EXIT( 1 );
-}
-
-
static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
{
MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
{ ATOM_alis, MP4_ReadBoxSkip, MP4_FreeBox_Common, ATOM_dref },
{ ATOM_url, MP4_ReadBox_url, MP4_FreeBox_url, 0 },
{ ATOM_urn, MP4_ReadBox_urn, MP4_FreeBox_urn, 0 },
- { ATOM_dref, MP4_ReadBox_dref, MP4_FreeBox_Common, 0 },
+ { ATOM_dref, MP4_ReadBox_LtdContainer, MP4_FreeBox_Common, 0 },
{ ATOM_stts, MP4_ReadBox_stts, MP4_FreeBox_stts, ATOM_stbl },
{ ATOM_ctts, MP4_ReadBox_ctts, MP4_FreeBox_ctts, ATOM_stbl },
- { ATOM_stsd, MP4_ReadBox_stsd, MP4_FreeBox_Common, ATOM_stbl },
+ { ATOM_stsd, MP4_ReadBox_LtdContainer, MP4_FreeBox_Common, ATOM_stbl },
{ ATOM_stsz, MP4_ReadBox_stsz, MP4_FreeBox_stsz, ATOM_stbl },
{ ATOM_stsc, MP4_ReadBox_stsc, MP4_FreeBox_stsc, ATOM_stbl },
{ ATOM_stco, MP4_ReadBox_stco_co64, MP4_FreeBox_stco_co64, ATOM_stbl },
} MP4_Box_data_urn_t;
-typedef struct MP4_Box_data_dref_s
+typedef struct MP4_Box_data_lcont_s
{
uint8_t i_version;
uint32_t i_flags;
uint32_t i_entry_count;
/* XXX it's also a container with i_entry_count entry */
-} MP4_Box_data_dref_t;
+} MP4_Box_data_lcont_t;
typedef struct MP4_Box_data_stts_s
{
} MP4_Box_data_moviehintinformation_rtp_t;
-
-
-typedef struct MP4_Box_data_stsd_s
-{
- uint8_t i_version;
- uint32_t i_flags;
-
- uint32_t i_entry_count;
-
- /* it contains SampleEntry handled as if it was Box */
-
-} MP4_Box_data_stsd_t;
-
-
typedef struct MP4_Box_data_stsz_s
{
uint8_t i_version;
MP4_Box_data_hmhd_t *p_hmhd;
MP4_Box_data_url_t *p_url;
MP4_Box_data_urn_t *p_urn;
- MP4_Box_data_dref_t *p_dref;
+ MP4_Box_data_lcont_t *p_lcont;
MP4_Box_data_stts_t *p_stts;
MP4_Box_data_ctts_t *p_ctts;
- MP4_Box_data_stsd_t *p_stsd;
MP4_Box_data_sample_vide_t *p_sample_vide;
MP4_Box_data_sample_soun_t *p_sample_soun;
MP4_Box_data_sample_text_t *p_sample_text;
p_str = NULL; \
}
-#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
- int64_t i_read = p_box->i_size; \
+#define MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_TYPE_t, maxread ) \
+ int64_t i_read = p_box->i_size; \
+ if( maxread < (uint64_t)i_read ) i_read = maxread;\
uint8_t *p_peek, *p_buff; \
int i_actually_read; \
if( !( p_peek = p_buff = malloc( i_read ) ) ) \
return( 0 ); \
}
+#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
+ MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_TYPE_t, p_box->i_size )
+
#define MP4_READBOX_EXIT( i_code ) \
do \
{ \