diff options
Diffstat (limited to 'media')
9 files changed, 204 insertions, 62 deletions
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp index 60cca69..6f336c7 100644 --- a/media/libstagefright/wifi-display/source/Converter.cpp +++ b/media/libstagefright/wifi-display/source/Converter.cpp @@ -44,7 +44,12 @@ Converter::Converter( mCodecLooper(codecLooper), mInputFormat(format), mIsVideo(false), - mDoMoreWorkPending(false) { + mDoMoreWorkPending(false) +#if ENABLE_SILENCE_DETECTION + ,mFirstSilentFrameUs(-1ll) + ,mInSilentMode(false) +#endif + { AString mime; CHECK(mInputFormat->findString("mime", &mime)); @@ -132,9 +137,9 @@ 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); + mOutputFormat->setInt32("prepend-sps-pps-to-idr-frames", 1); } ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); @@ -171,6 +176,20 @@ void Converter::notifyError(status_t err) { notify->post(); } +// static +bool Converter::IsSilence(const sp<ABuffer> &accessUnit) { + const uint8_t *ptr = accessUnit->data(); + const uint8_t *end = ptr + accessUnit->size(); + while (ptr < end) { + if (*ptr != 0) { + return false; + } + ++ptr; + } + + return true; +} + void Converter::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatMediaPullerNotify: @@ -220,6 +239,30 @@ void Converter::onMessageReceived(const sp<AMessage> &msg) { } #endif +#if ENABLE_SILENCE_DETECTION + if (!mIsVideo) { + if (IsSilence(accessUnit)) { + if (!mInSilentMode) { + int64_t nowUs = ALooper::GetNowUs(); + + if (mFirstSilentFrameUs < 0ll) { + mFirstSilentFrameUs = nowUs; + } else if (nowUs >= mFirstSilentFrameUs + 1000000ll) { + mInSilentMode = true; + ALOGI("audio in silent mode now."); + break; + } + } + } else { + if (mInSilentMode) { + ALOGI("audio no longer in silent mode."); + } + mInSilentMode = false; + mFirstSilentFrameUs = -1ll; + } + } +#endif + mInputBufferQueue.push_back(accessUnit); feedEncoderInputBuffers(); @@ -283,7 +326,7 @@ void Converter::scheduleDoMoreWork() { } mDoMoreWorkPending = true; - (new AMessage(kWhatDoMoreWork, id()))->post(1000ll); + (new AMessage(kWhatDoMoreWork, id()))->post(mIsVideo ? 10000ll : 5000ll); } status_t Converter::feedEncoderInputBuffers() { @@ -338,14 +381,21 @@ status_t Converter::doMoreWork() { feedEncoderInputBuffers(); } - size_t offset; - size_t size; - int64_t timeUs; - uint32_t flags; - err = mEncoder->dequeueOutputBuffer( - &bufferIndex, &offset, &size, &timeUs, &flags); + for (;;) { + size_t offset; + size_t size; + int64_t timeUs; + uint32_t flags; + err = mEncoder->dequeueOutputBuffer( + &bufferIndex, &offset, &size, &timeUs, &flags); + + if (err != OK) { + if (err == -EAGAIN) { + err = OK; + } + break; + } - if (err == OK) { if (flags & MediaCodec::BUFFER_FLAG_EOS) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatEOS); @@ -354,6 +404,10 @@ status_t Converter::doMoreWork() { sp<ABuffer> buffer = new ABuffer(size); buffer->meta()->setInt64("timeUs", timeUs); + if (!mIsVideo) { + ALOGV("audio time %lld us (%.2f secs)", timeUs, timeUs / 1E6); + } + memcpy(buffer->data(), mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset, size); @@ -368,9 +422,11 @@ status_t Converter::doMoreWork() { } } - err = mEncoder->releaseOutputBuffer(bufferIndex); - } else if (err == -EAGAIN) { - err = OK; + mEncoder->releaseOutputBuffer(bufferIndex); + + if (flags & MediaCodec::BUFFER_FLAG_EOS) { + break; + } } return err; diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h index 9f54523..93ff72f 100644 --- a/media/libstagefright/wifi-display/source/Converter.h +++ b/media/libstagefright/wifi-display/source/Converter.h @@ -25,6 +25,8 @@ namespace android { struct ABuffer; struct MediaCodec; +#define ENABLE_SILENCE_DETECTION 1 + // Utility class that receives media access units and converts them into // media access unit of a different format. // Right now this'll convert raw video into H.264 and raw audio into AAC. @@ -83,6 +85,11 @@ private: bool mDoMoreWorkPending; +#if ENABLE_SILENCE_DETECTION + int64_t mFirstSilentFrameUs; + bool mInSilentMode; +#endif + status_t initEncoder(); status_t feedEncoderInputBuffers(); @@ -92,6 +99,8 @@ private: void notifyError(status_t err); + static bool IsSilence(const sp<ABuffer> &accessUnit); + DISALLOW_EVIL_CONSTRUCTORS(Converter); }; diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index 7de607c..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( @@ -264,8 +291,10 @@ WifiDisplaySource::PlaybackSession::PlaybackSession( mNumRTPSent(0), mNumRTPOctetsSent(0), mNumSRsSent(0), - mSendSRPending(false), - mHistoryLength(0) + mSendSRPending(false) +#if ENABLE_RETRANSMISSION + ,mHistoryLength(0) +#endif #if TRACK_BANDWIDTH ,mFirstPacketTimeUs(-1ll) ,mTotalBytesSent(0ll) @@ -807,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"); @@ -869,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); @@ -885,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; @@ -908,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"); @@ -1126,7 +1166,9 @@ ssize_t WifiDisplaySource::PlaybackSession::appendTSData( #endif } +#if ENABLE_RETRANSMISSION mTSQueue->setInt32Data(mRTPSeqNo - 1); + mHistory.push_back(mTSQueue); ++mHistoryLength; @@ -1138,6 +1180,7 @@ ssize_t WifiDisplaySource::PlaybackSession::appendTSData( } else { mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188); } +#endif mTSQueue->setRange(0, 12); } @@ -1295,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(); } } @@ -1321,7 +1364,7 @@ bool WifiDisplaySource::PlaybackSession::allTracksHavePacketizerIndex() { } status_t WifiDisplaySource::PlaybackSession::packetizeAccessUnit( - size_t trackIndex, sp<ABuffer> accessUnit) { + size_t trackIndex, const sp<ABuffer> &accessUnit) { const sp<Track> &track = mTracks.valueFor(trackIndex); uint32_t flags = 0; @@ -1332,12 +1375,6 @@ status_t WifiDisplaySource::PlaybackSession::packetizeAccessUnit( if (mHDCP != NULL && !track->isAudio()) { isHDCPEncrypted = true; - if (IsIDR(accessUnit)) { - // XXX remove this once the encoder takes care of this. - accessUnit = mPacketizer->prependCSD( - track->packetizerTrackIndex(), accessUnit); - } - status_t err = mHDCP->encrypt( accessUnit->data(), accessUnit->size(), trackIndex /* streamCTR */, diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index 8d88648..5d4bde8 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -161,8 +161,10 @@ private: bool mSendSRPending; +#if ENABLE_RETRANSMISSION List<sp<ABuffer> > mHistory; size_t mHistoryLength; +#endif #if TRACK_BANDWIDTH int64_t mFirstPacketTimeUs; @@ -183,6 +185,7 @@ private: status_t addSource( bool isVideo, const sp<MediaSource> &source, + bool isRepeaterSource, size_t *numInputBuffers); status_t addVideoSource(); @@ -206,7 +209,7 @@ private: bool allTracksHavePacketizerIndex(); status_t packetizeAccessUnit( - size_t trackIndex, sp<ABuffer> accessUnit); + size_t trackIndex, const sp<ABuffer> &accessUnit); status_t packetizeQueuedAccessUnits(); 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/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp index dd18998..e5abd57 100644 --- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp +++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp @@ -294,12 +294,11 @@ status_t TSPacketizer::packetize( const sp<Track> &track = mTracks.itemAt(trackIndex); - if (track->isH264() && !(flags & IS_ENCRYPTED)) { - if (IsIDR(accessUnit)) { - // prepend codec specific data, i.e. SPS and PPS. - accessUnit = track->prependCSD(accessUnit); - } - } else if (track->lacksADTSHeader()) { + if (track->isH264() && (flags & PREPEND_SPS_PPS_TO_IDR_FRAMES) + && IsIDR(accessUnit)) { + // prepend codec specific data, i.e. SPS and PPS. + accessUnit = track->prependCSD(accessUnit); + } else if (track->isAudio() && track->lacksADTSHeader()) { CHECK(!(flags & IS_ENCRYPTED)); accessUnit = track->prependADTSHeader(accessUnit); } diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.h b/media/libstagefright/wifi-display/source/TSPacketizer.h index 01f174a..0733c06 100644 --- a/media/libstagefright/wifi-display/source/TSPacketizer.h +++ b/media/libstagefright/wifi-display/source/TSPacketizer.h @@ -38,9 +38,10 @@ struct TSPacketizer : public RefBase { ssize_t addTrack(const sp<AMessage> &format); enum { - EMIT_PAT_AND_PMT = 1, - EMIT_PCR = 2, - IS_ENCRYPTED = 4, + EMIT_PAT_AND_PMT = 1, + EMIT_PCR = 2, + IS_ENCRYPTED = 4, + PREPEND_SPS_PPS_TO_IDR_FRAMES = 8, }; status_t packetize( size_t trackIndex, const sp<ABuffer> &accessUnit, 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", |