]> git.sesse.net Git - vlc/commitdiff
* mp4: - add +1 to PCR/DTS/PTS.
authorLaurent Aimar <fenrir@videolan.org>
Sat, 15 May 2004 11:03:48 +0000 (11:03 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Sat, 15 May 2004 11:03:48 +0000 (11:03 +0000)
        - preliminary support of avc (using a draft+google without
samples to test, so don't expect it to work ;)
 * libmp4: parse the avcC atom.

modules/demux/mp4/libmp4.c
modules/demux/mp4/libmp4.h
modules/demux/mp4/mp4.c

index bcb5d801a34a5736e89db66e0dbccfd8a3386cf5..2cdb03ce29ecd43ba52449d904090e048f9db090 100644 (file)
@@ -1080,6 +1080,100 @@ static void MP4_FreeBox_esds( MP4_Box_t *p_box )
     FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
 }
 
+static int MP4_ReadBox_avcC( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_Box_data_avcC_t *p_avcC;
+    int i;
+
+    MP4_READBOX_ENTER( MP4_Box_data_avcC_t );
+    p_avcC = p_box->data.p_avcC;
+
+    p_avcC->i_avcC = i_read;
+    p_avcC->p_avcC = malloc( p_avcC->i_avcC );
+    memcpy( p_avcC->p_avcC, p_peek, i_read );
+
+    MP4_GET1BYTE( p_avcC->i_version );
+    MP4_GET1BYTE( p_avcC->i_profile );
+    MP4_GET1BYTE( p_avcC->i_profile_compatibility );
+    MP4_GET1BYTE( p_avcC->i_level );
+    MP4_GET1BYTE( p_avcC->i_reserved1 );
+    p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1;
+    p_avcC->i_reserved1 >>= 2;
+
+    MP4_GET1BYTE( p_avcC->i_reserved2 );
+    p_avcC->i_sps = p_avcC->i_reserved2&0x1f;
+    p_avcC->i_reserved2 >>= 5;
+
+    if( p_avcC->i_sps > 0 )
+    {
+        p_avcC->i_sps_length = malloc( p_avcC->i_sps * sizeof( uint16_t ) );
+        p_avcC->sps = malloc( p_avcC->i_sps * sizeof( uint8_t* ) );
+
+        for( i = 0; i < p_avcC->i_sps; i++ )
+        {
+            MP4_GET2BYTES( p_avcC->i_sps_length[i] );
+            p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
+            memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
+
+            p_peek += p_avcC->i_sps_length[i];
+            i_read -= p_avcC->i_sps_length[i];
+        }
+    }
+
+    MP4_GET1BYTE( p_avcC->i_pps );
+    if( p_avcC->i_pps > 0 )
+    {
+        p_avcC->i_pps_length = malloc( p_avcC->i_pps * sizeof( uint16_t ) );
+        p_avcC->pps = malloc( p_avcC->i_pps * sizeof( uint8_t* ) );
+
+        for( i = 0; i < p_avcC->i_pps; i++ )
+        {
+            MP4_GET2BYTES( p_avcC->i_pps_length[i] );
+            p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
+            memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
+
+            p_peek += p_avcC->i_pps_length[i];
+            i_read -= p_avcC->i_pps_length[i];
+        }
+    }
+#ifdef MP4_VERBOSE
+    msg_Dbg( p_stream->s,
+             "read box: \"avcC\" version=%d profile=0x%x level=0x%x lengh 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 );
+    for( i = 0; i < p_avcC->i_sps; i++ )
+    {
+        msg_Dbg( p_stream->s, "         - sps[%d] length=%d",
+                 i, p_avcC->i_sps_length[i] );
+    }
+    for( i = 0; i < p_avcC->i_pps; i++ )
+    {
+        msg_Dbg( p_stream->s, "         - pps[%d] length=%d",
+                 i, p_avcC->i_pps_length[i] );
+    }
+
+#endif
+    MP4_READBOX_EXIT( 1 );
+}
+
+static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
+{
+    MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
+    int i;
+
+    for( i = 0; i < p_avcC->i_sps; i++ )
+    {
+        FREE( p_avcC->sps[i] );
+    }
+    for( i = 0; i < p_avcC->i_pps; i++ )
+    {
+        FREE( p_avcC->pps[i] );
+    }
+    if( p_avcC->i_sps > 0 ) FREE( p_avcC->sps );
+    if( p_avcC->i_pps > 0 ) FREE( p_avcC->pps );
+}
+
 static int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
     unsigned int i;
@@ -2048,6 +2142,7 @@ static struct
     { FOURCC_esds,  MP4_ReadBox_esds,       MP4_FreeBox_esds },
     { FOURCC_dcom,  MP4_ReadBox_dcom,       MP4_FreeBox_Common },
     { FOURCC_cmvd,  MP4_ReadBox_cmvd,       MP4_FreeBox_cmvd },
+    { FOURCC_avcC,  MP4_ReadBox_avcC,       MP4_FreeBox_avcC },
 
     /* Nothing to do with this box */
     { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
@@ -2106,6 +2201,7 @@ static struct
     { FOURCC_h264,  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_mp4s,  NULL,                       MP4_FreeBox_Common },
 
index a89a1009ebddaf5689fb50a705652bf2874be796..8cb0c634e8f542e1c832b7369dd58d62afefb678 100644 (file)
 #define FOURCC_vp31 VLC_FOURCC( 'v', 'p', '3', '1' )
 #define FOURCC_h264 VLC_FOURCC( 'h', '2', '6', '4' )
 
+#define FOURCC_avc1 VLC_FOURCC( 'a', 'v', 'c', '1' )
+#define FOURCC_avcC VLC_FOURCC( 'a', 'v', 'c', 'C' )
+#define FOURCC_m4ds VLC_FOURCC( 'm', '4', 'd', 's' )
+
 #define FOURCC_dvc  VLC_FOURCC( 'd', 'v', 'c', ' ' )
 #define FOURCC_dvp  VLC_FOURCC( 'd', 'v', 'p', ' ' )
 #define FOURCC_raw  VLC_FOURCC( 'r', 'a', 'w', ' ' )
@@ -728,6 +732,31 @@ typedef struct
 
 } MP4_Box_data_0xa9xxx_t;
 
+typedef struct
+{
+    uint8_t i_version;
+    uint8_t i_profile;
+    uint8_t i_profile_compatibility;
+    uint8_t i_level;
+
+    uint8_t i_reserved1;     /* 6 bits */
+    uint8_t i_length_size;
+
+    uint8_t i_reserved2;    /* 3 bits */
+    uint8_t  i_sps;
+    uint16_t *i_sps_length;
+    uint8_t  **sps;
+
+    uint8_t  i_pps;
+    uint16_t *i_pps_length;
+    uint8_t  **pps;
+
+    /* XXX: Hack raw avcC atom payload */
+    int     i_avcC;
+    uint8_t *p_avcC;
+
+} MP4_Box_data_avcC_t;
+
 /*
 typedef struct MP4_Box_data__s
 {
@@ -759,6 +788,7 @@ typedef union MP4_Box_data_s
         MP4_Box_data_sample_hint_t *p_sample_hint;
 
         MP4_Box_data_esds_t *p_esds;
+        MP4_Box_data_avcC_t *p_avcC;
 
     MP4_Box_data_stsz_t *p_stsz;
     MP4_Box_data_stz2_t *p_stz2;
index f7e3925b7750408ad1b82b646e0f8e8c7cf24a3d..90fd492206f331a650e7736b0bfcbbf356920241 100644 (file)
@@ -529,7 +529,7 @@ static int Demux( demux_t *p_demux )
     }
 
     /* first wait for the good time to read a packet */
-    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
+    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 );
 
     p_sys->i_pcr = MP4_GetMoviePTS( p_sys );
 
@@ -580,9 +580,9 @@ static int Demux( demux_t *p_demux )
                                   (uint32_t*)p_block->p_buffer,
                                   p_block->i_buffer );
                 }
-                p_block->i_dts = MP4_TrackGetPTS( p_demux, tk );
+                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;
+                p_block->i_pts = tk->fmt.i_cat == VIDEO_ES ? 0 : p_block->i_dts + 1;
 
                 if( !tk->b_drms || ( tk->b_drms && tk->p_drms ) )
                 {
@@ -1179,6 +1179,28 @@ static int  TrackCreateES   ( demux_t   *p_demux,
                             p_track->fmt.i_extra);
                 }
                 break;
+
+            /* avc1: send avcC (h264 without annexe B) */
+            case VLC_FOURCC( 'a', 'v', 'c', '1' ):
+            {
+                MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
+
+                if( p_avcC )
+                {
+                    /* Hack: use a packetizer to reecampsulate data in anexe B format */
+                    msg_Dbg( p_demux, "avcC: size=%d", p_avcC->data.p_avcC->i_avcC );
+                    p_track->fmt.i_extra = p_avcC->data.p_avcC->i_avcC;
+                    p_track->fmt.p_extra = malloc( p_avcC->data.p_avcC->i_avcC );
+                    memcpy( p_track->fmt.p_extra, p_avcC->data.p_avcC->p_avcC, p_track->fmt.i_extra );
+                    p_track->fmt.b_packetized = VLC_FALSE;
+                }
+                else
+                {
+                    msg_Err( p_demux, "missing avcC" );
+                }
+                break;
+            }
+
             default:
                 break;
         }
@@ -1693,6 +1715,7 @@ static int  MP4_TrackSelect ( demux_t    *p_demux,
 static void MP4_TrackUnselect(demux_t    *p_demux,
                               mp4_track_t  *p_track )
 {
+    fprintf( stderr, "MP4_TrackUnselect: id=%d\n", p_track->i_track_ID );
     if( !p_track->b_ok )
     {
         return;