From 113275600c1e197f8503042b264a824217a27a73 Mon Sep 17 00:00:00 2001 From: Fancy code <258828110.@qq.com> Date: Fri, 14 Jun 2024 20:03:14 +0800 Subject: [PATCH] Improve:MediaManager. --- hal/abstract/IHalCpp.cpp | 5 ++ hal/include/IHalCpp.h | 8 +- hal/src/CameraHal.cpp | 51 ++---------- hal/src/CameraHal.h | 13 +-- middleware/MediaManager/src/MediaHandle.cpp | 83 ++++++++++++++++++- middleware/MediaManager/src/MediaHandle.h | 18 ++++ .../MediaManager/src/MediaManagerImpl.cpp | 16 +++- .../MediaManager/src/MediaManagerImpl.h | 1 + middleware/MediaManager/src/SaveStream.cpp | 48 +++++++++++ middleware/MediaManager/src/SaveStream.h | 33 ++++++++ middleware/MediaManager/src/VStreamHandle.cpp | 27 ++++++ middleware/MediaManager/src/VStreamHandle.h | 27 ++++++ .../src_mock/MediaManager_Mock_Test.cpp | 14 +++- 13 files changed, 284 insertions(+), 60 deletions(-) create mode 100644 middleware/MediaManager/src/SaveStream.cpp create mode 100644 middleware/MediaManager/src/SaveStream.h create mode 100644 middleware/MediaManager/src/VStreamHandle.cpp create mode 100644 middleware/MediaManager/src/VStreamHandle.h diff --git a/hal/abstract/IHalCpp.cpp b/hal/abstract/IHalCpp.cpp index 734f563..8d4bbd3 100644 --- a/hal/abstract/IHalCpp.cpp +++ b/hal/abstract/IHalCpp.cpp @@ -64,6 +64,11 @@ void VCameraHalMonitor::ReportEvent(const CameraReportEvent &event) { LogWarning("STATUS_CODE_VIRTUAL_FUNCTION.\n"); } +StatusCode VCameraTaskContext::TaskFinished(void) +{ + LogWarning("STATUS_CODE_VIRTUAL_FUNCTION.\n"); + return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); +} camera_task_param::camera_task_param(const CameraTaskType &cameraTask) : mCameraTask(cameraTask) { mVideoRecordingTimeMs = DEFAULT_VIDEO_RECORDING_TIME_MS; diff --git a/hal/include/IHalCpp.h b/hal/include/IHalCpp.h index 1a9902f..9f07636 100644 --- a/hal/include/IHalCpp.h +++ b/hal/include/IHalCpp.h @@ -15,6 +15,7 @@ #ifndef I_HAL_CPP_H #define I_HAL_CPP_H #include "StatusCode.h" +#include #include #include #include @@ -99,6 +100,7 @@ class VCameraTaskContext public: VCameraTaskContext() = default; virtual ~VCameraTaskContext() = default; + virtual StatusCode TaskFinished(void); }; template class CameraTaskContext : public VCameraTaskContext @@ -120,8 +122,10 @@ typedef struct camera_task_param unsigned int mVideoRecordingTimeMs; std::shared_ptr mCtx; } CameraTaskParam; -using AudioStreamCallback = void (*)(const void *, const int); -using VideoStreamCallback = void (*)(const void *, const int); +// using AudioStreamCallback = void (*)(const void *, const int, const unsigned long long); +// using VideoStreamCallback = void (*)(const void *, const int, const unsigned long long); +using AudioStreamCallback = std::function; +using VideoStreamCallback = std::function; class VCameraHal { public: diff --git a/hal/src/CameraHal.cpp b/hal/src/CameraHal.cpp index 5237355..eba4e05 100644 --- a/hal/src/CameraHal.cpp +++ b/hal/src/CameraHal.cpp @@ -14,9 +14,7 @@ */ #include "CameraHal.h" #include "ILog.h" -CameraHal::CameraHal() - : mTaskRuning(false), mMediaRecordingTimeMs(NO_MEDIA_RECORDING), mAudioStreamCallback(nullptr), - mVideoStreamCallback(nullptr) +CameraHal::CameraHal() : mTaskRuning(false), mAudioStreamCallback(nullptr), mVideoStreamCallback(nullptr) { } void CameraHal::Init(void) @@ -24,24 +22,15 @@ void CameraHal::Init(void) } void CameraHal::UnInit(void) { - mTaskRuning = false; - mCv.notify_one(); } StatusCode CameraHal::StartSingleTask(const CameraTaskParam ¶m) { - mMediaRecordingTimeMs = param.mVideoRecordingTimeMs; - auto taskTimerThread = [=](std::shared_ptr media) { - LogInfo("StartSingleTask start.\n"); - media->TaskTimer(); - }; - std::shared_ptr media = std::dynamic_pointer_cast(shared_from_this()); - mTaskTimerThread = std::thread(taskTimerThread, media); + mTaskRuning = true; return CreateStatusCode(STATUS_CODE_OK); } StatusCode CameraHal::StopTask(void) { mTaskRuning = false; - mCv.notify_one(); return CreateStatusCode(STATUS_CODE_OK); } StatusCode CameraHal::SetAudioStreamCallback(AudioStreamCallback callback) @@ -54,43 +43,15 @@ StatusCode CameraHal::SetVideoStreamCallback(VideoStreamCallback callback) mVideoStreamCallback = callback; return CreateStatusCode(STATUS_CODE_OK); } -void CameraHal::GetAudioStream(const void *stream, const unsigned int &length) +void CameraHal::GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) { if (mTaskRuning && nullptr != mAudioStreamCallback) { - mAudioStreamCallback(stream, length); + mAudioStreamCallback(stream, length, timeStamp); } - // if (mTaskRuning) { - // LogInfo("GetAudioStream length33:%d\n", length); - // FILE *file = nullptr; - // file = fopen("/tmp/audio.bin", "a+"); - - // if (file) { - // fwrite(stream, 1, length, file); - // fflush(file); - // } - - // if (file) { - // fclose(file); - // } - // } } -void CameraHal::GetVideoStream(const void *stream, const unsigned int &length) +void CameraHal::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) { if (mTaskRuning && nullptr != mVideoStreamCallback) { - mVideoStreamCallback(stream, length); - } -} -void CameraHal::TaskTimer(void) -{ - mTaskRuning = true; - while (mTaskRuning) { - std::unique_lock lock(mMutex); - mCv.wait_for(lock, std::chrono::milliseconds(mMediaRecordingTimeMs), [&] { - return !mTaskRuning; - }); - /** - * @brief If the recording time is over, you need to stop the recording timer here. - */ - mTaskRuning = false; + mVideoStreamCallback(stream, length, timeStamp); } } \ No newline at end of file diff --git a/hal/src/CameraHal.h b/hal/src/CameraHal.h index e01f2ac..1ab18c0 100644 --- a/hal/src/CameraHal.h +++ b/hal/src/CameraHal.h @@ -15,7 +15,6 @@ #ifndef CAMERA_HAL_H #define CAMERA_HAL_H #include "IHalCpp.h" -#include #include #include constexpr unsigned int NO_MEDIA_RECORDING = -1; @@ -34,18 +33,12 @@ protected: StatusCode SetVideoStreamCallback(VideoStreamCallback callback) override; protected: - void GetAudioStream(const void *stream, const unsigned int &length); - void GetVideoStream(const void *stream, const unsigned int &length); + void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp); + void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp); private: - void TaskTimer(void); - -private: - std::mutex mMutex; - std::condition_variable mCv; + // std::mutex mMutex; bool mTaskRuning; - std::thread mTaskTimerThread; - unsigned int mMediaRecordingTimeMs; AudioStreamCallback mAudioStreamCallback; VideoStreamCallback mVideoStreamCallback; }; diff --git a/middleware/MediaManager/src/MediaHandle.cpp b/middleware/MediaManager/src/MediaHandle.cpp index ca1f5fc..a702839 100644 --- a/middleware/MediaManager/src/MediaHandle.cpp +++ b/middleware/MediaManager/src/MediaHandle.cpp @@ -14,10 +14,38 @@ */ #include "MediaHandle.h" #include "ILog.h" +#include "SaveStream.h" MediaHandle::MediaHandle(const MediaChannel &mediaChannel, const std::shared_ptr &cameraHal) - : mMediaChannel(mediaChannel), mCameraHal(cameraHal) + : mMediaChannel(mediaChannel), mCameraHal(cameraHal), mTaskRuning(false) { } +void MediaHandle::Init(void) +{ + if (mCameraHal == nullptr) { + LogError("CameraHal is null.\n"); + return; + } + auto audioFunc = std::bind(&MediaHandle::GetVideoStreamCallback, this, _1, _2, _3); + mCameraHal->SetAudioStreamCallback(audioFunc); + auto videoFunc = std::bind(&MediaHandle::GetAudioStreamCallback, this, _1, _2, _3); + mCameraHal->SetVideoStreamCallback(videoFunc); +} +void MediaHandle::UnInit(void) +{ + mTaskRuning = false; + mCv.notify_one(); + if (mTaskTimerThread.joinable()) { + mTaskTimerThread.join(); + } + if (mCameraHal) { + /** + * @brief Before releasing the class instance, it is necessary to call the UnInit function to ensure that the + * callback function is cleared elsewhere, otherwise it will crash. + */ + mCameraHal->SetAudioStreamCallback(nullptr); + mCameraHal->SetVideoStreamCallback(nullptr); + } +} StatusCode MediaHandle::ExecuteTask(std::shared_ptr &task) { std::lock_guard locker(mMutex); @@ -29,11 +57,18 @@ StatusCode MediaHandle::ExecuteTask(std::shared_ptr &task) return CreateStatusCode(STATUS_CODE_NOT_OK); } } + mStreamHandle = std::make_shared(); + if (nullptr == mStreamHandle) { + LogError("Create stream handle failed.\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + mStreamHandle->Init(); CameraTaskType taskType = TaskTypeConvert(task->GetTaskType()); CameraTaskParam data(taskType); auto code = mCameraHal->StartSingleTask(data); if (IsCodeOK(code)) { mCurrentTask = task; + StartTaskTimer(); } else { LogError("Execute task failed.\n"); @@ -48,7 +83,53 @@ StatusCode MediaHandle::ClearTask(void) { return CreateStatusCode(STATUS_CODE_OK); } +void MediaHandle::StartTaskTimer(void) +{ + auto taskTimerThread = [=](std::shared_ptr media) { + LogInfo("StartTaskTimer start.\n"); + media->TaskTimer(); + }; + std::shared_ptr media = shared_from_this(); + mTaskTimerThread = std::thread(taskTimerThread, media); +} +void MediaHandle::TaskTimer(void) +{ + constexpr int TASK_TIMER = 1000 * 10; + mTaskRuning = true; + while (mTaskRuning) { + std::unique_lock lock(mMutex); + mCv.wait_for(lock, std::chrono::milliseconds(TASK_TIMER), [&] { + return !mTaskRuning; + }); + /** + * @brief If the recording time is over, you need to stop the recording timer here. + */ + mTaskRuning = false; + } + if (mCameraHal) { + mCameraHal->StopTask(); + } + mMutex.lock(); + auto runingTask = mCurrentTask.lock(); + if (mCurrentTask.expired()) { + LogWarning("SdCardHal: monitor is expired.\n"); + return; + } + LogInfo("Task finished response to application.\n"); + std::vector responses; + runingTask->Response(responses); + mCurrentTask.reset(); + mMutex.unlock(); +} CameraTaskType MediaHandle::TaskTypeConvert(const MediaTaskType &type) { return CameraTaskType::END; +} +void MediaHandle::GetVideoStreamCallback(const void *stream, const int &length, const unsigned long long &timeStamp) +{ + mStreamHandle->GetVideoStream(stream, length, timeStamp); +} +void MediaHandle::GetAudioStreamCallback(const void *stream, const int &length, const unsigned long long &timeStamp) +{ + mStreamHandle->GetAudioStream(stream, length, timeStamp); } \ No newline at end of file diff --git a/middleware/MediaManager/src/MediaHandle.h b/middleware/MediaManager/src/MediaHandle.h index 809785b..ecc733f 100644 --- a/middleware/MediaManager/src/MediaHandle.h +++ b/middleware/MediaManager/src/MediaHandle.h @@ -16,23 +16,41 @@ #define MEDI_AHANDLE_H #include "IHalCpp.h" #include "IMediaManager.h" +#include "VStreamHandle.h" +#include #include +#include +using std::placeholders::_1; +using std::placeholders::_2; +using std::placeholders::_3; class MediaHandle : public VMediaHandle, public std::enable_shared_from_this { public: MediaHandle(const MediaChannel &mediaChannel, const std::shared_ptr &cameraHal); virtual ~MediaHandle() = default; + void Init(void); + void UnInit(void); + +protected: StatusCode ExecuteTask(std::shared_ptr &task) override; StatusCode StopTask(void) override; StatusCode ClearTask(void) override; private: + void StartTaskTimer(void); + void TaskTimer(void); CameraTaskType TaskTypeConvert(const MediaTaskType &type); + void GetVideoStreamCallback(const void *stream, const int &length, const unsigned long long &timeStamp); + void GetAudioStreamCallback(const void *stream, const int &length, const unsigned long long &timeStamp); private: std::mutex mMutex; + std::condition_variable mCv; const MediaChannel &mMediaChannel; std::shared_ptr mCameraHal; std::weak_ptr mCurrentTask; + std::shared_ptr mStreamHandle; + bool mTaskRuning; + std::thread mTaskTimerThread; }; #endif \ No newline at end of file diff --git a/middleware/MediaManager/src/MediaManagerImpl.cpp b/middleware/MediaManager/src/MediaManagerImpl.cpp index a3356e8..ce03be8 100644 --- a/middleware/MediaManager/src/MediaManagerImpl.cpp +++ b/middleware/MediaManager/src/MediaManagerImpl.cpp @@ -23,6 +23,7 @@ StatusCode MediaManagerImpl::Init(void) } StatusCode MediaManagerImpl::UnInit(void) { + UnInitMediaHandles(); return CreateStatusCode(STATUS_CODE_OK); } StatusCode MediaManagerImpl::GetMediaChannel(const MediaChannel &channel, std::shared_ptr &handle) @@ -76,8 +77,21 @@ void MediaManagerImpl::InitMediaHandles(std::map(i); - std::shared_ptr media = std::make_shared(channel, camera->second); + std::shared_ptr media = std::make_shared(channel, camera->second); + media->Init(); mAllMediaChannels[channel] = media; LogInfo("InitMediaHandles. channel = %d \n", static_cast(i)); } +} +void MediaManagerImpl::UnInitMediaHandles(void) +{ + for (auto &media : mAllMediaChannels) { + LogInfo("UnInitMediaHandles. channel = %d \n", media.first); + std::shared_ptr mediaImpl = std::dynamic_pointer_cast(media.second); + if (nullptr == mediaImpl) { + LogWarning("mediaImpl is null.\n"); + continue; + } + mediaImpl->UnInit(); + } } \ No newline at end of file diff --git a/middleware/MediaManager/src/MediaManagerImpl.h b/middleware/MediaManager/src/MediaManagerImpl.h index 20fe1b7..330dc4a 100644 --- a/middleware/MediaManager/src/MediaManagerImpl.h +++ b/middleware/MediaManager/src/MediaManagerImpl.h @@ -33,6 +33,7 @@ public: private: void SetCamerasMonitor(std::map> &allCameras); void InitMediaHandles(std::map> &allCameras); + void UnInitMediaHandles(void); private: std::map> mAllCameras; diff --git a/middleware/MediaManager/src/SaveStream.cpp b/middleware/MediaManager/src/SaveStream.cpp new file mode 100644 index 0000000..bd8e158 --- /dev/null +++ b/middleware/MediaManager/src/SaveStream.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this mFileAudio except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "SaveStream.h" +SaveStream::SaveStream() : mFileAudio(nullptr), mFileVideo(nullptr) +{ +} +void SaveStream::Init(void) +{ + mFileAudio = fopen("/tmp/audio.g711", "a+"); // TODO: + mFileVideo = fopen("/tmp/video.h264", "a+"); // TODO: +} +void SaveStream::UnInit(void) +{ + if (mFileAudio) { + fclose(mFileAudio); + mFileAudio = nullptr; + } + if (mFileVideo) { + fclose(mFileVideo); + mFileVideo = nullptr; + } +} +void SaveStream::GetVideoStream(const void *stream, const int &length, const unsigned long long &timeStamp) +{ + if (mFileVideo) { + fwrite(stream, 1, length, mFileVideo); + fflush(mFileVideo); + } +} +void SaveStream::GetAudioStream(const void *stream, const int &length, const unsigned long long &timeStamp) +{ + if (mFileAudio) { + fwrite(stream, 1, length, mFileAudio); + fflush(mFileAudio); + } +} \ No newline at end of file diff --git a/middleware/MediaManager/src/SaveStream.h b/middleware/MediaManager/src/SaveStream.h new file mode 100644 index 0000000..9120282 --- /dev/null +++ b/middleware/MediaManager/src/SaveStream.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SAVE_STREAM_H +#define SAVE_STREAM_H +#include "VStreamHandle.h" +#include +class SaveStream : public VStreamHandle +{ +public: + SaveStream(); + virtual ~SaveStream() = default; + void Init(void) override; + void UnInit(void) override; + void GetVideoStream(const void *stream, const int &length, const unsigned long long &timeStamp) override; + void GetAudioStream(const void *stream, const int &length, const unsigned long long &timeStamp) override; + +private: + FILE *mFileAudio; + FILE *mFileVideo; +}; +#endif \ No newline at end of file diff --git a/middleware/MediaManager/src/VStreamHandle.cpp b/middleware/MediaManager/src/VStreamHandle.cpp new file mode 100644 index 0000000..431fbe3 --- /dev/null +++ b/middleware/MediaManager/src/VStreamHandle.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "VStreamHandle.h" +void VStreamHandle::Init(void) +{ +} +void VStreamHandle::UnInit(void) +{ +} +void VStreamHandle::GetVideoStream(const void *stream, const int &length, const unsigned long long &timeStamp) +{ +} +void VStreamHandle::GetAudioStream(const void *stream, const int &length, const unsigned long long &timeStamp) +{ +} \ No newline at end of file diff --git a/middleware/MediaManager/src/VStreamHandle.h b/middleware/MediaManager/src/VStreamHandle.h new file mode 100644 index 0000000..047aa5c --- /dev/null +++ b/middleware/MediaManager/src/VStreamHandle.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef V_STREAM_HANDLE_H +#define V_STREAM_HANDLE_H +class VStreamHandle +{ +public: + VStreamHandle() = default; + virtual ~VStreamHandle() = default; + virtual void Init(void); + virtual void UnInit(void); + virtual void GetVideoStream(const void *stream, const int &length, const unsigned long long &timeStamp); + virtual void GetAudioStream(const void *stream, const int &length, const unsigned long long &timeStamp); +}; +#endif \ No newline at end of file diff --git a/test/application/HuntingCamera/src_mock/MediaManager_Mock_Test.cpp b/test/application/HuntingCamera/src_mock/MediaManager_Mock_Test.cpp index dc5844e..dff135c 100644 --- a/test/application/HuntingCamera/src_mock/MediaManager_Mock_Test.cpp +++ b/test/application/HuntingCamera/src_mock/MediaManager_Mock_Test.cpp @@ -32,7 +32,6 @@ TEST_F(HuntingCameraTest, INTEGRATION_HunttingCamera_EXAMPLE_MediaReprot) MockReportCameraEvent("/tmp/test.MP4", CameraType::MAIN_CAMERA); CreateUpgradeFile(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - // McuManagerTestTool::MockMcuDeviceOpenFailed(mLinuxTest); MainThread::GetInstance()->Init(); TestManager::ResetTimeOut(1000 * 4); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -40,4 +39,17 @@ TEST_F(HuntingCameraTest, INTEGRATION_HunttingCamera_EXAMPLE_MediaReprot) MainThread::GetInstance()->Runing(); RemoveUpgradeFile(); } +// ../output_files/test/bin/HuntingCameraTest +// --gtest_filter=HuntingCameraTest.INTEGRATION_HunttingCamera_EXAMPLE_MediaTask +TEST_F(HuntingCameraTest, INTEGRATION_HunttingCamera_EXAMPLE_MediaTask) +{ + McuManagerTestTool::MockOtherSideIpcMissionReply(IpcMission::TEST); + SetAllCamerasResult(mAllCamerasMock); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + MainThread::GetInstance()->Init(); + TestManager::ResetTimeOut(1000 * 15); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + HalTestTool::MockKeyClick("reset", 200); // Simulate pressing a button. + MainThread::GetInstance()->Runing(); +} } // namespace MediaManager_Mock_Test \ No newline at end of file