]> 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 10d2810221ae53aba9e8c57e8a97cfadfa4f5fed..a0d812e3ac34691850dcd0f848990cf0defe8e2b 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdlib.h>                                      /* malloc(), free() */
 #include <string.h>
 
+#include <vlc_codecs.h>
 #include <vlc_demux.h>
 #include <vlc_interface.h>
 #include <vlc_network.h>
@@ -492,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" ) )
         {
@@ -1324,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 );
     }