X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=vlc-metacube.diff;h=91de18b760e1a0516c3fbfce164697b5a66618a6;hp=fbde59d1f0e3bbe2bd38b7b453b2c74c2f5aa967;hb=e42cde17932cfbb2bf54244d46c6f9cd7215105b;hpb=979a284b4039b0ea74525b700b9f1089b8c4248d 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