diff options
Diffstat (limited to 'media/libstagefright/wifi-display/sink')
4 files changed, 0 insertions, 1820 deletions
diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp b/media/libstagefright/wifi-display/sink/DirectRenderer.cpp deleted file mode 100644 index 15f9c88..0000000 --- a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "DirectRenderer" -#include <utils/Log.h> - -#include "DirectRenderer.h" - -#include <gui/SurfaceComposerClient.h> -#include <gui/Surface.h> -#include <media/AudioTrack.h> -#include <media/ICrypto.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/MediaCodec.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/Utils.h> - -namespace android { - -/* - Drives the decoding process using a MediaCodec instance. Input buffers - queued by calls to "queueInputBuffer" are fed to the decoder as soon - as the decoder is ready for them, the client is notified about output - buffers as the decoder spits them out. -*/ -struct DirectRenderer::DecoderContext : public AHandler { - enum { - kWhatOutputBufferReady, - }; - DecoderContext(const sp<AMessage> ¬ify); - - status_t init( - const sp<AMessage> &format, - const sp<IGraphicBufferProducer> &surfaceTex); - - void queueInputBuffer(const sp<ABuffer> &accessUnit); - - status_t renderOutputBufferAndRelease(size_t index); - status_t releaseOutputBuffer(size_t index); - -protected: - virtual ~DecoderContext(); - - virtual void onMessageReceived(const sp<AMessage> &msg); - -private: - enum { - kWhatDecoderNotify, - }; - - sp<AMessage> mNotify; - sp<ALooper> mDecoderLooper; - sp<MediaCodec> mDecoder; - Vector<sp<ABuffer> > mDecoderInputBuffers; - Vector<sp<ABuffer> > mDecoderOutputBuffers; - List<size_t> mDecoderInputBuffersAvailable; - bool mDecoderNotificationPending; - - List<sp<ABuffer> > mAccessUnits; - - void onDecoderNotify(); - void scheduleDecoderNotification(); - void queueDecoderInputBuffers(); - - void queueOutputBuffer( - size_t index, int64_t timeUs, const sp<ABuffer> &buffer); - - DISALLOW_EVIL_CONSTRUCTORS(DecoderContext); -}; - -//////////////////////////////////////////////////////////////////////////////// - -/* - A "push" audio renderer. The primary function of this renderer is to use - an AudioTrack in push mode and making sure not to block the event loop - be ensuring that calls to AudioTrack::write never block. This is done by - estimating an upper bound of data that can be written to the AudioTrack - buffer without delay. -*/ -struct DirectRenderer::AudioRenderer : public AHandler { - AudioRenderer(const sp<DecoderContext> &decoderContext); - - void queueInputBuffer( - size_t index, int64_t timeUs, const sp<ABuffer> &buffer); - -protected: - virtual ~AudioRenderer(); - virtual void onMessageReceived(const sp<AMessage> &msg); - -private: - enum { - kWhatPushAudio, - }; - - struct BufferInfo { - size_t mIndex; - int64_t mTimeUs; - sp<ABuffer> mBuffer; - }; - - sp<DecoderContext> mDecoderContext; - sp<AudioTrack> mAudioTrack; - - List<BufferInfo> mInputBuffers; - bool mPushPending; - - size_t mNumFramesWritten; - - void schedulePushIfNecessary(); - void onPushAudio(); - - ssize_t writeNonBlocking(const uint8_t *data, size_t size); - - DISALLOW_EVIL_CONSTRUCTORS(AudioRenderer); -}; - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::DecoderContext::DecoderContext(const sp<AMessage> ¬ify) - : mNotify(notify), - mDecoderNotificationPending(false) { -} - -DirectRenderer::DecoderContext::~DecoderContext() { - if (mDecoder != NULL) { - mDecoder->release(); - mDecoder.clear(); - - mDecoderLooper->stop(); - mDecoderLooper.clear(); - } -} - -status_t DirectRenderer::DecoderContext::init( - const sp<AMessage> &format, - const sp<IGraphicBufferProducer> &surfaceTex) { - CHECK(mDecoder == NULL); - - AString mime; - CHECK(format->findString("mime", &mime)); - - mDecoderLooper = new ALooper; - mDecoderLooper->setName("video codec looper"); - - mDecoderLooper->start( - false /* runOnCallingThread */, - false /* canCallJava */, - PRIORITY_DEFAULT); - - mDecoder = MediaCodec::CreateByType( - mDecoderLooper, mime.c_str(), false /* encoder */); - - CHECK(mDecoder != NULL); - - status_t err = mDecoder->configure( - format, - surfaceTex == NULL - ? NULL : new Surface(surfaceTex), - NULL /* crypto */, - 0 /* flags */); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->start(); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->getInputBuffers( - &mDecoderInputBuffers); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->getOutputBuffers( - &mDecoderOutputBuffers); - CHECK_EQ(err, (status_t)OK); - - scheduleDecoderNotification(); - - return OK; -} - -void DirectRenderer::DecoderContext::queueInputBuffer( - const sp<ABuffer> &accessUnit) { - CHECK(mDecoder != NULL); - - mAccessUnits.push_back(accessUnit); - queueDecoderInputBuffers(); -} - -status_t DirectRenderer::DecoderContext::renderOutputBufferAndRelease( - size_t index) { - return mDecoder->renderOutputBufferAndRelease(index); -} - -status_t DirectRenderer::DecoderContext::releaseOutputBuffer(size_t index) { - return mDecoder->releaseOutputBuffer(index); -} - -void DirectRenderer::DecoderContext::queueDecoderInputBuffers() { - if (mDecoder == NULL) { - return; - } - - bool submittedMore = false; - - while (!mAccessUnits.empty() - && !mDecoderInputBuffersAvailable.empty()) { - size_t index = *mDecoderInputBuffersAvailable.begin(); - - mDecoderInputBuffersAvailable.erase( - mDecoderInputBuffersAvailable.begin()); - - sp<ABuffer> srcBuffer = *mAccessUnits.begin(); - mAccessUnits.erase(mAccessUnits.begin()); - - const sp<ABuffer> &dstBuffer = - mDecoderInputBuffers.itemAt(index); - - memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); - - int64_t timeUs; - CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs)); - - status_t err = mDecoder->queueInputBuffer( - index, - 0 /* offset */, - srcBuffer->size(), - timeUs, - 0 /* flags */); - CHECK_EQ(err, (status_t)OK); - - submittedMore = true; - } - - if (submittedMore) { - scheduleDecoderNotification(); - } -} - -void DirectRenderer::DecoderContext::onMessageReceived( - const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatDecoderNotify: - { - onDecoderNotify(); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::DecoderContext::onDecoderNotify() { - mDecoderNotificationPending = false; - - for (;;) { - size_t index; - status_t err = mDecoder->dequeueInputBuffer(&index); - - if (err == OK) { - mDecoderInputBuffersAvailable.push_back(index); - } else if (err == -EAGAIN) { - break; - } else { - TRESPASS(); - } - } - - queueDecoderInputBuffers(); - - for (;;) { - size_t index; - size_t offset; - size_t size; - int64_t timeUs; - uint32_t flags; - status_t err = mDecoder->dequeueOutputBuffer( - &index, - &offset, - &size, - &timeUs, - &flags); - - if (err == OK) { - queueOutputBuffer( - index, timeUs, mDecoderOutputBuffers.itemAt(index)); - } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { - err = mDecoder->getOutputBuffers( - &mDecoderOutputBuffers); - CHECK_EQ(err, (status_t)OK); - } else if (err == INFO_FORMAT_CHANGED) { - // We don't care. - } else if (err == -EAGAIN) { - break; - } else { - TRESPASS(); - } - } - - scheduleDecoderNotification(); -} - -void DirectRenderer::DecoderContext::scheduleDecoderNotification() { - if (mDecoderNotificationPending) { - return; - } - - sp<AMessage> notify = - new AMessage(kWhatDecoderNotify, id()); - - mDecoder->requestActivityNotification(notify); - mDecoderNotificationPending = true; -} - -void DirectRenderer::DecoderContext::queueOutputBuffer( - size_t index, int64_t timeUs, const sp<ABuffer> &buffer) { - sp<AMessage> msg = mNotify->dup(); - msg->setInt32("what", kWhatOutputBufferReady); - msg->setSize("index", index); - msg->setInt64("timeUs", timeUs); - msg->setBuffer("buffer", buffer); - msg->post(); -} - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::AudioRenderer::AudioRenderer( - const sp<DecoderContext> &decoderContext) - : mDecoderContext(decoderContext), - mPushPending(false), - mNumFramesWritten(0) { - mAudioTrack = new AudioTrack( - AUDIO_STREAM_DEFAULT, - 48000.0f, - AUDIO_FORMAT_PCM, - AUDIO_CHANNEL_OUT_STEREO, - (int)0 /* frameCount */); - - CHECK_EQ((status_t)OK, mAudioTrack->initCheck()); - - mAudioTrack->start(); -} - -DirectRenderer::AudioRenderer::~AudioRenderer() { -} - -void DirectRenderer::AudioRenderer::queueInputBuffer( - size_t index, int64_t timeUs, const sp<ABuffer> &buffer) { - BufferInfo info; - info.mIndex = index; - info.mTimeUs = timeUs; - info.mBuffer = buffer; - - mInputBuffers.push_back(info); - schedulePushIfNecessary(); -} - -void DirectRenderer::AudioRenderer::onMessageReceived( - const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatPushAudio: - { - onPushAudio(); - break; - } - - default: - break; - } -} - -void DirectRenderer::AudioRenderer::schedulePushIfNecessary() { - if (mPushPending || mInputBuffers.empty()) { - return; - } - - mPushPending = true; - - uint32_t numFramesPlayed; - CHECK_EQ(mAudioTrack->getPosition(&numFramesPlayed), - (status_t)OK); - - uint32_t numFramesPendingPlayout = mNumFramesWritten - numFramesPlayed; - - // This is how long the audio sink will have data to - // play back. - const float msecsPerFrame = 1000.0f / mAudioTrack->getSampleRate(); - - int64_t delayUs = - msecsPerFrame * numFramesPendingPlayout * 1000ll; - - // Let's give it more data after about half that time - // has elapsed. - (new AMessage(kWhatPushAudio, id()))->post(delayUs / 2); -} - -void DirectRenderer::AudioRenderer::onPushAudio() { - mPushPending = false; - - while (!mInputBuffers.empty()) { - const BufferInfo &info = *mInputBuffers.begin(); - - ssize_t n = writeNonBlocking( - info.mBuffer->data(), info.mBuffer->size()); - - if (n < (ssize_t)info.mBuffer->size()) { - CHECK_GE(n, 0); - - info.mBuffer->setRange( - info.mBuffer->offset() + n, info.mBuffer->size() - n); - break; - } - - mDecoderContext->releaseOutputBuffer(info.mIndex); - - mInputBuffers.erase(mInputBuffers.begin()); - } - - schedulePushIfNecessary(); -} - -ssize_t DirectRenderer::AudioRenderer::writeNonBlocking( - const uint8_t *data, size_t size) { - uint32_t numFramesPlayed; - status_t err = mAudioTrack->getPosition(&numFramesPlayed); - if (err != OK) { - return err; - } - - ssize_t numFramesAvailableToWrite = - mAudioTrack->frameCount() - (mNumFramesWritten - numFramesPlayed); - - size_t numBytesAvailableToWrite = - numFramesAvailableToWrite * mAudioTrack->frameSize(); - - if (size > numBytesAvailableToWrite) { - size = numBytesAvailableToWrite; - } - - CHECK_EQ(mAudioTrack->write(data, size), (ssize_t)size); - - size_t numFramesWritten = size / mAudioTrack->frameSize(); - mNumFramesWritten += numFramesWritten; - - return size; -} - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::DirectRenderer( - const sp<IGraphicBufferProducer> &bufferProducer) - : mSurfaceTex(bufferProducer), - mVideoRenderPending(false), - mNumFramesLate(0), - mNumFrames(0) { -} - -DirectRenderer::~DirectRenderer() { -} - -void DirectRenderer::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatDecoderNotify: - { - onDecoderNotify(msg); - break; - } - - case kWhatRenderVideo: - { - onRenderVideo(); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::setFormat(size_t trackIndex, const sp<AMessage> &format) { - CHECK_LT(trackIndex, 2u); - - CHECK(mDecoderContext[trackIndex] == NULL); - - sp<AMessage> notify = new AMessage(kWhatDecoderNotify, id()); - notify->setSize("trackIndex", trackIndex); - - mDecoderContext[trackIndex] = new DecoderContext(notify); - looper()->registerHandler(mDecoderContext[trackIndex]); - - CHECK_EQ((status_t)OK, - mDecoderContext[trackIndex]->init( - format, trackIndex == 0 ? mSurfaceTex : NULL)); - - if (trackIndex == 1) { - // Audio - mAudioRenderer = new AudioRenderer(mDecoderContext[1]); - looper()->registerHandler(mAudioRenderer); - } -} - -void DirectRenderer::queueAccessUnit( - size_t trackIndex, const sp<ABuffer> &accessUnit) { - CHECK_LT(trackIndex, 2u); - - if (mDecoderContext[trackIndex] == NULL) { - CHECK_EQ(trackIndex, 0u); - - sp<AMessage> format = new AMessage; - format->setString("mime", "video/avc"); - format->setInt32("width", 640); - format->setInt32("height", 360); - - setFormat(trackIndex, format); - } - - mDecoderContext[trackIndex]->queueInputBuffer(accessUnit); -} - -void DirectRenderer::onDecoderNotify(const sp<AMessage> &msg) { - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case DecoderContext::kWhatOutputBufferReady: - { - size_t index; - CHECK(msg->findSize("index", &index)); - - int64_t timeUs; - CHECK(msg->findInt64("timeUs", &timeUs)); - - sp<ABuffer> buffer; - CHECK(msg->findBuffer("buffer", &buffer)); - - queueOutputBuffer(trackIndex, index, timeUs, buffer); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::queueOutputBuffer( - size_t trackIndex, - size_t index, int64_t timeUs, const sp<ABuffer> &buffer) { - if (trackIndex == 1) { - // Audio - mAudioRenderer->queueInputBuffer(index, timeUs, buffer); - return; - } - - OutputInfo info; - info.mIndex = index; - info.mTimeUs = timeUs; - info.mBuffer = buffer; - mVideoOutputBuffers.push_back(info); - - scheduleVideoRenderIfNecessary(); -} - -void DirectRenderer::scheduleVideoRenderIfNecessary() { - if (mVideoRenderPending || mVideoOutputBuffers.empty()) { - return; - } - - mVideoRenderPending = true; - - int64_t timeUs = (*mVideoOutputBuffers.begin()).mTimeUs; - int64_t nowUs = ALooper::GetNowUs(); - - int64_t delayUs = timeUs - nowUs; - - (new AMessage(kWhatRenderVideo, id()))->post(delayUs); -} - -void DirectRenderer::onRenderVideo() { - mVideoRenderPending = false; - - int64_t nowUs = ALooper::GetNowUs(); - - while (!mVideoOutputBuffers.empty()) { - const OutputInfo &info = *mVideoOutputBuffers.begin(); - - if (info.mTimeUs > nowUs) { - break; - } - - if (info.mTimeUs + 15000ll < nowUs) { - ++mNumFramesLate; - } - ++mNumFrames; - - status_t err = - mDecoderContext[0]->renderOutputBufferAndRelease(info.mIndex); - CHECK_EQ(err, (status_t)OK); - - mVideoOutputBuffers.erase(mVideoOutputBuffers.begin()); - } - - scheduleVideoRenderIfNecessary(); -} - -} // namespace android - diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.h b/media/libstagefright/wifi-display/sink/DirectRenderer.h deleted file mode 100644 index c5a4a83..0000000 --- a/media/libstagefright/wifi-display/sink/DirectRenderer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DIRECT_RENDERER_H_ - -#define DIRECT_RENDERER_H_ - -#include <media/stagefright/foundation/AHandler.h> - -namespace android { - -struct ABuffer; -struct AudioTrack; -struct IGraphicBufferProducer; -struct MediaCodec; - -// Renders audio and video data queued by calls to "queueAccessUnit". -struct DirectRenderer : public AHandler { - DirectRenderer(const sp<IGraphicBufferProducer> &bufferProducer); - - void setFormat(size_t trackIndex, const sp<AMessage> &format); - void queueAccessUnit(size_t trackIndex, const sp<ABuffer> &accessUnit); - -protected: - virtual void onMessageReceived(const sp<AMessage> &msg); - virtual ~DirectRenderer(); - -private: - struct DecoderContext; - struct AudioRenderer; - - enum { - kWhatDecoderNotify, - kWhatRenderVideo, - }; - - struct OutputInfo { - size_t mIndex; - int64_t mTimeUs; - sp<ABuffer> mBuffer; - }; - - sp<IGraphicBufferProducer> mSurfaceTex; - - sp<DecoderContext> mDecoderContext[2]; - List<OutputInfo> mVideoOutputBuffers; - - bool mVideoRenderPending; - - sp<AudioRenderer> mAudioRenderer; - - int32_t mNumFramesLate; - int32_t mNumFrames; - - void onDecoderNotify(const sp<AMessage> &msg); - - void queueOutputBuffer( - size_t trackIndex, - size_t index, int64_t timeUs, const sp<ABuffer> &buffer); - - void scheduleVideoRenderIfNecessary(); - void onRenderVideo(); - - DISALLOW_EVIL_CONSTRUCTORS(DirectRenderer); -}; - -} // namespace android - -#endif // DIRECT_RENDERER_H_ diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp deleted file mode 100644 index 5db2099..0000000 --- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WifiDisplaySink" -#include <utils/Log.h> - -#include "WifiDisplaySink.h" - -#include "DirectRenderer.h" -#include "MediaReceiver.h" -#include "ParsedMessage.h" -#include "TimeSyncer.h" - -#include <cutils/properties.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/Utils.h> - -namespace android { - -// static -const AString WifiDisplaySink::sUserAgent = MakeUserAgent(); - -WifiDisplaySink::WifiDisplaySink( - uint32_t flags, - const sp<ANetworkSession> &netSession, - const sp<IGraphicBufferProducer> &bufferProducer, - const sp<AMessage> ¬ify) - : mState(UNDEFINED), - mFlags(flags), - mNetSession(netSession), - mSurfaceTex(bufferProducer), - mNotify(notify), - mUsingTCPTransport(false), - mUsingTCPInterleaving(false), - mSessionID(0), - mNextCSeq(1), - mIDRFrameRequestPending(false), - mTimeOffsetUs(0ll), - mTimeOffsetValid(false), - mSetupDeferred(false), - mLatencyCount(0), - mLatencySumUs(0ll), - mLatencyMaxUs(0ll), - mMaxDelayMs(-1ll) { - // We support any and all resolutions, but prefer 720p30 - mSinkSupportedVideoFormats.setNativeResolution( - VideoFormats::RESOLUTION_CEA, 5); // 1280 x 720 p30 - - mSinkSupportedVideoFormats.enableAll(); -} - -WifiDisplaySink::~WifiDisplaySink() { -} - -void WifiDisplaySink::start(const char *sourceHost, int32_t sourcePort) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setString("sourceHost", sourceHost); - msg->setInt32("sourcePort", sourcePort); - msg->post(); -} - -void WifiDisplaySink::start(const char *uri) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setString("setupURI", uri); - msg->post(); -} - -// static -bool WifiDisplaySink::ParseURL( - const char *url, AString *host, int32_t *port, AString *path, - AString *user, AString *pass) { - host->clear(); - *port = 0; - path->clear(); - user->clear(); - pass->clear(); - - if (strncasecmp("rtsp://", url, 7)) { - return false; - } - - const char *slashPos = strchr(&url[7], '/'); - - if (slashPos == NULL) { - host->setTo(&url[7]); - path->setTo("/"); - } else { - host->setTo(&url[7], slashPos - &url[7]); - path->setTo(slashPos); - } - - ssize_t atPos = host->find("@"); - - if (atPos >= 0) { - // Split of user:pass@ from hostname. - - AString userPass(*host, 0, atPos); - host->erase(0, atPos + 1); - - ssize_t colonPos = userPass.find(":"); - - if (colonPos < 0) { - *user = userPass; - } else { - user->setTo(userPass, 0, colonPos); - pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1); - } - } - - const char *colonPos = strchr(host->c_str(), ':'); - - if (colonPos != NULL) { - char *end; - unsigned long x = strtoul(colonPos + 1, &end, 10); - - if (end == colonPos + 1 || *end != '\0' || x >= 65536) { - return false; - } - - *port = x; - - size_t colonOffset = colonPos - host->c_str(); - size_t trailing = host->size() - colonOffset; - host->erase(colonOffset, trailing); - } else { - *port = 554; - } - - return true; -} - -void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatStart: - { - sleep(2); // XXX - - int32_t sourcePort; - CHECK(msg->findString("sourceHost", &mRTSPHost)); - CHECK(msg->findInt32("sourcePort", &sourcePort)); - - sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); - - status_t err = mNetSession->createRTSPClient( - mRTSPHost.c_str(), sourcePort, notify, &mSessionID); - CHECK_EQ(err, (status_t)OK); - - mState = CONNECTING; - break; - } - - case kWhatRTSPNotify: - { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatError: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - AString detail; - CHECK(msg->findString("detail", &detail)); - - ALOGE("An error occurred in session %d (%d, '%s/%s').", - sessionID, - err, - detail.c_str(), - strerror(-err)); - - if (sessionID == mSessionID) { - ALOGI("Lost control connection."); - - // The control connection is dead now. - mNetSession->destroySession(mSessionID); - mSessionID = 0; - - if (mNotify == NULL) { - looper()->stop(); - } else { - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatDisconnected); - notify->post(); - } - } - break; - } - - case ANetworkSession::kWhatConnected: - { - ALOGI("We're now connected."); - mState = CONNECTED; - - if (mFlags & FLAG_SPECIAL_MODE) { - sp<AMessage> notify = new AMessage( - kWhatTimeSyncerNotify, id()); - - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - mTimeSyncer->startClient(mRTSPHost.c_str(), 8123); - } - break; - } - - case ANetworkSession::kWhatData: - { - onReceiveClientData(msg); - break; - } - - default: - TRESPASS(); - } - break; - } - - case kWhatStop: - { - looper()->stop(); - break; - } - - case kWhatMediaReceiverNotify: - { - onMediaReceiverNotify(msg); - break; - } - - case kWhatTimeSyncerNotify: - { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - if (what == TimeSyncer::kWhatTimeOffset) { - CHECK(msg->findInt64("offset", &mTimeOffsetUs)); - mTimeOffsetValid = true; - - if (mSetupDeferred) { - CHECK_EQ((status_t)OK, - sendSetup( - mSessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0")); - - mSetupDeferred = false; - } - } - break; - } - - case kWhatReportLateness: - { - if (mLatencyCount > 0) { - int64_t avgLatencyUs = mLatencySumUs / mLatencyCount; - - ALOGV("avg. latency = %lld ms (max %lld ms)", - avgLatencyUs / 1000ll, - mLatencyMaxUs / 1000ll); - - sp<AMessage> params = new AMessage; - params->setInt64("avgLatencyUs", avgLatencyUs); - params->setInt64("maxLatencyUs", mLatencyMaxUs); - mMediaReceiver->informSender(0 /* trackIndex */, params); - } - - mLatencyCount = 0; - mLatencySumUs = 0ll; - mLatencyMaxUs = 0ll; - - msg->post(kReportLatenessEveryUs); - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::dumpDelay(size_t trackIndex, int64_t timeUs) { - int64_t delayMs = (ALooper::GetNowUs() - timeUs) / 1000ll; - - if (delayMs > mMaxDelayMs) { - mMaxDelayMs = delayMs; - } - - static const int64_t kMinDelayMs = 0; - static const int64_t kMaxDelayMs = 300; - - const char *kPattern = "########################################"; - size_t kPatternSize = strlen(kPattern); - - int n = (kPatternSize * (delayMs - kMinDelayMs)) - / (kMaxDelayMs - kMinDelayMs); - - if (n < 0) { - n = 0; - } else if ((size_t)n > kPatternSize) { - n = kPatternSize; - } - - ALOGI("[%lld]: (%4lld ms / %4lld ms) %s", - timeUs / 1000, - delayMs, - mMaxDelayMs, - kPattern + kPatternSize - n); -} - -void WifiDisplaySink::onMediaReceiverNotify(const sp<AMessage> &msg) { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case MediaReceiver::kWhatInitDone: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGI("MediaReceiver initialization completed w/ err %d", err); - break; - } - - case MediaReceiver::kWhatError: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGE("MediaReceiver signaled error %d", err); - break; - } - - case MediaReceiver::kWhatAccessUnit: - { - if (mRenderer == NULL) { - mRenderer = new DirectRenderer(mSurfaceTex); - looper()->registerHandler(mRenderer); - } - - sp<ABuffer> accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - int64_t timeUs; - CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); - - if (!mTimeOffsetValid && !(mFlags & FLAG_SPECIAL_MODE)) { - mTimeOffsetUs = timeUs - ALooper::GetNowUs(); - mTimeOffsetValid = true; - } - - CHECK(mTimeOffsetValid); - - // We are the timesync _client_, - // client time = server time - time offset. - timeUs -= mTimeOffsetUs; - - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayUs = nowUs - timeUs; - - mLatencySumUs += delayUs; - if (mLatencyCount == 0 || delayUs > mLatencyMaxUs) { - mLatencyMaxUs = delayUs; - } - ++mLatencyCount; - - // dumpDelay(trackIndex, timeUs); - - timeUs += 220000ll; // Assume 220 ms of latency - accessUnit->meta()->setInt64("timeUs", timeUs); - - sp<AMessage> format; - if (msg->findMessage("format", &format)) { - mRenderer->setFormat(trackIndex, format); - } - - mRenderer->queueAccessUnit(trackIndex, accessUnit); - break; - } - - case MediaReceiver::kWhatPacketLost: - { -#if 0 - if (!mIDRFrameRequestPending) { - ALOGI("requesting IDR frame"); - - sendIDRFrameRequest(mSessionID); - } -#endif - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::registerResponseHandler( - int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - mResponseHandlers.add(id, func); -} - -status_t WifiDisplaySink::sendM2(int32_t sessionID) { - AString request = "OPTIONS * RTSP/1.0\r\n"; - AppendCommonResponse(&request, mNextCSeq); - - request.append( - "Require: org.wfa.wfd1.0\r\n" - "\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveM2Response); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::onReceiveM2Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - return OK; -} - -status_t WifiDisplaySink::onReceiveSetupResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - if (!msg->findString("session", &mPlaybackSessionID)) { - return ERROR_MALFORMED; - } - - if (!ParsedMessage::GetInt32Attribute( - mPlaybackSessionID.c_str(), - "timeout", - &mPlaybackSessionTimeoutSecs)) { - mPlaybackSessionTimeoutSecs = -1; - } - - ssize_t colonPos = mPlaybackSessionID.find(";"); - if (colonPos >= 0) { - // Strip any options from the returned session id. - mPlaybackSessionID.erase( - colonPos, mPlaybackSessionID.size() - colonPos); - } - - status_t err = configureTransport(msg); - - if (err != OK) { - return err; - } - - mState = PAUSED; - - return sendPlay( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); -} - -status_t WifiDisplaySink::configureTransport(const sp<ParsedMessage> &msg) { - if (mUsingTCPTransport && !(mFlags & FLAG_SPECIAL_MODE)) { - // In "special" mode we still use a UDP RTCP back-channel that - // needs connecting. - return OK; - } - - AString transport; - if (!msg->findString("transport", &transport)) { - ALOGE("Missing 'transport' field in SETUP response."); - return ERROR_MALFORMED; - } - - AString sourceHost; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "source", &sourceHost)) { - sourceHost = mRTSPHost; - } - - AString serverPortStr; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "server_port", &serverPortStr)) { - ALOGE("Missing 'server_port' in Transport field."); - return ERROR_MALFORMED; - } - - int rtpPort, rtcpPort; - if (sscanf(serverPortStr.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 - || rtpPort <= 0 || rtpPort > 65535 - || rtcpPort <=0 || rtcpPort > 65535 - || rtcpPort != rtpPort + 1) { - ALOGE("Invalid server_port description '%s'.", - serverPortStr.c_str()); - - return ERROR_MALFORMED; - } - - if (rtpPort & 1) { - ALOGW("Server picked an odd numbered RTP port."); - } - - return mMediaReceiver->connectTrack( - 0 /* trackIndex */, sourceHost.c_str(), rtpPort, rtcpPort); -} - -status_t WifiDisplaySink::onReceivePlayResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - mState = PLAYING; - - (new AMessage(kWhatReportLateness, id()))->post(kReportLatenessEveryUs); - - return OK; -} - -status_t WifiDisplaySink::onReceiveIDRFrameRequestResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - CHECK(mIDRFrameRequestPending); - mIDRFrameRequestPending = false; - - return OK; -} - -void WifiDisplaySink::onReceiveClientData(const sp<AMessage> &msg) { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - sp<RefBase> obj; - CHECK(msg->findObject("data", &obj)); - - sp<ParsedMessage> data = - static_cast<ParsedMessage *>(obj.get()); - - ALOGV("session %d received '%s'", - sessionID, data->debugString().c_str()); - - AString method; - AString uri; - data->getRequestField(0, &method); - - int32_t cseq; - if (!data->findInt32("cseq", &cseq)) { - sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); - return; - } - - if (method.startsWith("RTSP/")) { - // This is a response. - - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - - ssize_t index = mResponseHandlers.indexOfKey(id); - - if (index < 0) { - ALOGW("Received unsolicited server response, cseq %d", cseq); - return; - } - - HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); - mResponseHandlers.removeItemsAt(index); - - status_t err = (this->*func)(sessionID, data); - CHECK_EQ(err, (status_t)OK); - } else { - AString version; - data->getRequestField(2, &version); - if (!(version == AString("RTSP/1.0"))) { - sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); - return; - } - - if (method == "OPTIONS") { - onOptionsRequest(sessionID, cseq, data); - } else if (method == "GET_PARAMETER") { - onGetParameterRequest(sessionID, cseq, data); - } else if (method == "SET_PARAMETER") { - onSetParameterRequest(sessionID, cseq, data); - } else { - sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); - } - } -} - -void WifiDisplaySink::onOptionsRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n"); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); - - err = sendM2(sessionID); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::onGetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - AString body; - - if (mState == CONNECTED) { - mUsingTCPTransport = false; - mUsingTCPInterleaving = false; - - char val[PROPERTY_VALUE_MAX]; - if (property_get("media.wfd-sink.tcp-mode", val, NULL)) { - if (!strcasecmp("true", val) || !strcmp("1", val)) { - ALOGI("Using TCP unicast transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = false; - } else if (!strcasecmp("interleaved", val)) { - ALOGI("Using TCP interleaved transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = true; - } - } else if (mFlags & FLAG_SPECIAL_MODE) { - mUsingTCPTransport = true; - } - - body = "wfd_video_formats: "; - body.append(mSinkSupportedVideoFormats.getFormatSpec()); - - body.append( - "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n" - "wfd_client_rtp_ports: RTP/AVP/"); - - if (mUsingTCPTransport) { - body.append("TCP;"); - if (mUsingTCPInterleaving) { - body.append("interleaved"); - } else { - body.append("unicast 19000 0"); - } - } else { - body.append("UDP;unicast 19000 0"); - } - - body.append(" mode=play\r\n"); - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Content-Type: text/parameters\r\n"); - response.append(StringPrintf("Content-Length: %d\r\n", body.size())); - response.append("\r\n"); - response.append(body); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) { - sp<AMessage> notify = new AMessage(kWhatMediaReceiverNotify, id()); - - mMediaReceiverLooper = new ALooper; - mMediaReceiverLooper->setName("media_receiver"); - - mMediaReceiverLooper->start( - false /* runOnCallingThread */, - false /* canCallJava */, - PRIORITY_AUDIO); - - mMediaReceiver = new MediaReceiver(mNetSession, notify); - mMediaReceiverLooper->registerHandler(mMediaReceiver); - - RTPReceiver::TransportMode rtpMode = RTPReceiver::TRANSPORT_UDP; - if (mUsingTCPTransport) { - if (mUsingTCPInterleaving) { - rtpMode = RTPReceiver::TRANSPORT_TCP_INTERLEAVED; - } else { - rtpMode = RTPReceiver::TRANSPORT_TCP; - } - } - - int32_t localRTPPort; - status_t err = mMediaReceiver->addTrack( - rtpMode, RTPReceiver::TRANSPORT_UDP /* rtcpMode */, &localRTPPort); - - if (err == OK) { - err = mMediaReceiver->initAsync(MediaReceiver::MODE_TRANSPORT_STREAM); - } - - if (err != OK) { - mMediaReceiverLooper->unregisterHandler(mMediaReceiver->id()); - mMediaReceiver.clear(); - - mMediaReceiverLooper->stop(); - mMediaReceiverLooper.clear(); - - return err; - } - - AString request = StringPrintf("SETUP %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - if (rtpMode == RTPReceiver::TRANSPORT_TCP_INTERLEAVED) { - request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n"); - } else if (rtpMode == RTPReceiver::TRANSPORT_TCP) { - if (mFlags & FLAG_SPECIAL_MODE) { - // This isn't quite true, since the RTP connection is through TCP - // and the RTCP connection through UDP... - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d-%d\r\n", - localRTPPort, localRTPPort + 1)); - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d\r\n", - localRTPPort)); - } - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n", - localRTPPort, - localRTPPort + 1)); - } - - request.append("\r\n"); - - ALOGV("request = '%s'", request.c_str()); - - err = mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveSetupResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendPlay(int32_t sessionID, const char *uri) { - AString request = StringPrintf("PLAY %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append("\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceivePlayResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendIDRFrameRequest(int32_t sessionID) { - CHECK(!mIDRFrameRequestPending); - - AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; - - AppendCommonResponse(&request, mNextCSeq); - - AString content = "wfd_idr_request\r\n"; - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append(StringPrintf("Content-Length: %d\r\n", content.size())); - request.append("\r\n"); - request.append(content); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, - mNextCSeq, - &WifiDisplaySink::onReceiveIDRFrameRequestResponse); - - ++mNextCSeq; - - mIDRFrameRequestPending = true; - - return OK; -} - -void WifiDisplaySink::onSetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - const char *content = data->getContent(); - - if (strstr(content, "wfd_trigger_method: SETUP\r\n") != NULL) { - if ((mFlags & FLAG_SPECIAL_MODE) && !mTimeOffsetValid) { - mSetupDeferred = true; - } else { - status_t err = - sendSetup( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); - - CHECK_EQ(err, (status_t)OK); - } - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::sendErrorResponse( - int32_t sessionID, - const char *errorDetail, - int32_t cseq) { - AString response; - response.append("RTSP/1.0 "); - response.append(errorDetail); - response.append("\r\n"); - - AppendCommonResponse(&response, cseq); - - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -// static -void WifiDisplaySink::AppendCommonResponse(AString *response, int32_t cseq) { - time_t now = time(NULL); - struct tm *now2 = gmtime(&now); - char buf[128]; - strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); - - response->append("Date: "); - response->append(buf); - response->append("\r\n"); - - response->append(StringPrintf("User-Agent: %s\r\n", sUserAgent.c_str())); - - if (cseq >= 0) { - response->append(StringPrintf("CSeq: %d\r\n", cseq)); - } -} - -} // namespace android diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h b/media/libstagefright/wifi-display/sink/WifiDisplaySink.h deleted file mode 100644 index adb9d89..0000000 --- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WIFI_DISPLAY_SINK_H_ - -#define WIFI_DISPLAY_SINK_H_ - -#include "ANetworkSession.h" - -#include "VideoFormats.h" - -#include <gui/Surface.h> -#include <media/stagefright/foundation/AHandler.h> - -namespace android { - -struct AMessage; -struct DirectRenderer; -struct MediaReceiver; -struct ParsedMessage; -struct TimeSyncer; - -// Represents the RTSP client acting as a wifi display sink. -// Connects to a wifi display source and renders the incoming -// transport stream using a MediaPlayer instance. -struct WifiDisplaySink : public AHandler { - enum { - kWhatDisconnected, - }; - - enum Flags { - FLAG_SPECIAL_MODE = 1, - }; - - // If no notification message is specified (notify == NULL) - // the sink will stop its looper() once the session ends, - // otherwise it will post an appropriate notification but leave - // the looper() running. - WifiDisplaySink( - uint32_t flags, - const sp<ANetworkSession> &netSession, - const sp<IGraphicBufferProducer> &bufferProducer = NULL, - const sp<AMessage> ¬ify = NULL); - - void start(const char *sourceHost, int32_t sourcePort); - void start(const char *uri); - -protected: - virtual ~WifiDisplaySink(); - virtual void onMessageReceived(const sp<AMessage> &msg); - -private: - enum State { - UNDEFINED, - CONNECTING, - CONNECTED, - PAUSED, - PLAYING, - }; - - enum { - kWhatStart, - kWhatRTSPNotify, - kWhatStop, - kWhatMediaReceiverNotify, - kWhatTimeSyncerNotify, - kWhatReportLateness, - }; - - struct ResponseID { - int32_t mSessionID; - int32_t mCSeq; - - bool operator<(const ResponseID &other) const { - return mSessionID < other.mSessionID - || (mSessionID == other.mSessionID - && mCSeq < other.mCSeq); - } - }; - - typedef status_t (WifiDisplaySink::*HandleRTSPResponseFunc)( - int32_t sessionID, const sp<ParsedMessage> &msg); - - static const int64_t kReportLatenessEveryUs = 1000000ll; - - static const AString sUserAgent; - - State mState; - uint32_t mFlags; - VideoFormats mSinkSupportedVideoFormats; - sp<ANetworkSession> mNetSession; - sp<IGraphicBufferProducer> mSurfaceTex; - sp<AMessage> mNotify; - sp<TimeSyncer> mTimeSyncer; - bool mUsingTCPTransport; - bool mUsingTCPInterleaving; - AString mRTSPHost; - int32_t mSessionID; - - int32_t mNextCSeq; - - KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers; - - sp<ALooper> mMediaReceiverLooper; - sp<MediaReceiver> mMediaReceiver; - sp<DirectRenderer> mRenderer; - - AString mPlaybackSessionID; - int32_t mPlaybackSessionTimeoutSecs; - - bool mIDRFrameRequestPending; - - int64_t mTimeOffsetUs; - bool mTimeOffsetValid; - - bool mSetupDeferred; - - size_t mLatencyCount; - int64_t mLatencySumUs; - int64_t mLatencyMaxUs; - - int64_t mMaxDelayMs; - - status_t sendM2(int32_t sessionID); - status_t sendSetup(int32_t sessionID, const char *uri); - status_t sendPlay(int32_t sessionID, const char *uri); - status_t sendIDRFrameRequest(int32_t sessionID); - - status_t onReceiveM2Response( - int32_t sessionID, const sp<ParsedMessage> &msg); - - status_t onReceiveSetupResponse( - int32_t sessionID, const sp<ParsedMessage> &msg); - - status_t configureTransport(const sp<ParsedMessage> &msg); - - status_t onReceivePlayResponse( - int32_t sessionID, const sp<ParsedMessage> &msg); - - status_t onReceiveIDRFrameRequestResponse( - int32_t sessionID, const sp<ParsedMessage> &msg); - - void registerResponseHandler( - int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func); - - void onReceiveClientData(const sp<AMessage> &msg); - - void onOptionsRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data); - - void onGetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data); - - void onSetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data); - - void onMediaReceiverNotify(const sp<AMessage> &msg); - - void sendErrorResponse( - int32_t sessionID, - const char *errorDetail, - int32_t cseq); - - static void AppendCommonResponse(AString *response, int32_t cseq); - - bool ParseURL( - const char *url, AString *host, int32_t *port, AString *path, - AString *user, AString *pass); - - void dumpDelay(size_t trackIndex, int64_t timeUs); - - DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySink); -}; - -} // namespace android - -#endif // WIFI_DISPLAY_SINK_H_ |