Sunday, March 1, 2009

Imprudence Source Adventures

I would like, for a moment, to take you on a tour of the media system Imprudence currently uses (aka the one we've inherited from 1.21.6). First, a little quiz. Can you guess which function currently in the source code is called when you click "play" for streaming video?

1.

void LLViewerMediaImpl::play(const std::string& media_url,
const std::string& mime_type,
const LLUUID& placeholder_texture_id,
S32 media_width, S32 media_height, U8 media_auto_scale,
U8 media_loop)
{
// first stop any previously playing media
stop();

// Save this first, as init/load below may fire events
mMovieImageID = placeholder_texture_id;

// If the mime_type passed in is different than the cached one, and
// Auto-discovery is turned OFF, replace the cached mime_type with the new one.
if(mime_type != mMimeType &&
! gSavedSettings.getBOOL("AutoMimeDiscovery"))
{
mMimeType = mime_type;
}
LLURI url(media_url);
std::string scheme = url.scheme() != "" ? url.scheme() : "http";

LLMediaManager* mgr = LLMediaManager::getInstance();
mMediaSource = mgr->createSourceFromMimeType(scheme, mMimeType );
if ( !mMediaSource )
{
if (mMimeType != "none/none")
{
llwarns << "media source create failed " << mmediaurl =" media_url;">setRequestedMediaSize(media_width, media_height);
}

mMediaSource->setLooping(media_loop);
mMediaSource->setAutoScaled(media_auto_scale);
mMediaSource->addObserver( this );
mMediaSource->navigateTo( media_url );
mMediaSource->addCommand(LLMediaBase::COMMAND_START);
}

2.

void LLViewerParcelMedia::play(LLParcel* parcel)
{
lldebugs << "LLViewerParcelMedia::play" << media_url =" parcel-">getMediaURL();
std::string mime_type = parcel->getMediaType();
LLUUID placeholder_texture_id = parcel->getMediaID();
U8 media_auto_scale = parcel->getMediaAutoScale();
U8 media_loop = parcel->getMediaLoop();
S32 media_width = parcel->getMediaWidth();
S32 media_height = parcel->getMediaHeight();
LLViewerMedia::play(media_url, mime_type, placeholder_texture_id,
media_width, media_height, media_auto_scale,
media_loop);
LLFirstUse::useMedia();

LLViewerParcelMediaAutoPlay::playStarted();
}

3.

bool LLMediaImplCommon::navigateTo( const std::string url )
{
return false;
}

4.

void LLOverlayBar::toggleMediaPlay(void*)
{
if (!gOverlayBar)
{
return;
}


if (LLViewerMedia::isMediaPaused())
{
LLViewerParcelMedia::start();
}
else if(LLViewerMedia::isMediaPlaying())
{
LLViewerParcelMedia::pause();
}
else
{
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (parcel)
{
LLViewerParcelMedia::play(parcel);
}
}
}

If your answer was "none of the above" then congrats! You obviously understand the current state of Imprudence's media system! Although it appears as though all of these should play some role, none of them are involved with the streaming media tab (some are called in other--more mysterious--places, though).

What's really going on is, after it's initialized GStreamer begins constantly checking for updates to your media state. As soon as your state changes, GStreamer picks up on it and sends information to a callback. This is, at least, how streaming video/web currently works. Streaming audio uses a completely different method! Did I mention that there are three places for recording your current state: LLMediaBase, GstState*, and gAudiop? And that all/some/none of these are referenced depending on where you're looking in the source?

Oh, yes. Welcome to the joy that is Imprudence's media system (AKA my demon for the past month).

0 comments: