void SoundChannel::stop()
{
    {
        Mutex::Autolock lock(&mLock);
        stop_l();
    }
    mSoundPool->done(this);
}
status_t CedarXPlayer::stop() {
    LOGV("CedarXPlayer::stop");

    if(mPlayer != NULL) {
        mPlayer->control(mPlayer, CDX_CMD_STOP_ASYNC, 0, 0);
    }
    stop_l();

    if(this->display_3d_mode == CEDARX_DISPLAY_3D_MODE_3D)
    {
        set3DMode(CEDARV_3D_MODE_NONE, CEDARX_DISPLAY_3D_MODE_2D);
    }

    this->_3d_mode 							= CEDARV_3D_MODE_NONE;
    this->display_3d_mode 					= CEDARX_DISPLAY_3D_MODE_2D;
    this->anaglagh_en						= 0;
    this->anaglagh_type						= 0;
    this->wait_anaglagh_display_change 		= 0;

    //* need to reset the display?
    //* TODO.

    return OK;
}
Ejemplo n.º 3
0
// call with sound pool lock held
void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
        float rightVolume, int priority, int loop, float rate)
{
    sp<AudioTrack> oldTrack;
    sp<AudioTrack> newTrack;
    status_t status;

    { // scope for the lock
        Mutex::Autolock lock(&mLock);

        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
                " priority=%d, loop=%d, rate=%f",
                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
                priority, loop, rate);

        // if not idle, this voice is being stolen
        if (mState != IDLE) {
            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
            stop_l();
            return;
        }

        // initialize track
        size_t afFrameCount;
        uint32_t afSampleRate;
        audio_stream_type_t streamType = mSoundPool->streamType();
        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
            afFrameCount = kDefaultFrameCount;
        }
        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
            afSampleRate = kDefaultSampleRate;
        }
        int numChannels = sample->numChannels();
        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
        uint32_t frameCount = 0;

        if (loop) {
            frameCount = sample->size()/numChannels/
                ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
        }

#ifndef USE_SHARED_MEM_BUFFER
        // Ensure minimum audio buffer size in case of short looped sample
        if(frameCount < totalFrames) {
            frameCount = totalFrames;
        }
#endif

        // mToggle toggles each time a track is started on a given channel.
        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
        // as callback user data. This enables the detection of callbacks received from the old
        // audio track while the new one is being started and avoids processing them with
        // wrong audio audio buffer size  (mAudioBufferSize)
        unsigned long toggle = mToggle ^ 1;
        void *userData = (void *)((unsigned long)this | toggle);
        uint32_t channels = (numChannels == 2) ?
                AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO;

        // do not create a new audio track if current track is compatible with sample parameters
#ifdef USE_SHARED_MEM_BUFFER
        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
                channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
#else
        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
                channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
                bufferFrames);
#endif
        oldTrack = mAudioTrack;
        status = newTrack->initCheck();
        if (status != NO_ERROR) {
            ALOGE("Error creating AudioTrack");
            goto exit;
        }
        ALOGV("setVolume %p", newTrack.get());
        newTrack->setVolume(leftVolume, rightVolume);
        newTrack->setLoop(0, frameCount, loop);

        // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
        mToggle = toggle;
        mAudioTrack = newTrack;
        mPos = 0;
        mSample = sample;
        mChannelID = nextChannelID;
        mPriority = priority;
        mLoop = loop;
        mLeftVolume = leftVolume;
        mRightVolume = rightVolume;
        mNumChannels = numChannels;
        mRate = rate;
        clearNextEvent();
        mState = PLAYING;
        mAudioTrack->start();
        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
    }

exit:
    ALOGV("delete oldTrack %p", oldTrack.get());
    if (status != NO_ERROR) {
        mAudioTrack.clear();
    }
}
int CedarXPlayer::CedarXPlayerCallback(int event, void *info)
{
    int ret = 0;
    int *para = (int*)info;

    //LOGV("----------CedarXPlayerCallback event:%d info:%p\n", event, info);

    switch (event) {
    case CDX_EVENT_PLAYBACK_COMPLETE:
        mFlags &= ~PLAYING;
        mFlags |= AT_EOS;
        stop_l(); //for gallery
        break;

    case CDX_EVENT_VIDEORENDERINIT:
        StagefrightVideoRenderInit(para[0], para[1], para[2], (void *)para[3]);
        break;

    case CDX_EVENT_VIDEORENDERDATA:
        StagefrightVideoRenderData((void*)para[0],para[1]);
        break;

    case CDX_EVENT_VIDEORENDEREXIT:
        StagefrightVideoRenderExit();
        break;

    case CDX_EVENT_VIDEORENDERGETDISPID:
        *((int*)para) = StagefrightVideoRenderGetFrameID();
        break;

    case CDX_EVENT_AUDIORENDERINIT:
        StagefrightAudioRenderInit(para[0], para[1], para[2]);
        break;

    case CDX_EVENT_AUDIORENDEREXIT:
        StagefrightAudioRenderExit(0);
        break;

    case CDX_EVENT_AUDIORENDERDATA:
        ret = StagefrightAudioRenderData((void*)para[0],para[1]);
        break;

    case CDX_EVENT_AUDIORENDERGETSPACE:
        ret = StagefrightAudioRenderGetSpace();
        break;

    case CDX_EVENT_AUDIORENDERGETDELAY:
        ret = StagefrightAudioRenderGetDelay();
        break;

    case CDX_EVENT_AUDIORENDERFLUSHCACHE:
        ret = StagefrightAudioRenderFlushCache();
        break;

    case CDX_MEDIA_INFO_BUFFERING_START:
        LOGV("MEDIA_INFO_BUFFERING_START");
        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
        break;

    case CDX_MEDIA_INFO_BUFFERING_END:
        LOGV("MEDIA_INFO_BUFFERING_END ...");
        notifyListener_l(MEDIA_BUFFERING_UPDATE, 0);//clear buffer scroll
        usleep(1000);
        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
        break;

    case CDX_MEDIA_BUFFERING_UPDATE:
    {
        int64_t positionUs;
        int progress = (int)para;

        progress = progress > 100 ? 100 : progress;

        getPosition(&positionUs);
        if(mDurationUs > 0) {
            progress = (int)((positionUs + (mDurationUs - positionUs) * progress / 100) * 100 / mDurationUs);
            LOGV("MEDIA_INFO_BUFFERING_UPDATE: %d %lld", (int)progress, positionUs);
            notifyListener_l(MEDIA_BUFFERING_UPDATE, (int)progress);
        }
        break;
    }

    case CDX_MEDIA_WHOLE_BUFFERING_UPDATE:
        notifyListener_l(MEDIA_BUFFERING_UPDATE, (int)para);
        break;

    case CDX_EVENT_PREPARED:
        finishAsyncPrepare_l((int)para);
        break;

    case CDX_EVENT_SEEK_COMPLETE:
        finishSeek_l(0);
        break;

    case CDX_EVENT_NATIVE_SUSPEND:
        LOGV("receive CDX_EVENT_NATIVE_SUSPEND");
        ret = nativeSuspend();
        break;

//	case CDX_MEDIA_INFO_SRC_3D_MODE:
//		{
//			cdx_3d_mode_e tmp_3d_mode;
//			tmp_3d_mode = *((cdx_3d_mode_e *)info);
//			LOGV("source 3d mode get from parser is %d", tmp_3d_mode);
//			notifyListener_l(MEDIA_INFO_SRC_3D_MODE, tmp_3d_mode);
//		}
//		break;

    default:
        break;
    }

    return ret;
}