Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2d549f3 authored by Guang Qiao's avatar Guang Qiao Committed by Gopalakrishnan Nallasamy
Browse files

Modify MediaRecorder stopping process to avoid blocking

1. Puller.setStopTimeUs() and Puller.stopSource() should not traverse
the looper thread because the thread may be blocked by MediaSource.read().
2. Encoder should always be released before stopping MediaSource because
MediaSource.stop() would be blocked if there are still some input
buffers being encoding.

Bug: 143046445
Bug: 148988986

Test: atest android.media.cts.MediaRecorderTest
Test: atest android.mediastress.cts.MediaRecorderStressTest
Test: atest android.hardware.cts.CameraTest

Change-Id: Ia576619dfb40c45fc7840d8febd1614d5ef09118
(cherry picked from commit 96ae963e)
parent 28a802c5
Loading
Loading
Loading
Loading
+10 −25
Original line number Diff line number Diff line
@@ -168,9 +168,7 @@ status_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
}

status_t MediaCodecSource::Puller::setStopTimeUs(int64_t stopTimeUs) {
    sp<AMessage> msg = new AMessage(kWhatSetStopTimeUs, this);
    msg->setInt64("stop-time-us", stopTimeUs);
    return postSynchronouslyAndReturnError(msg);
    return mSource->setStopTimeUs(stopTimeUs);
}

status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
@@ -188,21 +186,13 @@ status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMes
}

void MediaCodecSource::Puller::stop() {
    bool interrupt = false;
    {
    // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
    // stop.
    Mutexed<Queue>::Locked queue(mQueue);
    queue->mPulling = false;
        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
    queue->flush(); // flush any unprocessed pulled buffers
}

    if (interrupt) {
        interruptSource();
    }
}

void MediaCodecSource::Puller::interruptSource() {
    // call source->stop if read has been pending for over a second
    // We have to call this outside the looper as looper is pending on the read.
@@ -660,9 +650,9 @@ void MediaCodecSource::signalEOS(status_t err) {
    if (mStopping && reachedEOS) {
        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
        if (mPuller != NULL) {
            mPuller->stopSource();
            mPuller->interruptSource();
        }
        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
        ALOGI("source (%s) stopped", mIsVideo ? "video" : "audio");
        // posting reply to everyone that's waiting
        List<sp<AReplyToken>>::iterator it;
        for (it = mStopReplyIDQueue.begin();
@@ -851,7 +841,7 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
    {
        int32_t eos = 0;
        if (msg->findInt32("eos", &eos) && eos) {
            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
            ALOGI("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
            signalEOS();
            break;
        }
@@ -1069,12 +1059,7 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
        if (generation != mGeneration) {
             break;
        }

        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
            mPuller->interruptSource();
            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
        }
        ALOGD("source (%s) stopping stalled", mIsVideo ? "video" : "audio");
        signalEOS();
        break;
    }