diff options
-rw-r--r-- | include/media/AudioTrack.h | 98 | ||||
-rw-r--r-- | include/media/IAudioTrack.h | 10 | ||||
-rw-r--r-- | include/private/media/AudioTrackShared.h | 4 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 37 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/RTSPSource.cpp | 57 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/RTSPSource.h | 6 | ||||
-rw-r--r-- | media/libstagefright/foundation/ABitReader.cpp | 8 | ||||
-rw-r--r-- | media/libstagefright/rtsp/AAMRAssembler.cpp | 16 | ||||
-rw-r--r-- | media/libstagefright/rtsp/ARTSPConnection.cpp | 24 | ||||
-rw-r--r-- | media/libstagefright/rtsp/MyHandler.h | 14 | ||||
-rw-r--r-- | media/mediaserver/main_mediaserver.cpp | 6 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 56 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.cpp | 101 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.h | 4 | ||||
-rw-r--r-- | services/audioflinger/AudioPolicyService.cpp | 1 | ||||
-rw-r--r-- | services/audioflinger/AudioPolicyService.h | 3 |
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 : |