[vlc-devel] [PATCH v2] Fix Metacube header handling with multiple header blocks.

Steinar H. Gunderson steinar+vlc at gunderson.no
Sun Mar 29 21:30:22 CEST 2015


Some muxes, e.g. MP4, will send multiple header blocks. These are
merged by the HTTP server to a single header which is sent out to
the beginning of each client. However, they are _also_ sent out
directly on the wire to any client that connected before the first
block. In this case, we would send two separate Metacube header
blocks, which would have Cubemap (correctly) discard the first and
set only the second as header.

This would make us send only part of the MP4 header when sending
through Cubemap, if Cubemap connected before the first non-header
block, which would in turn confuse Chrome on Android (although not
Chrome on e.g. Linux). As Cubemap is pretty aggressive about
reconnecting (trying every 200 ms), this could easily happen in practice.
---
 modules/access_output/http.c |   29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/modules/access_output/http.c b/modules/access_output/http.c
index f85eb42..f82e87c 100644
--- a/modules/access_output/http.c
+++ b/modules/access_output/http.c
@@ -380,13 +380,21 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
                 hdr.csum = hton16( metacube2_compute_crc( &hdr ) );
 
                 int i_header_size = p_sys->i_header_size + sizeof( hdr );
-                uint8_t *p_hdr_block = xmalloc( i_header_size );
-                memcpy( p_hdr_block, &hdr, sizeof( hdr ) );
-                memcpy( p_hdr_block + sizeof( hdr ), p_sys->p_header, p_sys->i_header_size );
-
-                httpd_StreamHeader( p_sys->p_httpd_stream, p_hdr_block, i_header_size );
-
-                free( p_hdr_block );
+                block_t *p_hdr_block = block_Alloc( i_header_size );
+                if( p_hdr_block == NULL ) {
+                    block_ChainRelease( p_buffer );
+                    return VLC_ENOMEM;
+                }
+                p_hdr_block->i_flags = 0;
+                memcpy( p_hdr_block->p_buffer, &hdr, sizeof( hdr ) );
+                memcpy( p_hdr_block->p_buffer + sizeof( hdr ), p_sys->p_header, p_sys->i_header_size );
+
+                /* send the combined header here instead of sending them as regular
+                 * data, so that we get them as a single Metacube header block */
+                httpd_StreamHeader( p_sys->p_httpd_stream, p_hdr_block->p_buffer, p_hdr_block->i_buffer );
+                httpd_StreamSend( p_sys->p_httpd_stream, p_hdr_block );
+
+                block_Release( p_hdr_block );
             }
             else
             {
@@ -406,6 +414,13 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
 
         if( p_sys->b_metacube )
         {
+            /* header data is combined into one packet and sent earlier */
+            if( p_buffer->i_flags & BLOCK_FLAG_HEADER ) {
+                block_Release( p_buffer );
+                p_buffer = p_next;
+                continue;
+            }
+
             /* prepend Metacube header */
             struct metacube2_block_header hdr;
             memcpy( hdr.sync, METACUBE2_SYNC, sizeof( METACUBE2_SYNC ) );
-- 
1.7.10.4




More information about the vlc-devel mailing list