diff options
author | Andreas Huber <andih@google.com> | 2013-01-29 09:22:16 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2013-01-29 10:30:47 -0800 |
commit | 94a483bf2bd699275673d9cd57cb125d48572f30 (patch) | |
tree | 3896a7d6691cdae1607bd87dff011f53ef5aea3b /media/libstagefright/wifi-display/source/WifiDisplaySource.cpp | |
parent | 2d45dbd1910a7e51d383e8583017e6f26cd3498a (diff) | |
download | frameworks_av-94a483bf2bd699275673d9cd57cb125d48572f30.zip frameworks_av-94a483bf2bd699275673d9cd57cb125d48572f30.tar.gz frameworks_av-94a483bf2bd699275673d9cd57cb125d48572f30.tar.bz2 |
Squashed commit of the following:
commit f2c38e5cf8cee3b597c744c9d6a9c0969ac8599a
Author: Andreas Huber <andih@google.com>
Date: Mon Jan 28 16:33:07 2013 -0800
Proper support for video format selection/negotiation.
Change-Id: I7db86cef939d63b8064be1c74de9ad78e85d45d9
commit 488023b7bad086692ffe942114fa3cc0e59a16c0
Author: Andreas Huber <andih@google.com>
Date: Mon Jan 28 11:21:23 2013 -0800
Sink now notifies clients once it is disconnected.
Change-Id: I2f0a458ef1ec30dda1272ad5a013fee4ee70edc9
commit 783932e40dd904aa531c263ad51280d9ca814dcb
Author: Andreas Huber <andih@google.com>
Date: Tue Dec 18 15:03:40 2012 -0800
Alternative DirectRenderer implementation.
Change-Id: I307beb913d7a61cb938bcb02696cc2e82d2b8b07
commit 1935cc9a87824aea71fc8ebe2162f62ec634ce5a
Author: Andreas Huber <andih@google.com>
Date: Tue Dec 18 10:24:27 2012 -0800
Experimenting with wifi sink timing.
Change-Id: I059bae9762cf11777666988a8b4ab2012b5807be
commit a859ee1eadd6a1d6a080667917e8b102c3770d61
Author: Andreas Huber <andih@google.com>
Date: Thu Nov 15 11:16:30 2012 -0800
wfd sink update.
Change-Id: I026dfc580be92aa40dbbe7c1bc061fadf3b08be8
Change-Id: I191d3d7015869ca99254d813d074328fb5b2f479
Diffstat (limited to 'media/libstagefright/wifi-display/source/WifiDisplaySource.cpp')
-rw-r--r-- | media/libstagefright/wifi-display/source/WifiDisplaySource.cpp | 217 |
1 files changed, 147 insertions, 70 deletions
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 9ec1064..0fed19b 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -58,8 +58,19 @@ WifiDisplaySource::WifiDisplaySource( mIsHDCP2_0(false), mHDCPPort(0), mHDCPInitializationComplete(false), - mSetupTriggerDeferred(false) -{ + mSetupTriggerDeferred(false) { + mSupportedSourceVideoFormats.enableAll(); + + mSupportedSourceVideoFormats.setNativeResolution( + VideoFormats::RESOLUTION_CEA, 5); // 1280x720 p30 + + // Disable resolutions above 1080p since the encoder won't be able to + // handle them. + mSupportedSourceVideoFormats.setResolutionEnabled( + VideoFormats::RESOLUTION_VESA, 28, false); // 1920x1200 p30 + + mSupportedSourceVideoFormats.setResolutionEnabled( + VideoFormats::RESOLUTION_VESA, 29, false); // 1920x1200 p60 } WifiDisplaySource::~WifiDisplaySource() { @@ -375,13 +386,33 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { IRemoteDisplayClient::kDisplayErrorUnknown); } else if (what == PlaybackSession::kWhatSessionEstablished) { if (mClient != NULL) { - mClient->onDisplayConnected( - mClientInfo.mPlaybackSession->getSurfaceTexture(), - mClientInfo.mPlaybackSession->width(), - mClientInfo.mPlaybackSession->height(), - mUsingHDCP - ? IRemoteDisplayClient::kDisplayFlagSecure - : 0); + if (!mSinkSupportsVideo) { + mClient->onDisplayConnected( + NULL, // SurfaceTexture + 0, // width, + 0, // height, + mUsingHDCP + ? IRemoteDisplayClient::kDisplayFlagSecure + : 0); + } else { + size_t width, height; + + CHECK(VideoFormats::GetConfiguration( + mChosenVideoResolutionType, + mChosenVideoResolutionIndex, + &width, + &height, + NULL /* framesPerSecond */, + NULL /* interlaced */)); + + mClient->onDisplayConnected( + mClientInfo.mPlaybackSession->getSurfaceTexture(), + width, + height, + mUsingHDCP + ? IRemoteDisplayClient::kDisplayFlagSecure + : 0); + } } if (mState == ABOUT_TO_PLAY) { @@ -564,22 +595,6 @@ status_t WifiDisplaySource::sendM3(int32_t sessionID) { } status_t WifiDisplaySource::sendM4(int32_t sessionID) { - // wfd_video_formats: - // 1 byte "native" - // 1 byte "preferred-display-mode-supported" 0 or 1 - // one or more avc codec structures - // 1 byte profile - // 1 byte level - // 4 byte CEA mask - // 4 byte VESA mask - // 4 byte HH mask - // 1 byte latency - // 2 byte min-slice-slice - // 2 byte slice-enc-params - // 1 byte framerate-control-support - // max-hres (none or 2 byte) - // max-vres (none or 2 byte) - CHECK_EQ(sessionID, mClientSessionID); AString transportString = "UDP"; @@ -591,28 +606,35 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) { transportString = "TCP"; } - // For 720p60: - // use "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n" - // For 720p30: - // use "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n" - // For 720p24: - // use "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n" - // For 1080p30: - // use "38 00 02 02 00000080 00000000 00000000 00 0000 0000 00 none none\r\n" - AString body = StringPrintf( - "wfd_video_formats: " -#if USE_1080P - "38 00 02 02 00000080 00000000 00000000 00 0000 0000 00 none none\r\n" -#else - "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n" -#endif - "wfd_audio_codecs: %s\r\n" - "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n" - "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n", - (mUsingPCMAudio - ? "LPCM 00000002 00" // 2 ch PCM 48kHz - : "AAC 00000001 00"), // 2 ch AAC 48kHz - mClientInfo.mLocalIP.c_str(), transportString.c_str(), mChosenRTPPort); + AString body; + + if (mSinkSupportsVideo) { + body.append("wfd_video_formats: "); + + VideoFormats chosenVideoFormat; + chosenVideoFormat.disableAll(); + chosenVideoFormat.setNativeResolution( + mChosenVideoResolutionType, mChosenVideoResolutionIndex); + + body.append(chosenVideoFormat.getFormatSpec()); + body.append("\r\n"); + } + + if (mSinkSupportsAudio) { + body.append( + StringPrintf("wfd_audio_codecs: %s\r\n", + (mUsingPCMAudio + ? "LPCM 00000002 00" // 2 ch PCM 48kHz + : "AAC 00000001 00"))); // 2 ch AAC 48kHz + } + + body.append( + StringPrintf( + "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n" + "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n", + mClientInfo.mLocalIP.c_str(), + transportString.c_str(), + mChosenRTPPort)); AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; AppendCommonResponse(&request, mNextCSeq); @@ -789,39 +811,90 @@ status_t WifiDisplaySource::onReceiveM3Response( mChosenRTPPort = port0; + if (!params->findParameter("wfd_video_formats", &value)) { + ALOGE("Sink doesn't report its choice of wfd_video_formats."); + return ERROR_MALFORMED; + } + + mSinkSupportsVideo = false; + + if (!(value == "none")) { + mSinkSupportsVideo = true; + if (!mSupportedSinkVideoFormats.parseFormatSpec(value.c_str())) { + ALOGE("Failed to parse sink provided wfd_video_formats (%s)", + value.c_str()); + + return ERROR_MALFORMED; + } + + if (!VideoFormats::PickBestFormat( + mSupportedSinkVideoFormats, + mSupportedSourceVideoFormats, + &mChosenVideoResolutionType, + &mChosenVideoResolutionIndex)) { + ALOGE("Sink and source share no commonly supported video " + "formats."); + + return ERROR_UNSUPPORTED; + } + + size_t width, height, framesPerSecond; + bool interlaced; + CHECK(VideoFormats::GetConfiguration( + mChosenVideoResolutionType, + mChosenVideoResolutionIndex, + &width, + &height, + &framesPerSecond, + &interlaced)); + + ALOGI("Picked video resolution %u x %u %c%u", + width, height, interlaced ? 'i' : 'p', framesPerSecond); + } else { + ALOGI("Sink doesn't support video at all."); + } + if (!params->findParameter("wfd_audio_codecs", &value)) { ALOGE("Sink doesn't report its choice of wfd_audio_codecs."); return ERROR_MALFORMED; } - if (value == "none") { - ALOGE("Sink doesn't support audio at all."); - return ERROR_UNSUPPORTED; - } + mSinkSupportsAudio = false; - uint32_t modes; - GetAudioModes(value.c_str(), "AAC", &modes); + if (!(value == "none")) { + mSinkSupportsAudio = true; - bool supportsAAC = (modes & 1) != 0; // AAC 2ch 48kHz + uint32_t modes; + GetAudioModes(value.c_str(), "AAC", &modes); - GetAudioModes(value.c_str(), "LPCM", &modes); + bool supportsAAC = (modes & 1) != 0; // AAC 2ch 48kHz - bool supportsPCM = (modes & 2) != 0; // LPCM 2ch 48kHz + GetAudioModes(value.c_str(), "LPCM", &modes); - char val[PROPERTY_VALUE_MAX]; - if (supportsPCM - && property_get("media.wfd.use-pcm-audio", val, NULL) - && (!strcasecmp("true", val) || !strcmp("1", val))) { - ALOGI("Using PCM audio."); - mUsingPCMAudio = true; - } else if (supportsAAC) { - ALOGI("Using AAC audio."); - mUsingPCMAudio = false; - } else if (supportsPCM) { - ALOGI("Using PCM audio."); - mUsingPCMAudio = true; + bool supportsPCM = (modes & 2) != 0; // LPCM 2ch 48kHz + + char val[PROPERTY_VALUE_MAX]; + if (supportsPCM + && property_get("media.wfd.use-pcm-audio", val, NULL) + && (!strcasecmp("true", val) || !strcmp("1", val))) { + ALOGI("Using PCM audio."); + mUsingPCMAudio = true; + } else if (supportsAAC) { + ALOGI("Using AAC audio."); + mUsingPCMAudio = false; + } else if (supportsPCM) { + ALOGI("Using PCM audio."); + mUsingPCMAudio = true; + } else { + ALOGI("Sink doesn't support an audio format we do."); + return ERROR_UNSUPPORTED; + } } else { - ALOGI("Sink doesn't support an audio format we do."); + ALOGI("Sink doesn't support audio at all."); + } + + if (!mSinkSupportsVideo && !mSinkSupportsAudio) { + ALOGE("Sink supports neither video nor audio..."); return ERROR_UNSUPPORTED; } @@ -1160,7 +1233,11 @@ status_t WifiDisplaySource::onSetupRequest( clientRtp, clientRtcp, transportMode, - mUsingPCMAudio); + mSinkSupportsAudio, + mUsingPCMAudio, + mSinkSupportsVideo, + mChosenVideoResolutionType, + mChosenVideoResolutionIndex); if (err != OK) { looper()->unregisterHandler(playbackSession->id()); |