diff options
| author | Haynes Mathew George <hgeorge@codeaurora.org> | 2013-02-01 18:49:00 -0800 | 
|---|---|---|
| committer | Steve Kondik <shade@chemlab.org> | 2013-02-27 09:54:05 -0800 | 
| commit | 9be07ef6a1d4dc591a25b3364a6ca0ad6f524ab9 (patch) | |
| tree | bedd8ff41e77f38a68a1db51e20b05351aa307ea | |
| parent | 1bf291a765608ea51db743389e01e98d9a5a8bf8 (diff) | |
| download | frameworks_av-9be07ef6a1d4dc591a25b3364a6ca0ad6f524ab9.zip frameworks_av-9be07ef6a1d4dc591a25b3364a6ca0ad6f524ab9.tar.gz frameworks_av-9be07ef6a1d4dc591a25b3364a6ca0ad6f524ab9.tar.bz2  | |
libstagefright: Squashed commit of LPA/tunnel updates from CAF
libstagefright: Exceptions in using Tunnel mode decode
- Accumulate all known exceptions to a separate function
Change-Id: I61bbc288c9a087559db210e76141b8c57e67fff0
CRs-Fixed: 432080
libstagefright : Stability fixes for Tunnel Player (part 2)
- Synchronize b/w reset() and onPauseTimeout
- Synchronize b/w seekTo() and onPauseTimeout
Change-Id: Ia5cfc6b4dcc326ead440fba35d809d4f3f1b5a81
CRs-Fixed: 449122
Revert "Revert "libstagefright: Convert mono to stereo for LPA clips""
This reverts commit 0db8a19fb3216a8a83d5d6cbd5f1ccbf997a20d8.
libstagefright: Port Tunnel mode fixes to LPA
- Miscellaneous fixes for seek, pause/resume, EOS handling
- Miscellaneous fixes for synchronization between the decoder thread,
  TimedEventQueue and the player thread.
- This change is a port of a similar set of changes made for
  TunnelPlayer
Change-Id: I82c2904f7aedfb9c4f03200419fcba8b038e3d54
libstagefright: Avoid use of extra bytes to signal seek processed
- A few bytes were reserved in the buffer sent by Tunnel/LPA
  player to audio HAL to indicate a seek has been processed and
  there is no need to skip it.
- We won't need this method anymore as this can be fixed instead
  by synchronizing seekTo() and the extractor/decoder threads.
Change-Id: Ic02ae1699bb59e2f6b8d9fb599d0fa43fd3f19e3
libstagefright: LPAPlayer synchronization fixes
- synchronize b/w seekTo() and onPauseTimeout()
- synchronize b/w reset() and onPauseTimeout()
Change-Id: I29a4ccf02e28fe7b7c00e35a679ff2b5271ffb6f
libstagefright: TunnelPlayer performance tweaks
Some tweaks when TunnelPlayer is used for audio/video playback
- Keep the extractor thread at ANDROID_PRIORITY_NORMAL
- sched_yield() after reading a frame to give the video thread(s)
  (CallbackDispatcher and/or TimedEventQueue) to be scheduled
Change-Id: If0d86d629fd0e15aff917af8589472578cd28bf4
CRs-Fixed: 444041
| -rwxr-xr-x | include/media/stagefright/LPAPlayer.h | 5 | ||||
| -rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 53 | ||||
| -rw-r--r-- | media/libstagefright/LPAPlayerALSA.cpp | 267 | ||||
| -rw-r--r-- | media/libstagefright/TunnelPlayer.cpp | 59 | ||||
| -rw-r--r-- | media/libstagefright/include/AwesomePlayer.h | 3 | 
5 files changed, 289 insertions, 98 deletions
diff --git a/include/media/stagefright/LPAPlayer.h b/include/media/stagefright/LPAPlayer.h index b0e1d31..91f9b3a 100755 --- a/include/media/stagefright/LPAPlayer.h +++ b/include/media/stagefright/LPAPlayer.h @@ -93,6 +93,8 @@ private:      bool mA2DPEnabled;      int32_t mChannelMask;      int32_t numChannels; +    int32_t mNumOutputChannels; +    int32_t mNumInputChannels;      int32_t mSampleRate;      int64_t mLatencyUs;      size_t mFrameSize; @@ -258,6 +260,9 @@ private:          MediaPlayerBase::AudioSink *audioSink,          void *buffer, size_t size, void *cookie);      size_t AudioCallback(void *cookie, void *data, size_t size); +    int64_t getMediaTimeUs_l(); + +    void convertMonoToStereo(int16_t *data, size_t size);      LPAPlayer(const LPAPlayer &);      LPAPlayer &operator=(const LPAPlayer &); diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 6dc18f8..6c1f4c5 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1537,9 +1537,10 @@ status_t AwesomePlayer::initAudioDecoder() {      int32_t isADTS = 0;      meta->findInt32( kKeyChannelCount, &nchannels );      meta->findInt32(kKeyIsADTS, &isADTS); -    if(isADTS == 1){ +    if (isADTS == 1) {          ALOGV("Widevine content\n");      } +      ALOGV("nchannels %d;LPA will be skipped if nchannels is > 2 or nchannels == 0",             nchannels);  #endif @@ -1555,7 +1556,7 @@ status_t AwesomePlayer::initAudioDecoder() {      //widevine will fallback to software decoder      if (sys_prop_enabled && (TunnelPlayer::mTunnelObjectsAlive == 0) && -        mTunnelAliveAP == 0 && (isADTS == 0) && +       (mTunnelAliveAP == 0) && (isADTS == 0) &&          mAudioSink->realtime() &&          inSupportedTunnelFormats(mime)) { @@ -1576,10 +1577,7 @@ status_t AwesomePlayer::initAudioDecoder() {      else         ALOGD("Normal Audio Playback"); -    if (isStreamingHTTP()) { -      ALOGV("Streaming, force disable tunnel mode playback"); -      mIsTunnelAudio = false; -    } +    checkTunnelExceptions();      if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW) ||               (mIsTunnelAudio && (mTunnelAliveAP == 0))) { @@ -2050,8 +2048,8 @@ void AwesomePlayer::onVideoEvent() {          if (latenessUs > 40000) {              // We're more than 40ms late. -            ALOGV("we're late by %lld us (%.2f secs)", -                 latenessUs, latenessUs / 1E6); +            ALOGE("we're late by %lld us nowUs %lld, timeUs %lld", +                  latenessUs, nowUs, timeUs);              if (!(mFlags & SLOW_DECODER_HACK)                      || mSinceLastDropped > FRAME_DROP_FREQ) @@ -3056,6 +3054,45 @@ bool AwesomePlayer::inSupportedTunnelFormats(const char * mime) {      ALOGW("Tunnel playback unsupported for %s", mime);      return false;  } + +void AwesomePlayer::checkTunnelExceptions() +{ +    /* exception 1: No streaming */ +    if (isStreamingHTTP()) { +        ALOGV("Streaming, force disable tunnel mode playback"); +        mIsTunnelAudio = false; +        return; +    } + +    /* below exceptions are only for av content */ +    if (mVideoTrack == NULL) return; + +    /* exception 2: No avi having video + mp3 */ +    if (mExtractor == NULL) return; + +    sp<MetaData> metaData = mExtractor->getMetaData(); +    const char * container; + +    /*only proceed for avi content.*/ +    if (!metaData->findCString(kKeyMIMEType, &container) || +        strcmp(container, MEDIA_MIMETYPE_CONTAINER_AVI)) { +        return; +    } + +    CHECK(mAudioTrack != NULL); + +    const char * mime; +    metaData = mAudioTrack->getFormat(); +    /*disable for av content having mp3*/ +    if (metaData->findCString(kKeyMIMEType, &mime) && +        !strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { +        ALOGV("Clip has AVI extractor and mp3 content, disable tunnel mode"); +        mIsTunnelAudio = false; +        return; +    } + +    return; +}  #endif  }  // namespace android diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp index 38d6bac..56746d0 100644 --- a/media/libstagefright/LPAPlayerALSA.cpp +++ b/media/libstagefright/LPAPlayerALSA.cpp @@ -1,6 +1,6 @@  /*   * Copyright (C) 2009 The Android Open Source Project - * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.   * Not a Contribution, Apache license notifications and license are retained   * for attribution purposes only.   * @@ -51,11 +51,14 @@  static const char   mName[] = "LPAPlayer"; -#define MEM_BUFFER_SIZE 262144 +#define MEM_PADDING 64 +#define MEM_BUFFER_SIZE (256*1024)  #define MEM_BUFFER_COUNT 4  #define PCM_FORMAT 2  #define NUM_FDS 2 +#define LPA_BUFFER_TIME 1500000 +  namespace android {  int LPAPlayer::objectsAlive = 0; @@ -87,7 +90,8 @@ mAudioSink(audioSink),  mObserver(observer) {      ALOGV("LPAPlayer::LPAPlayer() ctor");      objectsAlive++; -    numChannels =0; +    mNumOutputChannels =0; +    mNumInputChannels = 0;      mPaused = false;      mIsA2DPEnabled = false;      mAudioFlinger = NULL; @@ -256,20 +260,24 @@ status_t LPAPlayer::start(bool sourceAlreadyStarted) {      success = format->findInt32(kKeySampleRate, &mSampleRate);      CHECK(success); -    success = format->findInt32(kKeyChannelCount, &numChannels); +    success = format->findInt32(kKeyChannelCount, &mNumInputChannels);      CHECK(success); +    // Always produce stereo output +    mNumOutputChannels = 2; +      if(!format->findInt32(kKeyChannelMask, &mChannelMask)) {          // log only when there's a risk of ambiguity of channel mask selection -        ALOGI_IF(numChannels > 2, -                "source format didn't specify channel mask, using (%d) channel order", numChannels); +        ALOGI_IF(mNumInputChannels > 2, +                "source format didn't specify channel mask, using (%d) channel order", mNumInputChannels);          mChannelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;      }      audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_LPA |                                                           AUDIO_OUTPUT_FLAG_DIRECT); -    ALOGV("mAudiosink->open() mSampleRate %d, numChannels %d, mChannelMask %d, flags %d",mSampleRate, numChannels, mChannelMask, flags); +    ALOGV("mAudiosink->open() mSampleRate %d, numOutputChannels %d, mChannelMask %d, flags %d",mSampleRate, +          mNumOutputChannels, mChannelMask, flags);      err = mAudioSink->open( -        mSampleRate, numChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT, +        mSampleRate, mNumOutputChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,          DEFAULT_AUDIOSINK_BUFFERCOUNT,          &LPAPlayer::AudioSinkCallback,          this, @@ -301,16 +309,40 @@ status_t LPAPlayer::start(bool sourceAlreadyStarted) {  status_t LPAPlayer::seekTo(int64_t time_us) {      Mutex::Autolock autoLock(mLock);      ALOGV("seekTo: time_us %lld", time_us); -    if ( mReachedEOS ) { -        mReachedEOS = false; -        mReachedOutputEOS = false; + +    int64_t mediaTimeUs = getMediaTimeUs_l(); + +    if (mediaTimeUs != 0) { +      //check for return conditions only if seektime +      // is set +      int64_t diffUs = time_us - mediaTimeUs; + +      if (labs(diffUs) < LPA_BUFFER_TIME) { +          ALOGV("In seekTo(), ignoring time_us %lld mSeekTimeUs %lld", time_us, mSeekTimeUs); +          mObserver->postAudioSeekComplete(); +          return OK; +      }      } +      mSeeking = true;      mSeekTimeUs = time_us;      mPauseTime = mSeekTimeUs;      ALOGV("In seekTo(), mSeekTimeUs %lld",mSeekTimeUs); -    mAudioSink->flush(); -    pthread_cond_signal(&decoder_cv); + +    if (mIsAudioRouted) { +        mAudioSink->flush(); +    } + +    if (mReachedEOS) { +        mReachedEOS = false; +        mReachedOutputEOS = false; +        if(mPaused == false) { +            ALOGV("Going to signal decoder thread since playback is already going on "); +            pthread_cond_signal(&decoder_cv); +            ALOGV("Signalled extractor thread."); +        } +    } +    ALOGV("seek done.");      return OK;  } @@ -322,41 +354,26 @@ void LPAPlayer::pause(bool playPendingSamples) {      ALOGV("pause: playPendingSamples %d", playPendingSamples);      mPaused = true;      A2DPState state; -    if (playPendingSamples) { -        if (!mIsA2DPEnabled) { -            if (!mPauseEventPending) { -                ALOGV("Posting an event for Pause timeout"); -                mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC); -                mPauseEventPending = true; -            } -            mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_DISABLED); -        } -        else { -            mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_ENABLED); -        } -        if (mAudioSink.get() != NULL) -            mAudioSink->pause(); +    if (!mIsA2DPEnabled) { +       if (!mPauseEventPending) { +           ALOGV("Posting an event for Pause timeout"); +           mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC); +           mPauseEventPending = true; +       } +       mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_DISABLED);      } else { -        if (!mIsA2DPEnabled) { -            if(!mPauseEventPending) { -                ALOGV("Posting an event for Pause timeout"); -                mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC); -                mPauseEventPending = true; -            } -            mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_DISABLED); -        } else { -            mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_ENABLED); -        } -        if (mAudioSink.get() != NULL) { -            ALOGV("AudioSink pause"); -            mAudioSink->pause(); -        } +        mPauseTime = mSeekTimeUs + getTimeStamp(A2DP_ENABLED); +    } + +    if (mAudioSink.get() != NULL) { +        ALOGV("AudioSink pause"); +        mAudioSink->pause();      }  }  void LPAPlayer::resume() {      ALOGV("resume: mPaused %d",mPaused); -    Mutex::Autolock autoLock(mResumeLock); +    Mutex::Autolock autoLock(mLock);      if ( mPaused) {          CHECK(mStarted);          if (!mIsA2DPEnabled) { @@ -372,7 +389,7 @@ void LPAPlayer::resume() {              audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_LPA |                                                                  AUDIO_OUTPUT_FLAG_DIRECT);              status_t err = mAudioSink->open( -                mSampleRate, numChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT, +                mSampleRate, mNumOutputChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,                  DEFAULT_AUDIOSINK_BUFFERCOUNT,                  &LPAPlayer::AudioSinkCallback,                  this, @@ -394,30 +411,42 @@ size_t LPAPlayer::AudioSinkCallback(          void *buffer, size_t size, void *cookie) {      if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {          LPAPlayer *me = (LPAPlayer *)cookie; -        me->mReachedEOS = true; -        me->mReachedOutputEOS = true; -        ALOGV("postAudioEOS"); -        me->mObserver->postAudioEOS(0); +        if(me->mReachedEOS == true) { +            //in the case of seek all these flags will be reset +            me->mReachedOutputEOS = true; +            ALOGV("postAudioEOS mSeeking %d", me->mSeeking); +            me->mObserver->postAudioEOS(0); +        }else { +            ALOGV("postAudioEOS ignored since %d", me->mSeeking); +        }      }      return 1;  }  void LPAPlayer::reset() { +    ALOGD("Reset"); + +    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout + +    //cancel any pending onpause timeout events +    //doesnt matter if the event is really present or not +    mPauseEventPending = false; +    mQueue.cancelEvent(mPauseEvent->eventID()); -    ALOGV("Reset");      // Close the audiosink after all the threads exited to make sure      mReachedEOS = true;      // make sure Decoder thread has exited -    ALOGV("Closing all the threads"); +    ALOGD("Closing all the threads");      requestAndWaitForDecoderThreadExit();      requestAndWaitForA2DPNotificationThreadExit(); -    ALOGV("Close the Sink"); +    ALOGD("Close the Sink");      if (mIsAudioRouted) {  	    mAudioSink->stop();          mAudioSink->close();          mAudioSink.clear(); +        mIsAudioRouted = false;      }      // Make sure to release any buffer we hold onto so that the      // source is able to stop(). @@ -490,25 +519,80 @@ void LPAPlayer::decoderThreadEntry() {          return;      }      void* local_buf = malloc(MEM_BUFFER_SIZE); +    if(local_buf == (void*) NULL) { +        killDecoderThread = true; +        ALOGE("Malloc failed"); +        return; +    } +    int *lptr = ((int*)local_buf);      int bytesWritten = 0; + +    if (!local_buf) { +      ALOGE("Failed to allocate temporary buffer for decoderThread"); +      return; +    } + +    bool lSeeking = false; +    bool lPaused = false; +      while (!killDecoderThread) {          if (mReachedEOS || mPaused || !mIsAudioRouted) { +            ALOGV("Going to sleep before write since " +                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", +                  mReachedEOS, mPaused, mIsAudioRouted);              pthread_mutex_lock(&decoder_mutex);              pthread_cond_wait(&decoder_cv, &decoder_mutex);              pthread_mutex_unlock(&decoder_mutex); +            ALOGV("Woke up from sleep before write since " +                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", +                  mReachedEOS, mPaused, mIsAudioRouted);              continue;          }          if (!mIsA2DPEnabled) {              ALOGV("FillBuffer: MemBuffer size %d", MEM_BUFFER_SIZE);              ALOGV("Fillbuffer started"); -            //TODO: Add memset -            bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE); -            ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten); +            if (mNumInputChannels == 1) { +                bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE/2); +                CHECK(bytesWritten <= MEM_BUFFER_SIZE/2); + +                convertMonoToStereo((int16_t*)local_buf, bytesWritten); +                bytesWritten *= 2; +            } else { +                bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE); +                CHECK(bytesWritten <= MEM_BUFFER_SIZE); +            } +            ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten);              if(!killDecoderThread) { -                mAudioSink->write(local_buf, bytesWritten); +                mLock.lock(); +                lPaused = mPaused; +                mLock.unlock(); + +                if(lPaused == true) { +                    //write only if player is not in paused state. Sleep on lock +                    // resume is called +                    ALOGV("Going to sleep in decodethreadiwrite since sink is paused"); +                    pthread_mutex_lock(&decoder_mutex); +                    pthread_cond_wait(&decoder_cv, &decoder_mutex); +                    ALOGV("Going to unlock n decodethreadwrite since sink " +                          "resumed mPaused %d, mIsAudioRouted %d, mReachedEOS %d", +                          mPaused, mIsAudioRouted, mReachedEOS); +                    pthread_mutex_unlock(&decoder_mutex); +                } +                mLock.lock(); +                lSeeking = mSeeking||mInternalSeeking; +                mLock.unlock(); + +                if(lSeeking == false && (killDecoderThread == false)){ +                    //if we are seeking, ignore write, otherwise write +                    ALOGV("Fillbuffer before seeling flag %d", mSeeking); +                    int lWrittenBytes = mAudioSink->write(local_buf, bytesWritten); +                    ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", lWrittenBytes, mSeeking); +                } else { +                    ALOGV("Fillbuffer ignored since we seeked after fillBuffer was set %d", mSeeking); +                }              }          }      } @@ -580,19 +664,27 @@ size_t LPAPlayer::fillBuffer(void *data, size_t size) {          return 0;      } +    if ((data == (void*) NULL) || size > MEM_BUFFER_SIZE) { +        ALOGE("fillBuffer given wrong buffer"); +        return 0; +    } +      bool postSeekComplete = false;      size_t size_done = 0;      size_t size_remaining = size; +    ALOGV("fillBuffer: Clearing seek flag in fill buffer"); +      while (size_remaining > 0) {          MediaSource::ReadOptions options;          {              Mutex::Autolock autoLock(mLock); -            if (mSeeking) { +            if(mSeeking) {                  mInternalSeeking = false;              } +              if (mSeeking || mInternalSeeking) {                  if (mIsFirstBuffer) {                      if (mFirstBuffer != NULL) { @@ -609,8 +701,9 @@ size_t LPAPlayer::fillBuffer(void *data, size_t size) {                      mInputBuffer = NULL;                  } -                size_remaining = size; +                // This is to ignore the data already filled in the output buffer                  size_done = 0; +                size_remaining = size;                  mSeeking = false;                  if (mObserver && !mInternalSeeking) { @@ -618,6 +711,7 @@ size_t LPAPlayer::fillBuffer(void *data, size_t size) {                      postSeekComplete = true;                  }                  mInternalSeeking = false; +                ALOGV("fillBuffer: Setting seek flag in fill buffer");              }          } @@ -635,14 +729,16 @@ size_t LPAPlayer::fillBuffer(void *data, size_t size) {              }              CHECK((err == OK && mInputBuffer != NULL) -                   || (err != OK && mInputBuffer == NULL)); - -            Mutex::Autolock autoLock(mLock); - -            if (err != OK) { -                mReachedEOS = true; -                mFinalStatus = err; -                break; +                  || (err != OK && mInputBuffer == NULL)); +            { +                Mutex::Autolock autoLock(mLock); + +                if (err != OK) { +                    ALOGD("fill buffer - reached eos true"); +                    mReachedEOS = true; +                    mFinalStatus = err; +                    break; +                }              }              CHECK(mInputBuffer->meta_data()->findInt64( @@ -662,7 +758,7 @@ size_t LPAPlayer::fillBuffer(void *data, size_t size) {          size_t copy = size_remaining;          if (copy > mInputBuffer->range_length()) {              copy = mInputBuffer->range_length(); -        } +        } //is size_remaining < range_length impossible?          memcpy((char *)data + size_done,                 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), @@ -712,9 +808,7 @@ int64_t LPAPlayer::getTimeStamp(A2DPState state) {      return timestamp;  } -int64_t LPAPlayer::getMediaTimeUs() { -    Mutex::Autolock autoLock(mLock); -    ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime); +int64_t LPAPlayer::getMediaTimeUs_l() {      if (mPaused) {          return mPauseTime;      } else { @@ -723,16 +817,21 @@ int64_t LPAPlayer::getMediaTimeUs() {      }  } -bool LPAPlayer::getMediaTimeMapping( -                                   int64_t *realtime_us, int64_t *mediatime_us) { +int64_t LPAPlayer::getMediaTimeUs() {      Mutex::Autolock autoLock(mLock); +    ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime); +    return getMediaTimeUs_l(); +} -    *realtime_us = mPositionTimeRealUs; -    *mediatime_us = mPositionTimeMediaUs; - -    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; +bool LPAPlayer::getMediaTimeMapping( +                                   int64_t *realtime_us, int64_t *mediatime_us) { +    ALOGE("getMediaTimeMapping is invalid for LPA Player"); +    *realtime_us = -1; +    *mediatime_us = -1; +    return false;  } +//lock taken in reset()  void LPAPlayer::requestAndWaitForDecoderThreadExit() {      if (!decoderThreadAlive) @@ -745,8 +844,10 @@ void LPAPlayer::requestAndWaitForDecoderThreadExit() {          mAudioSink->flush();      pthread_cond_signal(&decoder_cv); +    mLock.unlock();      pthread_join(decoderThread,NULL); -    ALOGV("decoder thread killed"); +    mLock.lock(); +    ALOGD("decoder thread killed");  } @@ -761,7 +862,7 @@ void LPAPlayer::requestAndWaitForA2DPNotificationThreadExit() {  void LPAPlayer::onPauseTimeOut() {      ALOGV("onPauseTimeOut"); -    Mutex::Autolock autoLock(mResumeLock); +    Mutex::Autolock autoLock(mLock);      if (!mPauseEventPending) {          return;      } @@ -790,4 +891,18 @@ void LPAPlayer::onPauseTimeOut() {  } +//dup each mono frame +void LPAPlayer::convertMonoToStereo(int16_t *data, size_t size) +{ +    int i =0; +    int16_t *start_pointer = data; +    int monoFrameCount = (size) / (sizeof(int16_t)); + +    for (i = monoFrameCount; i > 0 ; i--) { +      int16_t temp_sample = *(start_pointer + i - 1); +      *(start_pointer + (i*2) - 1) = temp_sample; +      *(start_pointer + (i*2) - 2) = temp_sample; +    } +} +  } //namespace android diff --git a/media/libstagefright/TunnelPlayer.cpp b/media/libstagefright/TunnelPlayer.cpp index c5f8066..3b45db4 100644 --- a/media/libstagefright/TunnelPlayer.cpp +++ b/media/libstagefright/TunnelPlayer.cpp @@ -51,6 +51,13 @@  static const char   mName[] = "TunnelPlayer";  #define MEM_METADATA_SIZE 64  #define MEM_PADDING 64 +/* + * We need to reserve some space in the + * ion buffer (used in HAL) to save the + * metadata. so read from the extractor + * a somewhat smaller number of bytes. + * ideally this number should be bufer_size - sizeof(struct output_metadata_t) + */  #define MEM_BUFFER_SIZE (240*1024 - MEM_METADATA_SIZE)  #define MEM_BUFFER_COUNT 4  #define TUNNEL_BUFFER_TIME 1500000 @@ -374,7 +381,9 @@ status_t TunnelPlayer::start(bool sourceAlreadyStarted) {  status_t TunnelPlayer::seekTo(int64_t time_us) { -    ALOGV("seekTo: time_us %lld", time_us); +    ALOGD("seekTo: time_us %lld", time_us); + +    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout      //This can happen if the client calls seek      //without ever calling getPosition @@ -385,19 +394,26 @@ status_t TunnelPlayer::seekTo(int64_t time_us) {      if (mPositionTimeRealUs > 0) {        //check for return conditions only if seektime        // is set +      bool postSeekComplete = false; +        if (time_us > mPositionTimeRealUs){ -           if((time_us - mPositionTimeRealUs) < TUNNEL_BUFFER_TIME){ +           if ((time_us - mPositionTimeRealUs) < TUNNEL_BUFFER_TIME){               ALOGV("In seekTo(), ignoring time_us %lld mSeekTimeUs %lld", time_us, mSeekTimeUs); -             mObserver->postAudioSeekComplete(); -             return OK; +             postSeekComplete = true;             }        } else { -           if((mPositionTimeRealUs - time_us) < TUNNEL_BUFFER_TIME){ +           if ((mPositionTimeRealUs - time_us) < TUNNEL_BUFFER_TIME){                 ALOGV("In seekTo(), ignoring time_us %lld mSeekTimeUs %lld", time_us, mSeekTimeUs); -               mObserver->postAudioSeekComplete(); -               return OK; +               postSeekComplete = true;             }        } + +      if (postSeekComplete) { +          mLock.unlock(); //unlock and post +          mObserver->postAudioSeekComplete(); +          mLock.lock(); +          return OK; +      }      }      mSeeking = true; @@ -502,6 +518,13 @@ size_t TunnelPlayer::AudioSinkCallback(  void TunnelPlayer::reset() {      ALOGV("Reset"); +    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout + +    //cancel any pending onpause timeout events +    //doesnt matter if the event is really present or not +    mPauseEventPending = false; +    mQueue.cancelEvent(mPauseEvent->eventID()); +      mReachedEOS = true;      // make sure Decoder thread has exited @@ -568,7 +591,8 @@ void TunnelPlayer::extractorThreadEntry() {      uint32_t BufferSizeToUse = MEM_BUFFER_SIZE;      pid_t tid  = gettid(); -    androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO); +    androidSetThreadPriority(tid, mHasVideo ? ANDROID_PRIORITY_NORMAL : +                                              ANDROID_PRIORITY_AUDIO);      prctl(PR_SET_NAME, (unsigned long)"Extractor Thread", 0, 0, 0);      ALOGV("extractorThreadEntry wait for signal \n"); @@ -585,7 +609,7 @@ void TunnelPlayer::extractorThreadEntry() {          const char *mime;          bool success = format->findCString(kKeyMIMEType, &mime);      } -    void* local_buf = malloc(BufferSizeToUse + MEM_PADDING); +    void* local_buf = malloc(BufferSizeToUse);      int *lptr = ((int*)local_buf);      int bytesWritten = 0;      bool lSeeking = false; @@ -632,8 +656,7 @@ void TunnelPlayer::extractorThreadEntry() {                  if(lSeeking == false && (killExtractorThread == false)){                      //if we are seeking, ignore write, otherwise write -                    ALOGV("Fillbuffer before write %d and seek flag %d", mSeeking, -                          lptr[MEM_BUFFER_SIZE/sizeof(int)]); +                  ALOGV("Fillbuffer before seek flag %d", mSeeking);                      int lWrittenBytes = mAudioSink->write(local_buf, bytesWritten);                      ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", lWrittenBytes, mSeeking);                      if(lWrittenBytes > 0) { @@ -660,6 +683,7 @@ void TunnelPlayer::extractorThreadEntry() {                  }              }          } +      }      free(local_buf); @@ -696,11 +720,11 @@ size_t TunnelPlayer::fillBuffer(void *data, size_t size) {      size_t size_done = 0;      size_t size_remaining = size; -    int *ldataptr = (int*) data;      //clear the flag since we dont know whether we are seeking or not, yet -    ldataptr[(MEM_BUFFER_SIZE/sizeof(int))] = 0;      ALOGV("fillBuffer: Clearing seek flag in fill buffer"); +    bool yield = !mIsFirstBuffer; +      while (size_remaining > 0) {          MediaSource::ReadOptions options;          { @@ -738,7 +762,6 @@ size_t TunnelPlayer::fillBuffer(void *data, size_t size) {                  mInternalSeeking = false;                  ALOGV("fillBuffer: Setting seek flag in fill buffer");                  //set the flag since we know that this buffer is the new positions buffer -                ldataptr[(MEM_BUFFER_SIZE/sizeof(int))] = 1;              }          }          if (mInputBuffer == NULL) { @@ -787,6 +810,10 @@ size_t TunnelPlayer::fillBuffer(void *data, size_t size) {          size_done += copy;          size_remaining -= copy; + +        if (mHasVideo && yield) { +            sched_yield(); +        }      }      if(mReachedEOS)          memset((char *)data + size_done, 0x0, size_remaining); @@ -841,7 +868,9 @@ bool TunnelPlayer::getMediaTimeMapping(      return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;  } +//lock has been taken in reset() to sync with onpausetimeout  void TunnelPlayer::requestAndWaitForExtractorThreadExit() { +    ALOGV("requestAndWaitForExtractorThreadExit -1");      if (!extractorThreadAlive)          return; @@ -856,7 +885,9 @@ void TunnelPlayer::requestAndWaitForExtractorThreadExit() {      ALOGV("requestAndWaitForExtractorThreadExit +1");      pthread_cond_signal(&extractor_cv);      ALOGV("requestAndWaitForExtractorThreadExit +2"); +    mLock.unlock();      pthread_join(extractorThread,NULL); +    mLock.lock();      ALOGV("requestAndWaitForExtractorThreadExit +3");      ALOGV("Extractor thread killed"); diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index ee885a5..8bda7f8 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -309,6 +309,9 @@ private:      void logLate(int64_t ts, int64_t clock, int64_t delta);      void logOnTime(int64_t ts, int64_t clock, int64_t delta);      int64_t getTimeOfDayUs(); +#ifdef QCOM_HARDWARE +    void checkTunnelExceptions(); +#endif      bool mStatistics;      struct TrackStat {  | 
