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

Commit e82a5c75 authored by Changyeon Jo's avatar Changyeon Jo
Browse files

Fix various issues in video stream emulation

- Return early from EvsCamera::stopVideoStream() method when current
  video stream is already being stopped.
- Reconfigure the media codec and try again when it fails to start
  decoding a media file.
- Send the STREAM_STOPPED event after closing a video stream.
- Rewind the media extractor when it reaches the end of current source
  media file, to be able to playback repeatedly.

Bug: 335901181
Test: Run a test described in the associated bug.
Change-Id: If952a63700402885f794a7ef544f393314101606
parent 1eaced66
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ class EvsVideoEmulatedCamera : public EvsCamera {

    bool initialize();

    bool initializeMediaCodec();

    void generateFrames();

    void renderOneFrame();
+7 −2
Original line number Diff line number Diff line
@@ -198,9 +198,14 @@ ndk::ScopedAStatus EvsCamera::stopVideoStream() {
    auto status = ndk::ScopedAStatus::ok();
    {
        std::unique_lock lck(mMutex);
        if (mStreamState != StreamState::RUNNING) {
            // We're already in the middle of the procedure to stop current data
            // stream.
            return status;
        }

        if ((!preVideoStreamStop_locked(status, lck) || !stopVideoStreamImpl_locked(status, lck) ||
             !postVideoStreamStop_locked(status, lck)) &&
            !status.isOk()) {
             !postVideoStreamStop_locked(status, lck)) && !status.isOk()) {
            needShutdown = true;
        }
    }
+35 −5
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@ bool EvsVideoEmulatedCamera::initialize() {
        }
    }

    return initializeMediaCodec();
}

bool EvsVideoEmulatedCamera::initializeMediaCodec() {
    // Initialize Media Codec and file format.
    std::unique_ptr<AMediaFormat, FormatDeleter> format;
    const char* mime;
@@ -304,6 +308,13 @@ void EvsVideoEmulatedCamera::renderOneFrame() {
        LOG(ERROR) << __func__
                   << ": Received error in releasing output buffer. Error code: " << release_status;
    }

    if ((info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) != 0) {
        LOG(INFO) << "Start video playback from the beginning.";
        AMediaExtractor_seekTo(mVideoExtractor.get(), /* seekPosUs= */ 0,
                               AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
        AMediaCodec_flush(mVideoCodec.get());
    }
}

void EvsVideoEmulatedCamera::initializeParameters() {
@@ -337,12 +348,25 @@ bool EvsVideoEmulatedCamera::startVideoStreamImpl_locked(
        std::unique_lock<std::mutex>& /* lck */) {
    mStream = receiver;

    const media_status_t status = AMediaCodec_start(mVideoCodec.get());
    if (status != AMEDIA_OK) {
        LOG(ERROR) << __func__ << ": Received error in starting decoder. Error code: " << status
                   << ".";
    if (auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) {
        LOG(INFO) << __func__ << ": Received error in starting decoder. "
                     << "Trying again after resetting this emulated device.";

        if (!initializeMediaCodec()) {
            LOG(ERROR) << __func__ << ": Failed to re-configure the media codec.";
            return false;
        }

        AMediaExtractor_seekTo(mVideoExtractor.get(), /* seekPosUs= */ 0,
                               AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
        AMediaCodec_flush(mVideoCodec.get());

        if(auto status = AMediaCodec_start(mVideoCodec.get()); status != AMEDIA_OK) {
            LOG(ERROR) << __func__ << ": Received error again in starting decoder. "
                       << "Error code: " << status;
            return false;
        }
    }
    mCaptureThread = std::thread([this]() { generateFrames(); });

    return true;
@@ -364,6 +388,12 @@ bool EvsVideoEmulatedCamera::postVideoStreamStop_locked(ndk::ScopedAStatus& stat
    if (!Base::postVideoStreamStop_locked(status, lck)) {
        return false;
    }

    EvsEventDesc event = { .aType = EvsEventType::STREAM_STOPPED, };
    if (auto result = mStream->notify(event); !result.isOk()) {
        LOG(WARNING) << "Failed to notify the end of the stream.";
    }

    mStream = nullptr;
    return true;
}