From e11ab0240a0262fd722f04f104eabbf3949a8cef Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 6 May 2016 17:43:47 -0700 Subject: Moving to a private repo --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/LibVLCPlugin.cmake | 16 + indra/media_plugins/CMakeLists.txt | 1 + indra/media_plugins/libvlc/CMakeLists.txt | 85 ++++ indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 445 +++++++++++++++++++++ indra/newview/CMakeLists.txt | 3 +- indra/newview/llmimetypes.cpp | 3 +- indra/newview/skins/default/xui/en/mime_types.xml | 13 +- indra/newview/viewer_manifest.py | 5 + 9 files changed, 569 insertions(+), 3 deletions(-) create mode 100644 indra/cmake/LibVLCPlugin.cmake create mode 100644 indra/media_plugins/libvlc/CMakeLists.txt create mode 100644 indra/media_plugins/libvlc/media_plugin_libvlc.cpp diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 3eed9cecba..4aca33e8d1 100755 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -98,6 +98,7 @@ set(cmake_SOURCE_FILES Variables.cmake ViewerMiscLibs.cmake VisualLeakDetector.cmake + LibVLCPlugin.cmake XmlRpcEpi.cmake ZLIB.cmake ) diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake new file mode 100644 index 0000000000..286a8d8d1b --- /dev/null +++ b/indra/cmake/LibVLCPlugin.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (USESYSTEMLIBS) + set(LIBVLCPLUGIN OFF CACHE BOOL + "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") +else (USESYSTEMLIBS) + set(LIBVLCPLUGIN ON CACHE BOOL + "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") +endif (USESYSTEMLIBS) + +if (WINDOWS) +elseif (DARWIN) +elseif (LINUX) +endif (WINDOWS) diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index c9fc1c602d..7ef29b9027 100755 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -12,6 +12,7 @@ endif (WINDOWS OR DARWIN) if (WINDOWS) add_subdirectory(winmmshim) + add_subdirectory(libvlc) endif (WINDOWS) ### add_subdirectory(example) diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt new file mode 100644 index 0000000000..1b6adaa290 --- /dev/null +++ b/indra/media_plugins/libvlc/CMakeLists.txt @@ -0,0 +1,85 @@ +# -*- cmake -*- + +project(media_plugin_libvlc) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(OpenGL) + +include(LibVLCPlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) + + +### media_plugin_libvlc + +if(NOT WORD_SIZE EQUAL 32) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif(NOT WORD_SIZE EQUAL 32) + +set(media_plugin_libvlc_SOURCE_FILES + media_plugin_libvlc.cpp + ) + +add_library(media_plugin_libvlc + SHARED + ${media_plugin_libvlc_SOURCE_FILES} +) + +target_link_libraries(media_plugin_libvlc + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${LIBVLC_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_libvlc + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_libvlc + PROPERTIES + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT" + ) +endif (WINDOWS) + +if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_libvlc + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +endif (DARWIN) diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp new file mode 100644 index 0000000000..47ba6f48b4 --- /dev/null +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -0,0 +1,445 @@ +/** + * @file media_plugin_libvlc.cpp + * @brief LibVLC plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library 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; + * version 2.1 of the License only. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#include "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include "vlc/vlc.h" + +#include + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginLibVLC : + public MediaPluginBase +{ + public: + MediaPluginLibVLC( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); + ~MediaPluginLibVLC(); + + /*virtual*/ void receiveMessage( const char* message_string ); + + private: + bool init(); + void update( F64 milliseconds ); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 10 }; + unsigned char* mBackgroundPixels; + int mColorR[ ENumObjects ]; + int mColorG[ ENumObjects ]; + int mColorB[ ENumObjects ]; + int mXpos[ ENumObjects ]; + int mYpos[ ENumObjects ]; + int mXInc[ ENumObjects ]; + int mYInc[ ENumObjects ]; + int mBlockSize[ ENumObjects ]; + + libvlc_instance_t* gLibVLC = 0; + libvlc_media_t* gLibVLCMedia = 0; + libvlc_media_player_t* gLibVLCMediaPlayer = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginLibVLC::MediaPluginLibVLC( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : + MediaPluginBase( host_send_func, host_user_data ) +{ + mFirstTime = true; + mTextureWidth = 64; + mTextureHeight = 64; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mLastUpdateTime = 0; + mBackgroundPixels = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginLibVLC::~MediaPluginLibVLC() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::receiveMessage( const char* message_string ) +{ +// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + char const* vlc_argv[] = + { + "--no-xlib", + }; + + int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); + gLibVLC = libvlc_new(vlc_argc, vlc_argv); + + if (!gLibVLC) + { + } + + //if (gLibVLCMediaPlayer) + //{ + // libvlc_media_player_stop(gLibVLCMediaPlayer); + // libvlc_media_player_release(gLibVLCMediaPlayer); + //} + + const char* url = "https://callum-linden.s3.amazonaws.com/sample_media/jb.mp4"; + + gLibVLCMedia = libvlc_media_new_location(gLibVLC, url); + if (!gLibVLCMedia) + { + printf("libvlc_media_new_location failed\n"); + } + else + { + printf("libvlc_media_new_location ok\n"); + } + + gLibVLCMediaPlayer = libvlc_media_player_new_from_media(gLibVLCMedia); + if (!gLibVLCMediaPlayer) + { + printf("libvlc_media_player_new_from_media failed\n"); + } + else + { + printf("libvlc_media_player_new_from_media ok...\n"); + } + + libvlc_media_release(gLibVLCMedia); + +// gVLCCallbackContext.texture_pixels = gTexturePixels; +// gVLCCallbackContext.mp = gLibVLCMediaPlayer; + +// libvlc_video_set_callbacks(gLibVLCMediaPlayer, lock, unlock, display, &gVLCCallbackContext); + libvlc_video_set_format(gLibVLCMediaPlayer, "RV32", mTextureWidth, mTextureHeight, mTextureWidth * 4); + libvlc_media_player_play(gLibVLCMediaPlayer); + + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "LibVLC plugin 0.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + libvlc_media_player_stop(gLibVLCMediaPlayer); + libvlc_media_player_release(gLibVLCMediaPlayer); + libvlc_release(gLibVLC); + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + mLastUpdateTime = 0; + mFirstTime = true; + + } + else if(message_name == "load_uri") + { + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + if(event == "down") + { + + } + else if(event == "up") + { + } + else if(event == "double_click") + { + } + } + } + else + { + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginLibVLC::update( F64 milliseconds ) +{ + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + for( int n = 0; n < ENumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0x60 + 0x60; + mColorG[ n ] = rand() % 0x60 + 0x60; + mColorB[ n ] = rand() % 0x60 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x30 + 0x10; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < ENumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ]= -mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ]= -mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + setDirty( 0, 0, mWidth, mHeight ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginLibVLC::init() +{ + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "LibVLC Plugin" ); + sendMessage( message ); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data ) +{ + MediaPluginLibVLC* self = new MediaPluginLibVLC( host_send_func, host_user_data ); + *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage; + *plugin_user_data = ( void* )self; + + return 0; +} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bb745bcb43..39514146b7 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1748,6 +1748,7 @@ if (WINDOWS) SLPlugin media_plugin_quicktime media_plugin_cef + media_plugin_libvlc winmm_shim windows-crash-logger ) @@ -2075,7 +2076,7 @@ if (DARWIN) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger) add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger) if (ENABLE_SIGNING) diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp index 790a184068..a2df14b4e7 100755 --- a/indra/newview/llmimetypes.cpp +++ b/indra/newview/llmimetypes.cpp @@ -184,7 +184,8 @@ std::string LLMIMETypes::implType(const std::string& mime_type) mime_info_map_t::const_iterator it = sMap.find(mime_type); if (it != sMap.end()) { - return it->second.mImpl; + return "media_plugin_libvlc"; + //return it->second.mImpl; } else { diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index b62cc7c779..e2dcc11fb0 100755 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -133,7 +133,18 @@ media_plugin_cef - + + + + movie + + + media_plugin_libvlc + + + diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 1c77cf805e..9302dd8e03 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -436,6 +436,11 @@ class Windows_i686_Manifest(ViewerManifest): self.path("media_plugin_cef.dll") self.end_prefix() + # Media plugins - LibVLC + if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_libvlc.dll") + self.end_prefix() + # winmm.dll shim if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""): self.path("winmm.dll") -- cgit v1.2.3