LLMediaImplGStreamer:: LLMediaImplGStreamer () : mediaData ( NULL ), mMediaRowbytes ( 1 ), mTextureFormatPrimary ( LL_MEDIA_BGRA ), mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ), mPump ( NULL ), mPlaybin ( NULL ), mVideoSink ( NULL ) #ifdef LL_GST_SOUNDSINK ,mAudioSink ( NULL ) #endif // LL_GST_SOUNDSINK { DEBUGMSG("constructing media..."); setMediaDepth(4); // Create a pumpable main-loop for this media mPump = g_main_loop_new (NULL, FALSE); if (!mPump) { return; // error } // instantiate a playbin element to do the hard work mPlaybin = llgst_element_factory_make ("playbin", "play"); if (!mPlaybin) { // todo: cleanup pump return; // error } if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate and connect a custom video sink mVideoSink = GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); if (!mVideoSink) { WARNMSG("Could not instantiate private-slvideo element."); // todo: cleanup. return; // error } g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); #ifdef LL_GST_SOUNDSINK // instantiate and connect a custom audio sink mAudioSink = GST_SLSOUND(llgst_element_factory_make ("private-slsound", "slsound")); if (!mAudioSink) { WARNMSG("Could not instantiate private-slsound element."); // todo: cleanup. return; // error } g_object_set(mPlaybin, "audio-sink", mAudioSink, NULL); #endif } }
LLMediaImplExample1::LLMediaImplExample1() : mMediaPixels( 0 ) { setRequestedMediaSize( 400, 200 ); setMediaDepth( 3 ); srand( (unsigned int)(time( NULL )) ); }
LLMediaImplExample2::LLMediaImplExample2() : mMediaPixels( 0 ) { setRequestedMediaSize( 500, 500 ); setMediaDepth( 3 ); mXpos = ( getMediaWidth() / 2 ) + rand() % ( getMediaWidth() / 16 ) - ( getMediaWidth() / 32 ); mYpos = ( getMediaHeight() / 2 ) + rand() % ( getMediaHeight() / 16 ) - ( getMediaHeight() / 32 ); srand( (unsigned int)(time( NULL )) ); }
LLMediaImplLLMozLib::LLMediaImplLLMozLib() : mBrowserWindowWidth( 800 ), mBrowserWindowHeight( 600 ), mMediaDataWidth( 0 ), mMediaDataHeight( 0 ), mWindowId( 0 ), mNeedsUpdate( false ) { setRequestedMediaSize( mBrowserWindowWidth, mBrowserWindowHeight ); setMediaDepth( 4 ); }
LLMediaImplGStreamer:: LLMediaImplGStreamer () : mediaData ( NULL ), mMediaRowbytes ( 1 ), mTextureFormatPrimary ( LL_MEDIA_BGRA ), mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ), mPump ( NULL ), mPlaybin ( NULL ), mVideoSink ( NULL ), mLastTitle ( "" ), mState( GST_STATE_NULL ), mPlayThread ( NULL ) { startup( NULL ); // Startup gstreamer if it hasn't been already. LL_DEBUGS("MediaManager") << "constructing media..." << LL_ENDL; mVolume = -1.0; // XXX Hack to make the vould change happend first time setMediaDepth(4); // Create a pumpable main-loop for this media mPump = g_main_loop_new (NULL, FALSE); if (!mPump) { return; // error } // instantiate a playbin element to do the hard work mPlaybin = gst_element_factory_make ("playbin", "play"); if (!mPlaybin) { // todo: cleanup pump return; // error } if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate and connect a custom video sink LL_DEBUGS("MediaManager") << "extrenal video sink..." << LL_ENDL; // Plays inworld instead of in external player mVideoSink = GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo")); if (!mVideoSink) { LL_WARNS("MediaImpl") << "Could not instantiate private-slvideo element." << LL_ENDL; // todo: cleanup. return; // error } g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); } }
//////////////////////////////////////////////////////////////////////////////// // virtual bool LLMediaImplLLMozLib::init() { // if mWindowId is non-0, it's we already called init() and shouldn't call it again // (::reset() will zero this value) if ( mWindowId ) return false; #if LL_LINUX static std::string saved_locale; saved_locale = setlocale(LC_ALL, NULL); #endif // LL_LINUX mWindowId = LLMozLib::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight ); LLMozLib::getInstance()->setSize( mWindowId, mBrowserWindowWidth, mBrowserWindowHeight ); LLMozLib::getInstance()->setBackgroundColor( mWindowId, 0x00, 0x00, 0x00 ); LLMozLib::getInstance()->addObserver( mWindowId, this ); // plugins only work with some client-side hackery and they cause // exception handling issues (DEV-10020) so we turn them off LLMozLib::getInstance()->enablePlugins( false ); // second life client needs the bitmap flipped LLMozLib::getInstance()->flipWindow( mWindowId, true ); // set media depth now we have created a browser window and know what it is setMediaDepth( LLMozLib::getInstance()->getBrowserDepth( mWindowId ) ); #if LL_LINUX setlocale(LC_ALL, saved_locale.c_str() ); #endif // LL_LINUX return true; }
/////////////////////////////////////////////////////////////////////////////// // virtual bool LLMediaImplGStreamer::updateMedia() { //LL_DEBUGS("MediaImpl") << "updating media..." << LL_ENDL; // sanity check if (mPump == NULL || mPlaybin == NULL) { #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaImpl") << "dead media..." << LL_ENDL; #endif mState = GST_STATE_NULL; setStatus(LLMediaBase::STATUS_DEAD); return false; } if (mState == GST_STATE_VOID_PENDING || mState == GST_STATE_NULL) return false; // process next outstanding command switch (nextCommand()) { case LLMediaBase::COMMAND_START: LL_DEBUGS("MediaImpl") << "COMMAND_START" << LL_ENDL; if (getStatus() == LLMediaBase::STATUS_PAUSED || getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STOPPED) { play(); setStatus(LLMediaBase::STATUS_STARTED); clearCommand(); } break; case LLMediaBase::COMMAND_STOP: LL_DEBUGS("MediaImpl") << "COMMAND_STOP" << LL_ENDL; stop(); setStatus(LLMediaBase::STATUS_STOPPED); clearCommand(); break; case LLMediaBase::COMMAND_PAUSE: LL_DEBUGS("MediaImpl") << "COMMAND_PAUSE" << LL_ENDL; if (getStatus() == LLMediaBase::STATUS_STARTED) { pause(); setStatus(LLMediaBase::STATUS_PAUSED); clearCommand(); } break; default: LL_INFOS("MediaImpl") << "Unknown command" << LL_ENDL; clearCommand(); break; case LLMediaBase::COMMAND_NONE: break; } // deal with results if (g_main_context_pending(g_main_loop_get_context(mPump))) { g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); } if (mVideoSink) { GST_OBJECT_LOCK(mVideoSink); if (mVideoSink->retained_frame_ready) { #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaImpl") <<"NEW FRAME " << LL_ENDL; #endif if (mVideoSink->retained_frame_width != getMediaWidth() || mVideoSink->retained_frame_height != getMediaHeight()) // *TODO: also check for change in format { // just resize containe int neww = mVideoSink->retained_frame_width; int newh = mVideoSink->retained_frame_height; int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; if (SLV_PF_RGBX == mVideoSink->retained_frame_format) { mTextureFormatPrimary = LL_MEDIA_RGBA; mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; } else { mTextureFormatPrimary = LL_MEDIA_BGRA; mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; } mMediaRowbytes = neww * newd; LL_DEBUGS("MediaImpl") << "video container resized to " << neww <<"x"<< newh << LL_ENDL; delete[] mediaData; mediaData = new unsigned char[mMediaRowbytes * newh]; GST_OBJECT_UNLOCK(mVideoSink); setMediaDepth(newd); setMediaSize(neww, newh); return true; } // we're gonna totally consume this frame - reset 'ready' flag mVideoSink->retained_frame_ready = FALSE; memcpy(mediaData, mVideoSink->retained_frame_data, mMediaRowbytes * getMediaHeight()); GST_OBJECT_UNLOCK(mVideoSink); LLMediaEvent event( this ); mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); return true; } else { // nothing to do yet. GST_OBJECT_UNLOCK(mVideoSink); return true; } } return true; }
//////////////////////////////////////////////////////////////////////////////// // private bool LLMediaImplQuickTime::load( const std::string url ) { if ( url.empty() ) return false; //In case std::string::c_str() makes a copy of the url data, //make sure there is memory to hold it before allocating memory for handle. //if fails, NewHandleClear(...) should return NULL. const char* url_string = url.c_str() ; Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); if ( NULL == handle ) return false; if(noErr != MemError() || NULL == *handle) { return false ; } BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); //std::cout << "LLMediaImplQuickTime::load( " << url << " )" << std::endl; // TODO: supposed to use NewMovieFromDataParams now OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); DisposeHandle( handle ); if ( noErr != err ) return false; // do pre-roll actions (typically fired for streaming movies but not always) PrePrerollMovie( mMovieHandle, 0, GetMoviePreferredRate( mMovieHandle ), moviePrePrerollCompleteCallback, ( void * )this ); // get movie rect (and check for min/max) Rect movie_rect; setMovieBoxEnhanced( &movie_rect ); // make a new movie controller mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); #if defined(__APPLE__) || defined(MACOSX) setMediaDepth( 4 ); #else setMediaDepth( 3 ); #endif // tell manager about the media size setMediaSize( movie_rect.right - movie_rect.left, movie_rect.bottom - movie_rect.top); // movie controller MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); // function that gets called when a frame is drawn SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); // emit an event to say that a media source was loaded LLMediaEvent event( this ); mEventEmitter.update( &LLMediaObserver::onMediaLoaded, event ); // set up inital state sizeChanged(); return true; }
/////////////////////////////////////////////////////////////////////////////// // virtual bool LLMediaImplGStreamer:: updateMedia () { DEBUGMSG("updating media..."); // sanity check if (NULL == mPump #ifdef LL_GST_SOUNDSINK || NULL == mAudioSink #endif || NULL == mPlaybin) { DEBUGMSG("dead media..."); return false; } // process next outstanding command switch (nextCommand()) { case LLMediaBase::COMMAND_START: DEBUGMSG("COMMAND_START"); if (getStatus() == LLMediaBase::STATUS_PAUSED || getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STOPPED) { DEBUGMSG("doing COMMAND_START"); play(); setStatus(LLMediaBase::STATUS_STARTED); clearCommand(); } break; case LLMediaBase::COMMAND_STOP: DEBUGMSG("COMMAND_STOP"); DEBUGMSG("doing COMMAND_STOP"); stop(); setStatus(LLMediaBase::STATUS_STOPPED); clearCommand(); break; case LLMediaBase::COMMAND_PAUSE: DEBUGMSG("COMMAND_PAUSE"); if (getStatus() == LLMediaBase::STATUS_STARTED) { DEBUGMSG("doing COMMAND_PAUSE"); pause(); setStatus(LLMediaBase::STATUS_PAUSED); clearCommand(); } break; default: DEBUGMSG("COMMAND_?"); clearCommand(); break; case LLMediaBase::COMMAND_NONE: break; } // deal with results if (g_main_context_pending(g_main_loop_get_context(mPump))) { g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); } if (mVideoSink) { GST_OBJECT_LOCK(mVideoSink); if (mVideoSink->retained_frame_ready) { DEBUGMSG("NEW FRAME "); if (mVideoSink->retained_frame_width != getMediaWidth() || mVideoSink->retained_frame_height != getMediaHeight()) // *TODO: also check for change in format { // just resize containe int neww = mVideoSink->retained_frame_width; int newh = mVideoSink->retained_frame_height; int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; if (SLV_PF_RGBX == mVideoSink->retained_frame_format) { mTextureFormatPrimary = LL_MEDIA_RGBA; mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; } else { mTextureFormatPrimary = LL_MEDIA_BGRA; mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; } mMediaRowbytes = neww * newd; DEBUGMSG("video container resized to %dx%d", neww, newh); delete[] mediaData; mediaData = new unsigned char[mMediaRowbytes * newh]; GST_OBJECT_UNLOCK(mVideoSink); setMediaDepth(newd); setMediaSize(neww, newh); return true; } // we're gonna totally consume this frame - reset 'ready' flag mVideoSink->retained_frame_ready = FALSE; memcpy(mediaData, mVideoSink->retained_frame_data, mMediaRowbytes * getMediaHeight()); GST_OBJECT_UNLOCK(mVideoSink); LLMediaEvent event( this ); mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); return true; } else { // nothing to do yet. GST_OBJECT_UNLOCK(mVideoSink); return true; } } return true; }