]> git.sesse.net Git - vlc/blobdiff - modules/demux/mp4/libmp4.c
Fix gvp demux
[vlc] / modules / demux / mp4 / libmp4.c
index dd557e032f2e5b17e371653d173e67cd12df3947..6c282ead393c51f0299c9742945181ead97f711e 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * libmp4.c : LibMP4 library for mp4 module for vlc
  *****************************************************************************
- * Copyright (C) 2001-2004 VideoLAN
+ * Copyright (C) 2001-2004 the VideoLAN team
  * $Id$
  *
  * Author: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
+#include <vlc/vlc.h>
+
+#include <stdio.h>
 #include <stdlib.h>                                      /* malloc(), free() */
 
-#include <vlc/vlc.h>
 #include <vlc/input.h>
 
 #ifdef HAVE_ZLIB_H
@@ -67,9 +69,9 @@
 #define MP4_GETSTRINGZ( p_str ) \
     if( ( i_read > 0 )&&(p_peek[0] ) ) \
     { \
-        p_str = calloc( sizeof( char ), __MIN( strlen( p_peek ), i_read )+1);\
-        memcpy( p_str, p_peek, __MIN( strlen( p_peek ), i_read ) ); \
-        p_str[__MIN( strlen( p_peek ), i_read )] = 0; \
+        p_str = calloc( sizeof( char ), __MIN( strlen( (char*)p_peek ), i_read )+1);\
+        memcpy( p_str, p_peek, __MIN( strlen( (char*)p_peek ), i_read ) ); \
+        p_str[__MIN( strlen( (char*)p_peek ), i_read )] = 0; \
         p_peek += strlen( p_str ) + 1; \
         i_read -= strlen( p_str ) + 1; \
     } \
 
 
 #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
-    int64_t  i_read = p_box->i_size; \
+    uint64_t  i_read = p_box->i_size; \
     uint8_t *p_peek, *p_buff; \
-    i_read = p_box->i_size; \
+    int i_actually_read; \
     if( !( p_peek = p_buff = malloc( i_read ) ) ) \
     { \
         return( 0 ); \
     } \
-    if( stream_Read( p_stream, p_peek, i_read ) < i_read )\
+    i_actually_read = stream_Read( p_stream, p_peek, i_read ); \
+    if( i_actually_read < 0 || (uint64_t)i_actually_read < i_read )\
     { \
         free( p_buff ); \
         return( 0 ); \
     } \
     return( i_code )
 
-#define FREE( p ) \
-    if( p ) {free( p ); p = NULL; }
-
-
 
 /* Some assumptions:
         * The input method HAVE to be seekable
@@ -225,7 +224,7 @@ int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
 /*****************************************************************************
  * MP4_NextBox : Go to the next box
  *****************************************************************************
- * if p_box == NULL, go to the next box in witch we are( at the begining ).
+ * if p_box == NULL, go to the next box in which we are( at the begining ).
  *****************************************************************************/
 static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
 {
@@ -248,6 +247,7 @@ static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
         if( p_box->i_size + p_box->i_pos >=
             p_box->p_father->i_size + p_box->p_father->i_pos )
         {
+            msg_Dbg( p_stream, "out of bound child" );
             return 0; /* out of bound */
         }
     }
@@ -375,7 +375,7 @@ static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_ftyp->i_compatible_brands );
+    FREENULL( p_box->data.p_ftyp->i_compatible_brands );
 }
 
 
@@ -582,30 +582,33 @@ static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( i_reserved );
     MP4_GET4BYTES( i_reserved );
     MP4_GET4BYTES( i_reserved );
+    p_box->data.p_hdlr->psz_name = NULL;
 
-    p_box->data.p_hdlr->psz_name = calloc( sizeof( char ), i_read + 1 );
-
-    /* Yes, I love .mp4 :( */
-    if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
+    if( i_read > 0 )
     {
-        uint8_t i_len;
-        int i_copy;
+        p_box->data.p_hdlr->psz_name = calloc( sizeof( char ), i_read + 1 );
 
-        MP4_GET1BYTE( i_len );
-        i_copy = __MIN( i_read, i_len );
+        /* Yes, I love .mp4 :( */
+        if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
+        {
+            uint8_t i_len;
+            int i_copy;
 
-        memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
-        p_box->data.p_hdlr->psz_name[i_copy] = '\0';
-    }
-    else
-    {
-        memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
-        p_box->data.p_hdlr->psz_name[i_read] = '\0';
-    }
+            MP4_GET1BYTE( i_len );
+            i_copy = __MIN( i_read, i_len );
 
+            memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
+            p_box->data.p_hdlr->psz_name[i_copy] = '\0';
+        }
+        else
+        {
+            memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
+            p_box->data.p_hdlr->psz_name[i_read] = '\0';
+        }
+    }
 
 #ifdef MP4_VERBOSE
-    msg_Dbg( p_stream, "read box: \"hdlr\" hanler type %4.4s name %s",
+    msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
                        (char*)&p_box->data.p_hdlr->i_handler_type,
                        p_box->data.p_hdlr->psz_name );
 
@@ -615,7 +618,7 @@ static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_hdlr->psz_name );
+    FREENULL( p_box->data.p_hdlr->psz_name );
 }
 
 static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
@@ -704,7 +707,7 @@ static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_url( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_url->psz_location )
+    FREENULL( p_box->data.p_url->psz_location )
 }
 
 static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
@@ -725,8 +728,8 @@ static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
 }
 static void MP4_FreeBox_urn( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_urn->psz_name );
-    FREE( p_box->data.p_urn->psz_location );
+    FREENULL( p_box->data.p_urn->psz_name );
+    FREENULL( p_box->data.p_urn->psz_location );
 }
 
 
@@ -779,8 +782,8 @@ static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stts( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stts->i_sample_count );
-    FREE( p_box->data.p_stts->i_sample_delta );
+    FREENULL( p_box->data.p_stts->i_sample_count );
+    FREENULL( p_box->data.p_stts->i_sample_delta );
 }
 
 static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
@@ -813,11 +816,11 @@ static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_ctts->i_sample_count );
-    FREE( p_box->data.p_ctts->i_sample_offset );
+    FREENULL( p_box->data.p_ctts->i_sample_count );
+    FREENULL( p_box->data.p_ctts->i_sample_offset );
 }
 
-static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t  *i_read )
+static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, uint64_t  *i_read )
 {
     unsigned int i_b;
     unsigned int i_len = 0;
@@ -937,12 +940,12 @@ static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_esds( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_esds->es_descriptor.psz_URL );
+    FREENULL( p_box->data.p_esds->es_descriptor.psz_URL );
     if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
     {
-        FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
+        FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
     }
-    FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
+    FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
 }
 
 static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1003,7 +1006,7 @@ static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
     }
 #ifdef MP4_VERBOSE
     msg_Dbg( p_stream,
-             "read box: \"avcC\" version=%d profile=0x%x level=0x%x lengh size=%d sps=%d pps=%d",
+             "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
              p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level,
              p_avcC->i_length_size,
              p_avcC->i_sps, p_avcC->i_pps );
@@ -1029,14 +1032,14 @@ static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
 
     for( i = 0; i < p_avcC->i_sps; i++ )
     {
-        FREE( p_avcC->sps[i] );
+        FREENULL( p_avcC->sps[i] );
     }
     for( i = 0; i < p_avcC->i_pps; i++ )
     {
-        FREE( p_avcC->pps[i] );
+        FREENULL( p_avcC->pps[i] );
     }
-    if( p_avcC->i_sps > 0 ) FREE( p_avcC->sps );
-    if( p_avcC->i_pps > 0 ) FREE( p_avcC->pps );
+    if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
+    if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
 }
 
 static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1087,10 +1090,9 @@ static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
 
-    if( p_box->data.p_sample_soun->i_qt_version == 1 &&
-        i_read >= 16 )
+    if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
     {
-        /* qt3+ */
+        /* SoundDescriptionV1 */
         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
@@ -1108,6 +1110,30 @@ static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
         stream_Seek( p_stream, p_box->i_pos +
                         MP4_BOX_HEADERSIZE( p_box ) + 44 );
     }
+    else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
+    {
+        /* SoundDescriptionV2 */
+        double f_sample_rate;
+       int64_t dummy;
+        uint32_t i_channel;
+
+        MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
+        MP4_GET8BYTES( dummy );
+       memcpy( &f_sample_rate, &dummy, 8 );
+
+        msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
+        p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536;
+        p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536;
+
+        MP4_GET4BYTES( i_channel );
+        p_box->data.p_sample_soun->i_channelcount = i_channel;
+
+#ifdef MP4_VERBOSE
+        msg_Dbg( p_stream, "read box: \"soun\" V2" );
+#endif
+        stream_Seek( p_stream, p_box->i_pos +
+                        MP4_BOX_HEADERSIZE( p_box ) + 28 + 36 );
+    }
     else
     {
         p_box->data.p_sample_soun->i_sample_per_packet = 0;
@@ -1124,7 +1150,7 @@ static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
     if( p_box->i_type == FOURCC_drms )
     {
         p_box->data.p_sample_soun->p_drms =
-            drms_alloc( p_stream->p_vlc->psz_homedir );
+            drms_alloc( p_stream->p_libvlc->psz_homedir );
 
         if( p_box->data.p_sample_soun->p_drms == NULL )
         {
@@ -1167,7 +1193,7 @@ static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_sample_soun->p_qt_description );
+    FREENULL( p_box->data.p_sample_soun->p_qt_description );
 
     if( p_box->i_type == FOURCC_drms )
     {
@@ -1246,7 +1272,7 @@ int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
 
 void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_sample_vide->p_qt_image_description );
+    FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
 }
 
 static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1258,52 +1284,92 @@ static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
 
 static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
 {
-    unsigned int i;
+    int32_t t;
 
     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_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
+
     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_GET4BYTES( t );
+    switch( t )
+    {
+        /* FIXME search right signification */
+        case 1: // Center
+            p_box->data.p_sample_text->i_justification_horizontal = 1;
+            p_box->data.p_sample_text->i_justification_vertical = 1;
+            break;
+        case -1:    // Flush Right
+            p_box->data.p_sample_text->i_justification_horizontal = -1;
+            p_box->data.p_sample_text->i_justification_vertical = -1;
+            break;
+        case -2:    // Flush Left
+            p_box->data.p_sample_text->i_justification_horizontal = 0;
+            p_box->data.p_sample_text->i_justification_vertical = 0;
+            break;
+        case 0: // Flush Default
+        default:
+            p_box->data.p_sample_text->i_justification_horizontal = 1;
+            p_box->data.p_sample_text->i_justification_vertical = -1;
+            break;
+    }
 
     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] );
+    p_box->data.p_sample_text->i_background_color[3] = 0;
 
-    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_text_box_top );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
 
-    MP4_GET2BYTES( p_box->data.p_sample_text->i_font_number );
-    MP4_GET2BYTES( p_box->data.p_sample_text->i_font_face );
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
+#endif
+    MP4_READBOX_EXIT( 1 );
+}
 
-    MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved3 );
+static int MP4_ReadBox_sample_tx3g( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
 
-    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_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
 
-    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';
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
+
+    MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
+
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_horizontal );
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_vertical );
+
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[0] );
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[1] );
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[2] );
+    MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[3] );
+
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
+    MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
 
 #ifdef MP4_VERBOSE
-    msg_Dbg( p_stream, "read box: \"text\" in stsd text name=%s",
-             p_box->data.p_sample_text->psz_text_name );
+    msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
 #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 );
+    FREENULL( p_box->data.p_sample_text->psz_text_name );
 }
 #endif
 
@@ -1364,7 +1430,7 @@ static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stsz->i_entry_size );
+    FREENULL( p_box->data.p_stsz->i_entry_size );
 }
 
 static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1401,9 +1467,9 @@ static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stsc->i_first_chunk );
-    FREE( p_box->data.p_stsc->i_samples_per_chunk );
-    FREE( p_box->data.p_stsc->i_sample_description_index );
+    FREENULL( p_box->data.p_stsc->i_first_chunk );
+    FREENULL( p_box->data.p_stsc->i_samples_per_chunk );
+    FREENULL( p_box->data.p_stsc->i_sample_description_index );
 }
 
 static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1449,7 +1515,7 @@ static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_co64->i_chunk_offset );
+    FREENULL( p_box->data.p_co64->i_chunk_offset );
 }
 
 static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1483,7 +1549,7 @@ static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stss( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stss->i_sample_number )
+    FREENULL( p_box->data.p_stss->i_sample_number )
 }
 
 static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1520,8 +1586,8 @@ static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stsh->i_shadowed_sample_number )
-    FREE( p_box->data.p_stsh->i_sync_sample_number )
+    FREENULL( p_box->data.p_stsh->i_shadowed_sample_number )
+    FREENULL( p_box->data.p_stsh->i_sync_sample_number )
 }
 
 
@@ -1552,7 +1618,7 @@ static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_stdp->i_priority )
+    FREENULL( p_box->data.p_stdp->i_priority )
 }
 
 static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1596,10 +1662,10 @@ static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_padb( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_padb->i_reserved1 );
-    FREE( p_box->data.p_padb->i_pad2 );
-    FREE( p_box->data.p_padb->i_reserved2 );
-    FREE( p_box->data.p_padb->i_pad1 );
+    FREENULL( p_box->data.p_padb->i_reserved1 );
+    FREENULL( p_box->data.p_padb->i_pad2 );
+    FREENULL( p_box->data.p_padb->i_reserved2 );
+    FREENULL( p_box->data.p_padb->i_pad1 );
 }
 
 static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1655,10 +1721,10 @@ static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_elst( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_elst->i_segment_duration );
-    FREE( p_box->data.p_elst->i_media_time );
-    FREE( p_box->data.p_elst->i_media_rate_integer );
-    FREE( p_box->data.p_elst->i_media_rate_fraction );
+    FREENULL( p_box->data.p_elst->i_segment_duration );
+    FREENULL( p_box->data.p_elst->i_media_time );
+    FREENULL( p_box->data.p_elst->i_media_rate_integer );
+    FREENULL( p_box->data.p_elst->i_media_rate_fraction );
 }
 
 static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
@@ -1692,7 +1758,7 @@ static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_cprt->psz_notice );
+    FREENULL( p_box->data.p_cprt->psz_notice );
 }
 
 
@@ -1739,7 +1805,7 @@ static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
 }
 static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_cmvd->p_data );
+    FREENULL( p_box->data.p_cmvd->p_data );
 }
 
 
@@ -1902,7 +1968,7 @@ static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
 
 static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_rdrf->psz_ref )
+    FREENULL( p_box->data.p_rdrf->psz_ref )
 }
 
 
@@ -1970,11 +2036,34 @@ static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
 
     if( p_drms_box && p_drms_box->data.p_sample_soun->p_drms )
     {
-        if( drms_init( p_drms_box->data.p_sample_soun->p_drms,
-                       p_box->i_type, p_peek, i_read ) )
+        int i_ret;
+        if( config_GetInt( p_stream, "france" ) )
         {
-            msg_Err( p_stream, "drms_init( %4.4s ) failed",
-                     (char *)&p_box->i_type );
+            i_ret = -7;
+        }
+        else
+        {
+            i_ret= drms_init( p_drms_box->data.p_sample_soun->p_drms,
+                               p_box->i_type, p_peek, i_read );
+        }
+        if( i_ret )
+        {
+            char *psz_error;
+
+            switch( i_ret )
+            {
+                case -1: psz_error = "unimplemented"; break;
+                case -2: psz_error = "invalid argument"; break;
+                case -3: psz_error = "could not get system key"; break;
+                case -4: psz_error = "could not get SCI data"; break;
+                case -5: psz_error = "no user key found in SCI data"; break;
+                case -6: psz_error = "invalid user key"; break;
+                case -7: psz_error = "you live in France"; break;
+                default: psz_error = "unknown error"; break;
+            }
+
+            msg_Err( p_stream, "drms_init(%4.4s) failed (%s)",
+                     (char *)&p_box->i_type, psz_error );
 
             drms_free( p_drms_box->data.p_sample_soun->p_drms );
             p_drms_box->data.p_sample_soun->p_drms = NULL;
@@ -1986,7 +2075,7 @@ static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
 
 static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int16_t i_length, i_dummy;
+    uint16_t i_length, i_dummy;
 
     MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
 
@@ -2017,7 +2106,7 @@ static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
 }
 static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
 {
-    FREE( p_box->data.p_0xa9xxx->psz_text );
+    FREENULL( p_box->data.p_0xa9xxx->psz_text );
 }
 
 /* For generic */
@@ -2045,6 +2134,8 @@ static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
                 return MP4_ReadBox_sample_vide( p_stream, p_box );
             case FOURCC_text:
                 return MP4_ReadBox_sample_text( p_stream, p_box );
+            case FOURCC_tx3g:
+                return MP4_ReadBox_sample_tx3g( p_stream, p_box );
             default:
                 msg_Warn( p_stream,
                           "unknown handler type in stsd (uncompletetly loaded)" );
@@ -2172,6 +2263,8 @@ static struct
     { FOURCC_mjpa,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
     { FOURCC_mjpb,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
     { FOURCC_qdrw,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
+    { FOURCC_mp2v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
+    { FOURCC_hdv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
 
     { FOURCC_mjqt,  MP4_ReadBox_default,        NULL }, /* found in mjpa/b */
     { FOURCC_mjht,  MP4_ReadBox_default,        NULL },
@@ -2514,7 +2607,7 @@ static void __MP4_BoxGet( MP4_Box_t **pp_result,
 
     if( !psz_path || !psz_path[0] )
     {
-        FREE( psz_path );
+        FREENULL( psz_path );
         *pp_result = NULL;
         return;
     }
@@ -2531,7 +2624,7 @@ static void __MP4_BoxGet( MP4_Box_t **pp_result,
 //                 psz_path,psz_token,i_number );
         if( !psz_token )
         {
-            FREE( psz_token );
+            FREENULL( psz_token );
             free( psz_fmt );
             *pp_result = p_box;
             return;
@@ -2620,7 +2713,7 @@ static void __MP4_BoxGet( MP4_Box_t **pp_result,
         else
         {
 //            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
-            FREE( psz_token );
+            FREENULL( psz_token );
             free( psz_fmt );
             *pp_result = NULL;
             return;