summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/sink
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/wifi-display/sink')
-rw-r--r--media/libstagefright/wifi-display/sink/DirectRenderer.cpp625
-rw-r--r--media/libstagefright/wifi-display/sink/DirectRenderer.h82
-rw-r--r--media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp917
-rw-r--r--media/libstagefright/wifi-display/sink/WifiDisplaySink.h196
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> &notify);
-
- 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> &notify)
- : 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> &notify)
- : 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> &notify = 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_