From: Steinar H. Gunderson Date: Tue, 1 Oct 2013 22:19:10 +0000 (+0200) Subject: Update the VLC Metacube patch to apply against current VLC master. X-Git-Tag: 1.0.2~12 X-Git-Url: https://git.sesse.net/?p=cubemap;a=commitdiff_plain;h=e42cde17932cfbb2bf54244d46c6f9cd7215105b;ds=sidebyside Update the VLC Metacube patch to apply against current VLC master. This version is identical to the one that was sent to the VLC mailing list for upstream inclusion (but not accepted), so it also contains some other cleanups. --- diff --git a/vlc-metacube.diff b/vlc-metacube.diff index fbde59d..91de18b 100644 --- a/vlc-metacube.diff +++ b/vlc-metacube.diff @@ -32,10 +32,10 @@ index 0000000..dfbfd24 + +#endif /* !defined(_METACUBE_H) */ diff --git a/include/vlc_httpd.h b/include/vlc_httpd.h -index 6100dd0..7a14515 100644 +index 9eb0b15..8eacf68 100644 --- a/include/vlc_httpd.h +++ b/include/vlc_httpd.h -@@ -135,10 +135,10 @@ VLC_API void httpd_RedirectDelete( httpd_redirect_t * ); +@@ -135,7 +135,7 @@ VLC_API void httpd_RedirectDelete( httpd_redirect_t * ); typedef struct httpd_stream_t httpd_stream_t; @@ -43,25 +43,31 @@ index 6100dd0..7a14515 100644 +VLC_API httpd_stream_t * httpd_StreamNew( httpd_host_t *, const char *psz_url, const char *psz_mime, const char *psz_user, const char *psz_password, bool b_metacube ) VLC_USED; VLC_API void httpd_StreamDelete( httpd_stream_t * ); VLC_API int httpd_StreamHeader( httpd_stream_t *, uint8_t *p_data, int i_data ); --VLC_API int httpd_StreamSend( httpd_stream_t *, uint8_t *p_data, int i_data ); -+VLC_API int httpd_StreamSend( httpd_stream_t *, uint8_t *p_data, int i_data, bool b_header, bool b_keyframe ); - - - /* Msg functions facilities */ + VLC_API int httpd_StreamSend( httpd_stream_t *, const block_t *p_block ); diff --git a/modules/access_output/http.c b/modules/access_output/http.c -index 364768c..f667e08 100644 +index bf75130..e608f8d 100644 --- a/modules/access_output/http.c +++ b/modules/access_output/http.c -@@ -72,6 +72,8 @@ vlc_module_begin () +@@ -57,6 +57,9 @@ static void Close( vlc_object_t * ); + #define MIME_TEXT N_("Mime") + #define MIME_LONGTEXT N_("MIME returned by the server (autodetected " \ + "if not specified)." ) ++#define METACUBE_TEXT N_("Metacube") ++#define METACUBE_LONGTEXT N_("Use the Metacube protocol. Needed for streaming " \ ++ "to the Cubemap reflector.") + + + vlc_module_begin () +@@ -72,6 +75,8 @@ vlc_module_begin () PASS_TEXT, PASS_LONGTEXT, true ) add_string( SOUT_CFG_PREFIX "mime", "", MIME_TEXT, MIME_LONGTEXT, true ) + add_bool( SOUT_CFG_PREFIX "metacube", false, -+ "Use the metacube protocol", "Use the metacube protocol", true ) ++ METACUBE_TEXT, METACUBE_LONGTEXT, true ) set_callbacks( Open, Close ) vlc_module_end () -@@ -80,7 +82,7 @@ vlc_module_end () +@@ -80,7 +85,7 @@ vlc_module_end () * Exported prototypes *****************************************************************************/ static const char *const ppsz_sout_options[] = { @@ -70,16 +76,16 @@ index 364768c..f667e08 100644 }; static ssize_t Write( sout_access_out_t *, block_t * ); -@@ -114,6 +116,8 @@ static int Open( vlc_object_t *p_this ) +@@ -114,6 +119,8 @@ static int Open( vlc_object_t *p_this ) char *psz_pwd; char *psz_mime; -+ bool b_metacube; ++ bool b_metacube; + if( !( p_sys = p_access->p_sys = malloc( sizeof( sout_access_out_sys_t ) ) ) ) return VLC_ENOMEM ; -@@ -189,9 +193,11 @@ static int Open( vlc_object_t *p_this ) +@@ -189,9 +196,11 @@ static int Open( vlc_object_t *p_this ) psz_mime = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "mime" ); } @@ -92,29 +98,8 @@ index 364768c..f667e08 100644 free( psz_user ); free( psz_pwd ); free( psz_mime ); -@@ -263,8 +269,10 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ) - while( p_buffer ) - { - block_t *p_next; -+ bool b_header_block = p_buffer->i_flags & BLOCK_FLAG_HEADER; -+ bool b_keyframe = p_buffer->i_flags & BLOCK_FLAG_TYPE_I; - -- if( p_buffer->i_flags & BLOCK_FLAG_HEADER ) -+ if( b_header_block ) - { - /* gather header */ - if( p_sys->b_header_complete ) -@@ -297,7 +305,7 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ) - i_len += p_buffer->i_buffer; - /* send data */ - i_err = httpd_StreamSend( p_sys->p_httpd_stream, p_buffer->p_buffer, -- p_buffer->i_buffer ); -+ p_buffer->i_buffer, b_header_block, b_keyframe ); - - p_next = p_buffer->p_next; - block_Release( p_buffer ); diff --git a/src/Makefile.am b/src/Makefile.am -index 639d157..89f78bc 100644 +index a7f42ef..18ffaa0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -480,6 +480,7 @@ SOURCES_libvlc_common = \ @@ -126,40 +111,18 @@ index 639d157..89f78bc 100644 SOURCES_libvlc_sout = \ diff --git a/src/network/httpd.c b/src/network/httpd.c -index bbfbd18..8e0b130 100644 +index ff7e653..b8f6768 100644 --- a/src/network/httpd.c +++ b/src/network/httpd.c -@@ -39,6 +39,7 @@ - #include +@@ -40,6 +40,7 @@ #include #include + #include +#include #include "../libvlc.h" #include -@@ -66,6 +67,7 @@ - #endif - - static void httpd_ClientClean( httpd_client_t *cl ); -+static void httpd_AppendData( httpd_stream_t *stream, uint8_t *p_data, int i_data ); - - /* each host run in his own thread */ - struct httpd_host_t -@@ -159,6 +161,13 @@ struct httpd_client_t - int i_buffer; - uint8_t *p_buffer; - -+ /* -+ * If waiting for a keyframe, this is the position (in bytes) of the -+ * last keyframe the stream saw before this client connected. -+ * Otherwise, -1. -+ */ -+ int64_t i_keyframe_wait_to_pass; -+ - /* */ - httpd_message_t query; /* client -> httpd */ - httpd_message_t answer; /* httpd -> client */ -@@ -621,11 +630,20 @@ struct httpd_stream_t +@@ -630,6 +631,7 @@ struct httpd_stream_t httpd_url_t *url; char *psz_mime; @@ -167,37 +130,7 @@ index bbfbd18..8e0b130 100644 /* Header to send as first packet */ uint8_t *p_header; - int i_header; - -+ /* Some muxes, in particular the avformat mux, can mark given blocks -+ * as keyframes, to ensure that the stream starts with one. -+ * (This is particularly important for WebM streaming to certain -+ * browsers.) Store if we've ever seen any such keyframe blocks, -+ * and if so, the byte position of the start of the last one. */ -+ bool b_has_keyframes; -+ int64_t i_last_keyframe_seen_pos; -+ - /* circular buffer */ - int i_buffer_size; /* buffer size, can't be reallocated smaller */ - uint8_t *p_buffer; /* buffer */ -@@ -659,6 +677,16 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, - /* fprintf( stderr, "httpd_StreamCallBack: no data\n" ); */ - return VLC_EGENERIC; /* wait, no data available */ - } -+ if( cl->i_keyframe_wait_to_pass >= 0 ) -+ { -+ if( stream->i_last_keyframe_seen_pos <= cl->i_keyframe_wait_to_pass ) -+ /* still waiting for the next keyframe */ -+ return VLC_EGENERIC; -+ -+ /* seek to the new keyframe */ -+ answer->i_body_offset = stream->i_last_keyframe_seen_pos; -+ cl->i_keyframe_wait_to_pass = -1; -+ } - if( answer->i_body_offset + stream->i_buffer_size < - stream->i_buffer_pos ) - { -@@ -712,11 +740,31 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, +@@ -739,9 +741,25 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, /* Send the header */ if( stream->i_header > 0 ) { @@ -210,7 +143,7 @@ index bbfbd18..8e0b130 100644 + memcpy( hdr.sync, METACUBE2_SYNC, sizeof(METACUBE2_SYNC) ); + hdr.size = htonl( stream->i_header ); + hdr.flags = htons( METACUBE_FLAGS_HEADER ); -+ hdr.csum = htons( metacube2_compute_crc( &hdr )); ++ hdr.csum = htons( metacube2_compute_crc( &hdr ) ); + + answer->i_body = stream->i_header + sizeof( hdr ); + answer->p_body = xmalloc( answer->i_body ); @@ -225,14 +158,8 @@ index bbfbd18..8e0b130 100644 + } } answer->i_body_offset = stream->i_buffer_last_pos; -+ if( stream->b_has_keyframes ) -+ cl->i_keyframe_wait_to_pass = stream->i_last_keyframe_seen_pos; -+ else -+ cl->i_keyframe_wait_to_pass = -1; - vlc_mutex_unlock( &stream->lock ); - } - else -@@ -758,13 +806,16 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, + if( stream->b_has_keyframes ) +@@ -789,13 +807,16 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, httpd_MsgAdd( answer, "Content-type", "%s", stream->psz_mime ); } httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" ); @@ -250,7 +177,7 @@ index bbfbd18..8e0b130 100644 { httpd_stream_t *stream = xmalloc( sizeof( httpd_stream_t ) ); -@@ -783,6 +834,7 @@ httpd_stream_t *httpd_StreamNew( httpd_host_t *host, +@@ -814,6 +835,7 @@ httpd_stream_t *httpd_StreamNew( httpd_host_t *host, { stream->psz_mime = strdup( vlc_mime_Ext2Mime( psz_url ) ); } @@ -258,101 +185,58 @@ index bbfbd18..8e0b130 100644 stream->i_header = 0; stream->p_header = NULL; stream->i_buffer_size = 5000000; /* 5 Mo per stream */ -@@ -791,6 +843,8 @@ httpd_stream_t *httpd_StreamNew( httpd_host_t *host, - * (this way i_body_offset can never be 0) */ - stream->i_buffer_pos = 1; - stream->i_buffer_last_pos = 1; -+ stream->b_has_keyframes = false; -+ stream->i_last_keyframe_seen_pos = 0; - - httpd_UrlCatch( stream->url, HTTPD_MSG_HEAD, httpd_StreamCallBack, - (httpd_callback_sys_t*)stream ); -@@ -819,22 +873,10 @@ int httpd_StreamHeader( httpd_stream_t *stream, uint8_t *p_data, int i_data ) - return VLC_SUCCESS; - } - --int httpd_StreamSend( httpd_stream_t *stream, uint8_t *p_data, int i_data ) -+static void httpd_AppendData( httpd_stream_t *stream, uint8_t *p_data, int i_data ) - { -- int i_count; -- int i_pos; -- -- if( i_data < 0 || p_data == NULL ) -- { -- return VLC_SUCCESS; -- } -- vlc_mutex_lock( &stream->lock ); -- -- /* save this pointer (to be used by new connection) */ -- stream->i_buffer_last_pos = stream->i_buffer_pos; -- -- i_pos = stream->i_buffer_pos % stream->i_buffer_size; -- i_count = i_data; -+ int i_pos = stream->i_buffer_pos % stream->i_buffer_size; -+ int i_count = i_data; - while( i_count > 0) - { - int i_copy; -@@ -850,6 +892,40 @@ int httpd_StreamSend( httpd_stream_t *stream, uint8_t *p_data, int i_data ) +@@ -890,6 +912,20 @@ int httpd_StreamSend( httpd_stream_t *stream, const block_t *p_block ) + stream->i_last_keyframe_seen_pos = stream->i_buffer_pos; } - stream->i_buffer_pos += i_data; -+} -+ -+int httpd_StreamSend( httpd_stream_t *stream, uint8_t *p_data, int i_data, bool b_header, bool b_keyframe ) -+{ -+ if( i_data < 0 || p_data == NULL ) -+ { -+ return VLC_SUCCESS; -+ } -+ vlc_mutex_lock( &stream->lock ); -+ -+ /* save this pointer (to be used by new connection) */ -+ stream->i_buffer_last_pos = stream->i_buffer_pos; -+ -+ if( b_keyframe ) -+ { -+ stream->b_has_keyframes = true; -+ stream->i_last_keyframe_seen_pos = stream->i_buffer_pos; -+ } -+ + if( stream->b_metacube ) + { + struct metacube2_block_header hdr; + memcpy( hdr.sync, METACUBE2_SYNC, sizeof(METACUBE2_SYNC) ); -+ hdr.size = htonl( i_data ); ++ hdr.size = htonl( p_block->i_buffer ); + hdr.flags = htons( 0 ); -+ if( b_header ) ++ if( p_block->i_flags & BLOCK_FLAG_HEADER ) + hdr.flags |= htons( METACUBE_FLAGS_HEADER ); -+ if( stream->b_has_keyframes && !b_keyframe ) ++ if( stream->b_has_keyframes && !( p_block->i_flags & BLOCK_FLAG_TYPE_I ) ) + hdr.flags |= htons( METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START ); -+ hdr.csum = htons( metacube2_compute_crc( &hdr )); ++ hdr.csum = htons( metacube2_compute_crc( &hdr ) ); + httpd_AppendData( stream, (uint8_t *)&hdr, sizeof(hdr) ); + } + -+ httpd_AppendData( stream, p_data, i_data ); + httpd_AppendData( stream, p_block->p_buffer, p_block->i_buffer ); vlc_mutex_unlock( &stream->lock ); - return VLC_SUCCESS; -@@ -1273,6 +1349,7 @@ static void httpd_ClientInit( httpd_client_t *cl, mtime_t now ) - cl->i_buffer_size = HTTPD_CL_BUFSIZE; - cl->i_buffer = 0; - cl->p_buffer = xmalloc( cl->i_buffer_size ); -+ cl->i_keyframe_wait_to_pass = -1; - cl->b_stream_mode = false; - - httpd_MsgInit( &cl->query ); diff --git a/src/network/metacube2.c b/src/network/metacube2.c new file mode 100644 -index 0000000..7b2dacf +index 0000000..353ce88 --- /dev/null +++ b/src/network/metacube2.c -@@ -0,0 +1,49 @@ +@@ -0,0 +1,69 @@ +/* -+ * Implementation of Metacube2 utility functions. ++ * Implementation of Metacube2 utility functions. Taken from the Cubemap ++ * distribution and then relicensed by the author to LGPL2.1+ for inclusion ++ * into VLC. + * + * Note: This file is meant to compile as both C and C++, for easier inclusion + * in other projects. ++ * ++ * Copyright (C) 2013 Steinar H. Gunderson ++ * ++ * Author: Steinar H. Gunderson ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2.1 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + */ + +#include