diff options
Diffstat (limited to 'indra/media_plugins/libvlc')
| -rw-r--r-- | indra/media_plugins/libvlc/CMakeLists.txt | 85 | ||||
| -rw-r--r-- | indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 445 | 
2 files changed, 530 insertions, 0 deletions
| 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 <time.h> + +//////////////////////////////////////////////////////////////////////////////// +// +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; +} | 
