summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/source
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2013-03-18 11:09:22 -0700
committerAndreas Huber <andih@google.com>2013-03-18 11:09:22 -0700
commit0b530f1050150bb751ae642d5a9dce34141d9475 (patch)
tree1e6efc9562c2f80f1acdce8883fa1116c4509cd9 /media/libstagefright/wifi-display/source
parent7d02488e0af9f21f5f15abcbd8dd8746606a124c (diff)
downloadframeworks_av-0b530f1050150bb751ae642d5a9dce34141d9475.zip
frameworks_av-0b530f1050150bb751ae642d5a9dce34141d9475.tar.gz
frameworks_av-0b530f1050150bb751ae642d5a9dce34141d9475.tar.bz2
Allow for streaming of media files (without recompression)
Change-Id: I1de356cc37506ba986822d12a1a59e7b64069e02
Diffstat (limited to 'media/libstagefright/wifi-display/source')
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp196
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h18
-rw-r--r--media/libstagefright/wifi-display/source/TSPacketizer.cpp2
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp36
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.h8
5 files changed, 239 insertions, 21 deletions
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 94cb2a4..a3b6542 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -39,6 +39,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/NuMediaExtractor.h>
#include <media/stagefright/SurfaceMediaSource.h>
#include <media/stagefright/Utils.h>
@@ -57,6 +58,8 @@ struct WifiDisplaySource::PlaybackSession::Track : public AHandler {
const sp<MediaPuller> &mediaPuller,
const sp<Converter> &converter);
+ Track(const sp<AMessage> &notify, const sp<AMessage> &format);
+
void setRepeaterSource(const sp<RepeaterSource> &source);
sp<AMessage> getFormat();
@@ -104,6 +107,7 @@ private:
sp<ALooper> mCodecLooper;
sp<MediaPuller> mMediaPuller;
sp<Converter> mConverter;
+ sp<AMessage> mFormat;
bool mStarted;
ssize_t mMediaSenderTrackIndex;
bool mIsAudio;
@@ -133,6 +137,15 @@ WifiDisplaySource::PlaybackSession::Track::Track(
mLastOutputBufferQueuedTimeUs(-1ll) {
}
+WifiDisplaySource::PlaybackSession::Track::Track(
+ const sp<AMessage> &notify, const sp<AMessage> &format)
+ : mNotify(notify),
+ mFormat(format),
+ mStarted(false),
+ mIsAudio(IsAudioFormat(format)),
+ mLastOutputBufferQueuedTimeUs(-1ll) {
+}
+
WifiDisplaySource::PlaybackSession::Track::~Track() {
CHECK(!mStarted);
}
@@ -147,7 +160,7 @@ bool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat(
}
sp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
- return mConverter->getOutputFormat();
+ return mFormat != NULL ? mFormat : mConverter->getOutputFormat();
}
bool WifiDisplaySource::PlaybackSession::Track::isAudio() const {
@@ -189,7 +202,9 @@ status_t WifiDisplaySource::PlaybackSession::Track::start() {
void WifiDisplaySource::PlaybackSession::Track::stopAsync() {
ALOGV("Track::stopAsync isAudio=%d", mIsAudio);
- mConverter->shutdownAsync();
+ if (mConverter != NULL) {
+ mConverter->shutdownAsync();
+ }
sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id());
@@ -201,6 +216,7 @@ void WifiDisplaySource::PlaybackSession::Track::stopAsync() {
mMediaPuller->stopAsync(msg);
} else {
+ mStarted = false;
msg->post();
}
}
@@ -324,7 +340,8 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
const sp<ANetworkSession> &netSession,
const sp<AMessage> &notify,
const in_addr &interfaceAddr,
- const sp<IHDCP> &hdcp)
+ const sp<IHDCP> &hdcp,
+ const char *path)
: mNetSession(netSession),
mNotify(notify),
mInterfaceAddr(interfaceAddr),
@@ -334,7 +351,14 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
mPaused(false),
mLastLifesignUs(),
mVideoTrackIndex(-1),
- mPrevTimeUs(-1ll) {
+ mPrevTimeUs(-1ll),
+ mPullExtractorPending(false),
+ mPullExtractorGeneration(0),
+ mFirstSampleTimeRealUs(-1ll),
+ mFirstSampleTimeUs(-1ll) {
+ if (path != NULL) {
+ mMediaPath.setTo(path);
+ }
}
status_t WifiDisplaySource::PlaybackSession::init(
@@ -405,10 +429,6 @@ status_t WifiDisplaySource::PlaybackSession::play() {
return OK;
}
-status_t WifiDisplaySource::PlaybackSession::finishPlay() {
- return OK;
-}
-
status_t WifiDisplaySource::PlaybackSession::onMediaSenderInitialized() {
for (size_t i = 0; i < mTracks.size(); ++i) {
CHECK_EQ((status_t)OK, mTracks.editValueAt(i)->start());
@@ -523,7 +543,10 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
const sp<Track> &videoTrack =
mTracks.valueFor(mVideoTrackIndex);
- videoTrack->converter()->dropAFrame();
+ sp<Converter> converter = videoTrack->converter();
+ if (converter != NULL) {
+ converter->dropAFrame();
+ }
}
} else {
TRESPASS();
@@ -564,6 +587,12 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
case kWhatPause:
{
+ if (mExtractor != NULL) {
+ ++mPullExtractorGeneration;
+ mFirstSampleTimeRealUs = -1ll;
+ mFirstSampleTimeUs = -1ll;
+ }
+
if (mPaused) {
break;
}
@@ -578,6 +607,10 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
case kWhatResume:
{
+ if (mExtractor != NULL) {
+ schedulePullExtractor();
+ }
+
if (!mPaused) {
break;
}
@@ -590,11 +623,152 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
break;
}
+ case kWhatPullExtractorSample:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mPullExtractorGeneration) {
+ break;
+ }
+
+ mPullExtractorPending = false;
+
+ onPullExtractor();
+ break;
+ }
+
default:
TRESPASS();
}
}
+status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer(
+ bool enableAudio, bool enableVideo) {
+ DataSource::RegisterDefaultSniffers();
+
+ mExtractor = new NuMediaExtractor;
+
+ status_t err = mExtractor->setDataSource(mMediaPath.c_str());
+
+ if (err != OK) {
+ return err;
+ }
+
+ size_t n = mExtractor->countTracks();
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < n; ++i) {
+ sp<AMessage> format;
+ err = mExtractor->getTrackFormat(i, &format);
+
+ if (err != OK) {
+ continue;
+ }
+
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
+ bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
+ bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
+
+ if (isAudio && enableAudio && !haveAudio) {
+ haveAudio = true;
+ } else if (isVideo && enableVideo && !haveVideo) {
+ haveVideo = true;
+ } else {
+ continue;
+ }
+
+ err = mExtractor->selectTrack(i);
+
+ size_t trackIndex = mTracks.size();
+
+ sp<AMessage> notify = new AMessage(kWhatTrackNotify, id());
+ notify->setSize("trackIndex", trackIndex);
+
+ sp<Track> track = new Track(notify, format);
+ looper()->registerHandler(track);
+
+ mTracks.add(trackIndex, track);
+
+ mExtractorTrackToInternalTrack.add(i, trackIndex);
+
+ if (isVideo) {
+ mVideoTrackIndex = trackIndex;
+ }
+
+ uint32_t flags = MediaSender::FLAG_MANUALLY_PREPEND_SPS_PPS;
+
+ ssize_t mediaSenderTrackIndex =
+ mMediaSender->addTrack(format, flags);
+ CHECK_GE(mediaSenderTrackIndex, 0);
+
+ track->setMediaSenderTrackIndex(mediaSenderTrackIndex);
+
+ if ((haveAudio || !enableAudio) && (haveVideo || !enableVideo)) {
+ break;
+ }
+ }
+
+ return OK;
+}
+
+void WifiDisplaySource::PlaybackSession::schedulePullExtractor() {
+ if (mPullExtractorPending) {
+ return;
+ }
+
+ int64_t sampleTimeUs;
+ status_t err = mExtractor->getSampleTime(&sampleTimeUs);
+
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mFirstSampleTimeRealUs < 0ll) {
+ mFirstSampleTimeRealUs = nowUs;
+ mFirstSampleTimeUs = sampleTimeUs;
+ }
+
+ int64_t whenUs = sampleTimeUs - mFirstSampleTimeUs + mFirstSampleTimeRealUs;
+
+ sp<AMessage> msg = new AMessage(kWhatPullExtractorSample, id());
+ msg->setInt32("generation", mPullExtractorGeneration);
+ msg->post(whenUs - nowUs);
+
+ mPullExtractorPending = true;
+}
+
+void WifiDisplaySource::PlaybackSession::onPullExtractor() {
+ sp<ABuffer> accessUnit = new ABuffer(1024 * 1024);
+ status_t err = mExtractor->readSampleData(accessUnit);
+ if (err != OK) {
+ // EOS.
+ return;
+ }
+
+ int64_t timeUs;
+ CHECK_EQ((status_t)OK, mExtractor->getSampleTime(&timeUs));
+
+ accessUnit->meta()->setInt64(
+ "timeUs", mFirstSampleTimeRealUs + timeUs - mFirstSampleTimeUs);
+
+ size_t trackIndex;
+ CHECK_EQ((status_t)OK, mExtractor->getSampleTrackIndex(&trackIndex));
+
+ sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
+
+ msg->setSize(
+ "trackIndex", mExtractorTrackToInternalTrack.valueFor(trackIndex));
+
+ msg->setInt32("what", Converter::kWhatAccessUnit);
+ msg->setBuffer("accessUnit", accessUnit);
+ msg->post();
+
+ mExtractor->advance();
+
+ schedulePullExtractor();
+}
+
status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
bool enableAudio,
bool usePCMAudio,
@@ -603,6 +777,10 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
size_t videoResolutionIndex) {
CHECK(enableAudio || enableVideo);
+ if (!mMediaPath.empty()) {
+ return setupMediaPacketizer(enableAudio, enableVideo);
+ }
+
if (enableVideo) {
status_t err = addVideoSource(
videoResolutionType, videoResolutionIndex);
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index cd6da85..da207e2 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -31,6 +31,7 @@ struct IGraphicBufferProducer;
struct MediaPuller;
struct MediaSource;
struct MediaSender;
+struct NuMediaExtractor;
// Encapsulates the state of an RTP/RTCP session in the context of wifi
// display.
@@ -39,7 +40,8 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
const sp<ANetworkSession> &netSession,
const sp<AMessage> &notify,
const struct in_addr &interfaceAddr,
- const sp<IHDCP> &hdcp);
+ const sp<IHDCP> &hdcp,
+ const char *path = NULL);
status_t init(
const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
@@ -87,12 +89,14 @@ private:
kWhatPause,
kWhatResume,
kWhatMediaSenderNotify,
+ kWhatPullExtractorSample,
};
sp<ANetworkSession> mNetSession;
sp<AMessage> mNotify;
in_addr mInterfaceAddr;
sp<IHDCP> mHDCP;
+ AString mMediaPath;
sp<MediaSender> mMediaSender;
int32_t mLocalRTPPort;
@@ -109,6 +113,15 @@ private:
int64_t mPrevTimeUs;
+ sp<NuMediaExtractor> mExtractor;
+ KeyedVector<size_t, size_t> mExtractorTrackToInternalTrack;
+ bool mPullExtractorPending;
+ int32_t mPullExtractorGeneration;
+ int64_t mFirstSampleTimeRealUs;
+ int64_t mFirstSampleTimeUs;
+
+ status_t setupMediaPacketizer(bool enableAudio, bool enableVideo);
+
status_t setupPacketizer(
bool enableAudio,
bool usePCMAudio,
@@ -133,6 +146,9 @@ private:
void notifySessionDead();
+ void schedulePullExtractor();
+ void onPullExtractor();
+
DISALLOW_EVIL_CONSTRUCTORS(PlaybackSession);
};
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
index 53b7187..d993764 100644
--- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp
+++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
@@ -261,7 +261,7 @@ void TSPacketizer::Track::finalize() {
data[0] = 40; // descriptor_tag
data[1] = 4; // descriptor_length
- CHECK_EQ(mCSD.size(), 1u);
+ CHECK_GE(mCSD.size(), 1u);
const sp<ABuffer> &sps = mCSD.itemAt(0);
CHECK(!memcmp("\x00\x00\x00\x01", sps->data(), 4));
CHECK_GE(sps->size(), 7u);
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index c8798c6..5167cb3 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -44,7 +44,8 @@ namespace android {
WifiDisplaySource::WifiDisplaySource(
const sp<ANetworkSession> &netSession,
- const sp<IRemoteDisplayClient> &client)
+ const sp<IRemoteDisplayClient> &client,
+ const char *path)
: mState(INITIALIZED),
mNetSession(netSession),
mClient(client),
@@ -59,7 +60,12 @@ WifiDisplaySource::WifiDisplaySource(
mIsHDCP2_0(false),
mHDCPPort(0),
mHDCPInitializationComplete(false),
- mSetupTriggerDeferred(false) {
+ mSetupTriggerDeferred(false),
+ mPlaybackSessionEstablished(false) {
+ if (path != NULL) {
+ mMediaPath.setTo(path);
+ }
+
mSupportedSourceVideoFormats.disableAll();
mSupportedSourceVideoFormats.setNativeResolution(
@@ -389,6 +395,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
mClient->onDisplayError(
IRemoteDisplayClient::kDisplayErrorUnknown);
} else if (what == PlaybackSession::kWhatSessionEstablished) {
+ mPlaybackSessionEstablished = true;
+
if (mClient != NULL) {
if (!mSinkSupportsVideo) {
mClient->onDisplayConnected(
@@ -419,6 +427,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
}
}
+ finishPlay();
+
if (mState == ABOUT_TO_PLAY) {
mState = PLAYING;
}
@@ -1222,7 +1232,7 @@ status_t WifiDisplaySource::onSetupRequest(
sp<PlaybackSession> playbackSession =
new PlaybackSession(
- mNetSession, notify, mInterfaceAddr, mHDCP);
+ mNetSession, notify, mInterfaceAddr, mHDCP, mMediaPath.c_str());
looper()->registerHandler(playbackSession);
@@ -1332,16 +1342,18 @@ status_t WifiDisplaySource::onPlayRequest(
}
ALOGI("Received PLAY request.");
-
- status_t err = playbackSession->play();
- CHECK_EQ(err, (status_t)OK);
+ if (mPlaybackSessionEstablished) {
+ finishPlay();
+ } else {
+ ALOGI("deferring PLAY request until session established.");
+ }
AString response = "RTSP/1.0 200 OK\r\n";
AppendCommonResponse(&response, cseq, playbackSessionID);
response.append("Range: npt=now-\r\n");
response.append("\r\n");
- err = mNetSession->sendRequest(sessionID, response.c_str());
+ status_t err = mNetSession->sendRequest(sessionID, response.c_str());
if (err != OK) {
return err;
@@ -1352,14 +1364,20 @@ status_t WifiDisplaySource::onPlayRequest(
return OK;
}
- playbackSession->finishPlay();
-
CHECK_EQ(mState, AWAITING_CLIENT_PLAY);
mState = ABOUT_TO_PLAY;
return OK;
}
+void WifiDisplaySource::finishPlay() {
+ const sp<PlaybackSession> &playbackSession =
+ mClientInfo.mPlaybackSession;
+
+ status_t err = playbackSession->play();
+ CHECK_EQ(err, (status_t)OK);
+}
+
status_t WifiDisplaySource::onPauseRequest(
int32_t sessionID,
int32_t cseq,
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 9e72682..3a1b0f9 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -39,7 +39,8 @@ struct WifiDisplaySource : public AHandler {
WifiDisplaySource(
const sp<ANetworkSession> &netSession,
- const sp<IRemoteDisplayClient> &client);
+ const sp<IRemoteDisplayClient> &client,
+ const char *path = NULL);
status_t start(const char *iface);
status_t stop();
@@ -116,6 +117,7 @@ private:
VideoFormats mSupportedSourceVideoFormats;
sp<ANetworkSession> mNetSession;
sp<IRemoteDisplayClient> mClient;
+ AString mMediaPath;
sp<TimeSyncer> mTimeSyncer;
struct in_addr mInterfaceAddr;
int32_t mSessionID;
@@ -161,6 +163,8 @@ private:
bool mHDCPInitializationComplete;
bool mSetupTriggerDeferred;
+ bool mPlaybackSessionEstablished;
+
status_t makeHDCP();
// <<<< HDCP specific section
@@ -257,6 +261,8 @@ private:
void finishStopAfterDisconnectingClient();
void finishStop2();
+ void finishPlay();
+
DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySource);
};