summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioTrack.h98
-rw-r--r--include/media/IAudioTrack.h10
-rw-r--r--include/private/media/AudioTrackShared.h4
-rw-r--r--media/libmedia/AudioTrack.cpp37
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp57
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.h6
-rw-r--r--media/libstagefright/foundation/ABitReader.cpp8
-rw-r--r--media/libstagefright/rtsp/AAMRAssembler.cpp16
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp24
-rw-r--r--media/libstagefright/rtsp/MyHandler.h14
-rw-r--r--media/mediaserver/main_mediaserver.cpp6
-rw-r--r--services/audioflinger/AudioFlinger.cpp56
-rw-r--r--services/audioflinger/AudioMixer.cpp101
-rw-r--r--services/audioflinger/AudioMixer.h4
-rw-r--r--services/audioflinger/AudioPolicyService.cpp1
-rw-r--r--services/audioflinger/AudioPolicyService.h3
16 files changed, 257 insertions, 188 deletions
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index cb3d833..b106042 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -75,15 +75,15 @@ public:
size_t size;
union {
void* raw;
- short* i16;
- int8_t* i8;
+ short* i16; // signed 16-bit
+ int8_t* i8; // unsigned 8-bit, offset by 0x80
};
};
/* As a convenience, if a callback is supplied, a handler thread
* is automatically created with the appropriate priority. This thread
- * invokes the callback when a new buffer becomes availlable or an underrun condition occurs.
+ * invokes the callback when a new buffer becomes available or an underrun condition occurs.
* Parameters:
*
* event: type of event notified (see enum AudioTrack::event_type).
@@ -94,8 +94,8 @@ public:
* written.
* - EVENT_UNDERRUN: unused.
* - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
- * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames.
- * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames.
+ * - EVENT_MARKER: pointer to an uint32_t containing the marker position in frames.
+ * - EVENT_NEW_POS: pointer to an uint32_t containing the new position in frames.
* - EVENT_BUFFER_END: unused.
*/
@@ -135,9 +135,10 @@ public:
* flags: Reserved for future use.
* cbf: Callback function. If not null, this function is called periodically
* to request new PCM data.
+ * user: Context for use by the callback receiver.
* notificationFrames: The callback function is called each time notificationFrames PCM
- * frames have been comsumed from track input buffer.
- * user Context for use by the callback receiver.
+ * frames have been consumed from track input buffer.
+ * sessionId: Specific session ID, or zero to use default.
*/
AudioTrack( int streamType,
@@ -152,11 +153,11 @@ public:
int sessionId = 0);
/* Creates an audio track and registers it with AudioFlinger. With this constructor,
- * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer
+ * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer
* identified by the argument sharedBuffer. This prototype is for static buffer playback.
- * PCM data must be present into memory before the AudioTrack is started.
- * The Write() and Flush() methods are not supported in this case.
- * It is recommented to pass a callback function to be notified of playback end by an
+ * PCM data must be present in memory before the AudioTrack is started.
+ * The write() and flush() methods are not supported in this case.
+ * It is recommended to pass a callback function to be notified of playback end by an
* EVENT_UNDERRUN event.
*/
@@ -172,15 +173,15 @@ public:
int sessionId = 0);
/* Terminates the AudioTrack and unregisters it from AudioFlinger.
- * Also destroys all resources assotiated with the AudioTrack.
+ * Also destroys all resources associated with the AudioTrack.
*/
~AudioTrack();
/* Initialize an uninitialized AudioTrack.
* Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful intialization
- * - INVALID_OPERATION: AudioTrack is already intitialized
+ * - NO_ERROR: successful initialization
+ * - INVALID_OPERATION: AudioTrack is already initialized
* - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
* - NO_INIT: audio server or audio hardware not initialized
* */
@@ -199,13 +200,13 @@ public:
/* Result of constructing the AudioTrack. This must be checked
- * before using any AudioTrack API (except for set()), using
+ * before using any AudioTrack API (except for set()), because using
* an uninitialized AudioTrack produces undefined results.
* See set() method above for possible return codes.
*/
status_t initCheck() const;
- /* Returns this track's latency in milliseconds.
+ /* Returns this track's estimated latency in milliseconds.
* This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
* and audio hardware driver.
*/
@@ -233,8 +234,8 @@ public:
void stop();
bool stopped() const;
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
+ /* Flush a stopped track. All pending buffers are discarded.
+ * This function has no effect if the track is not stopped.
*/
void flush();
@@ -244,26 +245,25 @@ public:
*/
void pause();
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
+ /* Mute or unmute this track.
+ * While muted, the callback, if set, is still called.
*/
void mute(bool);
bool muted() const;
-
- /* set volume for this track, mostly used for games' sound effects
- * left and right volumes. Levels must be <= 1.0.
+ /* Set volume for this track, mostly used for games' sound effects
+ * left and right volumes. Levels must be >= 0.0 and <= 1.0.
*/
status_t setVolume(float left, float right);
void getVolume(float* left, float* right);
- /* set the send level for this track. An auxiliary effect should be attached
- * to the track with attachEffect(). Level must be <= 1.0.
+ /* Set the send level for this track. An auxiliary effect should be attached
+ * to the track with attachEffect(). Level must be >= 0.0 and <= 1.0.
*/
status_t setAuxEffectSendLevel(float level);
void getAuxEffectSendLevel(float* level);
- /* set sample rate for this track, mostly used for games' sound effects
+ /* Set sample rate for this track, mostly used for games' sound effects
*/
status_t setSampleRate(int sampleRate);
uint32_t getSampleRate();
@@ -274,8 +274,8 @@ public:
*
* loopStart: loop start expressed as the number of PCM frames played since AudioTrack start.
* loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start.
- * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any pending or
- * active loop. loopCount = -1 means infinite looping.
+ * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any
+ * pending or active loop. loopCount = -1 means infinite looping.
*
* For proper operation the following condition must be respected:
* (loopEnd-loopStart) <= framecount()
@@ -283,10 +283,9 @@ public:
status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount);
-
- /* Sets marker position. When playback reaches the number of frames specified, a callback with event
- * type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker notification
- * callback.
+ /* Sets marker position. When playback reaches the number of frames specified, a callback with
+ * event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker
+ * notification callback.
* If the AudioTrack has been opened with no callback function associated, the operation will fail.
*
* Parameters:
@@ -301,10 +300,10 @@ public:
status_t getMarkerPosition(uint32_t *marker);
- /* Sets position update period. Every time the number of frames specified has been played,
- * a callback with event type EVENT_NEW_POS is called.
- * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
- * callback.
+ /* Sets position update period. Every time the number of frames specified has been played,
+ * a callback with event type EVENT_NEW_POS is called.
+ * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
+ * callback.
* If the AudioTrack has been opened with no callback function associated, the operation will fail.
*
* Parameters:
@@ -318,12 +317,11 @@ public:
status_t setPositionUpdatePeriod(uint32_t updatePeriod);
status_t getPositionUpdatePeriod(uint32_t *updatePeriod);
-
/* Sets playback head position within AudioTrack buffer. The new position is specified
- * in number of frames.
+ * in number of frames.
* This method must be called with the AudioTrack in paused or stopped state.
- * Note that the actual position set is <position> modulo the AudioTrack buffer size in frames.
- * Therefore using this method makes sense only when playing a "static" audio buffer
+ * Note that the actual position set is <position> modulo the AudioTrack buffer size in frames.
+ * Therefore using this method makes sense only when playing a "static" audio buffer
* as opposed to streaming.
* The getPosition() method on the other hand returns the total number of frames played since
* playback start.
@@ -335,12 +333,12 @@ public:
* Returned status (from utils/Errors.h) can be:
* - NO_ERROR: successful operation
* - INVALID_OPERATION: the AudioTrack is not stopped.
- * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer
+ * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer
*/
status_t setPosition(uint32_t position);
status_t getPosition(uint32_t *position);
- /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
+ /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
* rewriting the buffer before restarting playback after a stop.
* This method must be called with the AudioTrack in paused or stopped state.
*
@@ -350,7 +348,7 @@ public:
*/
status_t reload();
- /* returns a handle on the audio output used by this AudioTrack.
+ /* Returns a handle on the audio output used by this AudioTrack.
*
* Parameters:
* none.
@@ -360,18 +358,17 @@ public:
*/
audio_io_handle_t getOutput();
- /* returns the unique ID associated to this track.
+ /* Returns the unique session ID associated with this track.
*
* Parameters:
* none.
*
* Returned value:
- * AudioTrack ID.
+ * AudioTrack session ID.
*/
int getSessionId();
-
- /* Attach track auxiliary output to specified effect. Used effectId = 0
+ /* Attach track auxiliary output to specified effect. Use effectId = 0
* to detach track from effect.
*
* Parameters:
@@ -385,9 +382,9 @@ public:
*/
status_t attachAuxEffect(int effectId);
- /* obtains a buffer of "frameCount" frames. The buffer must be
+ /* Obtains a buffer of "frameCount" frames. The buffer must be
* filled entirely. If the track is stopped, obtainBuffer() returns
- * STOPPED instead of NO_ERROR as long as there are buffers availlable,
+ * STOPPED instead of NO_ERROR as long as there are buffers available,
* at which point NO_MORE_BUFFERS is returned.
* Buffers will be returned until the pool (buffercount())
* is exhausted, at which point obtainBuffer() will either block
@@ -403,10 +400,9 @@ public:
status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
void releaseBuffer(Buffer* audioBuffer);
-
/* As a convenience we provide a write() interface to the audio buffer.
* This is implemented on top of lockBuffer/unlockBuffer. For best
- * performance
+ * performance use callbacks. Return actual number of bytes written.
*
*/
ssize_t write(const void* buffer, size_t size);
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index 47d530b..3fa2bf8 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -46,13 +46,13 @@ public:
*/
virtual void stop() = 0;
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
+ /* Flush a stopped track. All pending buffers are discarded.
+ * This function has no effect if the track is not stopped.
*/
virtual void flush() = 0;
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
+ /* Mute or unmute this track.
+ * While muted, the callback, if set, is still called.
*/
virtual void mute(bool) = 0;
@@ -67,7 +67,7 @@ public:
*/
virtual status_t attachAuxEffect(int effectId) = 0;
- /* get this tracks control block */
+ /* get this track's control block */
virtual sp<IMemory> getCblk() const = 0;
};
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 20abd51..046d5e9 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -59,8 +59,8 @@ struct audio_track_cblk_t
// The data members are grouped so that members accessed frequently and in the same context
// are in the same line of data cache.
- Mutex lock;
- Condition cv;
+ Mutex lock; // sizeof(int)
+ Condition cv; // sizeof(int)
volatile uint32_t user;
volatile uint32_t server;
uint32_t userBase;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7e55fbd..6868d99 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1,4 +1,4 @@
-/* //device/extlibs/pv/android/AudioTrack.cpp
+/* frameworks/base/media/libmedia/AudioTrack.cpp
**
** Copyright 2007, The Android Open Source Project
**
@@ -477,7 +477,7 @@ bool AudioTrack::muted() const
status_t AudioTrack::setVolume(float left, float right)
{
- if (left > 1.0f || right > 1.0f) {
+ if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) {
return BAD_VALUE;
}
@@ -809,9 +809,7 @@ status_t AudioTrack::createTrack_l(
LOGE("Could not get control block");
return NO_INIT;
}
- mAudioTrack.clear();
mAudioTrack = track;
- mCblkMemory.clear();
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
@@ -1322,7 +1320,7 @@ audio_track_cblk_t::audio_track_cblk_t()
uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
{
- uint32_t u = this->user;
+ uint32_t u = user;
u += frameCount;
// Ensure that user is never ahead of server for AudioRecord
@@ -1331,16 +1329,16 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
}
- } else if (u > this->server) {
- LOGW("stepServer occured after track reset");
- u = this->server;
+ } else if (u > server) {
+ LOGW("stepServer occurred after track reset");
+ u = server;
}
if (u >= userBase + this->frameCount) {
userBase += this->frameCount;
}
- this->user = u;
+ user = u;
// Clear flow control error condition as new data has been written/read to/from buffer.
if (flags & CBLK_UNDERRUN_MSK) {
@@ -1357,7 +1355,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
return false;
}
- uint32_t s = this->server;
+ uint32_t s = server;
s += frameCount;
if (flags & CBLK_DIRECTION_MSK) {
@@ -1370,9 +1368,9 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
// while the mixer is processing a block: in this case,
// stepServer() is called After the flush() has reset u & s and
// we have s > u
- if (s > this->user) {
- LOGW("stepServer occured after track reset");
- s = this->user;
+ if (s > user) {
+ LOGW("stepServer occurred after track reset");
+ s = user;
}
}
@@ -1388,7 +1386,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
serverBase += this->frameCount;
}
- this->server = s;
+ server = s;
if (!(flags & CBLK_INVALID_MSK)) {
cv.signal();
@@ -1399,7 +1397,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
void* audio_track_cblk_t::buffer(uint32_t offset) const
{
- return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
+ return (int8_t *)buffers + (offset - userBase) * frameSize;
}
uint32_t audio_track_cblk_t::framesAvailable()
@@ -1410,8 +1408,8 @@ uint32_t audio_track_cblk_t::framesAvailable()
uint32_t audio_track_cblk_t::framesAvailable_l()
{
- uint32_t u = this->user;
- uint32_t s = this->server;
+ uint32_t u = user;
+ uint32_t s = server;
if (flags & CBLK_DIRECTION_MSK) {
uint32_t limit = (s < loopStart) ? s : loopStart;
@@ -1423,8 +1421,8 @@ uint32_t audio_track_cblk_t::framesAvailable_l()
uint32_t audio_track_cblk_t::framesReady()
{
- uint32_t u = this->user;
- uint32_t s = this->server;
+ uint32_t u = user;
+ uint32_t s = server;
if (flags & CBLK_DIRECTION_MSK) {
if (u < loopEnd) {
@@ -1469,4 +1467,3 @@ bool audio_track_cblk_t::tryLock()
// -------------------------------------------------------------------------
}; // namespace android
-
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e72adc4..6d28298 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -38,7 +38,8 @@ NuPlayer::RTSPSource::RTSPSource(
mFlags(0),
mState(DISCONNECTED),
mFinalResult(OK),
- mDisconnectReplyID(0) {
+ mDisconnectReplyID(0),
+ mSeekGeneration(0) {
if (headers) {
mExtraHeaders = *headers;
@@ -146,14 +147,21 @@ status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
}
status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
+ msg->setInt32("generation", ++mSeekGeneration);
+ msg->setInt64("timeUs", seekTimeUs);
+ msg->post(200000ll);
+
+ return OK;
+}
+
+void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
if (mState != CONNECTED) {
- return UNKNOWN_ERROR;
+ return;
}
mState = SEEKING;
mHandler->seek(seekTimeUs);
-
- return OK;
}
bool NuPlayer::RTSPSource::isSeekable() {
@@ -168,6 +176,20 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
mDisconnectReplyID = replyID;
finishDisconnectIfPossible();
return;
+ } else if (msg->what() == kWhatPerformSeek) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mSeekGeneration) {
+ // obsolete.
+ return;
+ }
+
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("timeUs", &seekTimeUs));
+
+ performSeek(seekTimeUs);
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -208,21 +230,32 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
break;
}
- const TrackInfo &info = mTracks.editItemAt(trackIndex);
- sp<AnotherPacketSource> source = info.mSource;
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+ sp<AnotherPacketSource> source = info->mSource;
if (source != NULL) {
-#if 1
uint32_t rtpTime;
CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ if (!info->mNPTMappingValid) {
+ // This is a live stream, we didn't receive any normal
+ // playtime mapping. Assume the first packets correspond
+ // to time 0.
+
+ ALOGV("This is a live stream, assuming time = 0");
+
+ info->mRTPTime = rtpTime;
+ info->mNormalPlaytimeUs = 0ll;
+ info->mNPTMappingValid = true;
+ }
+
int64_t nptUs =
- ((double)rtpTime - (double)info.mRTPTime)
- / info.mTimeScale
+ ((double)rtpTime - (double)info->mRTPTime)
+ / info->mTimeScale
* 1000000ll
- + info.mNormalPlaytimeUs;
+ + info->mNormalPlaytimeUs;
accessUnit->meta()->setInt64("timeUs", nptUs);
-#endif
source->queueAccessUnit(accessUnit);
}
@@ -278,6 +311,7 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
TrackInfo *info = &mTracks.editItemAt(trackIndex);
info->mRTPTime = rtpTime;
info->mNormalPlaytimeUs = nptUs;
+ info->mNPTMappingValid = true;
break;
}
@@ -305,6 +339,7 @@ void NuPlayer::RTSPSource::onConnected() {
info.mTimeScale = timeScale;
info.mRTPTime = 0;
info.mNormalPlaytimeUs = 0ll;
+ info.mNPTMappingValid = false;
if ((isAudio && mAudioTrack == NULL)
|| (isVideo && mVideoTrack == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 66eab72..59d06ad 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -56,6 +56,7 @@ private:
enum {
kWhatNotify = 'noti',
kWhatDisconnect = 'disc',
+ kWhatPerformSeek = 'seek',
};
enum State {
@@ -76,6 +77,7 @@ private:
int32_t mTimeScale;
uint32_t mRTPTime;
int64_t mNormalPlaytimeUs;
+ bool mNPTMappingValid;
};
AString mURL;
@@ -95,12 +97,16 @@ private:
sp<AnotherPacketSource> mAudioTrack;
sp<AnotherPacketSource> mVideoTrack;
+ int32_t mSeekGeneration;
+
sp<AnotherPacketSource> getSource(bool audio);
void onConnected();
void onDisconnected(const sp<AMessage> &msg);
void finishDisconnectIfPossible();
+ void performSeek(int64_t seekTimeUs);
+
DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
};
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index f07dd4f..5499c32 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -79,7 +79,13 @@ void ABitReader::skipBits(size_t n) {
}
void ABitReader::putBits(uint32_t x, size_t n) {
- CHECK_LE(mNumBitsLeft + n, 32u);
+ CHECK_LE(n, 32u);
+
+ while (mNumBitsLeft + n > 32) {
+ mNumBitsLeft -= 8;
+ --mData;
+ ++mSize;
+ }
mReservoir = (mReservoir >> n) | (x << (32 - n));
mNumBitsLeft += n;
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 547b202..9d72b1f 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -79,13 +79,17 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::assembleMore(
}
static size_t getFrameSize(bool isWide, unsigned FT) {
- static const size_t kFrameSizeNB[8] = {
- 95, 103, 118, 134, 148, 159, 204, 244
+ static const size_t kFrameSizeNB[9] = {
+ 95, 103, 118, 134, 148, 159, 204, 244, 39
};
- static const size_t kFrameSizeWB[9] = {
- 132, 177, 253, 285, 317, 365, 397, 461, 477
+ static const size_t kFrameSizeWB[10] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477, 40
};
+ if (FT == 15) {
+ return 1;
+ }
+
size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
// Round up bits to bytes and add 1 for the header byte.
@@ -161,8 +165,8 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
unsigned FT = (toc >> 3) & 0x0f;
if ((toc & 3) != 0
- || (mIsWide && FT > 8)
- || (!mIsWide && FT > 7)) {
+ || (mIsWide && FT > 9 && FT != 15)
+ || (!mIsWide && FT > 8 && FT != 15)) {
queue->erase(queue->begin());
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 0fbbb9e..d8107bc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -659,6 +659,7 @@ bool ARTSPConnection::receiveRTSPReponse() {
}
AString line;
+ ssize_t lastDictIndex = -1;
for (;;) {
if (!receiveLine(&line)) {
break;
@@ -668,7 +669,21 @@ bool ARTSPConnection::receiveRTSPReponse() {
break;
}
- ALOGV("line: %s", line.c_str());
+ ALOGV("line: '%s'", line.c_str());
+
+ if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
+ // Support for folded header values.
+
+ if (lastDictIndex < 0) {
+ // First line cannot be a continuation of the previous one.
+ return false;
+ }
+
+ AString &value = response->mHeaders.editValueAt(lastDictIndex);
+ value.append(line);
+
+ continue;
+ }
ssize_t colonPos = line.find(":");
if (colonPos < 0) {
@@ -681,9 +696,12 @@ bool ARTSPConnection::receiveRTSPReponse() {
key.tolower();
line.erase(0, colonPos + 1);
- line.trim();
- response->mHeaders.add(key, line);
+ lastDictIndex = response->mHeaders.add(key, line);
+ }
+
+ for (size_t i = 0; i < response->mHeaders.size(); ++i) {
+ response->mHeaders.editValueAt(i).trim();
}
unsigned long contentLength = 0;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index dd049c2..21ef298 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1100,6 +1100,8 @@ struct MyHandler : public AHandler {
float npt1, npt2;
if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
// This is a live stream and therefore not seekable.
+
+ LOGI("This is a live stream");
return;
}
@@ -1386,12 +1388,14 @@ private:
msg->setInt32("what", kWhatConnected);
msg->post();
- for (size_t i = 0; i < mTracks.size(); ++i) {
- TrackInfo *info = &mTracks.editItemAt(i);
+ if (mSeekable) {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
- postNormalPlayTimeMapping(
- i,
- info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ postNormalPlayTimeMapping(
+ i,
+ info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ }
}
mFirstAccessUnit = false;
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 7094cfa..b5f85f9 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -15,11 +15,6 @@
** limitations under the License.
*/
-// System headers required for setgroups, etc.
-#include <sys/types.h>
-#include <unistd.h>
-#include <grp.h>
-
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
@@ -29,7 +24,6 @@
#include <CameraService.h>
#include <MediaPlayerService.h>
#include <AudioPolicyService.h>
-#include <private/android_filesystem_config.h>
using namespace android;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b48f23d..fd82306 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -63,8 +63,8 @@
namespace android {
-static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
-static const char* kHardwareLockedString = "Hardware lock is taken\n";
+static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
+static const char kHardwareLockedString[] = "Hardware lock is taken\n";
//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
static const float MAX_GAIN = 4096.0f;
@@ -80,14 +80,16 @@ static const int8_t kMaxTrackStartupRetries = 50;
static const int8_t kMaxTrackRetriesDirect = 2;
static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 20000;
+static const int kDumpLockSleepUs = 20000;
-static const nsecs_t kWarningThrottle = seconds(5);
+// don't warn about blocked writes or record buffer overflows more often than this
+static const nsecs_t kWarningThrottleNs = seconds(5);
// RecordThread loop sleep time upon application overrun or audio HAL read error
static const int kRecordThreadSleepUs = 5000;
-static const nsecs_t kSetParametersTimeout = seconds(2);
+// maximum time to wait for setParameters to complete
+static const nsecs_t kSetParametersTimeoutNs = seconds(2);
// minimum sleep time for the mixer thread loop when tracks are active but in underrun
static const uint32_t kMinThreadSleepTimeUs = 5000;
@@ -147,7 +149,7 @@ out:
return rc;
}
-static const char *audio_interfaces[] = {
+static const char * const audio_interfaces[] = {
"primary",
"a2dp",
"usb",
@@ -320,7 +322,7 @@ static bool tryLock(Mutex& mutex)
locked = true;
break;
}
- usleep(kDumpLockSleep);
+ usleep(kDumpLockSleepUs);
}
return locked;
}
@@ -395,7 +397,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
int lSessionId;
if (streamType >= AUDIO_STREAM_CNT) {
- LOGE("invalid stream type");
+ LOGE("createTrack() invalid stream type %d", streamType);
lStatus = BAD_VALUE;
goto Exit;
}
@@ -427,6 +429,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
// prevent same audio session on different output threads
uint32_t sessions = t->hasAudioSession(*sessionId);
if (sessions & PlaybackThread::TRACK_SESSION) {
+ LOGE("createTrack() session ID %d already in use", *sessionId);
lStatus = BAD_VALUE;
goto Exit;
}
@@ -657,6 +660,7 @@ status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
}
if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ LOGE("setStreamVolume() invalid stream %d", stream);
return BAD_VALUE;
}
@@ -691,6 +695,7 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted)
if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
+ LOGE("setStreamMute() invalid stream %d", stream);
return BAD_VALUE;
}
@@ -988,7 +993,6 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int i
AudioFlinger::ThreadBase::~ThreadBase()
{
mParamCond.broadcast();
- mNewParameters.clear();
// do not lock the mutex in destructor
releaseWakeLock_l();
if (mPowerManager != 0) {
@@ -999,7 +1003,7 @@ AudioFlinger::ThreadBase::~ThreadBase()
void AudioFlinger::ThreadBase::exit()
{
- // keep a strong ref on ourself so that we wont get
+ // keep a strong ref on ourself so that we won't get
// destroyed in the middle of requestExitAndWait()
sp <ThreadBase> strongMe = this;
@@ -1044,7 +1048,7 @@ status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
mWaitWorkCV.signal();
// wait condition with timeout in case the thread loop has exited
// before the request could be processed
- if (mParamCond.waitRelative(mLock, kSetParametersTimeout) == NO_ERROR) {
+ if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
status = mParamStatus;
mWaitWorkCV.signal();
} else {
@@ -1526,8 +1530,10 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
for (size_t i = 0; i < mTracks.size(); ++i) {
sp<Track> t = mTracks[i];
if (t != 0) {
- if (sessionId == t->sessionId() &&
- strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
+ uint32_t actual = AudioSystem::getStrategyForStream((audio_stream_type_t)t->type());
+ if (sessionId == t->sessionId() && strategy != actual) {
+ LOGE("createTrack_l() mismatched strategy; expected %u but found %u",
+ strategy, actual);
lStatus = BAD_VALUE;
goto Exit;
}
@@ -1967,7 +1973,7 @@ bool AudioFlinger::MixerThread::threadLoop()
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
lockEffectChains_l(effectChains);
- }
+ }
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
// mix buffers...
@@ -2012,11 +2018,11 @@ bool AudioFlinger::MixerThread::threadLoop()
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
- for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
- }
- // enable changes in effect chain
- unlockEffectChains(effectChains);
+ for (size_t i = 0; i < effectChains.size(); i ++) {
+ effectChains[i]->process_l();
+ }
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
mLastWriteTime = systemTime();
mInWrite = true;
mBytesWritten += mixBufferSize;
@@ -2029,7 +2035,7 @@ bool AudioFlinger::MixerThread::threadLoop()
nsecs_t delta = now - mLastWriteTime;
if (!mStandby && delta > maxPeriod) {
mNumDelayedWrites++;
- if ((now - lastWarning) > kWarningThrottle) {
+ if ((now - lastWarning) > kWarningThrottleNs) {
LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
ns2ms(delta), mNumDelayedWrites, this);
lastWarning = now;
@@ -2344,7 +2350,7 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
// do not accept frame count changes if tracks are open as the track buffer
- // size depends on frame count and correct behavior would not be garantied
+ // size depends on frame count and correct behavior would not be guaranteed
// if frame count is changed after track creation
if (!mTracks.isEmpty()) {
status = INVALID_OPERATION;
@@ -2415,7 +2421,7 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
mParamCond.signal();
// wait for condition with time out in case the thread calling ThreadBase::setParameters()
// already timed out waiting for the status and will never signal the condition.
- mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
}
return reconfig;
}
@@ -2891,7 +2897,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
mParamCond.signal();
// wait for condition with time out in case the thread calling ThreadBase::setParameters()
// already timed out waiting for the status and will never signal the condition.
- mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
}
return reconfig;
}
@@ -4411,7 +4417,7 @@ bool AudioFlinger::RecordThread::threadLoop()
else {
if (!mActiveTrack->setOverflow()) {
nsecs_t now = systemTime();
- if ((now - lastWarning) > kWarningThrottle) {
+ if ((now - lastWarning) > kWarningThrottleNs) {
LOGW("RecordThread: buffer overflow");
lastWarning = now;
}
@@ -4734,7 +4740,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
mParamCond.signal();
// wait for condition with time out in case the thread calling ThreadBase::setParameters()
// already timed out waiting for the status and will never signal the condition.
- mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
}
return reconfig;
}
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 7c7fa56..847f8dc 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -58,10 +58,16 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
t->needs = 0;
t->volume[0] = UNITY_GAIN;
t->volume[1] = UNITY_GAIN;
+ // no initialization needed
+ // t->prevVolume[0]
+ // t->prevVolume[1]
t->volumeInc[0] = 0;
t->volumeInc[1] = 0;
t->auxLevel = 0;
t->auxInc = 0;
+ // no initialization needed
+ // t->prevAuxLevel
+ // t->frameCount
t->channelCount = 2;
t->enabled = 0;
t->format = 16;
@@ -78,19 +84,19 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
}
}
- AudioMixer::~AudioMixer()
- {
- track_t* t = mState.tracks;
- for (int i=0 ; i<32 ; i++) {
- delete t->resampler;
- t++;
- }
- delete [] mState.outputTemp;
- delete [] mState.resampleTemp;
- }
+AudioMixer::~AudioMixer()
+{
+ track_t* t = mState.tracks;
+ for (int i=0 ; i<32 ; i++) {
+ delete t->resampler;
+ t++;
+ }
+ delete [] mState.outputTemp;
+ delete [] mState.resampleTemp;
+}
- int AudioMixer::getTrackName()
- {
+int AudioMixer::getTrackName()
+{
uint32_t names = mTrackNames;
uint32_t mask = 1;
int n = 0;
@@ -104,18 +110,18 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
return TRACK0 + n;
}
return -1;
- }
+}
- void AudioMixer::invalidateState(uint32_t mask)
- {
+void AudioMixer::invalidateState(uint32_t mask)
+{
if (mask) {
mState.needsChanged |= mask;
mState.hook = process__validate;
}
}
- void AudioMixer::deleteTrackName(int name)
- {
+void AudioMixer::deleteTrackName(int name)
+{
name -= TRACK0;
if (uint32_t(name) < MAX_NUM_TRACKS) {
ALOGV("deleteTrackName(%d)", name);
@@ -135,7 +141,7 @@ AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
track.volumeInc[1] = 0;
mTrackNames &= ~(1<<name);
}
- }
+}
status_t AudioMixer::enable(int name)
{
@@ -450,33 +456,33 @@ void AudioMixer::process__validate(state_t* state)
countActiveTracks, state->enabledTracks,
all16BitsStereoNoResample, resampling, volumeRamp);
- state->hook(state);
-
- // Now that the volume ramp has been done, set optimal state and
- // track hooks for subsequent mixer process
- if (countActiveTracks) {
- int allMuted = 1;
- uint32_t en = state->enabledTracks;
- while (en) {
- const int i = 31 - __builtin_clz(en);
- en &= ~(1<<i);
- track_t& t = state->tracks[i];
- if (!t.doesResample() && t.volumeRL == 0)
- {
- t.needs |= NEEDS_MUTE_ENABLED;
- t.hook = track__nop;
- } else {
- allMuted = 0;
- }
- }
- if (allMuted) {
- state->hook = process__nop;
- } else if (all16BitsStereoNoResample) {
- if (countActiveTracks == 1) {
- state->hook = process__OneTrack16BitsStereoNoResampling;
- }
- }
- }
+ state->hook(state);
+
+ // Now that the volume ramp has been done, set optimal state and
+ // track hooks for subsequent mixer process
+ if (countActiveTracks) {
+ int allMuted = 1;
+ uint32_t en = state->enabledTracks;
+ while (en) {
+ const int i = 31 - __builtin_clz(en);
+ en &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ if (!t.doesResample() && t.volumeRL == 0)
+ {
+ t.needs |= NEEDS_MUTE_ENABLED;
+ t.hook = track__nop;
+ } else {
+ allMuted = 0;
+ }
+ }
+ if (allMuted) {
+ state->hook = process__nop;
+ } else if (all16BitsStereoNoResample) {
+ if (countActiveTracks == 1) {
+ state->hook = process__OneTrack16BitsStereoNoResampling;
+ }
+ }
+ }
}
static inline
@@ -993,7 +999,7 @@ void AudioMixer::process__genericNoResampling(state_t* state)
}
- // generic code with resampling
+// generic code with resampling
void AudioMixer::process__genericResampling(state_t* state)
{
int32_t* const outTemp = state->outputTemp;
@@ -1173,7 +1179,7 @@ void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
}
in1 = buff;
b1.frameCount = numFrames;
- } else {
+ } else {
in1 = b1.i16;
}
frameCount1 = b1.frameCount;
@@ -1215,4 +1221,3 @@ void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
// ----------------------------------------------------------------------------
}; // namespace android
-
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 75c9170..da9e2b5 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -65,10 +65,10 @@ public:
FORMAT = 0x4001,
MAIN_BUFFER = 0x4002,
AUX_BUFFER = 0x4003,
- // for TARGET RESAMPLE
+ // for target RESAMPLE
SAMPLE_RATE = 0x4100,
RESET = 0x4101,
- // for TARGET VOLUME (8 channels max)
+ // for target RAMP_VOLUME and VOLUME (8 channels max)
VOLUME0 = 0x4200,
VOLUME1 = 0x4201,
AUXLEVEL = 0x4210,
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 840d70d..bc4c90c 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -31,7 +31,6 @@
#include <utils/threads.h>
#include "AudioPolicyService.h"
#include <cutils/properties.h>
-#include <dlfcn.h>
#include <hardware_legacy/power.h>
#include <media/AudioEffect.h>
#include <media/EffectsFactoryApi.h>
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index d898a53..88cb1e9 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -19,6 +19,7 @@
#include <cutils/misc.h>
#include <cutils/config_utils.h>
+#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/SortedVector.h>
#include <binder/BinderService.h>
@@ -31,8 +32,6 @@
namespace android {
-class String8;
-
// ----------------------------------------------------------------------------
class AudioPolicyService :