X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=vlc-metacube.diff;h=91de18b760e1a0516c3fbfce164697b5a66618a6;hp=0d965a1a3d32d4d5959a5d80244f32cf8a4048f6;hb=e42cde17932cfbb2bf54244d46c6f9cd7215105b;hpb=aa3c6213114be76ab3adcfc3eeeed7865c746280 diff --git a/vlc-metacube.diff b/vlc-metacube.diff index 0d965a1..91de18b 100644 --- a/vlc-metacube.diff +++ b/vlc-metacube.diff @@ -1,8 +1,41 @@ +diff --git a/include/metacube2.h b/include/metacube2.h +new file mode 100644 +index 0000000..dfbfd24 +--- /dev/null ++++ b/include/metacube2.h +@@ -0,0 +1,27 @@ ++#ifndef _METACUBE2_H ++#define _METACUBE2_H ++ ++/* ++ * Definitions for the Metacube2 protocol, used to communicate with Cubemap. ++ * ++ * Note: This file is meant to compile as both C and C++, for easier inclusion ++ * in other projects. ++ */ ++ ++#include ++ ++#define METACUBE2_SYNC "cube!map" /* 8 bytes long. */ ++#define METACUBE_FLAGS_HEADER 0x1 ++#define METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START 0x2 ++ ++struct metacube2_block_header { ++ char sync[8]; /* METACUBE2_SYNC */ ++ uint32_t size; /* Network byte order. Does not include header. */ ++ uint16_t flags; /* Network byte order. METACUBE_FLAGS_*. */ ++ uint16_t csum; /* Network byte order. CRC16 of size and flags. */ ++}; ++ ++/* This code is based on code generated by pycrc. */ ++uint16_t metacube2_compute_crc(const struct metacube2_block_header *hdr); ++ ++#endif /* !defined(_METACUBE_H) */ diff --git a/include/vlc_httpd.h b/include/vlc_httpd.h -index 6100dd0..46d557a 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; @@ -10,25 +43,31 @@ index 6100dd0..46d557a 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 ); - - - /* 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 61095f5..95dd705 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[] = { @@ -37,22 +76,21 @@ index 61095f5..95dd705 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 ; -@@ -188,10 +192,12 @@ 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" ); } -+ -+ b_metacube = var_GetBool( p_access, SOUT_CFG_PREFIX "metacube" ); ++ b_metacube = var_GetBool( p_access, SOUT_CFG_PREFIX "metacube" ); ++ p_sys->p_httpd_stream = httpd_StreamNew( p_sys->p_httpd_host, path, psz_mime, - psz_user, psz_pwd ); @@ -60,51 +98,31 @@ index 61095f5..95dd705 100644 free( psz_user ); free( psz_pwd ); free( psz_mime ); -@@ -263,8 +269,9 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ) - while( p_buffer ) - { - block_t *p_next; -- -- if( p_buffer->i_flags & BLOCK_FLAG_HEADER ) -+ bool b_header_block = p_buffer->i_flags & BLOCK_FLAG_HEADER; -+ -+ if( b_header_block ) - { - /* gather header */ - if( p_sys->b_header_complete ) -@@ -295,9 +302,10 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ) - } +diff --git a/src/Makefile.am b/src/Makefile.am +index a7f42ef..18ffaa0 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -480,6 +480,7 @@ SOURCES_libvlc_common = \ - 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 ); + SOURCES_libvlc_httpd = \ + network/httpd.c \ ++ network/metacube2.c \ + $(NULL) - p_next = p_buffer->p_next; - block_Release( p_buffer ); + SOURCES_libvlc_sout = \ diff --git a/src/network/httpd.c b/src/network/httpd.c -index f76c47c..dcda968 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 #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 -@@ -621,6 +623,7 @@ struct httpd_stream_t +@@ -630,6 +631,7 @@ struct httpd_stream_t httpd_url_t *url; char *psz_mime; @@ -112,7 +130,7 @@ index f76c47c..dcda968 100644 /* Header to send as first packet */ uint8_t *p_header; -@@ -712,9 +715,24 @@ 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 ) { @@ -121,10 +139,11 @@ index f76c47c..dcda968 100644 - memcpy( answer->p_body, stream->p_header, stream->i_header ); + if ( stream->b_metacube ) + { -+ struct metacube_block_header hdr; -+ memcpy( hdr.sync, METACUBE_SYNC, sizeof(METACUBE_SYNC) ); ++ struct metacube2_block_header hdr; ++ memcpy( hdr.sync, METACUBE2_SYNC, sizeof(METACUBE2_SYNC) ); + hdr.size = htonl( stream->i_header ); -+ hdr.flags = htonl( METACUBE_FLAGS_HEADER ); ++ hdr.flags = htons( METACUBE_FLAGS_HEADER ); ++ hdr.csum = htons( metacube2_compute_crc( &hdr ) ); + + answer->i_body = stream->i_header + sizeof( hdr ); + answer->p_body = xmalloc( answer->i_body ); @@ -139,15 +158,13 @@ index f76c47c..dcda968 100644 + } } answer->i_body_offset = stream->i_buffer_last_pos; - vlc_mutex_unlock( &stream->lock ); -@@ -758,13 +776,18 @@ 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" ); -+ if ( stream->b_metacube ) -+ { ++ if( stream->b_metacube ) + httpd_MsgAdd( answer, "Content-encoding", "metacube"); -+ } return VLC_SUCCESS; } } @@ -160,7 +177,7 @@ index f76c47c..dcda968 100644 { httpd_stream_t *stream = xmalloc( sizeof( httpd_stream_t ) ); -@@ -783,6 +806,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 ) ); } @@ -168,84 +185,99 @@ index f76c47c..dcda968 100644 stream->i_header = 0; stream->p_header = NULL; stream->i_buffer_size = 5000000; /* 5 Mo per stream */ -@@ -819,22 +843,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 +862,31 @@ 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 ) -+{ -+ if( i_data < 0 || p_data == NULL ) ++ if( stream->b_metacube ) + { -+ 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 ( stream->b_metacube ) { -+ struct metacube_block_header hdr; -+ memcpy( hdr.sync, METACUBE_SYNC, sizeof(METACUBE_SYNC) ); -+ hdr.size = htonl( i_data ); -+ if ( b_header ) { -+ hdr.flags = htonl( METACUBE_FLAGS_HEADER ); -+ } else { -+ hdr.flags = htonl( 0 ); -+ } ++ struct metacube2_block_header hdr; ++ memcpy( hdr.sync, METACUBE2_SYNC, sizeof(METACUBE2_SYNC) ); ++ hdr.size = htonl( p_block->i_buffer ); ++ hdr.flags = htons( 0 ); ++ if( p_block->i_flags & BLOCK_FLAG_HEADER ) ++ hdr.flags |= htons( METACUBE_FLAGS_HEADER ); ++ 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 ) ); + 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; -diff --git a/include/metacube.h b/include/metacube.h +diff --git a/src/network/metacube2.c b/src/network/metacube2.c new file mode 100644 -index 0000000..b40a42e +index 0000000..353ce88 --- /dev/null -+++ b/include/metacube.h -@@ -0,0 +1,17 @@ -+#ifndef _METACUBE_H -+#define _METACUBE_H -+ -+/* Definitions for the Metacube protocol, used to communicate with Cubemap. */ ++++ b/src/network/metacube2.c +@@ -0,0 +1,69 @@ ++/* ++ * 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 + -+#define METACUBE_SYNC "\\o/_metacube_\\o/" /* 16 bytes long. */ -+#define METACUBE_FLAGS_HEADER 0x1 ++#include "metacube2.h" + -+struct metacube_block_header { -+ char sync[16]; /* METACUBE_SYNC */ -+ uint32_t size; /* Network byte order. Does not include header. */ -+ uint32_t flags; /* Network byte order. METACUBE_FLAGS_*. */ -+}; ++/* ++ * https://www.ece.cmu.edu/~koopman/pubs/KoopmanCRCWebinar9May2012.pdf ++ * recommends this for messages as short as ours (see table at page 34). ++ */ ++#define METACUBE2_CRC_POLYNOMIAL 0x8FDB + -+#endif /* !defined(_METACUBE_H) */ ++/* Semi-random starting value to make sure all-zero won't pass. */ ++#define METACUBE2_CRC_START 0x1234 ++ ++uint16_t metacube2_compute_crc(const struct metacube2_block_header *hdr) ++{ ++ static const int data_len = sizeof(hdr->size) + sizeof(hdr->flags); ++ const uint8_t *data = (uint8_t *)&hdr->size; ++ uint16_t crc = METACUBE2_CRC_START; ++ int i, j; ++ ++ for (i = 0; i < data_len; ++i) { ++ uint8_t c = data[i]; ++ for (j = 0; j < 8; j++) { ++ int bit = crc & 0x8000; ++ crc = (crc << 1) | ((c >> (7 - j)) & 0x01); ++ if (bit) { ++ crc ^= METACUBE2_CRC_POLYNOMIAL; ++ } ++ } ++ } ++ ++ /* Finalize. */ ++ for (i = 0; i < 16; i++) { ++ int bit = crc & 0x8000; ++ crc = crc << 1; ++ if (bit) { ++ crc ^= METACUBE2_CRC_POLYNOMIAL; ++ } ++ } ++ ++ return crc; ++}