]> git.sesse.net Git - vlc/blobdiff - modules/demux/live555.cpp
demux/live555.cpp: added support for avc1 in X-QT over RTSP
[vlc] / modules / demux / live555.cpp
index 3be874be48837023629ba2487a951f443d22cae0..a0d812e3ac34691850dcd0f848990cf0defe8e2b 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
 
 #include <vlc/vlc.h>
-#include <vlc/input.h>
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>
 
-#include "vlc_interaction.h"
-#include "network.h"
+#include <vlc_codecs.h>
+#include <vlc_demux.h>
+#include <vlc_interface.h>
+#include <vlc_network.h>
 
 #include <iostream>
 
@@ -491,6 +493,11 @@ static int  Open ( vlc_object_t *p_this )
                     p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf",
                                                         p_demux->out );
             }
+            else if( !strcmp( sub->codecName(), "X-QT" ) ||
+                     !strcmp( sub->codecName(), "X-QUICKTIME" ) )
+            {
+                tk->b_quicktime = VLC_TRUE;
+            }
         }
         else if( !strcmp( sub->mediumName(), "video" ) )
         {
@@ -515,7 +522,7 @@ static int  Open ( vlc_object_t *p_this )
                 unsigned int i_extra = 0;
                 uint8_t      *p_extra = NULL;
 #endif
-                tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '4' );
+                tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
                 tk->fmt.b_packetized = VLC_FALSE;
 
                 /* XXX not the right minimal version I fear */
@@ -737,7 +744,7 @@ describe:
     
     if( p_sdp == NULL )
     {
-        /* failure occured */
+        /* failure occurred */
         int i_code = 0;
         const char *psz_error = p_sys->env->getResultMsg();
                 
@@ -781,7 +788,7 @@ describe:
 
     /* malloc-ated copy */
     if( p_sys->p_sdp ) free( p_sys->p_sdp );
-    p_sys->p_sdp = strdup( (char*)p_sdp );
+    if( p_sdp ) p_sys->p_sdp = strdup( (char*)p_sdp );
     delete[] p_sdp;
 
     return i_ret;
@@ -1207,7 +1214,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 static int RollOverTcp( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
-    MediaSubsessionIterator *iter;
+    MediaSubsessionIterator *iter = 0;
     MediaSubsession *sub;
     int i_tk;
     int i_return;
@@ -1323,21 +1330,55 @@ static void StreamRead( void *p_private, unsigned int i_size,
         QuickTimeGenericRTPSource::QTState &qtState = qtRTPSource->qtState;
         uint8_t *sdAtom = (uint8_t*)&qtState.sdAtom[4];
 
-        if( qtState.sdAtomSize < 16 + 32 )
-        {
-            /* invalid */
-            p_sys->event = 0xff;
-            tk->waiting = 0;
-            return;
-        }
-        tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]);
-        tk->fmt.video.i_width  = (sdAtom[28] << 8) | sdAtom[29];
-        tk->fmt.video.i_height = (sdAtom[30] << 8) | sdAtom[31];
-
-        tk->fmt.i_extra        = qtState.sdAtomSize - 16;
-        tk->fmt.p_extra        = malloc( tk->fmt.i_extra );
-        memcpy( tk->fmt.p_extra, &sdAtom[12], tk->fmt.i_extra );
+        if( tk->fmt.i_cat == VIDEO_ES ) {
+            if( qtState.sdAtomSize < 16 + 32 )
+            {
+                /* invalid */
+                p_sys->event = 0xff;
+                tk->waiting = 0;
+                return;
+            }
+            tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]);
+            tk->fmt.video.i_width  = (sdAtom[28] << 8) | sdAtom[29];
+            tk->fmt.video.i_height = (sdAtom[30] << 8) | sdAtom[31];
 
+            if( tk->fmt.i_codec == VLC_FOURCC('a', 'v', 'c', '1') )
+            {
+                uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 86;
+                uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom
+                                  + qtRTPSource->qtState.sdAtomSize;
+                while (pos+8 < endpos) {
+                    unsigned atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3];
+                    if( atomLength == 0 || atomLength > endpos-pos) break;
+                    if( memcmp(pos+4, "avcC", 4) == 0 &&
+                        atomLength > 8 &&
+                        atomLength <= INT_MAX-sizeof(BITMAPINFOHEADER))
+                    {
+                        tk->fmt.i_extra = atomLength-8;
+                        tk->fmt.p_extra = malloc( tk->fmt.i_extra );
+                        memcpy(tk->fmt.p_extra, pos+8, atomLength-8);
+                        break;
+                    }
+                    pos += atomLength;
+                }
+            }
+            else
+            {
+                tk->fmt.i_extra        = qtState.sdAtomSize - 16;
+                tk->fmt.p_extra        = malloc( tk->fmt.i_extra );
+                memcpy( tk->fmt.p_extra, &sdAtom[12], tk->fmt.i_extra );
+            }
+        }
+        else {
+            if( qtState.sdAtomSize < 4 )
+            {
+                /* invalid */
+                p_sys->event = 0xff;
+                tk->waiting = 0;
+                return;
+            }
+            tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]);
+        }
         tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
     }
 
@@ -1395,7 +1436,7 @@ static void StreamRead( void *p_private, unsigned int i_size,
         if( tk->rtpSource->curPacketMarkerBit() )
             p_block->i_flags |= BLOCK_FLAG_END_OF_FRAME;
     }
-    else if( tk->fmt.i_codec == VLC_FOURCC('H','2','6','4') )
+    else if( tk->fmt.i_codec == VLC_FOURCC('h','2','6','4') )
     {
         if( (tk->p_buffer[0] & 0x1f) >= 24 )
             msg_Warn( p_demux, "unsupported NAL type for H264" );
@@ -1565,6 +1606,7 @@ static unsigned char* parseH264ConfigStr( char const* configStr,
                                           unsigned int& configSize )
 {
     char *dup, *psz;
+    int i, i_records = 1;
 
     if( configSize )
     configSize = 0;
@@ -1574,22 +1616,27 @@ static unsigned char* parseH264ConfigStr( char const* configStr,
 
     psz = dup = strdup( configStr );
 
-    unsigned char *cfg = new unsigned char[5 * strlen(psz)];
-    for( ;; )
+    /* Count the number of comma's */
+    for( psz = dup; *psz != '\0'; ++psz )
     {
-        char *p = strchr( psz, ',' );
-        if( p )
-            *p++ = '\0';
+        if( *psz == ',')
+        {
+            ++i_records;
+            *psz = '\0';
+        }
+    }
 
+    unsigned char *cfg = new unsigned char[5 * strlen(dup)];
+    psz = dup;
+    for( i = 0; i < i_records; i++ )
+    {
         cfg[configSize++] = 0x00;
         cfg[configSize++] = 0x00;
         cfg[configSize++] = 0x00;
         cfg[configSize++] = 0x01;
-        configSize += b64_decode( (char*)&cfg[configSize], psz );
 
-        if( p == NULL )
-            break;
-        psz = p;
+        configSize += b64_decode( (char*)&cfg[configSize], psz );
+        psz += strlen(psz)+1;
     }
 
     if( dup ) free( dup );