diff options
6 files changed, 106 insertions, 30 deletions
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp index a5fb6b8..b9539e9 100644 --- a/media/libstagefright/wifi-display/source/Converter.cpp +++ b/media/libstagefright/wifi-display/source/Converter.cpp @@ -132,7 +132,7 @@ status_t Converter::initEncoder() { mOutputFormat->setInt32("bitrate", audioBitrate); } else { mOutputFormat->setInt32("bitrate", videoBitrate); - mOutputFormat->setInt32("frame-rate", 60); + mOutputFormat->setInt32("frame-rate", 30); mOutputFormat->setInt32("i-frame-interval", 1); // Iframes every 1 secs mOutputFormat->setInt32("prepend-sps-pps-to-idr-frames", 1); } diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index 4ae9895..c91b4c8 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -64,6 +64,8 @@ struct WifiDisplaySource::PlaybackSession::Track : public AHandler { const sp<MediaPuller> &mediaPuller, const sp<Converter> &converter); + void setRepeaterSource(const sp<RepeaterSource> &source); + sp<AMessage> getFormat(); bool isAudio() const; @@ -78,6 +80,8 @@ struct WifiDisplaySource::PlaybackSession::Track : public AHandler { void queueAccessUnit(const sp<ABuffer> &accessUnit); sp<ABuffer> dequeueAccessUnit(); + void requestIDRFrame(); + protected: virtual void onMessageReceived(const sp<AMessage> &msg); virtual ~Track(); @@ -96,6 +100,7 @@ private: ssize_t mPacketizerTrackIndex; bool mIsAudio; List<sp<ABuffer> > mQueuedAccessUnits; + sp<RepeaterSource> mRepeaterSource; static bool IsAudioFormat(const sp<AMessage> &format); @@ -178,6 +183,11 @@ void WifiDisplaySource::PlaybackSession::Track::stopAsync() { sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id()); if (mStarted && mMediaPuller != NULL) { + if (mRepeaterSource != NULL) { + // Let's unblock MediaPuller's MediaSource::read(). + mRepeaterSource->wakeUp(); + } + mMediaPuller->stopAsync(msg); } else { msg->post(); @@ -224,6 +234,23 @@ sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueAccessUnit() { return accessUnit; } +void WifiDisplaySource::PlaybackSession::Track::setRepeaterSource( + const sp<RepeaterSource> &source) { + mRepeaterSource = source; +} + +void WifiDisplaySource::PlaybackSession::Track::requestIDRFrame() { + if (mIsAudio) { + return; + } + + if (mRepeaterSource != NULL) { + mRepeaterSource->wakeUp(); + } + + mConverter->requestIDRFrame(); +} + //////////////////////////////////////////////////////////////////////////////// WifiDisplaySource::PlaybackSession::PlaybackSession( @@ -809,7 +836,8 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer() { } status_t WifiDisplaySource::PlaybackSession::addSource( - bool isVideo, const sp<MediaSource> &source, size_t *numInputBuffers) { + bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource, + size_t *numInputBuffers) { sp<ALooper> pullLooper = new ALooper; pullLooper->setName("pull_looper"); @@ -871,6 +899,10 @@ status_t WifiDisplaySource::PlaybackSession::addSource( sp<Track> track = new Track( notify, pullLooper, codecLooper, puller, converter); + if (isRepeaterSource) { + track->setRepeaterSource(static_cast<RepeaterSource *>(source.get())); + } + looper()->registerHandler(track); mTracks.add(trackIndex, track); @@ -887,8 +919,13 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource() { source->setUseAbsoluteTimestamps(); + sp<RepeaterSource> videoSource = + new RepeaterSource(source, 30.0 /* rateHz */); + size_t numInputBuffers; - status_t err = addSource(true /* isVideo */, source, &numInputBuffers); + status_t err = addSource( + true /* isVideo */, videoSource, true /* isRepeaterSource */, + &numInputBuffers); if (err != OK) { return err; @@ -910,7 +947,8 @@ status_t WifiDisplaySource::PlaybackSession::addAudioSource() { if (audioSource->initCheck() == OK) { return addSource( - false /* isVideo */, audioSource, NULL /* numInputBuffers */); + false /* isVideo */, audioSource, false /* isRepeaterSource */, + NULL /* numInputBuffers */); } ALOGW("Unable to instantiate audio source"); @@ -1300,7 +1338,7 @@ void WifiDisplaySource::PlaybackSession::requestIDRFrame() { for (size_t i = 0; i < mTracks.size(); ++i) { const sp<Track> &track = mTracks.valueAt(i); - track->converter()->requestIDRFrame(); + track->requestIDRFrame(); } } diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index 3bdb223..5d4bde8 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -185,6 +185,7 @@ private: status_t addSource( bool isVideo, const sp<MediaSource> &source, + bool isRepeaterSource, size_t *numInputBuffers); status_t addVideoSource(); diff --git a/media/libstagefright/wifi-display/source/RepeaterSource.cpp b/media/libstagefright/wifi-display/source/RepeaterSource.cpp index dc216e8..641e63f 100644 --- a/media/libstagefright/wifi-display/source/RepeaterSource.cpp +++ b/media/libstagefright/wifi-display/source/RepeaterSource.cpp @@ -18,6 +18,7 @@ RepeaterSource::RepeaterSource(const sp<MediaSource> &source, double rateHz) mRateHz(rateHz), mBuffer(NULL), mResult(OK), + mLastBufferUpdateUs(-1ll), mStartTimeUs(-1ll), mFrameCount(0) { } @@ -91,38 +92,59 @@ status_t RepeaterSource::read( ReadOptions::SeekMode seekMode; CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &seekMode)); - int64_t bufferTimeUs = -1ll; + for (;;) { + int64_t bufferTimeUs = -1ll; - if (mStartTimeUs < 0ll) { - Mutex::Autolock autoLock(mLock); - while (mBuffer == NULL && mResult == OK) { - mCondition.wait(mLock); - } + if (mStartTimeUs < 0ll) { + Mutex::Autolock autoLock(mLock); + while ((mLastBufferUpdateUs < 0ll || mBuffer == NULL) + && mResult == OK) { + mCondition.wait(mLock); + } - mStartTimeUs = ALooper::GetNowUs(); - bufferTimeUs = mStartTimeUs; - } else { - bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz; + ALOGV("now resuming."); + mStartTimeUs = ALooper::GetNowUs(); + bufferTimeUs = mStartTimeUs; + } else { + bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz; - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayUs = bufferTimeUs - nowUs; + int64_t nowUs = ALooper::GetNowUs(); + int64_t delayUs = bufferTimeUs - nowUs; - if (delayUs > 0ll) { - usleep(delayUs); + if (delayUs > 0ll) { + usleep(delayUs); + } } - } - Mutex::Autolock autoLock(mLock); - if (mResult != OK) { - CHECK(mBuffer == NULL); - return mResult; - } + bool stale = false; - mBuffer->add_ref(); - *buffer = mBuffer; - (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs); + { + Mutex::Autolock autoLock(mLock); + if (mResult != OK) { + CHECK(mBuffer == NULL); + return mResult; + } - ++mFrameCount; + int64_t nowUs = ALooper::GetNowUs(); + if (nowUs - mLastBufferUpdateUs > 1000000ll) { + mLastBufferUpdateUs = -1ll; + stale = true; + } else { + mBuffer->add_ref(); + *buffer = mBuffer; + (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs); + ++mFrameCount; + } + } + + if (!stale) { + break; + } + + mStartTimeUs = -1ll; + mFrameCount = 0; + ALOGV("now dormant"); + } return OK; } @@ -147,6 +169,7 @@ void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) { } mBuffer = buffer; mResult = err; + mLastBufferUpdateUs = ALooper::GetNowUs(); mCondition.broadcast(); @@ -161,4 +184,13 @@ void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) { } } +void RepeaterSource::wakeUp() { + ALOGV("wakeUp"); + Mutex::Autolock autoLock(mLock); + if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) { + mLastBufferUpdateUs = ALooper::GetNowUs(); + mCondition.broadcast(); + } +} + } // namespace android diff --git a/media/libstagefright/wifi-display/source/RepeaterSource.h b/media/libstagefright/wifi-display/source/RepeaterSource.h index 3049362..e4aa2b6 100644 --- a/media/libstagefright/wifi-display/source/RepeaterSource.h +++ b/media/libstagefright/wifi-display/source/RepeaterSource.h @@ -22,6 +22,10 @@ struct RepeaterSource : public MediaSource { void onMessageReceived(const sp<AMessage> &msg); + // If RepeaterSource is currently dormant, because SurfaceFlinger didn't + // send updates in a while, this is its wakeup call. + void wakeUp(); + protected: virtual ~RepeaterSource(); @@ -43,6 +47,7 @@ private: MediaBuffer *mBuffer; status_t mResult; + int64_t mLastBufferUpdateUs; int64_t mStartTimeUs; int32_t mFrameCount; diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 1083a80..b0aaf3b 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -539,7 +539,7 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) { // use "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n" AString body = StringPrintf( "wfd_video_formats: " - "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n" + "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n" "wfd_audio_codecs: AAC 00000001 00\r\n" // 2 ch AAC 48kHz "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n" "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n", |