summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioSystem.h1
-rw-r--r--include/media/IAudioPolicyService.h1
-rw-r--r--media/libmedia/AudioSystem.cpp7
-rw-r--r--media/libmedia/IAudioPolicyService.cpp20
-rw-r--r--media/libstagefright/AwesomePlayer.cpp218
-rw-r--r--media/libstagefright/include/AwesomePlayer.h9
-rw-r--r--media/libstagefright/rtsp/ARTPAssembler.cpp4
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp38
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.h5
-rw-r--r--media/libstagefright/rtsp/ARTPSession.cpp4
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp51
-rw-r--r--media/libstagefright/rtsp/ARTPSource.h10
-rw-r--r--media/libstagefright/rtsp/Android.mk4
-rw-r--r--media/libstagefright/rtsp/MyHandler.h216
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp14
-rw-r--r--services/audioflinger/AudioPolicyService.cpp8
-rw-r--r--services/audioflinger/AudioPolicyService.h1
17 files changed, 294 insertions, 317 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 03f8944..2dc4beb 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -392,6 +392,7 @@ public:
static status_t getStreamVolumeIndex(stream_type stream, int *index);
static uint32_t getStrategyForStream(stream_type stream);
+ static uint32_t getDevicesForStream(stream_type stream);
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
static status_t registerEffect(effect_descriptor_t *desc,
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 5afceaa..720a562 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -74,6 +74,7 @@ public:
virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0;
virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0;
virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0;
+ virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream) = 0;
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
virtual status_t registerEffect(effect_descriptor_t *desc,
audio_io_handle_t output,
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 9d9b3c0..2f694ba 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -668,6 +668,13 @@ uint32_t AudioSystem::getStrategyForStream(AudioSystem::stream_type stream)
return aps->getStrategyForStream(stream);
}
+uint32_t AudioSystem::getDevicesForStream(AudioSystem::stream_type stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ return aps->getDevicesForStream(stream);
+}
+
audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 457f7ed..b89a278 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -49,7 +49,8 @@ enum {
GET_OUTPUT_FOR_EFFECT,
REGISTER_EFFECT,
UNREGISTER_EFFECT,
- IS_STREAM_ACTIVE
+ IS_STREAM_ACTIVE,
+ GET_DEVICES_FOR_STREAM,
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -263,6 +264,15 @@ public:
return reply.readInt32();
}
+ virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply);
+ return (uint32_t) reply.readInt32();
+ }
+
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
{
Parcel data, reply;
@@ -495,6 +505,14 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
+ case GET_DEVICES_FOR_STREAM: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
+ reply->writeInt32(static_cast <int>(getDevicesForStream(stream)));
+ return NO_ERROR;
+ } break;
+
case GET_OUTPUT_FOR_EFFECT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
effect_descriptor_t desc;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 2f5a202..e368848 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -27,11 +27,6 @@
#include "include/ThrottledSource.h"
#include "include/MPEG2TSExtractor.h"
-#include "ARTPSession.h"
-#include "APacketSource.h"
-#include "ASessionDescription.h"
-#include "UDPPusher.h"
-
#include <binder/IPCThreadState.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -58,6 +53,7 @@ namespace android {
static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
+static int64_t kHighWaterMarkRTSPUs = 4000000ll; // 4secs
static const size_t kLowWaterMarkBytes = 40000;
static const size_t kHighWaterMarkBytes = 200000;
@@ -463,10 +459,6 @@ void AwesomePlayer::reset_l() {
mLiveSession.clear();
}
- mRTPPusher.clear();
- mRTCPPusher.clear();
- mRTPSession.clear();
-
if (mVideoSource != NULL) {
mVideoSource->stop();
@@ -644,6 +636,9 @@ void AwesomePlayer::onBufferingUpdate() {
LOGV("cachedDurationUs = %.2f secs, eos=%d",
cachedDurationUs / 1E6, eos);
+ int64_t highWaterMarkUs =
+ (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
+
if ((mFlags & PLAYING) && !eos
&& (cachedDurationUs < kLowWaterMarkUs)) {
LOGI("cache is running low (%.2f secs) , pausing.",
@@ -652,7 +647,7 @@ void AwesomePlayer::onBufferingUpdate() {
pause_l();
ensureCacheIsFetching_l();
notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
- } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
+ } else if (eos || cachedDurationUs > highWaterMarkUs) {
if (mFlags & CACHE_UNDERRUN) {
LOGI("cache has filled up (%.2f secs), resuming.",
cachedDurationUs / 1E6);
@@ -799,34 +794,33 @@ status_t AwesomePlayer::play_l() {
mAudioPlayer = new AudioPlayer(mAudioSink, this);
mAudioPlayer->setSource(mAudioSource);
- // We've already started the MediaSource in order to enable
- // the prefetcher to read its data.
- status_t err = mAudioPlayer->start(
- true /* sourceAlreadyStarted */);
+ mTimeSource = mAudioPlayer;
- if (err != OK) {
- delete mAudioPlayer;
- mAudioPlayer = NULL;
+ deferredAudioSeek = true;
- mFlags &= ~(PLAYING | FIRST_FRAME);
+ mWatchForAudioSeekComplete = false;
+ mWatchForAudioEOS = true;
+ }
+ }
- if (mDecryptHandle != NULL) {
- mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
- Playback::STOP, 0);
- }
+ CHECK(!(mFlags & AUDIO_RUNNING));
- return err;
- }
+ if (mVideoSource == NULL) {
+ status_t err = startAudioPlayer_l();
- mTimeSource = mAudioPlayer;
+ if (err != OK) {
+ delete mAudioPlayer;
+ mAudioPlayer = NULL;
- deferredAudioSeek = true;
+ mFlags &= ~(PLAYING | FIRST_FRAME);
- mWatchForAudioSeekComplete = false;
- mWatchForAudioEOS = true;
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(
+ mDecryptHandle, Playback::STOP, 0);
+ }
+
+ return err;
}
- } else {
- mAudioPlayer->resume();
}
}
@@ -858,6 +852,36 @@ status_t AwesomePlayer::play_l() {
return OK;
}
+status_t AwesomePlayer::startAudioPlayer_l() {
+ CHECK(!(mFlags & AUDIO_RUNNING));
+
+ if (mAudioSource == NULL || mAudioPlayer == NULL) {
+ return OK;
+ }
+
+ if (!(mFlags & AUDIOPLAYER_STARTED)) {
+ mFlags |= AUDIOPLAYER_STARTED;
+
+ // We've already started the MediaSource in order to enable
+ // the prefetcher to read its data.
+ status_t err = mAudioPlayer->start(
+ true /* sourceAlreadyStarted */);
+
+ if (err != OK) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ return err;
+ }
+ } else {
+ mAudioPlayer->resume();
+ }
+
+ mFlags |= AUDIO_RUNNING;
+
+ mWatchForAudioEOS = true;
+
+ return OK;
+}
+
void AwesomePlayer::notifyVideoSize_l() {
sp<MetaData> meta = mVideoSource->getFormat();
@@ -959,7 +983,7 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
cancelPlayerEvents(true /* keepBufferingGoing */);
- if (mAudioPlayer != NULL) {
+ if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
if (at_eos) {
// If we played the audio stream to completion we
// want to make sure that all samples remaining in the audio
@@ -968,6 +992,8 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
} else {
mAudioPlayer->pause();
}
+
+ mFlags &= ~AUDIO_RUNNING;
}
mFlags &= ~PLAYING;
@@ -1200,9 +1226,7 @@ void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
// requested seek time instead.
mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
- mAudioPlayer->resume();
mWatchForAudioSeekComplete = true;
- mWatchForAudioEOS = true;
} else if (!mSeekNotificationSent) {
// If we're playing video only, report seek complete now,
// otherwise audio player will notify us later.
@@ -1246,8 +1270,10 @@ void AwesomePlayer::onVideoEvent() {
// locations, we'll "pause" the audio source, causing it to
// stop reading input data until a subsequent seek.
- if (mAudioPlayer != NULL) {
+ if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
mAudioPlayer->pause();
+
+ mFlags &= ~AUDIO_RUNNING;
}
mAudioSource->pause();
}
@@ -1317,6 +1343,14 @@ void AwesomePlayer::onVideoEvent() {
bool wasSeeking = mSeeking;
finishSeekIfNecessary(timeUs);
+ if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
+ status_t err = startAudioPlayer_l();
+ if (err != OK) {
+ LOGE("Startung the audio player failed w/ err %d", err);
+ return;
+ }
+ }
+
TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
if (mFlags & FIRST_FRAME) {
@@ -1331,10 +1365,8 @@ void AwesomePlayer::onVideoEvent() {
mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
}
- if (!wasSeeking && mRTPSession == NULL) {
+ if (!wasSeeking) {
// Let's display the first frame after seeking right away.
- // We'll completely ignore timestamps for gtalk videochat
- // and we'll play incoming video as fast as we get it.
int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
@@ -1594,118 +1626,6 @@ status_t AwesomePlayer::finishSetDataSource_l() {
->setLiveSession(mLiveSession);
return setDataSource_l(extractor);
- } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
- if (mLooper == NULL) {
- mLooper = new ALooper;
- mLooper->setName("gtalk rtp");
- mLooper->start(
- false /* runOnCallingThread */,
- false /* canCallJava */,
- PRIORITY_HIGHEST);
- }
-
- const char *startOfCodecString = &mUri.string()[13];
- const char *startOfSlash1 = strchr(startOfCodecString, '/');
- if (startOfSlash1 == NULL) {
- return BAD_VALUE;
- }
- const char *startOfWidthString = &startOfSlash1[1];
- const char *startOfSlash2 = strchr(startOfWidthString, '/');
- if (startOfSlash2 == NULL) {
- return BAD_VALUE;
- }
- const char *startOfHeightString = &startOfSlash2[1];
-
- String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
- String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
- String8 heightString(startOfHeightString);
-
-#if 0
- mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
- mLooper->registerHandler(mRTPPusher);
-
- mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
- mLooper->registerHandler(mRTCPPusher);
-#endif
-
- mRTPSession = new ARTPSession;
- mLooper->registerHandler(mRTPSession);
-
-#if 0
- // My AMR SDP
- static const char *raw =
- "v=0\r\n"
- "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
- "s=QuickTime\r\n"
- "t=0 0\r\n"
- "a=range:npt=0-315\r\n"
- "a=isma-compliance:2,2.0,2\r\n"
- "m=audio 5434 RTP/AVP 97\r\n"
- "c=IN IP4 127.0.0.1\r\n"
- "b=AS:30\r\n"
- "a=rtpmap:97 AMR/8000/1\r\n"
- "a=fmtp:97 octet-align\r\n";
-#elif 1
- String8 sdp;
- sdp.appendFormat(
- "v=0\r\n"
- "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
- "s=QuickTime\r\n"
- "t=0 0\r\n"
- "a=range:npt=0-315\r\n"
- "a=isma-compliance:2,2.0,2\r\n"
- "m=video 5434 RTP/AVP 97\r\n"
- "c=IN IP4 127.0.0.1\r\n"
- "b=AS:30\r\n"
- "a=rtpmap:97 %s/90000\r\n"
- "a=cliprect:0,0,%s,%s\r\n"
- "a=framesize:97 %s-%s\r\n",
-
- codecString.string(),
- heightString.string(), widthString.string(),
- widthString.string(), heightString.string()
- );
- const char *raw = sdp.string();
-
-#endif
-
- sp<ASessionDescription> desc = new ASessionDescription;
- CHECK(desc->setTo(raw, strlen(raw)));
-
- CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
-
- if (mRTPPusher != NULL) {
- mRTPPusher->start();
- }
-
- if (mRTCPPusher != NULL) {
- mRTCPPusher->start();
- }
-
- CHECK_EQ(mRTPSession->countTracks(), 1u);
- sp<MediaSource> source = mRTPSession->trackAt(0);
-
-#if 0
- bool eos;
- while (((APacketSource *)source.get())
- ->getQueuedDuration(&eos) < 5000000ll && !eos) {
- usleep(100000ll);
- }
-#endif
-
- const char *mime;
- CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
-
- if (!strncasecmp("video/", mime, 6)) {
- setVideoSource(source);
- } else {
- CHECK(!strncasecmp("audio/", mime, 6));
- setAudioSource(source);
- }
-
- mExtractorFlags = MediaExtractor::CAN_PAUSE;
-
- return OK;
} else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
if (mLooper == NULL) {
mLooper = new ALooper;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 3021359..797e5ca 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -39,8 +39,6 @@ struct NuCachedSource2;
struct ALooper;
struct ARTSPController;
-struct ARTPSession;
-struct UDPPusher;
class DrmManagerClinet;
class DecryptHandle;
@@ -123,6 +121,9 @@ private:
// We're triggering a single video event to display the first frame
// after the seekpoint.
SEEK_PREVIEW = 4096,
+
+ AUDIO_RUNNING = 8192,
+ AUDIOPLAYER_STARTED = 16384,
};
mutable Mutex mLock;
@@ -204,8 +205,6 @@ private:
sp<ALooper> mLooper;
sp<ARTSPController> mRTSPController;
- sp<ARTPSession> mRTPSession;
- sp<UDPPusher> mRTPPusher, mRTCPPusher;
sp<LiveSession> mLiveSession;
@@ -260,6 +259,8 @@ private:
void finishSeekIfNecessary(int64_t videoTimeUs);
void ensureCacheIsFetching_l();
+ status_t startAudioPlayer_l();
+
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
};
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index 9ba2b37..a897c10 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -65,13 +65,9 @@ void ARTPAssembler::onPacketReceived(const sp<ARTPSource> &source) {
// static
void ARTPAssembler::CopyTimes(const sp<ABuffer> &to, const sp<ABuffer> &from) {
- uint64_t ntpTime;
- CHECK(from->meta()->findInt64("ntp-time", (int64_t *)&ntpTime));
-
uint32_t rtpTime;
CHECK(from->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
- to->meta()->setInt64("ntp-time", ntpTime);
to->meta()->setInt32("rtp-time", rtpTime);
// Copy the seq number.
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 5a1ea5c..601f569 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -169,12 +169,6 @@ void ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
break;
}
- case kWhatFakeTimestamps:
- {
- onFakeTimestamps();
- break;
- }
-
default:
{
TRESPASS();
@@ -461,12 +455,6 @@ status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
buffer->setInt32Data(u16at(&data[2]));
buffer->setRange(payloadOffset, size - payloadOffset);
- if ((mFlags & kFakeTimestamps) && !source->timeEstablished()) {
- source->timeUpdate(rtpTime, 0);
- source->timeUpdate(rtpTime + 90000, 0x100000000ll);
- CHECK(source->timeEstablished());
- }
-
source->processRTPPacket(buffer);
return OK;
@@ -592,9 +580,7 @@ status_t ARTPConnection::parseSR(
sp<ARTPSource> source = findSource(s, id);
- if ((mFlags & kFakeTimestamps) == 0) {
- source->timeUpdate(rtpTime, ntpTime);
- }
+ source->timeUpdate(rtpTime, ntpTime);
return 0;
}
@@ -652,27 +638,5 @@ void ARTPConnection::onInjectPacket(const sp<AMessage> &msg) {
}
}
-void ARTPConnection::fakeTimestamps() {
- (new AMessage(kWhatFakeTimestamps, id()))->post();
-}
-
-void ARTPConnection::onFakeTimestamps() {
- List<StreamInfo>::iterator it = mStreams.begin();
- while (it != mStreams.end()) {
- StreamInfo &info = *it++;
-
- for (size_t j = 0; j < info.mSources.size(); ++j) {
- sp<ARTPSource> source = info.mSources.valueAt(j);
-
- if (!source->timeEstablished()) {
- source->timeUpdate(0, 0);
- source->timeUpdate(0 + 90000, 0x100000000ll);
-
- mFlags |= kFakeTimestamps;
- }
- }
- }
-}
-
} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index a17b382..edbcc35 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -29,7 +29,6 @@ struct ASessionDescription;
struct ARTPConnection : public AHandler {
enum Flags {
- kFakeTimestamps = 1,
kRegularlyRequestFIR = 2,
};
@@ -51,8 +50,6 @@ struct ARTPConnection : public AHandler {
static void MakePortPair(
int *rtpSocket, int *rtcpSocket, unsigned *rtpPort);
- void fakeTimestamps();
-
protected:
virtual ~ARTPConnection();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -63,7 +60,6 @@ private:
kWhatRemoveStream,
kWhatPollStreams,
kWhatInjectPacket,
- kWhatFakeTimestamps,
};
static const int64_t kSelectTimeoutUs;
@@ -81,7 +77,6 @@ private:
void onPollStreams();
void onInjectPacket(const sp<AMessage> &msg);
void onSendReceiverReports();
- void onFakeTimestamps();
status_t receive(StreamInfo *info, bool receiveRTP);
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index 39c6619..c6bcb12 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -44,9 +44,7 @@ status_t ARTPSession::setup(const sp<ASessionDescription> &desc) {
mDesc = desc;
- mRTPConn = new ARTPConnection(
- ARTPConnection::kFakeTimestamps
- | ARTPConnection::kRegularlyRequestFIR);
+ mRTPConn = new ARTPConnection(ARTPConnection::kRegularlyRequestFIR);
looper()->registerHandler(mRTPConn);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 5aae4e7..893a387 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -42,12 +42,12 @@ ARTPSource::ARTPSource(
: mID(id),
mHighestSeqNumber(0),
mNumBuffersReceived(0),
- mNumTimes(0),
mLastNTPTime(0),
mLastNTPTimeUpdateUs(0),
mIssueFIRRequests(false),
mLastFIRRequestUs(-1),
- mNextFIRSeqNo((rand() * 256.0) / RAND_MAX) {
+ mNextFIRSeqNo((rand() * 256.0) / RAND_MAX),
+ mNotify(notify) {
unsigned long PT;
AString desc;
AString params;
@@ -80,52 +80,25 @@ static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) {
}
void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
- if (queuePacket(buffer)
- && mNumTimes == 2
- && mAssembler != NULL) {
+ if (queuePacket(buffer) && mAssembler != NULL) {
mAssembler->onPacketReceived(this);
}
}
void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
- LOGV("timeUpdate");
-
mLastNTPTime = ntpTime;
mLastNTPTimeUpdateUs = ALooper::GetNowUs();
- if (mNumTimes == 2) {
- mNTPTime[0] = mNTPTime[1];
- mRTPTime[0] = mRTPTime[1];
- mNumTimes = 1;
- }
- mNTPTime[mNumTimes] = ntpTime;
- mRTPTime[mNumTimes++] = rtpTime;
-
- if (timeEstablished()) {
- for (List<sp<ABuffer> >::iterator it = mQueue.begin();
- it != mQueue.end(); ++it) {
- sp<AMessage> meta = (*it)->meta();
-
- uint32_t rtpTime;
- CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
-
- meta->setInt64("ntp-time", RTP2NTP(rtpTime));
- }
- }
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("time-update", true);
+ notify->setInt32("rtp-time", rtpTime);
+ notify->setInt64("ntp-time", ntpTime);
+ notify->post();
}
bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
uint32_t seqNum = (uint32_t)buffer->int32Data();
- if (mNumTimes == 2) {
- sp<AMessage> meta = buffer->meta();
-
- uint32_t rtpTime;
- CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
-
- meta->setInt64("ntp-time", RTP2NTP(rtpTime));
- }
-
if (mNumBuffersReceived++ == 0) {
mHighestSeqNumber = seqNum;
mQueue.push_back(buffer);
@@ -180,14 +153,6 @@ bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
return true;
}
-uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
- CHECK_EQ(mNumTimes, 2u);
-
- return mNTPTime[0] + (double)(mNTPTime[1] - mNTPTime[0])
- * ((double)rtpTime - (double)mRTPTime[0])
- / (double)(mRTPTime[1] - mRTPTime[0]);
-}
-
void ARTPSource::byeReceived() {
mAssembler->onByeReceived();
}
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index e62c3f1..b70f94e 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -46,10 +46,6 @@ struct ARTPSource : public RefBase {
void addReceiverReport(const sp<ABuffer> &buffer);
void addFIR(const sp<ABuffer> &buffer);
- bool timeEstablished() const {
- return mNumTimes == 2;
- }
-
private:
uint32_t mID;
uint32_t mHighestSeqNumber;
@@ -58,10 +54,6 @@ private:
List<sp<ABuffer> > mQueue;
sp<ARTPAssembler> mAssembler;
- size_t mNumTimes;
- uint64_t mNTPTime[2];
- uint32_t mRTPTime[2];
-
uint64_t mLastNTPTime;
int64_t mLastNTPTimeUpdateUs;
@@ -69,7 +61,7 @@ private:
int64_t mLastFIRRequestUs;
uint8_t mNextFIRSeqNo;
- uint64_t RTP2NTP(uint32_t rtpTime) const;
+ sp<AMessage> mNotify;
bool queuePacket(const sp<ABuffer> &buffer);
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index 0bbadc1..fb42de8 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -11,13 +11,11 @@ LOCAL_SRC_FILES:= \
APacketSource.cpp \
ARTPAssembler.cpp \
ARTPConnection.cpp \
- ARTPSession.cpp \
ARTPSource.cpp \
ARTPWriter.cpp \
ARTSPConnection.cpp \
ARTSPController.cpp \
ASessionDescription.cpp \
- UDPPusher.cpp \
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
@@ -57,4 +55,4 @@ LOCAL_MODULE_TAGS := debug
LOCAL_MODULE:= rtp_test
-include $(BUILD_EXECUTABLE)
+# include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 306a9c1..ba7c1b2 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -39,9 +39,9 @@
#include <arpa/inet.h>
#include <sys/socket.h>
-// If no access units are received within 3 secs, assume that the rtp
+// If no access units are received within 5 secs, assume that the rtp
// stream has ended and signal end of stream.
-static int64_t kAccessUnitTimeoutUs = 3000000ll;
+static int64_t kAccessUnitTimeoutUs = 5000000ll;
// If no access units arrive for the first 10 secs after starting the
// stream, assume none ever will and signal EOS or switch transports.
@@ -101,7 +101,9 @@ struct MyHandler : public AHandler {
mSetupTracksSuccessful(false),
mSeekPending(false),
mFirstAccessUnit(true),
- mFirstAccessUnitNTP(0),
+ mNTPAnchorUs(-1),
+ mMediaAnchorUs(-1),
+ mLastMediaTimeUs(0),
mNumAccessUnitsReceived(0),
mCheckPending(false),
mCheckGeneration(0),
@@ -551,7 +553,8 @@ struct MyHandler : public AHandler {
mSetupTracksSuccessful = false;
mSeekPending = false;
mFirstAccessUnit = true;
- mFirstAccessUnitNTP = 0;
+ mNTPAnchorUs = -1;
+ mMediaAnchorUs = -1;
mNumAccessUnitsReceived = 0;
mReceivedFirstRTCPPacket = false;
mReceivedFirstRTPPacket = false;
@@ -632,6 +635,20 @@ struct MyHandler : public AHandler {
case 'accu':
{
+ int32_t timeUpdate;
+ if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ uint32_t rtpTime;
+ uint64_t ntpTime;
+ CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime));
+ CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime));
+
+ onTimeUpdate(trackIndex, rtpTime, ntpTime);
+ break;
+ }
+
int32_t first;
if (msg->findInt32("first-rtcp", &first)) {
mReceivedFirstRTCPPacket = true;
@@ -683,51 +700,11 @@ struct MyHandler : public AHandler {
break;
}
- uint64_t ntpTime;
- CHECK(accessUnit->meta()->findInt64(
- "ntp-time", (int64_t *)&ntpTime));
-
- uint32_t rtpTime;
- CHECK(accessUnit->meta()->findInt32(
- "rtp-time", (int32_t *)&rtpTime));
-
if (track->mNewSegment) {
track->mNewSegment = false;
-
- LOGV("first segment unit ntpTime=0x%016llx rtpTime=%u seq=%d",
- ntpTime, rtpTime, seqNum);
}
- if (mFirstAccessUnit) {
- mDoneMsg->setInt32("result", OK);
- mDoneMsg->post();
- mDoneMsg = NULL;
-
- mFirstAccessUnit = false;
- mFirstAccessUnitNTP = ntpTime;
- }
-
- if (ntpTime >= mFirstAccessUnitNTP) {
- ntpTime -= mFirstAccessUnitNTP;
- } else {
- ntpTime = 0;
- }
-
- int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
-
- accessUnit->meta()->setInt64("timeUs", timeUs);
-
-#if 0
- int32_t damaged;
- if (accessUnit->meta()->findInt32("damaged", &damaged)
- && damaged != 0) {
- LOGI("ignoring damaged AU");
- } else
-#endif
- {
- TrackInfo *track = &mTracks.editItemAt(trackIndex);
- track->mPacketSource->queueAccessUnit(accessUnit);
- }
+ onAccessUnitComplete(trackIndex, accessUnit);
break;
}
@@ -778,9 +755,15 @@ struct MyHandler : public AHandler {
{
// Session is paused now.
for (size_t i = 0; i < mTracks.size(); ++i) {
- mTracks.editItemAt(i).mPacketSource->flushQueue();
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ info->mPacketSource->flushQueue();
+ info->mRTPAnchor = 0;
+ info->mNTPAnchorUs = -1;
}
+ mNTPAnchorUs = -1;
+
int64_t timeUs;
CHECK(msg->findInt64("time", &timeUs));
@@ -831,6 +814,11 @@ struct MyHandler : public AHandler {
} else {
parsePlayResponse(response);
+ ssize_t i = response->mHeaders.indexOfKey("rtp-info");
+ CHECK_GE(i, 0);
+
+ LOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str());
+
LOGI("seek completed.");
}
}
@@ -875,7 +863,6 @@ struct MyHandler : public AHandler {
mTryFakeRTCP = true;
mReceivedFirstRTCPPacket = true;
- mRTPConn->fakeTimestamps();
} else {
LOGW("Never received any data, switching transports.");
@@ -980,7 +967,7 @@ struct MyHandler : public AHandler {
uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
- LOGV("track #%d: rtpTime=%u <=> ntp=%.2f", n, rtpTime, npt1);
+ LOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1);
info->mPacketSource->setNormalPlayTimeMapping(
rtpTime, (int64_t)(npt1 * 1E6));
@@ -1003,6 +990,25 @@ struct MyHandler : public AHandler {
}
private:
+ struct TrackInfo {
+ AString mURL;
+ int mRTPSocket;
+ int mRTCPSocket;
+ bool mUsingInterleavedTCP;
+ uint32_t mFirstSeqNumInSegment;
+ bool mNewSegment;
+
+ uint32_t mRTPAnchor;
+ int64_t mNTPAnchorUs;
+ int32_t mTimeScale;
+
+ sp<APacketSource> mPacketSource;
+
+ // Stores packets temporarily while no notion of time
+ // has been established yet.
+ List<sp<ABuffer> > mPackets;
+ };
+
sp<ALooper> mLooper;
sp<ALooper> mNetLooper;
sp<ARTSPConnection> mConn;
@@ -1015,7 +1021,11 @@ private:
bool mSetupTracksSuccessful;
bool mSeekPending;
bool mFirstAccessUnit;
- uint64_t mFirstAccessUnitNTP;
+
+ int64_t mNTPAnchorUs;
+ int64_t mMediaAnchorUs;
+ int64_t mLastMediaTimeUs;
+
int64_t mNumAccessUnitsReceived;
bool mCheckPending;
int32_t mCheckGeneration;
@@ -1025,16 +1035,6 @@ private:
bool mReceivedFirstRTPPacket;
bool mSeekable;
- struct TrackInfo {
- AString mURL;
- int mRTPSocket;
- int mRTCPSocket;
- bool mUsingInterleavedTCP;
- uint32_t mFirstSeqNumInSegment;
- bool mNewSegment;
-
- sp<APacketSource> mPacketSource;
- };
Vector<TrackInfo> mTracks;
sp<AMessage> mDoneMsg;
@@ -1066,6 +1066,20 @@ private:
info->mUsingInterleavedTCP = false;
info->mFirstSeqNumInSegment = 0;
info->mNewSegment = true;
+ info->mRTPAnchor = 0;
+ info->mNTPAnchorUs = -1;
+
+ unsigned long PT;
+ AString formatDesc;
+ AString formatParams;
+ mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams);
+
+ int32_t timescale;
+ int32_t numChannels;
+ ASessionDescription::ParseFormatDesc(
+ formatDesc.c_str(), &timescale, &numChannels);
+
+ info->mTimeScale = timescale;
LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str());
@@ -1144,6 +1158,90 @@ private:
return true;
}
+ void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
+ LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx",
+ trackIndex, rtpTime, ntpTime);
+
+ int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ track->mRTPAnchor = rtpTime;
+ track->mNTPAnchorUs = ntpTimeUs;
+
+ if (mNTPAnchorUs < 0) {
+ mNTPAnchorUs = ntpTimeUs;
+ mMediaAnchorUs = mLastMediaTimeUs;
+ }
+ }
+
+ void onAccessUnitComplete(
+ int32_t trackIndex, const sp<ABuffer> &accessUnit) {
+ LOGV("onAccessUnitComplete track %d", trackIndex);
+
+ if (mFirstAccessUnit) {
+ mDoneMsg->setInt32("result", OK);
+ mDoneMsg->post();
+ mDoneMsg = NULL;
+
+ mFirstAccessUnit = false;
+ }
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ if (mNTPAnchorUs < 0 || mMediaAnchorUs < 0 || track->mNTPAnchorUs < 0) {
+ LOGV("storing accessUnit, no time established yet");
+ track->mPackets.push_back(accessUnit);
+ return;
+ }
+
+ while (!track->mPackets.empty()) {
+ sp<ABuffer> accessUnit = *track->mPackets.begin();
+ track->mPackets.erase(track->mPackets.begin());
+
+ if (addMediaTimestamp(trackIndex, track, accessUnit)) {
+ track->mPacketSource->queueAccessUnit(accessUnit);
+ }
+ }
+
+ if (addMediaTimestamp(trackIndex, track, accessUnit)) {
+ track->mPacketSource->queueAccessUnit(accessUnit);
+ }
+ }
+
+ bool addMediaTimestamp(
+ int32_t trackIndex, const TrackInfo *track,
+ const sp<ABuffer> &accessUnit) {
+ uint32_t rtpTime;
+ CHECK(accessUnit->meta()->findInt32(
+ "rtp-time", (int32_t *)&rtpTime));
+
+ int64_t relRtpTimeUs =
+ (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll)
+ / track->mTimeScale;
+
+ int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs;
+
+ int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs;
+
+ if (mediaTimeUs > mLastMediaTimeUs) {
+ mLastMediaTimeUs = mediaTimeUs;
+ }
+
+ if (mediaTimeUs < 0) {
+ LOGV("dropping early accessUnit.");
+ return false;
+ }
+
+ LOGV("track %d rtpTime=%d mediaTimeUs = %lld us (%.2f secs)",
+ trackIndex, rtpTime, mediaTimeUs, mediaTimeUs / 1E6);
+
+ accessUnit->meta()->setInt64("timeUs", mediaTimeUs);
+
+ return true;
+ }
+
+
DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
};
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index a9e8bc0..6a82a59 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -1543,6 +1543,20 @@ uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type s
return (uint32_t)getStrategy(stream);
}
+uint32_t AudioPolicyManagerBase::getDevicesForStream(AudioSystem::stream_type stream) {
+ uint32_t devices;
+ // By checking the range of stream before calling getStrategy, we avoid
+ // getStrategy's behavior for invalid streams. getStrategy would do a LOGE
+ // and then return STRATEGY_MEDIA, but we want to return the empty set.
+ if (stream < (AudioSystem::stream_type) 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+ devices = 0;
+ } else {
+ AudioPolicyManagerBase::routing_strategy strategy = getStrategy(stream);
+ devices = getDeviceForStrategy(strategy, true);
+ }
+ return devices;
+}
+
AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
AudioSystem::stream_type stream) {
// stream to strategy mapping
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 953ddac..b614c48 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -365,6 +365,14 @@ uint32_t AudioPolicyService::getStrategyForStream(AudioSystem::stream_type strea
return mpPolicyManager->getStrategyForStream(stream);
}
+uint32_t AudioPolicyService::getDevicesForStream(AudioSystem::stream_type stream)
+{
+ if (mpPolicyManager == NULL) {
+ return 0;
+ }
+ return mpPolicyManager->getDevicesForStream(stream);
+}
+
audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
{
if (mpPolicyManager == NULL) {
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 4749b8b..faad893 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -86,6 +86,7 @@ public:
virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream);
+ virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream);
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
virtual status_t registerEffect(effect_descriptor_t *desc,