From e82a5c75660cd7ec70f7373ee041e3b47be2cba0 Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Fri, 19 Apr 2024 14:54:50 -0700 Subject: [PATCH] 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 --- .../default/include/EvsVideoEmulatedCamera.h | 2 + .../evs/aidl/impl/default/src/EvsCamera.cpp | 9 ++++- .../default/src/EvsVideoEmulatedCamera.cpp | 40 ++++++++++++++++--- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h index a850d6598b..9d1610a928 100644 --- a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h +++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h @@ -93,6 +93,8 @@ class EvsVideoEmulatedCamera : public EvsCamera { bool initialize(); + bool initializeMediaCodec(); + void generateFrames(); void renderOneFrame(); diff --git a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp index bc3bfdd367..005c71f9e5 100644 --- a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp +++ b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp @@ -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; } } diff --git a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp index e3f7b5e125..480c28d6a8 100644 --- a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp +++ b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp @@ -81,6 +81,10 @@ bool EvsVideoEmulatedCamera::initialize() { } } + return initializeMediaCodec(); +} + +bool EvsVideoEmulatedCamera::initializeMediaCodec() { // Initialize Media Codec and file format. std::unique_ptr 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,11 +348,24 @@ bool EvsVideoEmulatedCamera::startVideoStreamImpl_locked( std::unique_lock& /* 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 - << "."; - return false; + 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(); }); @@ -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; }