summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/wifi-display/source/Converter.cpp84
-rw-r--r--media/libstagefright/wifi-display/source/Converter.h9
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp63
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h5
-rw-r--r--media/libstagefright/wifi-display/source/RepeaterSource.cpp80
-rw-r--r--media/libstagefright/wifi-display/source/RepeaterSource.h5
-rw-r--r--media/libstagefright/wifi-display/source/TSPacketizer.cpp11
-rw-r--r--media/libstagefright/wifi-display/source/TSPacketizer.h7
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp2
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",