mirror of
https://gitee.com/jiuyilian/embedded-framework.git
synced 2025-01-06 10:16:51 -05:00
Merge branch 'master-develop' into without-testtool
This commit is contained in:
commit
b530437393
|
@ -31,6 +31,7 @@ enum class InternalStateEvent
|
||||||
KEY_EVENT_HANDLE,
|
KEY_EVENT_HANDLE,
|
||||||
RESET_KEY_MEDIA_TASK,
|
RESET_KEY_MEDIA_TASK,
|
||||||
MEDIA_HANDLE_STATE_TASK_TIME_OUT,
|
MEDIA_HANDLE_STATE_TASK_TIME_OUT,
|
||||||
|
MEDIA_HANDLE_STATE_TASK_FINISHED,
|
||||||
END
|
END
|
||||||
};
|
};
|
||||||
typedef struct key_event_data
|
typedef struct key_event_data
|
||||||
|
|
|
@ -16,11 +16,14 @@
|
||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "IStateMachine.h"
|
#include "IStateMachine.h"
|
||||||
|
#include "MissionStateMachine.h"
|
||||||
|
#include <functional>
|
||||||
IdleState::IdleState() : State("IdleState")
|
IdleState::IdleState() : State("IdleState")
|
||||||
{
|
{
|
||||||
// mEventHandle[InternalStateEvent::MEDIA_REPORT_EVENT] = std::bind(&IdleState::MediaReportHandle, this, _1);
|
// mEventHandle[InternalStateEvent::MEDIA_REPORT_EVENT] = std::bind(&IdleState::MediaReportHandle, this, _1);
|
||||||
// mEventHandle[InternalStateEvent::SD_CARD_HANDLE_STATE_SD_STATUS_REPORTED] =
|
// mEventHandle[InternalStateEvent::SD_CARD_HANDLE_STATE_SD_STATUS_REPORTED] =
|
||||||
// std::bind(&IdleState::SdCardEventHandle, this, _1);
|
// std::bind(&IdleState::SdCardEventHandle, this, _1);
|
||||||
|
mEventHandle[InternalStateEvent::RESET_KEY_MEDIA_TASK] = std::bind(&IdleState::ResetKeyMediaTaskHandle, this, _1);
|
||||||
}
|
}
|
||||||
void IdleState::GoInState()
|
void IdleState::GoInState()
|
||||||
{
|
{
|
||||||
|
@ -34,3 +37,9 @@ bool IdleState::ExecuteStateMsg(VStateMachineData *msg)
|
||||||
{
|
{
|
||||||
return DataProcessing::EventHandle(msg);
|
return DataProcessing::EventHandle(msg);
|
||||||
}
|
}
|
||||||
|
bool IdleState::ResetKeyMediaTaskHandle(VStateMachineData *msg)
|
||||||
|
{
|
||||||
|
MissionStateMachine::GetInstance()->DelayMessage(msg);
|
||||||
|
MissionStateMachine::GetInstance()->SwitchState(SystemState::STORAGE_HANDLE_STATE);
|
||||||
|
return EXECUTED;
|
||||||
|
}
|
|
@ -25,6 +25,9 @@ public:
|
||||||
void GoOutState() override;
|
void GoOutState() override;
|
||||||
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ResetKeyMediaTaskHandle(VStateMachineData *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -14,9 +14,12 @@
|
||||||
*/
|
*/
|
||||||
#include "MediaHandleState.h"
|
#include "MediaHandleState.h"
|
||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
|
#include "IFilesManager.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
|
#include "IMissionManager.h"
|
||||||
#include "IStateMachine.h"
|
#include "IStateMachine.h"
|
||||||
|
#include "MediaTask.h"
|
||||||
#include "MediaTaskHandle.h"
|
#include "MediaTaskHandle.h"
|
||||||
#include "MissionStateMachine.h"
|
#include "MissionStateMachine.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -26,6 +29,8 @@ MediaHandleState::MediaHandleState() : State("MediaHandleState")
|
||||||
{
|
{
|
||||||
mEventHandle[InternalStateEvent::RESET_KEY_MEDIA_TASK] =
|
mEventHandle[InternalStateEvent::RESET_KEY_MEDIA_TASK] =
|
||||||
std::bind(&MediaHandleState::ResetKeyMediaTaskHandle, this, _1);
|
std::bind(&MediaHandleState::ResetKeyMediaTaskHandle, this, _1);
|
||||||
|
mEventHandle[InternalStateEvent::MEDIA_HANDLE_STATE_TASK_FINISHED] =
|
||||||
|
std::bind(&MediaHandleState::MediaTaskFinishedHandle, this, _1);
|
||||||
}
|
}
|
||||||
void MediaHandleState::GoInState()
|
void MediaHandleState::GoInState()
|
||||||
{
|
{
|
||||||
|
@ -42,11 +47,28 @@ bool MediaHandleState::ExecuteStateMsg(VStateMachineData *msg)
|
||||||
{
|
{
|
||||||
return DataProcessing::EventHandle(msg);
|
return DataProcessing::EventHandle(msg);
|
||||||
}
|
}
|
||||||
void MediaHandleState::TaskResponse(const std::vector<MediaTaskResponse> &response)
|
void MediaHandleState::TaskResponse(const MediaTaskInfo &taskinfo)
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<VMissionData> message = std::make_shared<VMissionDataV2<MediaTaskInfo>>(
|
||||||
|
static_cast<MissionEvent>(InternalStateEvent::MEDIA_HANDLE_STATE_TASK_FINISHED), taskinfo);
|
||||||
|
MissionStateMachine::GetInstance()->SendStateMessage(message);
|
||||||
}
|
}
|
||||||
bool MediaHandleState::ResetKeyMediaTaskHandle(VStateMachineData *msg)
|
bool MediaHandleState::ResetKeyMediaTaskHandle(VStateMachineData *msg)
|
||||||
{
|
{
|
||||||
MakeSingleTask(InternalStateEvent::RESET_KEY_MEDIA_TASK, shared_from_this());
|
MediaTaskHandle::MakeSingleTask(InternalStateEvent::RESET_KEY_MEDIA_TASK, shared_from_this());
|
||||||
|
return EXECUTED;
|
||||||
|
}
|
||||||
|
bool MediaHandleState::MediaTaskFinishedHandle(VStateMachineData *msg)
|
||||||
|
{
|
||||||
|
std::shared_ptr<MissionMessage> message = std::dynamic_pointer_cast<MissionMessage>(msg->GetMessageObj());
|
||||||
|
std::shared_ptr<VMissionDataV2<MediaTaskInfo>> data =
|
||||||
|
std::dynamic_pointer_cast<VMissionDataV2<MediaTaskInfo>>(message->mMissionData);
|
||||||
|
LogInfo("response files = %d.\n", data->mData.mResponse.size());
|
||||||
|
std::vector<SyncFileInfo> files;
|
||||||
|
for (auto &response : data->mData.mResponse) {
|
||||||
|
SyncFileInfo file(data->mData.mSerialNumber, response.mFileName, 0, 0, FileCreateType::END, FileStatus::END);
|
||||||
|
files.push_back(file);
|
||||||
|
}
|
||||||
|
IFilesManager::GetInstance()->SaveFiles(files);
|
||||||
return EXECUTED;
|
return EXECUTED;
|
||||||
}
|
}
|
|
@ -31,7 +31,8 @@ public:
|
||||||
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void TaskResponse(const std::vector<MediaTaskResponse> &response) override;
|
void TaskResponse(const MediaTaskInfo &taskinfo) override;
|
||||||
bool ResetKeyMediaTaskHandle(VStateMachineData *msg);
|
bool ResetKeyMediaTaskHandle(VStateMachineData *msg);
|
||||||
|
bool MediaTaskFinishedHandle(VStateMachineData *msg);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -14,11 +14,22 @@
|
||||||
*/
|
*/
|
||||||
#include "MediaTask.h"
|
#include "MediaTask.h"
|
||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
|
#include "ILog.h"
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
|
#include <cctype>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
MediaTask::MediaTask(const MediaTaskType &type, const InternalStateEvent &bindEvent,
|
MediaTask::MediaTask(const MediaTaskType &type, const InternalStateEvent &bindEvent,
|
||||||
const std::weak_ptr<VMediaTaskIniator> &iniator)
|
const std::weak_ptr<VMediaTaskIniator> &iniator, const unsigned long &serialNumber,
|
||||||
: mType(type), mBindEvent(bindEvent), mIniator(iniator)
|
const std::string &savePath)
|
||||||
|
: mType(type), mBindEvent(bindEvent), mIniator(iniator), mSerialNumber(serialNumber), mSavePath(savePath)
|
||||||
{
|
{
|
||||||
mResponseData.reset();
|
mResponseData.reset();
|
||||||
}
|
}
|
||||||
|
@ -26,3 +37,32 @@ unsigned int MediaTask::GetTaskTimeOutMs(void)
|
||||||
{
|
{
|
||||||
return MEDIA_TASK_TIMEOUT_MS;
|
return MEDIA_TASK_TIMEOUT_MS;
|
||||||
}
|
}
|
||||||
|
std::string MediaTask::GetTargetNameForSaving(void)
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
time_t t_now = std::chrono::system_clock::to_time_t(now);
|
||||||
|
struct tm tm_now = *std::localtime(&t_now);
|
||||||
|
|
||||||
|
int hour = tm_now.tm_hour;
|
||||||
|
int minute = tm_now.tm_min;
|
||||||
|
int second = tm_now.tm_sec;
|
||||||
|
|
||||||
|
std::ostringstream pathStream;
|
||||||
|
pathStream << mSavePath << std::setw(2) << std::setfill('0') << hour << std::setw(2) << std::setfill('0') << minute
|
||||||
|
<< std::setw(2) << std::setfill('0') << second << ".mp4";
|
||||||
|
return pathStream.str();
|
||||||
|
}
|
||||||
|
void MediaTask::Response(const std::vector<MediaTaskResponse> &response)
|
||||||
|
{
|
||||||
|
LogInfo("Response handle.\n");
|
||||||
|
auto iniator = mIniator.lock();
|
||||||
|
if (mIniator.expired()) {
|
||||||
|
LogWarning("mIniator is expired.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MediaTaskInfo info = {
|
||||||
|
.mResponse = response,
|
||||||
|
.mSerialNumber = mSerialNumber,
|
||||||
|
};
|
||||||
|
iniator->TaskResponse(info);
|
||||||
|
}
|
|
@ -16,26 +16,37 @@
|
||||||
#define MEDIA_TASK_H
|
#define MEDIA_TASK_H
|
||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
|
#include <string>
|
||||||
constexpr unsigned int MEDIA_TASK_TIMEOUT_MS = 1000 * 60;
|
constexpr unsigned int MEDIA_TASK_TIMEOUT_MS = 1000 * 60;
|
||||||
|
typedef struct media_task_info
|
||||||
|
{
|
||||||
|
const std::vector<MediaTaskResponse> mResponse;
|
||||||
|
const unsigned long mSerialNumber;
|
||||||
|
} MediaTaskInfo;
|
||||||
class VMediaTaskIniator
|
class VMediaTaskIniator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VMediaTaskIniator() = default;
|
VMediaTaskIniator() = default;
|
||||||
virtual ~VMediaTaskIniator() = default;
|
virtual ~VMediaTaskIniator() = default;
|
||||||
virtual void TaskResponse(const std::vector<MediaTaskResponse> &response) = 0;
|
virtual void TaskResponse(const MediaTaskInfo &taskinfo) = 0;
|
||||||
};
|
};
|
||||||
class MediaTask : public VMediaTask
|
class MediaTask : public VMediaTask
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MediaTask(const MediaTaskType &type, const InternalStateEvent &bindEvent,
|
MediaTask(const MediaTaskType &type, const InternalStateEvent &bindEvent,
|
||||||
const std::weak_ptr<VMediaTaskIniator> &iniator);
|
const std::weak_ptr<VMediaTaskIniator> &iniator, const unsigned long &serialNumber,
|
||||||
|
const std::string &savePath);
|
||||||
virtual ~MediaTask() = default;
|
virtual ~MediaTask() = default;
|
||||||
virtual unsigned int GetTaskTimeOutMs(void);
|
virtual unsigned int GetTaskTimeOutMs(void);
|
||||||
|
std::string GetTargetNameForSaving(void) override;
|
||||||
|
void Response(const std::vector<MediaTaskResponse> &response) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const MediaTaskType mType;
|
const MediaTaskType mType;
|
||||||
const InternalStateEvent mBindEvent;
|
const InternalStateEvent mBindEvent;
|
||||||
const std::weak_ptr<VMediaTaskIniator> mIniator;
|
const std::weak_ptr<VMediaTaskIniator> mIniator;
|
||||||
|
const unsigned long mSerialNumber;
|
||||||
|
const std::string mSavePath;
|
||||||
bool mFinished = false;
|
bool mFinished = false;
|
||||||
std::shared_ptr<MediaTaskResponse> mResponseData;
|
std::shared_ptr<MediaTaskResponse> mResponseData;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
#include "MediaTaskHandle.h"
|
#include "MediaTaskHandle.h"
|
||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
|
#include "IFilesManager.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
#include "IMissionManager.h"
|
#include "IMissionManager.h"
|
||||||
|
@ -38,14 +39,16 @@ void MediaTaskHandle::UnInit(void)
|
||||||
void MediaTaskHandle::MakeSingleTask(const InternalStateEvent &bindEvent,
|
void MediaTaskHandle::MakeSingleTask(const InternalStateEvent &bindEvent,
|
||||||
const std::shared_ptr<VMediaTaskIniator> &iniator)
|
const std::shared_ptr<VMediaTaskIniator> &iniator)
|
||||||
{
|
{
|
||||||
std::shared_ptr<VMediaTask> task = std::make_shared<MediaTask>(MediaTaskType::END, bindEvent, iniator);
|
InfoToBeSaved info = IFilesManager::GetInstance()->GetInfoForSavingFiles(1);
|
||||||
|
std::shared_ptr<VMediaTask> task =
|
||||||
|
std::make_shared<MediaTask>(MediaTaskType::END, bindEvent, iniator, info.mSerialNumber, info.mSavingPath);
|
||||||
if (!mMediaHandle) {
|
if (!mMediaHandle) {
|
||||||
LogError("MediaHandle is null");
|
LogError("MediaHandle is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto code = mMediaHandle->ExecuteTask(task);
|
auto code = mMediaHandle->ExecuteTask(task);
|
||||||
if (IsCodeOK(code)) {
|
if (IsCodeOK(code)) {
|
||||||
mRuningTask = task;
|
mRuningTask = task; // task should be saved here.
|
||||||
long long timeOut = std::dynamic_pointer_cast<MediaTask>(task)->GetTaskTimeOutMs();
|
long long timeOut = std::dynamic_pointer_cast<MediaTask>(task)->GetTaskTimeOutMs();
|
||||||
std::shared_ptr<VMissionData> message = std::make_shared<VMissionData>(
|
std::shared_ptr<VMissionData> message = std::make_shared<VMissionData>(
|
||||||
static_cast<MissionEvent>(InternalStateEvent::MEDIA_HANDLE_STATE_TASK_TIME_OUT));
|
static_cast<MissionEvent>(InternalStateEvent::MEDIA_HANDLE_STATE_TASK_TIME_OUT));
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "McuAskBase.h"
|
#include "McuAskBase.h"
|
||||||
#include "MissionManagerMakePtr.h"
|
#include "MissionManagerMakePtr.h"
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
|
#include "VStateBase.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
// #include "TopState.h"
|
// #include "TopState.h"
|
||||||
std::shared_ptr<MissionStateMachine> &MissionStateMachine::GetInstance(std::shared_ptr<MissionStateMachine> *impl)
|
std::shared_ptr<MissionStateMachine> &MissionStateMachine::GetInstance(std::shared_ptr<MissionStateMachine> *impl)
|
||||||
|
@ -57,6 +58,7 @@ void MissionStateMachine::Init(void)
|
||||||
void MissionStateMachine::UnInit(void)
|
void MissionStateMachine::UnInit(void)
|
||||||
{
|
{
|
||||||
mStateMachine->StopHandlerThread();
|
mStateMachine->StopHandlerThread();
|
||||||
|
UnInitAllState();
|
||||||
mStateTree.clear();
|
mStateTree.clear();
|
||||||
}
|
}
|
||||||
StatusCode MissionStateMachine::SendStateMessage(const std::shared_ptr<VMissionData> &message)
|
StatusCode MissionStateMachine::SendStateMessage(const std::shared_ptr<VMissionData> &message)
|
||||||
|
@ -119,11 +121,30 @@ void MissionStateMachine::RunStateMachine(const IpcMission &mission)
|
||||||
mStateMachine->StatePlus(mStateTree[SystemState::IDLE_STATE].get(), mStateTree[SystemState::MISSION_STATE].get());
|
mStateMachine->StatePlus(mStateTree[SystemState::IDLE_STATE].get(), mStateTree[SystemState::MISSION_STATE].get());
|
||||||
mStateMachine->SetCurrentState(mStateTree[SystemState::TOP_STATE].get());
|
mStateMachine->SetCurrentState(mStateTree[SystemState::TOP_STATE].get());
|
||||||
mStateMachine->StartStateMachine();
|
mStateMachine->StartStateMachine();
|
||||||
/**
|
// /**
|
||||||
* @brief The business can only be processed after the state machine is started.
|
// * @brief The business can only be processed after the state machine is started.
|
||||||
*
|
// *
|
||||||
*/
|
// */
|
||||||
std::shared_ptr<VMissionData> message =
|
// std::shared_ptr<VMissionData> message =
|
||||||
std::make_shared<VMissionData>(static_cast<MissionEvent>(InternalStateEvent::STORAGE_HANDLE_STATE_INIT));
|
// std::make_shared<VMissionData>(static_cast<MissionEvent>(InternalStateEvent::STORAGE_HANDLE_STATE_INIT));
|
||||||
SendStateMessage(message);
|
// SendStateMessage(message);
|
||||||
|
InitAllState();
|
||||||
|
}
|
||||||
|
void MissionStateMachine::InitAllState(void)
|
||||||
|
{
|
||||||
|
for (auto &state : mStateTree) {
|
||||||
|
std::shared_ptr<VStateBase> stateBase = std::dynamic_pointer_cast<VStateBase>(state.second);
|
||||||
|
if (stateBase) {
|
||||||
|
stateBase->StateInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void MissionStateMachine::UnInitAllState(void)
|
||||||
|
{
|
||||||
|
for (auto &state : mStateTree) {
|
||||||
|
std::shared_ptr<VStateBase> stateBase = std::dynamic_pointer_cast<VStateBase>(state.second);
|
||||||
|
if (stateBase) {
|
||||||
|
stateBase->StateUnInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
const bool NOT_EXECUTED = false;
|
const bool NOT_EXECUTED = false;
|
||||||
const bool EXECUTED = true;
|
const bool EXECUTED = true;
|
||||||
|
constexpr bool FATHER_HANDLE_MESSAGE = NOT_EXECUTED;
|
||||||
|
constexpr bool HANDLE_HELPESS = EXECUTED;
|
||||||
enum class SystemState
|
enum class SystemState
|
||||||
{
|
{
|
||||||
TOP_STATE = 0,
|
TOP_STATE = 0,
|
||||||
|
@ -49,6 +51,8 @@ public:
|
||||||
private:
|
private:
|
||||||
IpcMission GetStartMission(void);
|
IpcMission GetStartMission(void);
|
||||||
void RunStateMachine(const IpcMission &mission);
|
void RunStateMachine(const IpcMission &mission);
|
||||||
|
void InitAllState(void);
|
||||||
|
void UnInitAllState(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<VStateMachineHandle> mStateMachine;
|
std::shared_ptr<VStateMachineHandle> mStateMachine;
|
||||||
|
|
|
@ -30,6 +30,8 @@ SdCardHandleState::SdCardHandleState() : State("SdCardHandleState"), mSdCardStat
|
||||||
mEventHandle[InternalStateEvent::MEDIA_REPORT_EVENT] = std::bind(&SdCardHandleState::MediaReportHandle, this, _1);
|
mEventHandle[InternalStateEvent::MEDIA_REPORT_EVENT] = std::bind(&SdCardHandleState::MediaReportHandle, this, _1);
|
||||||
mEventHandle[InternalStateEvent::SD_CARD_HANDLE_STATE_SD_STATUS_REPORTED] =
|
mEventHandle[InternalStateEvent::SD_CARD_HANDLE_STATE_SD_STATUS_REPORTED] =
|
||||||
std::bind(&SdCardHandleState::SdCardEventHandle, this, _1);
|
std::bind(&SdCardHandleState::SdCardEventHandle, this, _1);
|
||||||
|
mEventHandle[InternalStateEvent::RESET_KEY_MEDIA_TASK] =
|
||||||
|
std::bind(&SdCardHandleState::ResetKeyMediaTaskHandle, this, _1);
|
||||||
}
|
}
|
||||||
void SdCardHandleState::GoInState()
|
void SdCardHandleState::GoInState()
|
||||||
{
|
{
|
||||||
|
@ -43,6 +45,13 @@ bool SdCardHandleState::ExecuteStateMsg(VStateMachineData *msg)
|
||||||
{
|
{
|
||||||
return DataProcessing::EventHandle(msg);
|
return DataProcessing::EventHandle(msg);
|
||||||
}
|
}
|
||||||
|
void SdCardHandleState::StateInit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SdCardHandleState::StateUnInit(void)
|
||||||
|
{
|
||||||
|
IFilesManager::GetInstance()->UnInit();
|
||||||
|
}
|
||||||
bool SdCardHandleState::MediaReportHandle(VStateMachineData *msg)
|
bool SdCardHandleState::MediaReportHandle(VStateMachineData *msg)
|
||||||
{
|
{
|
||||||
LogInfo(" MediaReportHandle.\n");
|
LogInfo(" MediaReportHandle.\n");
|
||||||
|
@ -86,9 +95,18 @@ bool SdCardHandleState::SdCardEventHandle(VStateMachineData *msg)
|
||||||
}
|
}
|
||||||
mSdCardStatus = data->mData;
|
mSdCardStatus = data->mData;
|
||||||
if (StorageEvent::SD_CARD_INSERT == mSdCardStatus) {
|
if (StorageEvent::SD_CARD_INSERT == mSdCardStatus) {
|
||||||
|
IFilesManager::GetInstance()->Init();
|
||||||
std::shared_ptr<VMissionData> message =
|
std::shared_ptr<VMissionData> message =
|
||||||
std::make_shared<VMissionData>(static_cast<MissionEvent>(InternalStateEvent::CHECK_UPGRADE_FILE));
|
std::make_shared<VMissionData>(static_cast<MissionEvent>(InternalStateEvent::CHECK_UPGRADE_FILE));
|
||||||
MissionStateMachine::GetInstance()->SendStateMessage(message);
|
MissionStateMachine::GetInstance()->SendStateMessage(message);
|
||||||
}
|
}
|
||||||
return EXECUTED;
|
return EXECUTED;
|
||||||
}
|
}
|
||||||
|
bool SdCardHandleState::ResetKeyMediaTaskHandle(VStateMachineData *msg)
|
||||||
|
{
|
||||||
|
if (StorageEvent::SD_CARD_INSERT == mSdCardStatus) {
|
||||||
|
return FATHER_HANDLE_MESSAGE;
|
||||||
|
}
|
||||||
|
LogWarning("Sd card is not inserted, ignore reset key media task.\n");
|
||||||
|
return HANDLE_HELPESS;
|
||||||
|
}
|
|
@ -19,7 +19,11 @@
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
#include "IStateMachine.h"
|
#include "IStateMachine.h"
|
||||||
#include "IStorageManager.h"
|
#include "IStorageManager.h"
|
||||||
class SdCardHandleState : public State, public DataProcessing, public std::enable_shared_from_this<SdCardHandleState>
|
#include "VStateBase.h"
|
||||||
|
class SdCardHandleState : public State,
|
||||||
|
public DataProcessing,
|
||||||
|
public VStateBase,
|
||||||
|
public std::enable_shared_from_this<SdCardHandleState>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SdCardHandleState();
|
SdCardHandleState();
|
||||||
|
@ -29,8 +33,11 @@ public:
|
||||||
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
bool ExecuteStateMsg(VStateMachineData *msg) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void StateInit(void) override;
|
||||||
|
void StateUnInit(void) override;
|
||||||
bool MediaReportHandle(VStateMachineData *msg);
|
bool MediaReportHandle(VStateMachineData *msg);
|
||||||
bool SdCardEventHandle(VStateMachineData *msg);
|
bool SdCardEventHandle(VStateMachineData *msg);
|
||||||
|
bool ResetKeyMediaTaskHandle(VStateMachineData *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StorageEvent mSdCardStatus;
|
StorageEvent mSdCardStatus;
|
||||||
|
|
|
@ -19,12 +19,11 @@
|
||||||
#include "IStateMachine.h"
|
#include "IStateMachine.h"
|
||||||
#include "IStorageManager.h"
|
#include "IStorageManager.h"
|
||||||
#include "MissionStateMachine.h"
|
#include "MissionStateMachine.h"
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
StorageHandleState::StorageHandleState() : State("StorageHandleState")
|
StorageHandleState::StorageHandleState() : State("StorageHandleState")
|
||||||
{
|
{
|
||||||
mEventHandle[InternalStateEvent::STORAGE_HANDLE_STATE_INIT] =
|
// mEventHandle[InternalStateEvent::STORAGE_HANDLE_STATE_INIT] =
|
||||||
std::bind(&StorageHandleState::StorageStartInitHandle, this, _1);
|
// std::bind(&StorageHandleState::StorageStartInitHandle, this, _1);
|
||||||
}
|
}
|
||||||
void StorageHandleState::GoInState()
|
void StorageHandleState::GoInState()
|
||||||
{
|
{
|
||||||
|
@ -57,8 +56,10 @@ void StorageHandleState::ReportEvent(const StorageEvent &event)
|
||||||
static_cast<MissionEvent>(InternalStateEvent::ANY_STATE_SD_STATUS_PERORIED), event);
|
static_cast<MissionEvent>(InternalStateEvent::ANY_STATE_SD_STATUS_PERORIED), event);
|
||||||
MissionStateMachine::GetInstance()->SendStateMessage(message2);
|
MissionStateMachine::GetInstance()->SendStateMessage(message2);
|
||||||
}
|
}
|
||||||
bool StorageHandleState::StorageStartInitHandle(VStateMachineData *msg)
|
void StorageHandleState::StateInit(void)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
return EXECUTED;
|
}
|
||||||
|
void StorageHandleState::StateUnInit(void)
|
||||||
|
{
|
||||||
}
|
}
|
|
@ -18,9 +18,11 @@
|
||||||
#include "IMediaManager.h"
|
#include "IMediaManager.h"
|
||||||
#include "IStateMachine.h"
|
#include "IStateMachine.h"
|
||||||
#include "IStorageManager.h"
|
#include "IStorageManager.h"
|
||||||
|
#include "VStateBase.h"
|
||||||
class StorageHandleState : public State,
|
class StorageHandleState : public State,
|
||||||
public DataProcessing,
|
public DataProcessing,
|
||||||
public VStorageMoniter,
|
public VStorageMoniter,
|
||||||
|
public VStateBase,
|
||||||
public std::enable_shared_from_this<StorageHandleState>
|
public std::enable_shared_from_this<StorageHandleState>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -34,6 +36,7 @@ public:
|
||||||
|
|
||||||
private: // About VStorageMoniter
|
private: // About VStorageMoniter
|
||||||
void ReportEvent(const StorageEvent &event) override;
|
void ReportEvent(const StorageEvent &event) override;
|
||||||
bool StorageStartInitHandle(VStateMachineData *msg);
|
void StateInit(void) override;
|
||||||
|
void StateUnInit(void) override;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -24,12 +24,11 @@
|
||||||
#include "McuMonitor.h"
|
#include "McuMonitor.h"
|
||||||
#include "MissionStateMachine.h"
|
#include "MissionStateMachine.h"
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
TopState::TopState() : State("TopState")
|
TopState::TopState() : State("TopState")
|
||||||
{
|
{
|
||||||
mEventHandle[InternalStateEvent::STORAGE_HANDLE_STATE_INIT] =
|
// mEventHandle[InternalStateEvent::STORAGE_HANDLE_STATE_INIT] =
|
||||||
std::bind(&TopState::StorageStartInitHandle, this, _1);
|
// std::bind(&TopState::StorageStartInitHandle, this, _1);
|
||||||
}
|
}
|
||||||
void TopState::GoInState()
|
void TopState::GoInState()
|
||||||
{
|
{
|
||||||
|
@ -69,9 +68,3 @@ void TopState::KeyEventReport(const std::string &keyName, const VirtualKeyEvent
|
||||||
static_cast<MissionEvent>(InternalStateEvent::KEY_EVENT_HANDLE), data);
|
static_cast<MissionEvent>(InternalStateEvent::KEY_EVENT_HANDLE), data);
|
||||||
MissionStateMachine::GetInstance()->SendStateMessage(message);
|
MissionStateMachine::GetInstance()->SendStateMessage(message);
|
||||||
}
|
}
|
||||||
bool TopState::StorageStartInitHandle(VStateMachineData *msg)
|
|
||||||
{
|
|
||||||
MissionStateMachine::GetInstance()->DelayMessage(msg);
|
|
||||||
MissionStateMachine::GetInstance()->SwitchState(SystemState::STORAGE_HANDLE_STATE);
|
|
||||||
return EXECUTED;
|
|
||||||
}
|
|
|
@ -38,8 +38,5 @@ private: // About VMediaMonitor
|
||||||
|
|
||||||
private: // About KeyMonitor
|
private: // About KeyMonitor
|
||||||
void KeyEventReport(const std::string &keyName, const VirtualKeyEvent &event, const unsigned int &timeMs) override;
|
void KeyEventReport(const std::string &keyName, const VirtualKeyEvent &event, const unsigned int &timeMs) override;
|
||||||
|
|
||||||
private:
|
|
||||||
bool StorageStartInitHandle(VStateMachineData *msg);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
21
application/MissionManager/src/VStateBase.cpp
Normal file
21
application/MissionManager/src/VStateBase.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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 "VStateBase.h"
|
||||||
|
void VStateBase::StateInit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void VStateBase::StateUnInit(void)
|
||||||
|
{
|
||||||
|
}
|
25
application/MissionManager/src/VStateBase.h
Normal file
25
application/MissionManager/src/VStateBase.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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_STATE_BASE_H
|
||||||
|
#define V_STATE_BASE_H
|
||||||
|
class VStateBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VStateBase() = default;
|
||||||
|
virtual ~VStateBase() = default;
|
||||||
|
virtual void StateInit(void);
|
||||||
|
virtual void StateUnInit(void);
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -10,8 +10,27 @@
|
||||||
|
|
||||||
### 1.2.1. 数据库表
|
### 1.2.1. 数据库表
|
||||||
|
|
||||||
|
**文件保存表**
|
||||||
|
|
||||||
|
| key | 路径 | 时间 | 类型 | 大小 | 状态 |
|
||||||
|
| ---- | ---- | ---- | ---- | ---- | ---- |
|
||||||
|
| 数据库键值 | 文件保存的相对路径 | 录制的时间<br>可能不准确 | 录制的类型:<br>PIR<br>手动<br>手机app<br>定时 | 文件大小 | 枚举:<br>正在拍摄<br>已完成拍摄<br>待上传<br>正在上传<br>上传完成 |
|
||||||
|
|
||||||
|
**如何应对未知的数据表临加**
|
||||||
|
|
||||||
|
解决基于一个已存在的数据库文件,临加数据元素。
|
||||||
|
|
||||||
|
拍摄流程:
|
||||||
|
|
||||||
|
1. 拍摄前先创建数据,获取唯一自增键值;
|
||||||
|
2. 拍摄结束后,更新数据状态为已完成;
|
||||||
|
|
||||||
|
**状态使用TEXT数据类型,如果使用枚举,可能会存在枚举值变化导致的bug。**
|
||||||
|
|
||||||
## 1.3. 文件夹管理
|
## 1.3. 文件夹管理
|
||||||
|
|
||||||
|
**目录树**
|
||||||
|
|
||||||
```
|
```
|
||||||
DCIM/ // 根目录
|
DCIM/ // 根目录
|
||||||
├── picture // 图片目录
|
├── picture // 图片目录
|
||||||
|
@ -25,6 +44,10 @@ DCIM/ // 根目录
|
||||||
└── xxx.MP4
|
└── xxx.MP4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**野数据**
|
||||||
|
|
||||||
|
  插入一些非软件保存文件的sd卡时,忽略这些数据(不做任何处理)。
|
||||||
|
|
||||||
## 1.4. 文件命名规则
|
## 1.4. 文件命名规则
|
||||||
|
|
||||||
**文件类型**
|
**文件类型**
|
||||||
|
@ -32,3 +55,7 @@ DCIM/ // 根目录
|
||||||
1. PIR抓拍;
|
1. PIR抓拍;
|
||||||
2. 定时抓拍;
|
2. 定时抓拍;
|
||||||
3. 手动抓拍;
|
3. 手动抓拍;
|
||||||
|
|
||||||
|
**文件名命名规则**
|
||||||
|
|
||||||
|
基于文件保存表的数据元素:类型+时间+key
|
||||||
|
|
|
@ -16,11 +16,51 @@
|
||||||
#define I_FILES_MANAGER_H
|
#define I_FILES_MANAGER_H
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <vector>
|
||||||
|
enum class FileCreateType
|
||||||
|
{
|
||||||
|
PIR = 0,
|
||||||
|
MANUAL_TEST,
|
||||||
|
MANUAL_PHONE,
|
||||||
|
TIMED,
|
||||||
|
END
|
||||||
|
};
|
||||||
|
enum class FileStatus
|
||||||
|
{
|
||||||
|
RECORDING = 0,
|
||||||
|
FINISHED_RECORD,
|
||||||
|
SHOULD_BE_UPLOAD,
|
||||||
|
UPLOADING,
|
||||||
|
UPLOADED,
|
||||||
|
END
|
||||||
|
};
|
||||||
|
constexpr unsigned long UNDEFINE_SERIAL_NUMBER = -1;
|
||||||
|
constexpr unsigned long UNDEFINE_FILE_SIZE = 0;
|
||||||
|
constexpr time_t UNDEFINE_CREATE_TIME = -1;
|
||||||
|
typedef struct sync_file_info
|
||||||
|
{
|
||||||
|
sync_file_info(const unsigned long &serialNumber, const std::string &fileName, const unsigned long &fileSize,
|
||||||
|
const time_t &createTime_s, const FileCreateType &type, const FileStatus &status);
|
||||||
|
const unsigned long mSerialNumber;
|
||||||
|
const std::string mFileName;
|
||||||
|
const unsigned long mFileSize;
|
||||||
|
const time_t mCreateTime_s;
|
||||||
|
const FileCreateType mType;
|
||||||
|
const FileStatus mStatus;
|
||||||
|
} SyncFileInfo;
|
||||||
typedef struct save_file_info
|
typedef struct save_file_info
|
||||||
{
|
{
|
||||||
save_file_info(const std::string &fileName);
|
save_file_info(const std::string &fileName);
|
||||||
const std::string mFileName;
|
const std::string mFileName;
|
||||||
} SaveFileInfo;
|
} SaveFileInfo;
|
||||||
|
typedef struct info_to_be_saved
|
||||||
|
{
|
||||||
|
info_to_be_saved(const unsigned long &serialNumber, const std::string mSavingPath);
|
||||||
|
const unsigned long mSerialNumber;
|
||||||
|
const std::string mSavingPath;
|
||||||
|
} InfoToBeSaved;
|
||||||
bool CreateFilesManagerModule(void);
|
bool CreateFilesManagerModule(void);
|
||||||
bool DestroyFilesManagerModule(void);
|
bool DestroyFilesManagerModule(void);
|
||||||
class IFilesManager
|
class IFilesManager
|
||||||
|
@ -32,5 +72,7 @@ public:
|
||||||
virtual StatusCode Init(void);
|
virtual StatusCode Init(void);
|
||||||
virtual StatusCode UnInit(void);
|
virtual StatusCode UnInit(void);
|
||||||
virtual StatusCode SaveFile(const SaveFileInfo &fileInfo);
|
virtual StatusCode SaveFile(const SaveFileInfo &fileInfo);
|
||||||
|
virtual InfoToBeSaved GetInfoForSavingFiles(const unsigned int &count);
|
||||||
|
virtual StatusCode SaveFiles(const std::vector<SyncFileInfo> &info);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -24,6 +24,8 @@ public:
|
||||||
virtual ~FilesDatabase() = default;
|
virtual ~FilesDatabase() = default;
|
||||||
void Init(void);
|
void Init(void);
|
||||||
void UnInit(void);
|
void UnInit(void);
|
||||||
StatusCode DatabaseSaveFile(const SaveFileInfo &fileInfo);
|
StatusCode DbSaveFile(const SaveFileInfo &fileInfo);
|
||||||
|
InfoToBeSaved CreateInfoForSavingFiles(const unsigned int &count);
|
||||||
|
StatusCode DbSaveFiles(const std::vector<SyncFileInfo> &info);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -17,6 +17,7 @@
|
||||||
// #include "IStorageManager.h"
|
// #include "IStorageManager.h"
|
||||||
#include "FilesDatabase.h"
|
#include "FilesDatabase.h"
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
|
#include <vector>
|
||||||
StatusCode FilesManagerImpl::Init(void)
|
StatusCode FilesManagerImpl::Init(void)
|
||||||
{
|
{
|
||||||
FilesDatabase::Init();
|
FilesDatabase::Init();
|
||||||
|
@ -24,9 +25,18 @@ StatusCode FilesManagerImpl::Init(void)
|
||||||
}
|
}
|
||||||
StatusCode FilesManagerImpl::UnInit(void)
|
StatusCode FilesManagerImpl::UnInit(void)
|
||||||
{
|
{
|
||||||
|
FilesDatabase::UnInit();
|
||||||
return CreateStatusCode(STATUS_CODE_OK);
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
}
|
}
|
||||||
StatusCode FilesManagerImpl::SaveFile(const SaveFileInfo &fileInfo)
|
StatusCode FilesManagerImpl::SaveFile(const SaveFileInfo &fileInfo)
|
||||||
{
|
{
|
||||||
return FilesDatabase::DatabaseSaveFile(fileInfo);
|
return FilesDatabase::DbSaveFile(fileInfo);
|
||||||
|
}
|
||||||
|
InfoToBeSaved FilesManagerImpl::GetInfoForSavingFiles(const unsigned int &count)
|
||||||
|
{
|
||||||
|
return FilesDatabase::CreateInfoForSavingFiles(count);
|
||||||
|
}
|
||||||
|
StatusCode FilesManagerImpl::SaveFiles(const std::vector<SyncFileInfo> &info)
|
||||||
|
{
|
||||||
|
return FilesDatabase::DbSaveFiles(info);
|
||||||
}
|
}
|
|
@ -27,5 +27,7 @@ protected:
|
||||||
StatusCode Init(void) override;
|
StatusCode Init(void) override;
|
||||||
StatusCode UnInit(void) override;
|
StatusCode UnInit(void) override;
|
||||||
StatusCode SaveFile(const SaveFileInfo &fileInfo) override;
|
StatusCode SaveFile(const SaveFileInfo &fileInfo) override;
|
||||||
|
InfoToBeSaved GetInfoForSavingFiles(const unsigned int &count) override;
|
||||||
|
StatusCode SaveFiles(const std::vector<SyncFileInfo> &info) override;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -17,9 +17,22 @@
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <time.h>
|
||||||
|
#include <vector>
|
||||||
save_file_info::save_file_info(const std::string &fileName) : mFileName(fileName)
|
save_file_info::save_file_info(const std::string &fileName) : mFileName(fileName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
sync_file_info::sync_file_info(const unsigned long &serialNumber, const std::string &fileName,
|
||||||
|
const unsigned long &fileSize, const time_t &createTime_s, const FileCreateType &type,
|
||||||
|
const FileStatus &status)
|
||||||
|
: mSerialNumber(serialNumber), mFileName(fileName), mFileSize(fileSize), mCreateTime_s(createTime_s), mType(type),
|
||||||
|
mStatus(status)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
info_to_be_saved::info_to_be_saved(const unsigned long &serialNumber, const std::string mSavingPath)
|
||||||
|
: mSerialNumber(serialNumber), mSavingPath(mSavingPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
std::shared_ptr<IFilesManager> &IFilesManager::GetInstance(std::shared_ptr<IFilesManager> *impl)
|
std::shared_ptr<IFilesManager> &IFilesManager::GetInstance(std::shared_ptr<IFilesManager> *impl)
|
||||||
{
|
{
|
||||||
static auto instance = std::make_shared<IFilesManager>();
|
static auto instance = std::make_shared<IFilesManager>();
|
||||||
|
@ -36,13 +49,27 @@ std::shared_ptr<IFilesManager> &IFilesManager::GetInstance(std::shared_ptr<IFile
|
||||||
}
|
}
|
||||||
StatusCode IFilesManager::Init(void)
|
StatusCode IFilesManager::Init(void)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
StatusCode IFilesManager::UnInit(void)
|
StatusCode IFilesManager::UnInit(void)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
StatusCode IFilesManager::SaveFile(const SaveFileInfo &fileInfo)
|
StatusCode IFilesManager::SaveFile(const SaveFileInfo &fileInfo)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
|
}
|
||||||
|
InfoToBeSaved IFilesManager::GetInfoForSavingFiles(const unsigned int &count)
|
||||||
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
InfoToBeSaved info(0, ".");
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
StatusCode IFilesManager::SaveFiles(const std::vector<SyncFileInfo> &info)
|
||||||
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
|
@ -20,15 +20,19 @@
|
||||||
#include "SqliteHandle.h"
|
#include "SqliteHandle.h"
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#define DATABASE_FILE_NAME "/files.db"
|
||||||
void FilesDatabase::Init(void)
|
void FilesDatabase::Init(void)
|
||||||
{
|
{
|
||||||
SqliteHandle::GetInstance()->Init();
|
std::string dbPath = IStorageManager::GetInstance()->GetFilesDatabasePath();
|
||||||
|
LogInfo("Database path:%s\n", (dbPath + DATABASE_FILE_NAME).c_str());
|
||||||
|
SqliteHandle::GetInstance()->Init(dbPath + DATABASE_FILE_NAME);
|
||||||
}
|
}
|
||||||
void FilesDatabase::UnInit(void)
|
void FilesDatabase::UnInit(void)
|
||||||
{
|
{
|
||||||
SqliteHandle::GetInstance()->UnInit();
|
SqliteHandle::GetInstance()->UnInit();
|
||||||
}
|
}
|
||||||
StatusCode FilesDatabase::DatabaseSaveFile(const SaveFileInfo &fileInfo)
|
StatusCode FilesDatabase::DbSaveFile(const SaveFileInfo &fileInfo)
|
||||||
{
|
{
|
||||||
std::string saveFile = FilesHandle::CreateFilePathName(fileInfo.mFileName);
|
std::string saveFile = FilesHandle::CreateFilePathName(fileInfo.mFileName);
|
||||||
LogInfo("Save file:%s\n", saveFile.c_str());
|
LogInfo("Save file:%s\n", saveFile.c_str());
|
||||||
|
@ -43,3 +47,21 @@ StatusCode FilesDatabase::DatabaseSaveFile(const SaveFileInfo &fileInfo)
|
||||||
}
|
}
|
||||||
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
}
|
}
|
||||||
|
InfoToBeSaved FilesDatabase::CreateInfoForSavingFiles(const unsigned int &count)
|
||||||
|
{
|
||||||
|
const unsigned long key = SqliteHandle::GetInstance()->CreateFiles(count);
|
||||||
|
std::string savingPath = IStorageManager::GetInstance()->GetFilesSavingPath();
|
||||||
|
InfoToBeSaved info(key, savingPath);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
StatusCode FilesDatabase::DbSaveFiles(const std::vector<SyncFileInfo> &info)
|
||||||
|
{
|
||||||
|
for (auto &each : info) {
|
||||||
|
bool result = SqliteHandle::GetInstance()->SyncFile(each);
|
||||||
|
if (!result) {
|
||||||
|
LogError("Save file failed.\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
|
@ -13,10 +13,35 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "SqliteHandle.h"
|
#include "SqliteHandle.h"
|
||||||
|
#include "IFilesManager.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdio.h>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <time.h>
|
||||||
|
#define FILES_TABLE "files"
|
||||||
|
#define TABLE_KEY "key"
|
||||||
|
#define FILE_PATH "path"
|
||||||
|
#define CREATE_TIME "time"
|
||||||
|
#define FILE_TYPE "type"
|
||||||
|
#define FILE_SIZE "size"
|
||||||
|
#define FILE_STATUS "status"
|
||||||
|
#define FILE_STATUS_BE_RECORDING "recording"
|
||||||
|
#define FILE_STATUS_COMPLETE_RECORD "complete_record"
|
||||||
|
#define FILE_STATUS_SHOULD_BE_UPLOADED "should_be_uploaded"
|
||||||
|
#define FILE_STATUS_UPLOADING "uploading"
|
||||||
|
#define FILE_STATUS_UPLOADED "uploaded"
|
||||||
|
#define FIEL_TYPE_PIR "pir"
|
||||||
|
#define FIEL_TYPE_MANUAL_TEST "manual_test"
|
||||||
|
#define FIEL_TYPE_MANUAL_PHONE "manual_phone"
|
||||||
|
#define FIEL_TYPE_TIMED "timed"
|
||||||
|
#define FILE_TYPE_UNDEFINE "undefine"
|
||||||
|
SqliteHandle::SqliteHandle() : mDb(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
std::shared_ptr<SqliteHandle> &SqliteHandle::GetInstance(std::shared_ptr<SqliteHandle> *impl)
|
std::shared_ptr<SqliteHandle> &SqliteHandle::GetInstance(std::shared_ptr<SqliteHandle> *impl)
|
||||||
{
|
{
|
||||||
static auto instance = std::make_shared<SqliteHandle>();
|
static auto instance = std::make_shared<SqliteHandle>();
|
||||||
|
@ -31,17 +56,244 @@ std::shared_ptr<SqliteHandle> &SqliteHandle::GetInstance(std::shared_ptr<SqliteH
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
void SqliteHandle::Init(void)
|
void SqliteHandle::Init(const std::string &dbFileName)
|
||||||
{
|
{
|
||||||
sqlite3 *db;
|
if (nullptr != mDb) {
|
||||||
int rc;
|
LogWarning("SqliteHandle has been init.\n");
|
||||||
rc = sqlite3_open("test.db", &db);
|
|
||||||
if (rc) {
|
|
||||||
fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));
|
|
||||||
sqlite3_close(db);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
rc = sqlite3_open(dbFileName.c_str(), &mDb);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("open sqlite3 failed: %s\n", sqlite3_errmsg(mDb));
|
||||||
|
sqlite3_close(mDb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DbInit(mDb);
|
||||||
}
|
}
|
||||||
void SqliteHandle::UnInit(void)
|
void SqliteHandle::UnInit(void)
|
||||||
{
|
{
|
||||||
|
if (mDb) {
|
||||||
|
sqlite3_close(mDb);
|
||||||
|
mDb = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned long int SqliteHandle::CreateFiles(const unsigned int &count)
|
||||||
|
{
|
||||||
|
char *err_msg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
const char *sql =
|
||||||
|
"INSERT INTO " FILES_TABLE " (" FILE_PATH ", " CREATE_TIME ", " FILE_TYPE ", " FILE_SIZE ", " FILE_STATUS
|
||||||
|
") VALUES (\"\", 0, \"" FILE_TYPE_UNDEFINE "\", 0, \"" FILE_STATUS_BE_RECORDING "\");";
|
||||||
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
|
rc = sqlite3_exec(mDb, sql, nullptr, nullptr, &err_msg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", err_msg);
|
||||||
|
sqlite3_free(err_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto last_rowid_lambda = [](void *last_rowid, int argc, char **argv, char **azColName) -> int {
|
||||||
|
if (argc > 0) {
|
||||||
|
LogInfo("last_rowid = %s\n", argv[0]);
|
||||||
|
*(unsigned long int *)last_rowid = strtoul(argv[0], nullptr, 10);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
unsigned long int last_rowid = 0;
|
||||||
|
const char *sql2 = "SELECT last_insert_rowid();";
|
||||||
|
rc = sqlite3_exec(mDb, sql2, last_rowid_lambda, &last_rowid, &err_msg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", err_msg);
|
||||||
|
sqlite3_free(err_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return last_rowid - count;
|
||||||
|
}
|
||||||
|
bool SqliteHandle::SyncFile(const SyncFileInfo &info)
|
||||||
|
{
|
||||||
|
if (UNDEFINE_SERIAL_NUMBER == info.mSerialNumber) {
|
||||||
|
LogError("Serial number is undefine.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UpdateCreateTime(mDb, info.mSerialNumber, info.mCreateTime_s) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UpdateFileName(mDb, info.mSerialNumber, info.mFileName) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UpdateFileSize(mDb, info.mSerialNumber, info.mFileSize) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UpdateFileStatus(mDb, info.mSerialNumber, info.mStatus) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UpdateFileType(mDb, info.mSerialNumber, info.mType) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void SqliteHandle::DbInit(sqlite3 *db)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
const char *sql =
|
||||||
|
"CREATE TABLE IF NOT EXISTS " FILES_TABLE " (" TABLE_KEY " INTEGER PRIMARY KEY AUTOINCREMENT, " FILE_PATH
|
||||||
|
" TEXT, " CREATE_TIME " INTEGER," FILE_TYPE " TEXT, " FILE_SIZE " INTEGER, " FILE_STATUS " TEXT);";
|
||||||
|
rc = sqlite3_exec(db, sql, nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("Sql: %s, errMsg: %s\n", sql, errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogInfo("Sqlite init success. table = %s\n", FILES_TABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool SqliteHandle::UpdateCreateTime(sqlite3 *db, const unsigned long &key, const time_t &createTime)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
if (UNDEFINE_CREATE_TIME != createTime) {
|
||||||
|
std::stringstream sqlStream;
|
||||||
|
sqlStream << "UPDATE " FILES_TABLE " SET " CREATE_TIME " = '" << createTime << "' WHERE " TABLE_KEY " = " << key
|
||||||
|
<< ";";
|
||||||
|
LogInfo("Sql: %s\n", sqlStream.str().c_str());
|
||||||
|
rc = sqlite3_exec(db, sqlStream.str().c_str(), nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool SqliteHandle::UpdateFileName(sqlite3 *db, const unsigned long &key, const std::string &fileName)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
if (fileName.empty() == false) {
|
||||||
|
std::stringstream sqlStream;
|
||||||
|
sqlStream << "UPDATE " FILES_TABLE " SET " FILE_PATH " = '" << fileName << "' WHERE " TABLE_KEY " = " << key
|
||||||
|
<< ";";
|
||||||
|
LogInfo("Sql: %s\n", sqlStream.str().c_str());
|
||||||
|
rc = sqlite3_exec(db, sqlStream.str().c_str(), nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool SqliteHandle::UpdateFileSize(sqlite3 *db, const unsigned long &key, const unsigned long &fileSize)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
if (UNDEFINE_FILE_SIZE != fileSize) {
|
||||||
|
std::stringstream sqlStream;
|
||||||
|
sqlStream << "UPDATE " FILES_TABLE " SET " FILE_SIZE " = '" << fileSize << "' WHERE " TABLE_KEY " = " << key
|
||||||
|
<< ";";
|
||||||
|
LogInfo("Sql: %s\n", sqlStream.str().c_str());
|
||||||
|
rc = sqlite3_exec(db, sqlStream.str().c_str(), nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool SqliteHandle::UpdateFileType(sqlite3 *db, const unsigned long &key, const FileCreateType &type)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
if (FileCreateType::END != type) {
|
||||||
|
std::stringstream sqlStream;
|
||||||
|
sqlStream << "UPDATE " FILES_TABLE " SET " FILE_TYPE " = '" << ConvertFileType(type)
|
||||||
|
<< "' WHERE " TABLE_KEY " = " << key << ";";
|
||||||
|
LogInfo("Sql: %s\n", sqlStream.str().c_str());
|
||||||
|
rc = sqlite3_exec(db, sqlStream.str().c_str(), nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::string SqliteHandle::ConvertFileType(const FileCreateType &type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case FileCreateType::PIR:
|
||||||
|
return "PIR";
|
||||||
|
case FileCreateType::MANUAL_TEST:
|
||||||
|
return "MANUAL_TEST";
|
||||||
|
case FileCreateType::MANUAL_PHONE:
|
||||||
|
return "MANUAL_PHONE";
|
||||||
|
case FileCreateType::TIMED:
|
||||||
|
return "TIMED";
|
||||||
|
case FileCreateType::END:
|
||||||
|
default:
|
||||||
|
return "undefine";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool SqliteHandle::UpdateFileStatus(sqlite3 *db, const unsigned long &key, const FileStatus &status)
|
||||||
|
{
|
||||||
|
if (nullptr == db) {
|
||||||
|
LogError("db is null.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *errMsg = nullptr;
|
||||||
|
int rc = SQLITE_UNDEFINE;
|
||||||
|
if (FileStatus::END != status) {
|
||||||
|
std::stringstream sqlStream;
|
||||||
|
sqlStream << "UPDATE " FILES_TABLE " SET " FILE_STATUS " = '" << ConvertFileStatus(status)
|
||||||
|
<< "' WHERE " TABLE_KEY " = " << key << ";";
|
||||||
|
LogInfo("Sql: %s\n", sqlStream.str().c_str());
|
||||||
|
rc = sqlite3_exec(db, sqlStream.str().c_str(), nullptr, nullptr, &errMsg);
|
||||||
|
if (SQLITE_OK != rc) {
|
||||||
|
LogError("SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::string SqliteHandle::ConvertFileStatus(const FileStatus &status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case FileStatus::RECORDING:
|
||||||
|
return "RECORDING";
|
||||||
|
case FileStatus::FINISHED_RECORD:
|
||||||
|
return "FINISHED_RECORD";
|
||||||
|
case FileStatus::SHOULD_BE_UPLOAD:
|
||||||
|
return "SHOULD_BE_UPLOAD";
|
||||||
|
case FileStatus::UPLOADING:
|
||||||
|
return "UPLOADING";
|
||||||
|
case FileStatus::UPLOADED:
|
||||||
|
return "UPLOADED";
|
||||||
|
case FileStatus::END:
|
||||||
|
default:
|
||||||
|
return "undefine";
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -14,14 +14,37 @@
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_HANDLE_H
|
#ifndef SQLITE_HANDLE_H
|
||||||
#define SQLITE_HANDLE_H
|
#define SQLITE_HANDLE_H
|
||||||
|
#include "IFilesManager.h"
|
||||||
|
#include "sqlite3.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
constexpr int SQLITE_UNDEFINE = -1;
|
||||||
class SqliteHandle
|
class SqliteHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SqliteHandle() = default;
|
SqliteHandle();
|
||||||
virtual ~SqliteHandle() = default;
|
virtual ~SqliteHandle() = default;
|
||||||
static std::shared_ptr<SqliteHandle> &GetInstance(std::shared_ptr<SqliteHandle> *impl = nullptr);
|
static std::shared_ptr<SqliteHandle> &GetInstance(std::shared_ptr<SqliteHandle> *impl = nullptr);
|
||||||
void Init(void);
|
void Init(const std::string &dbFileName);
|
||||||
void UnInit(void);
|
void UnInit(void);
|
||||||
|
unsigned long int CreateFiles(const unsigned int &count);
|
||||||
|
bool SyncFile(const SyncFileInfo &info);
|
||||||
|
bool Remove();
|
||||||
|
bool Modified();
|
||||||
|
bool Serach();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void DbInit(sqlite3 *db);
|
||||||
|
static bool UpdateCreateTime(sqlite3 *db, const unsigned long &key, const time_t &createTime);
|
||||||
|
static bool UpdateFileName(sqlite3 *db, const unsigned long &key, const std::string &fileName);
|
||||||
|
static bool UpdateFileSize(sqlite3 *db, const unsigned long &key, const unsigned long &fileSize);
|
||||||
|
static bool UpdateFileType(sqlite3 *db, const unsigned long &key, const FileCreateType &type);
|
||||||
|
static std::string ConvertFileType(const FileCreateType &type);
|
||||||
|
static bool UpdateFileStatus(sqlite3 *db, const unsigned long &key, const FileStatus &status);
|
||||||
|
static std::string ConvertFileStatus(const FileStatus &status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
sqlite3 *mDb;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -56,6 +56,7 @@ public:
|
||||||
VMediaTask() = default;
|
VMediaTask() = default;
|
||||||
virtual ~VMediaTask() = default;
|
virtual ~VMediaTask() = default;
|
||||||
virtual const MediaTaskType GetTaskType(void);
|
virtual const MediaTaskType GetTaskType(void);
|
||||||
|
virtual std::string GetTargetNameForSaving(void);
|
||||||
virtual void Response(const std::vector<MediaTaskResponse> &response);
|
virtual void Response(const std::vector<MediaTaskResponse> &response);
|
||||||
virtual bool IsTaskFinished(void);
|
virtual bool IsTaskFinished(void);
|
||||||
virtual const signed int GetIsNight(void);
|
virtual const signed int GetIsNight(void);
|
||||||
|
@ -77,10 +78,6 @@ public:
|
||||||
virtual StatusCode StopTask(void);
|
virtual StatusCode StopTask(void);
|
||||||
virtual StatusCode ClearTask(void);
|
virtual StatusCode ClearTask(void);
|
||||||
virtual StatusCode SetSpontaneousTaskMonitor(std::shared_ptr<VMediaTask> &task);
|
virtual StatusCode SetSpontaneousTaskMonitor(std::shared_ptr<VMediaTask> &task);
|
||||||
// virtual StatusCode BeReadyForLive(void);
|
|
||||||
// virtual StatusCode SetMediaMonitor(std::shared_ptr<VMediaMonitor> &monitor);
|
|
||||||
// virtual StatusCode StartMedia(void);
|
|
||||||
// virtual StatusCode StopMedia(void);
|
|
||||||
};
|
};
|
||||||
class IMediaManager
|
class IMediaManager
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,11 @@ const MediaTaskType VMediaTask::GetTaskType(void)
|
||||||
{
|
{
|
||||||
return MediaTaskType::END;
|
return MediaTaskType::END;
|
||||||
}
|
}
|
||||||
|
std::string VMediaTask::GetTargetNameForSaving(void)
|
||||||
|
{
|
||||||
|
const std::string fileName = "Undefined";
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
void VMediaTask::Response(const std::vector<MediaTaskResponse> &response)
|
void VMediaTask::Response(const std::vector<MediaTaskResponse> &response)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,12 +66,17 @@ StatusCode MediaHandle::ExecuteTask(std::shared_ptr<VMediaTask> &task)
|
||||||
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mStreamHandle = std::make_shared<RecordMp4>();
|
mStreamHandle = std::make_shared<RecordMp4>(task);
|
||||||
if (nullptr == mStreamHandle) {
|
if (nullptr == mStreamHandle) {
|
||||||
LogError("Create stream handle failed.\n");
|
LogError("Create stream handle failed.\n");
|
||||||
|
mStreamHandle.reset();
|
||||||
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
}
|
}
|
||||||
mStreamHandle->Init();
|
auto code2 = mStreamHandle->Init();
|
||||||
|
if (!IsCodeOK(code2)) {
|
||||||
|
LogError("StreamHandle init failed.\n");
|
||||||
|
return code2;
|
||||||
|
}
|
||||||
CameraTaskType taskType = TaskTypeConvert(task->GetTaskType());
|
CameraTaskType taskType = TaskTypeConvert(task->GetTaskType());
|
||||||
CameraTaskParam data(taskType);
|
CameraTaskParam data(taskType);
|
||||||
auto code = mCameraHal->StartSingleTask(data);
|
auto code = mCameraHal->StartSingleTask(data);
|
||||||
|
@ -115,19 +120,22 @@ void MediaHandle::TaskTimer(void)
|
||||||
*/
|
*/
|
||||||
mTaskRuning = false;
|
mTaskRuning = false;
|
||||||
}
|
}
|
||||||
|
mStreamHandle->StopHandleStream();
|
||||||
|
std::vector<MediaTaskResponse> files;
|
||||||
|
mStreamHandle->GetAllFiles(files);
|
||||||
mStreamHandle->UnInit();
|
mStreamHandle->UnInit();
|
||||||
if (mCameraHal) {
|
if (mCameraHal) {
|
||||||
mCameraHal->StopTask();
|
mCameraHal->StopTask();
|
||||||
}
|
}
|
||||||
|
mStreamHandle.reset();
|
||||||
mMutex.lock();
|
mMutex.lock();
|
||||||
auto runingTask = mCurrentTask.lock();
|
auto runingTask = mCurrentTask.lock();
|
||||||
if (mCurrentTask.expired()) {
|
if (mCurrentTask.expired()) {
|
||||||
LogWarning("SdCardHal: monitor is expired.\n");
|
LogWarning("mCurrentTask is expired.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogInfo("Task finished response to application.\n");
|
LogInfo("Task finished response to application.\n");
|
||||||
std::vector<MediaTaskResponse> responses;
|
runingTask->Response(files);
|
||||||
runingTask->Response(responses);
|
|
||||||
mCurrentTask.reset();
|
mCurrentTask.reset();
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,32 +14,55 @@
|
||||||
*/
|
*/
|
||||||
#include "RecordMp4.h"
|
#include "RecordMp4.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
|
#include "IMediaManager.h"
|
||||||
#include "MediaBase.h"
|
#include "MediaBase.h"
|
||||||
|
#include "StatusCode.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
RecordMp4::RecordMp4() : mRecordMp4Object(nullptr)
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
RecordMp4::RecordMp4(std::shared_ptr<VMediaTask> &recordTask) : mRecordMp4Object(nullptr), mRecordTask(recordTask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void RecordMp4::Init(void)
|
StatusCode RecordMp4::Init(void)
|
||||||
{
|
{
|
||||||
mRecordMp4Object = ICreateMediaBase(MEDIA_HANDLE_TYPE_COMBINE_MP4);
|
mRecordMp4Object = ICreateMediaBase(MEDIA_HANDLE_TYPE_COMBINE_MP4);
|
||||||
if (nullptr == mRecordMp4Object) {
|
if (nullptr == mRecordMp4Object) {
|
||||||
LogError("mRecordMp4Object is null.\n");
|
LogError("mRecordMp4Object is null.\n");
|
||||||
return;
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
}
|
}
|
||||||
IOpenOutputFile(mRecordMp4Object, "./record.mp4");
|
std::string videoPath = mRecordTask->GetTargetNameForSaving();
|
||||||
|
StatusCode code = IOpenOutputFile(mRecordMp4Object, videoPath.c_str());
|
||||||
|
if (!IsCodeOK(code)) {
|
||||||
|
LogError("OpenOutputFile failed.\n");
|
||||||
|
ICloseOutputFile(mRecordMp4Object);
|
||||||
|
IMediaBaseFree(mRecordMp4Object);
|
||||||
|
mRecordMp4Object = nullptr;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
void RecordMp4::UnInit(void)
|
StatusCode RecordMp4::UnInit(void)
|
||||||
{
|
{
|
||||||
|
StopHandleStream();
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
||||||
|
void RecordMp4::StopHandleStream(void)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(mMutex);
|
||||||
if (mRecordMp4Object) {
|
if (mRecordMp4Object) {
|
||||||
ICloseOutputFile(mRecordMp4Object);
|
ICloseOutputFile(mRecordMp4Object);
|
||||||
IMediaBaseFree(mRecordMp4Object);
|
IMediaBaseFree(mRecordMp4Object);
|
||||||
mRecordMp4Object = nullptr;
|
mRecordMp4Object = nullptr;
|
||||||
}
|
}
|
||||||
|
std::string videoPath = mRecordTask->GetTargetNameForSaving();
|
||||||
|
MediaTaskResponse response(videoPath.c_str());
|
||||||
|
mTaskResponse.push_back(response);
|
||||||
}
|
}
|
||||||
void RecordMp4::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
void RecordMp4::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(mMutex);
|
||||||
if (mRecordMp4Object) {
|
if (mRecordMp4Object) {
|
||||||
StreamInfo info = {.mType = STREAM_TYPE_VIDEO_H264};
|
StreamInfo info = {.mType = STREAM_TYPE_VIDEO_H264};
|
||||||
IGetStreamData(mRecordMp4Object, stream, length, info);
|
IGetStreamData(mRecordMp4Object, stream, length, info);
|
||||||
|
@ -47,8 +70,15 @@ void RecordMp4::GetVideoStream(const void *stream, const unsigned int &length, c
|
||||||
}
|
}
|
||||||
void RecordMp4::GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
void RecordMp4::GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(mMutex);
|
||||||
if (mRecordMp4Object) {
|
if (mRecordMp4Object) {
|
||||||
StreamInfo info = {.mType = STREAM_TYPE_AUDIO_G711A};
|
StreamInfo info = {.mType = STREAM_TYPE_AUDIO_G711A};
|
||||||
IGetStreamData(mRecordMp4Object, stream, length, info);
|
IGetStreamData(mRecordMp4Object, stream, length, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StatusCode RecordMp4::GetAllFiles(std::vector<MediaTaskResponse> &files)
|
||||||
|
{
|
||||||
|
files = std::move(mTaskResponse);
|
||||||
|
mTaskResponse.clear();
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
|
@ -14,19 +14,27 @@
|
||||||
*/
|
*/
|
||||||
#ifndef RECORD_MP4_H
|
#ifndef RECORD_MP4_H
|
||||||
#define RECORD_MP4_H
|
#define RECORD_MP4_H
|
||||||
|
#include "IMediaManager.h"
|
||||||
#include "VStreamHandle.h"
|
#include "VStreamHandle.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
class RecordMp4 : public VStreamHandle
|
class RecordMp4 : public VStreamHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RecordMp4();
|
RecordMp4(std::shared_ptr<VMediaTask> &recordTask);
|
||||||
virtual ~RecordMp4() = default;
|
virtual ~RecordMp4() = default;
|
||||||
void Init(void) override;
|
StatusCode Init(void) override;
|
||||||
void UnInit(void) override;
|
StatusCode UnInit(void) override;
|
||||||
|
void StopHandleStream(void) override;
|
||||||
void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
||||||
void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
||||||
|
StatusCode GetAllFiles(std::vector<MediaTaskResponse> &files) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::mutex mMutex;
|
||||||
void *mRecordMp4Object;
|
void *mRecordMp4Object;
|
||||||
|
std::shared_ptr<VMediaTask> mRecordTask;
|
||||||
|
std::vector<MediaTaskResponse> mTaskResponse;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -14,18 +14,20 @@
|
||||||
*/
|
*/
|
||||||
#include "SaveStream.h"
|
#include "SaveStream.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
|
#include "StatusCode.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
SaveStream::SaveStream() : mFileAudio(nullptr), mFileVideo(nullptr)
|
SaveStream::SaveStream() : mFileAudio(nullptr), mFileVideo(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void SaveStream::Init(void)
|
StatusCode SaveStream::Init(void)
|
||||||
{
|
{
|
||||||
mFileAudio = fopen("./audio.g711", "a+"); // TODO:
|
mFileAudio = fopen("./audio.g711", "a+"); // TODO:
|
||||||
mFileVideo = fopen("./video.h264", "a+"); // TODO:
|
mFileVideo = fopen("./video.h264", "a+"); // TODO:
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
}
|
}
|
||||||
void SaveStream::UnInit(void)
|
StatusCode SaveStream::UnInit(void)
|
||||||
{
|
{
|
||||||
if (mFileAudio) {
|
if (mFileAudio) {
|
||||||
fclose(mFileAudio);
|
fclose(mFileAudio);
|
||||||
|
@ -35,6 +37,7 @@ void SaveStream::UnInit(void)
|
||||||
fclose(mFileVideo);
|
fclose(mFileVideo);
|
||||||
mFileVideo = nullptr;
|
mFileVideo = nullptr;
|
||||||
}
|
}
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
}
|
}
|
||||||
void SaveStream::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
void SaveStream::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,8 @@ class SaveStream : public VStreamHandle
|
||||||
public:
|
public:
|
||||||
SaveStream();
|
SaveStream();
|
||||||
virtual ~SaveStream() = default;
|
virtual ~SaveStream() = default;
|
||||||
void Init(void) override;
|
StatusCode Init(void) override;
|
||||||
void UnInit(void) override;
|
StatusCode UnInit(void) override;
|
||||||
void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
||||||
void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp) override;
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,33 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "VStreamHandle.h"
|
#include "VStreamHandle.h"
|
||||||
void VStreamHandle::Init(void)
|
#include "ILog.h"
|
||||||
|
#include "StatusCode.h"
|
||||||
|
#include <vector>
|
||||||
|
StatusCode VStreamHandle::Init(void)
|
||||||
{
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
void VStreamHandle::UnInit(void)
|
StatusCode VStreamHandle::UnInit(void)
|
||||||
{
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
|
}
|
||||||
|
void VStreamHandle::StopHandleStream(void)
|
||||||
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
}
|
}
|
||||||
void VStreamHandle::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
void VStreamHandle::GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
||||||
{
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
}
|
}
|
||||||
void VStreamHandle::GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
void VStreamHandle::GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp)
|
||||||
{
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
}
|
||||||
|
StatusCode VStreamHandle::GetAllFiles(std::vector<MediaTaskResponse> &files)
|
||||||
|
{
|
||||||
|
LogInfo("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
|
@ -14,14 +14,19 @@
|
||||||
*/
|
*/
|
||||||
#ifndef V_STREAM_HANDLE_H
|
#ifndef V_STREAM_HANDLE_H
|
||||||
#define V_STREAM_HANDLE_H
|
#define V_STREAM_HANDLE_H
|
||||||
|
#include "IMediaManager.h"
|
||||||
|
#include "StatusCode.h"
|
||||||
|
#include <vector>
|
||||||
class VStreamHandle
|
class VStreamHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VStreamHandle() = default;
|
VStreamHandle() = default;
|
||||||
virtual ~VStreamHandle() = default;
|
virtual ~VStreamHandle() = default;
|
||||||
virtual void Init(void);
|
virtual StatusCode Init(void);
|
||||||
virtual void UnInit(void);
|
virtual StatusCode UnInit(void);
|
||||||
|
virtual void StopHandleStream(void);
|
||||||
virtual void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp);
|
virtual void GetVideoStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp);
|
||||||
virtual void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp);
|
virtual void GetAudioStream(const void *stream, const unsigned int &length, const unsigned long long &timeStamp);
|
||||||
|
virtual StatusCode GetAllFiles(std::vector<MediaTaskResponse> &files);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -16,6 +16,7 @@
|
||||||
#define I_STORAGE_MANAGER_H
|
#define I_STORAGE_MANAGER_H
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
bool CreateStorageManagerModule(void);
|
bool CreateStorageManagerModule(void);
|
||||||
bool DestroyStorageManagerModule(void);
|
bool DestroyStorageManagerModule(void);
|
||||||
enum class StorageEvent
|
enum class StorageEvent
|
||||||
|
@ -53,5 +54,7 @@ public:
|
||||||
virtual StatusCode SaveFile(const std::string &sourceFile, const std::string &savePaht);
|
virtual StatusCode SaveFile(const std::string &sourceFile, const std::string &savePaht);
|
||||||
virtual const char *PrintStringStorageEvent(const StorageEvent &event);
|
virtual const char *PrintStringStorageEvent(const StorageEvent &event);
|
||||||
virtual StatusCode GetSdCardInfo(SdCardInfo &info);
|
virtual StatusCode GetSdCardInfo(SdCardInfo &info);
|
||||||
|
virtual std::string GetFilesDatabasePath(void);
|
||||||
|
virtual std::string GetFilesSavingPath(void);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -43,21 +43,38 @@ StatusCode IStorageManager::Init(void)
|
||||||
}
|
}
|
||||||
StatusCode IStorageManager::UnInit(void)
|
StatusCode IStorageManager::UnInit(void)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
StatusCode IStorageManager::SetMonitor(std::shared_ptr<VStorageMoniter> &monitor)
|
StatusCode IStorageManager::SetMonitor(std::shared_ptr<VStorageMoniter> &monitor)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
StatusCode IStorageManager::SaveFile(const std::string &sourceFile, const std::string &savePaht)
|
StatusCode IStorageManager::SaveFile(const std::string &sourceFile, const std::string &savePaht)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
const char *IStorageManager::PrintStringStorageEvent(const StorageEvent &event)
|
const char *IStorageManager::PrintStringStorageEvent(const StorageEvent &event)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return "STATUS_CODE_VIRTUAL_FUNCTION";
|
return "STATUS_CODE_VIRTUAL_FUNCTION";
|
||||||
}
|
}
|
||||||
StatusCode IStorageManager::GetSdCardInfo(SdCardInfo &info)
|
StatusCode IStorageManager::GetSdCardInfo(SdCardInfo &info)
|
||||||
{
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
|
||||||
}
|
}
|
||||||
|
std::string IStorageManager::GetFilesDatabasePath(void)
|
||||||
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
std::string path = "undefined";
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
std::string IStorageManager::GetFilesSavingPath(void)
|
||||||
|
{
|
||||||
|
LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n");
|
||||||
|
std::string path = "undefined";
|
||||||
|
return path;
|
||||||
|
}
|
|
@ -15,10 +15,18 @@
|
||||||
#include "StorageBase.h"
|
#include "StorageBase.h"
|
||||||
#include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "IStorageManager.h"
|
#include "IStorageManager.h"
|
||||||
|
#include <cctype>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
bool StorageBase::CheckDirectory(const char *filepath)
|
bool StorageBase::CheckDirectory(const char *filepath)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +49,7 @@ bool StorageBase::CheckDirectory(const char *filepath)
|
||||||
}
|
}
|
||||||
if (stat(path, &st) == -1) {
|
if (stat(path, &st) == -1) {
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
|
// LogInfo("mkdir:%s\n", path);
|
||||||
if (mkdir(path, 0755) == -1) {
|
if (mkdir(path, 0755) == -1) {
|
||||||
LogError("mkdir path failed:%s\n", path);
|
LogError("mkdir path failed:%s\n", path);
|
||||||
free(path);
|
free(path);
|
||||||
|
@ -65,28 +74,38 @@ const char *StorageBase::PrintStringStorageEvent(const StorageEvent &event)
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case StorageEvent::SD_CARD_INSERT: {
|
case StorageEvent::SD_CARD_INSERT: {
|
||||||
return "SD_CARD_INSERT";
|
return "SD_CARD_INSERT";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case StorageEvent::SD_CARD_REMOVE: {
|
case StorageEvent::SD_CARD_REMOVE: {
|
||||||
return "SD_CARD_REMOVE";
|
return "SD_CARD_REMOVE";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case StorageEvent::SD_ABNORMAL: {
|
case StorageEvent::SD_ABNORMAL: {
|
||||||
return "SD_ABNORMAL";
|
return "SD_ABNORMAL";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case StorageEvent::EMMC_NORMAL: {
|
case StorageEvent::EMMC_NORMAL: {
|
||||||
return "EMMC_NORMAL";
|
return "EMMC_NORMAL";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case StorageEvent::END: {
|
case StorageEvent::END: {
|
||||||
return "END";
|
return "END";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
return "UNDEFINE";
|
return "UNDEFINE";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string StorageBase::CreateFilesSavingPath(void)
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
time_t t_now = std::chrono::system_clock::to_time_t(now);
|
||||||
|
struct tm tm_now = *std::localtime(&t_now);
|
||||||
|
|
||||||
|
int year = tm_now.tm_year + 1900;
|
||||||
|
int month = tm_now.tm_mon + 1;
|
||||||
|
int day = tm_now.tm_mday;
|
||||||
|
|
||||||
|
std::ostringstream pathStream;
|
||||||
|
pathStream << SD_CARD_MOUNT_PATH << "/DCIM/" << std::setw(4) << std::setfill('0') << year << "/" << std::setw(2)
|
||||||
|
<< std::setfill('0') << month << "/" << std::setw(2) << std::setfill('0') << day << "/";
|
||||||
|
CheckDirectory((pathStream.str() + "anyfile").c_str());
|
||||||
|
return pathStream.str();
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char *PrintStringStorageEvent(const StorageEvent &event);
|
const char *PrintStringStorageEvent(const StorageEvent &event);
|
||||||
|
std::string CreateFilesSavingPath(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::weak_ptr<VStorageMoniter> mStorageMonitor;
|
std::weak_ptr<VStorageMoniter> mStorageMonitor;
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "StorageManagerImpl.h"
|
#include "StorageManagerImpl.h"
|
||||||
// #include "ILog.h"
|
#include "ILog.h"
|
||||||
#include "IStorageManager.h"
|
#include "IStorageManager.h"
|
||||||
#include "SdCardHandle.h"
|
#include "SdCardHandle.h"
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include "StorageBase.h"
|
#include "StorageBase.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#define SYSTEM_FILE_PATH "/system"
|
||||||
StatusCode StorageManagerImpl::Init(void)
|
StatusCode StorageManagerImpl::Init(void)
|
||||||
{
|
{
|
||||||
SdCardHandle::SdCardInit();
|
SdCardHandle::SdCardInit();
|
||||||
|
@ -44,3 +45,18 @@ const char *StorageManagerImpl::PrintStringStorageEvent(const StorageEvent &even
|
||||||
{
|
{
|
||||||
return StorageBase::PrintStringStorageEvent(event);
|
return StorageBase::PrintStringStorageEvent(event);
|
||||||
}
|
}
|
||||||
|
std::string StorageManagerImpl::GetFilesDatabasePath(void)
|
||||||
|
{
|
||||||
|
std::string path = SD_CARD_MOUNT_PATH SYSTEM_FILE_PATH "/anyfile";
|
||||||
|
bool directoryExist = StorageBase::CheckDirectory(path.c_str());
|
||||||
|
if (false == directoryExist) {
|
||||||
|
LogError("Directory not exist.\n");
|
||||||
|
path = "Unavailable";
|
||||||
|
}
|
||||||
|
path = SD_CARD_MOUNT_PATH SYSTEM_FILE_PATH;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
std::string StorageManagerImpl::GetFilesSavingPath(void)
|
||||||
|
{
|
||||||
|
return StorageBase::CreateFilesSavingPath();
|
||||||
|
}
|
|
@ -23,10 +23,14 @@ class StorageManagerImpl : public SdCardHandle, public EmmcHandle
|
||||||
public:
|
public:
|
||||||
StorageManagerImpl() = default;
|
StorageManagerImpl() = default;
|
||||||
virtual ~StorageManagerImpl() = default;
|
virtual ~StorageManagerImpl() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
StatusCode Init(void) override;
|
StatusCode Init(void) override;
|
||||||
StatusCode UnInit(void) override;
|
StatusCode UnInit(void) override;
|
||||||
StatusCode SetMonitor(std::shared_ptr<VStorageMoniter> &monitor) override;
|
StatusCode SetMonitor(std::shared_ptr<VStorageMoniter> &monitor) override;
|
||||||
StatusCode SaveFile(const std::string &sourceFile, const std::string &savePaht) override;
|
StatusCode SaveFile(const std::string &sourceFile, const std::string &savePaht) override;
|
||||||
const char *PrintStringStorageEvent(const StorageEvent &event) override;
|
const char *PrintStringStorageEvent(const StorageEvent &event) override;
|
||||||
|
std::string GetFilesDatabasePath(void) override;
|
||||||
|
std::string GetFilesSavingPath(void) override;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
193
utils/MediaBase/src/FfmpegDecoder.cpp
Normal file
193
utils/MediaBase/src/FfmpegDecoder.cpp
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* 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 "FfmpegDecoder.h"
|
||||||
|
#include "ILog.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/codec.h>
|
||||||
|
#include <libavcodec/codec_id.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/error.h>
|
||||||
|
#include <libavutil/frame.h>
|
||||||
|
#include <libavutil/samplefmt.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <functional>
|
||||||
|
FfmpegDecoder::FfmpegDecoder(const enum AVCodecID &codecId)
|
||||||
|
: mCodecId(codecId), mCodec(nullptr), mCodecCtx(nullptr), mFrame(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool FfmpegDecoder::Init(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
LogInfo("find decoder : %s\n", avcodec_get_name(mCodecId));
|
||||||
|
mCodec = (AVCodec *)avcodec_find_decoder(mCodecId);
|
||||||
|
// mCodec = (AVCodec *)avcodec_find_decoder_by_name("libfdk_aac");
|
||||||
|
if (!(mCodec)) {
|
||||||
|
LogError("Codec not found\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mCodecCtx = avcodec_alloc_context3((const AVCodec *)(mCodec));
|
||||||
|
if (!(mCodecCtx)) {
|
||||||
|
LogError("Could not allocate codec context\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (AVMEDIA_TYPE_AUDIO == mCodec->type) {
|
||||||
|
LogInfo("Audio decoder.\n");
|
||||||
|
/* put sample parameters */
|
||||||
|
mCodecCtx->bit_rate = 64000;
|
||||||
|
// mCodecCtx->bit_rate = 352800;
|
||||||
|
// mCodecCtx->sample_rate = 8000;
|
||||||
|
|
||||||
|
/* check that the encoder supports s16 pcm input */
|
||||||
|
mCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||||
|
if (!check_sample_fmt(mCodec, mCodecCtx->sample_fmt)) {
|
||||||
|
LogError("Encoder does not support sample format %s", av_get_sample_fmt_name(mCodecCtx->sample_fmt));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select other audio parameters supported by the encoder */
|
||||||
|
mCodecCtx->sample_rate = select_sample_rate(mCodec);
|
||||||
|
ret = select_channel_layout(mCodec, &(mCodecCtx->ch_layout));
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Could not set channel layout\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ret = avcodec_open2(mCodecCtx, mCodec, nullptr)) < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogError("Could not open codec:%s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mFrame = av_frame_alloc();
|
||||||
|
if (!mFrame) {
|
||||||
|
LogError("Could not allocate video frame\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (AVMEDIA_TYPE_AUDIO == mCodec->type) {
|
||||||
|
mFrame->nb_samples = mCodecCtx->frame_size;
|
||||||
|
mFrame->format = mCodecCtx->sample_fmt;
|
||||||
|
ret = av_channel_layout_copy(&(mFrame->ch_layout), &(mCodecCtx->ch_layout));
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Could not copy channel layout\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool FfmpegDecoder::UnInit(void)
|
||||||
|
{
|
||||||
|
if (mFrame) {
|
||||||
|
av_frame_free(&mFrame);
|
||||||
|
mFrame = nullptr;
|
||||||
|
}
|
||||||
|
if (mCodecCtx) {
|
||||||
|
avcodec_free_context(&mCodecCtx);
|
||||||
|
mCodecCtx = nullptr;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void FfmpegDecoder::DecodeData(const void *data, const size_t &size, std::function<void(AVFrame *frame)> callback)
|
||||||
|
{
|
||||||
|
AVPacket *packet = nullptr;
|
||||||
|
packet = av_packet_alloc();
|
||||||
|
packet->data = (unsigned char *)data;
|
||||||
|
packet->size = size;
|
||||||
|
int ret = avcodec_send_packet(mCodecCtx, packet);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Error sending a packet for decoding\n");
|
||||||
|
av_packet_unref(packet);
|
||||||
|
av_packet_free(&packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (ret >= 0) {
|
||||||
|
ret = avcodec_receive_frame(mCodecCtx, mFrame);
|
||||||
|
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Error during decoding\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback(mFrame);
|
||||||
|
}
|
||||||
|
// mFrame->pts = mAudioSt.next_pts;
|
||||||
|
// mAudioSt.next_pts += mFrame->nb_samples;
|
||||||
|
// ConvertAudioFrame(mFrame, mAudioSt.enc, &mAudioSt);
|
||||||
|
// write_frame(mOc, mAudioSt.enc, mAudioSt.st, mAudioSt.frame, mAudioSt.tmp_pkt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
av_packet_unref(packet);
|
||||||
|
av_packet_free(&packet);
|
||||||
|
}
|
||||||
|
/* just pick the highest supported samplerate */
|
||||||
|
int FfmpegDecoder::select_sample_rate(const AVCodec *codec)
|
||||||
|
{
|
||||||
|
const int *p;
|
||||||
|
int best_samplerate = 0;
|
||||||
|
|
||||||
|
if (!codec->supported_samplerates)
|
||||||
|
return 44100;
|
||||||
|
|
||||||
|
p = codec->supported_samplerates;
|
||||||
|
while (*p) {
|
||||||
|
if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
|
||||||
|
best_samplerate = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return best_samplerate;
|
||||||
|
}
|
||||||
|
/* select layout with the highest channel count */
|
||||||
|
int FfmpegDecoder::select_channel_layout(const AVCodec *codec, AVChannelLayout *dst)
|
||||||
|
{
|
||||||
|
const AVChannelLayout *p, *best_ch_layout = nullptr;
|
||||||
|
int best_nb_channels = 0;
|
||||||
|
AVChannelLayout channelLayout = AV_CHANNEL_LAYOUT_STEREO;
|
||||||
|
if (!codec->ch_layouts)
|
||||||
|
return av_channel_layout_copy(dst, &channelLayout);
|
||||||
|
|
||||||
|
p = codec->ch_layouts;
|
||||||
|
while (p->nb_channels) {
|
||||||
|
int nb_channels = p->nb_channels;
|
||||||
|
|
||||||
|
if (nb_channels > best_nb_channels) {
|
||||||
|
best_ch_layout = p;
|
||||||
|
best_nb_channels = nb_channels;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return av_channel_layout_copy(dst, best_ch_layout);
|
||||||
|
}
|
||||||
|
/* check that a given sample format is supported by the encoder */
|
||||||
|
int FfmpegDecoder::check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
|
||||||
|
{
|
||||||
|
const enum AVSampleFormat *p = codec->sample_fmts;
|
||||||
|
|
||||||
|
while (*p != AV_SAMPLE_FMT_NONE) {
|
||||||
|
if (*p == sample_fmt)
|
||||||
|
return 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
56
utils/MediaBase/src/FfmpegDecoder.h
Normal file
56
utils/MediaBase/src/FfmpegDecoder.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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 FFMPEG_DECODER_H
|
||||||
|
#define FFMPEG_DECODER_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#include <libavutil/timestamp.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
class FfmpegDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FfmpegDecoder(const enum AVCodecID &codecId);
|
||||||
|
virtual ~FfmpegDecoder() = default;
|
||||||
|
bool Init(void);
|
||||||
|
bool UnInit(void);
|
||||||
|
void DecodeData(const void *data, const size_t &size, std::function<void(AVFrame *frame)> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int select_sample_rate(const AVCodec *codec);
|
||||||
|
static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst);
|
||||||
|
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const enum AVCodecID mCodecId;
|
||||||
|
AVCodec *mCodec;
|
||||||
|
AVCodecContext *mCodecCtx;
|
||||||
|
AVFrame *mFrame;
|
||||||
|
};
|
||||||
|
#endif
|
386
utils/MediaBase/src/FfmpegEncoder.cpp
Normal file
386
utils/MediaBase/src/FfmpegEncoder.cpp
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
/*
|
||||||
|
* 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 "FfmpegEncoder.h"
|
||||||
|
#include "ILog.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/codec.h>
|
||||||
|
#include <libavcodec/codec_id.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/dict.h>
|
||||||
|
#include <libavutil/error.h>
|
||||||
|
#include <libavutil/frame.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#include <libavutil/pixfmt.h>
|
||||||
|
#include <libavutil/samplefmt.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <cstdint>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <functional>
|
||||||
|
#define STREAM_DURATION 10.0
|
||||||
|
#define STREAM_FRAME_RATE 25 /* 25 images/s */
|
||||||
|
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
|
||||||
|
FfmpegEncoder::FfmpegEncoder(const enum AVCodecID &codecId)
|
||||||
|
: mCodecId(codecId), mCodecCtx(nullptr), mCodec(nullptr), mFrame(nullptr), mTmpFrame(nullptr), mTmpPkt(nullptr),
|
||||||
|
mSamplesCount(0), mSwrCtx(nullptr), next_pts(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool FfmpegEncoder::Init(int &outputFlags)
|
||||||
|
{
|
||||||
|
mTmpPkt = av_packet_alloc();
|
||||||
|
if (!mTmpPkt) {
|
||||||
|
LogError("Could not allocate AVPacket\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LogInfo("find encoder : %s\n", avcodec_get_name(mCodecId));
|
||||||
|
int i = 0;
|
||||||
|
/* find the encoder */
|
||||||
|
mCodec = (AVCodec *)avcodec_find_encoder(mCodecId);
|
||||||
|
if (!mCodec) {
|
||||||
|
LogError("Could not find encoder for '%s'\n", avcodec_get_name(mCodecId));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mCodecCtx = avcodec_alloc_context3(mCodec);
|
||||||
|
if (!mCodecCtx) {
|
||||||
|
LogError("Could not alloc an encoding context\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const AVChannelLayout src = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
|
||||||
|
switch (mCodec->type) {
|
||||||
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
|
mCodecCtx->sample_fmt = mCodec->sample_fmts ? mCodec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
|
||||||
|
mCodecCtx->bit_rate = 64000;
|
||||||
|
mCodecCtx->sample_rate = 44100;
|
||||||
|
if (mCodec->supported_samplerates) {
|
||||||
|
mCodecCtx->sample_rate = mCodec->supported_samplerates[0];
|
||||||
|
for (i = 0; mCodec->supported_samplerates[i]; i++) {
|
||||||
|
if (mCodec->supported_samplerates[i] == 44100)
|
||||||
|
mCodecCtx->sample_rate = 44100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCodecCtx->sample_rate = 8000;
|
||||||
|
av_channel_layout_copy(&mCodecCtx->ch_layout, &src);
|
||||||
|
// st->time_base = (AVRational){1, mCodecCtx->sample_rate};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
|
mCodecCtx->codec_id = mCodecId;
|
||||||
|
|
||||||
|
mCodecCtx->bit_rate = 400000;
|
||||||
|
/* Resolution must be a multiple of two. */
|
||||||
|
mCodecCtx->width = 1920;
|
||||||
|
mCodecCtx->height = 2160;
|
||||||
|
/* timebase: This is the fundamental unit of time (in seconds) in terms
|
||||||
|
* of which frame timestamps are represented. For fixed-fps content,
|
||||||
|
* timebase should be 1/framerate and timestamp increments should be
|
||||||
|
* identical to 1. */
|
||||||
|
// st->time_base = (AVRational){1, STREAM_FRAME_RATE};
|
||||||
|
mCodecCtx->time_base = (AVRational){1, STREAM_FRAME_RATE};
|
||||||
|
|
||||||
|
mCodecCtx->gop_size = 12; /* emit one intra frame every twelve frames at most */
|
||||||
|
mCodecCtx->pix_fmt = STREAM_PIX_FMT;
|
||||||
|
if (mCodecCtx->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
|
/* just for testing, we also add B-frames */
|
||||||
|
mCodecCtx->max_b_frames = 2;
|
||||||
|
}
|
||||||
|
if (mCodecCtx->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
|
||||||
|
/* Needed to avoid using macroblocks in which some coeffs overflow.
|
||||||
|
* This does not happen with normal video, it just happens here as
|
||||||
|
* the motion of the chroma plane does not match the luma plane. */
|
||||||
|
mCodecCtx->mb_decision = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Some formats want stream headers to be separate. */
|
||||||
|
if (outputFlags & AVFMT_GLOBALHEADER) {
|
||||||
|
mCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void FfmpegEncoder::UnInit(void)
|
||||||
|
{
|
||||||
|
if (mFrame) {
|
||||||
|
av_frame_free(&mFrame);
|
||||||
|
mFrame = nullptr;
|
||||||
|
}
|
||||||
|
if (mTmpFrame) {
|
||||||
|
av_frame_free(&mTmpFrame);
|
||||||
|
mTmpFrame = nullptr;
|
||||||
|
}
|
||||||
|
if (mCodecCtx) {
|
||||||
|
avcodec_free_context(&mCodecCtx);
|
||||||
|
mCodecCtx = nullptr;
|
||||||
|
}
|
||||||
|
av_packet_free(&mTmpPkt);
|
||||||
|
swr_free(&mSwrCtx);
|
||||||
|
}
|
||||||
|
AVRational FfmpegEncoder::GetTimeBase(void)
|
||||||
|
{
|
||||||
|
switch (mCodec->type) {
|
||||||
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
|
return (AVRational){1, mCodecCtx->sample_rate};
|
||||||
|
|
||||||
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
|
return mCodecCtx->time_base;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LogError("Unsupported media type.\n");
|
||||||
|
return (AVRational){0, -1};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool FfmpegEncoder::OpenEncoder(AVDictionary *optArg, AVStream *stream)
|
||||||
|
{
|
||||||
|
switch (mCodec->type) {
|
||||||
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
|
return OpenAudio(optArg, stream);
|
||||||
|
|
||||||
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
|
return OpenVideo(optArg, stream);
|
||||||
|
|
||||||
|
default:
|
||||||
|
LogError("Unsupported media type.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int FfmpegEncoder::EncodeData(AVFrame *frame, AVStream *stream, std::function<void(AVPacket *pkt)> callback)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
AVFrame *tmpFrame = frame;
|
||||||
|
if (AVMEDIA_TYPE_AUDIO == mCodec->type) {
|
||||||
|
tmpFrame = ConvertAudioFrame(frame, mSwrCtx);
|
||||||
|
}
|
||||||
|
if (!tmpFrame) {
|
||||||
|
LogError("Could not convert audio frame.\n");
|
||||||
|
return AVERROR_EXIT;
|
||||||
|
}
|
||||||
|
// send the frame to the encoder
|
||||||
|
ret = avcodec_send_frame(mCodecCtx, tmpFrame);
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogInfo("Error sending a frame to the encoder: %s\n",
|
||||||
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return AVERROR_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ret >= 0) {
|
||||||
|
ret = avcodec_receive_packet(mCodecCtx, mTmpPkt);
|
||||||
|
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogInfo("Error encoding a frame: %s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return AVERROR_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rescale output packet timestamp values from codec to stream timebase */
|
||||||
|
av_packet_rescale_ts(mTmpPkt, mCodecCtx->time_base, stream->time_base);
|
||||||
|
mTmpPkt->stream_index = stream->index;
|
||||||
|
|
||||||
|
/* Write the compressed frame to the media file. */
|
||||||
|
// log_packet(fmt_ctx, pkt);
|
||||||
|
// ret = av_interleaved_write_frame(fmt_ctx, pkt);
|
||||||
|
if (callback) {
|
||||||
|
callback(mTmpPkt);
|
||||||
|
}
|
||||||
|
/* pkt is now blank (av_interleaved_write_frame() takes ownership of
|
||||||
|
* its contents and resets pkt), so that no unreferencing is necessary.
|
||||||
|
* This would be different if one used av_write_frame(). */
|
||||||
|
// if (ret < 0) {
|
||||||
|
// fprintf(stderr, "Error while writing output packet: %s\n", av_err2str(ret));
|
||||||
|
// return AVERROR_EXIT;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret == AVERROR_EOF ? 1 : 0;
|
||||||
|
}
|
||||||
|
bool FfmpegEncoder::OpenVideo(AVDictionary *optArg, AVStream *stream)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
AVDictionary *opt = nullptr;
|
||||||
|
av_dict_copy(&opt, optArg, 0);
|
||||||
|
/* open the codec */
|
||||||
|
ret = avcodec_open2(mCodecCtx, mCodec, &opt);
|
||||||
|
av_dict_free(&opt);
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogError("Could not open video codec: %s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* allocate and init a re-usable frame */
|
||||||
|
mFrame = alloc_frame(mCodecCtx->pix_fmt, mCodecCtx->width, mCodecCtx->height);
|
||||||
|
if (!mFrame) {
|
||||||
|
LogError("Could not allocate video frame\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mCodecCtx->pix_fmt != AV_PIX_FMT_YUV420P) {
|
||||||
|
mTmpFrame = alloc_frame(AV_PIX_FMT_YUV420P, mCodecCtx->width, mCodecCtx->height);
|
||||||
|
if (!mTmpFrame) {
|
||||||
|
LogError("Could not allocate temporary video frame\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* copy the stream parameters to the muxer */
|
||||||
|
ret = avcodec_parameters_from_context(stream->codecpar, mCodecCtx);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Could not copy the stream parameters\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool FfmpegEncoder::OpenAudio(AVDictionary *optArg, AVStream *stream)
|
||||||
|
{
|
||||||
|
int nb_samples = 0;
|
||||||
|
int ret = 0;
|
||||||
|
AVDictionary *opt = nullptr;
|
||||||
|
av_dict_copy(&opt, optArg, 0);
|
||||||
|
/* open it */
|
||||||
|
ret = avcodec_open2(mCodecCtx, mCodec, &opt);
|
||||||
|
av_dict_free(&opt);
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogError("Could not open audio codec: %s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mCodecCtx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
|
||||||
|
nb_samples = 10000;
|
||||||
|
else
|
||||||
|
nb_samples = mCodecCtx->frame_size;
|
||||||
|
mFrame = alloc_audio_frame(mCodecCtx->sample_fmt, &mCodecCtx->ch_layout, mCodecCtx->sample_rate, nb_samples);
|
||||||
|
mTmpFrame = alloc_audio_frame(AV_SAMPLE_FMT_S16, &mCodecCtx->ch_layout, mCodecCtx->sample_rate, nb_samples);
|
||||||
|
/* copy the stream parameters to the muxer */
|
||||||
|
ret = avcodec_parameters_from_context(stream->codecpar, mCodecCtx);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Could not copy the stream parameters\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* create resampler context */
|
||||||
|
mSwrCtx = swr_alloc();
|
||||||
|
if (!mSwrCtx) {
|
||||||
|
LogError("Could not allocate resampler context\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* set options */
|
||||||
|
av_opt_set_chlayout(mSwrCtx, "in_chlayout", &mCodecCtx->ch_layout, 0);
|
||||||
|
av_opt_set_int(mSwrCtx, "in_sample_rate", mCodecCtx->sample_rate, 0);
|
||||||
|
av_opt_set_sample_fmt(mSwrCtx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||||
|
av_opt_set_chlayout(mSwrCtx, "out_chlayout", &mCodecCtx->ch_layout, 0);
|
||||||
|
av_opt_set_int(mSwrCtx, "out_sample_rate", mCodecCtx->sample_rate, 0);
|
||||||
|
av_opt_set_sample_fmt(mSwrCtx, "out_sample_fmt", mCodecCtx->sample_fmt, 0);
|
||||||
|
/* initialize the resampling context */
|
||||||
|
if ((ret = swr_init(mSwrCtx)) < 0) {
|
||||||
|
LogError("Failed to initialize the resampling context\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AVFrame *FfmpegEncoder::ConvertAudioFrame(AVFrame *decodeFrame, struct SwrContext *swr_ctx)
|
||||||
|
{
|
||||||
|
if (nullptr == decodeFrame) {
|
||||||
|
LogError("decodeFrame is null\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
decodeFrame->pts = next_pts;
|
||||||
|
next_pts += decodeFrame->nb_samples;
|
||||||
|
int ret = 0;
|
||||||
|
int dst_nb_samples = 0;
|
||||||
|
/* convert samples from native format to destination codec format, using the resampler */
|
||||||
|
/* compute destination number of samples */
|
||||||
|
dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, mCodecCtx->sample_rate) + decodeFrame->nb_samples,
|
||||||
|
mCodecCtx->sample_rate,
|
||||||
|
mCodecCtx->sample_rate,
|
||||||
|
AV_ROUND_UP);
|
||||||
|
av_assert0(dst_nb_samples == decodeFrame->nb_samples);
|
||||||
|
|
||||||
|
/* when we pass a frame to the encoder, it may keep a reference to it
|
||||||
|
* internally;
|
||||||
|
* make sure we do not overwrite it here
|
||||||
|
*/
|
||||||
|
ret = av_frame_make_writable(mFrame);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("av_frame_make_writable failed\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert to destination format */
|
||||||
|
ret = swr_convert(
|
||||||
|
swr_ctx, mFrame->data, dst_nb_samples, (const uint8_t **)decodeFrame->data, decodeFrame->nb_samples);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogError("Error while converting\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFrame->pts = av_rescale_q(mSamplesCount, (AVRational){1, mCodecCtx->sample_rate}, mCodecCtx->time_base);
|
||||||
|
mSamplesCount += dst_nb_samples;
|
||||||
|
return mFrame;
|
||||||
|
}
|
||||||
|
AVFrame *FfmpegEncoder::alloc_frame(enum AVPixelFormat pix_fmt, int width, int height)
|
||||||
|
{
|
||||||
|
AVFrame *frame;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
frame = av_frame_alloc();
|
||||||
|
if (!frame)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
frame->format = pix_fmt;
|
||||||
|
frame->width = width;
|
||||||
|
frame->height = height;
|
||||||
|
|
||||||
|
/* allocate the buffers for the frame data */
|
||||||
|
ret = av_frame_get_buffer(frame, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
LogInfo("Could not allocate frame data.\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
AVFrame *FfmpegEncoder::alloc_audio_frame(enum AVSampleFormat sample_fmt, const AVChannelLayout *channel_layout,
|
||||||
|
int sample_rate, int nb_samples)
|
||||||
|
{
|
||||||
|
AVFrame *frame = av_frame_alloc();
|
||||||
|
if (!frame) {
|
||||||
|
LogInfo("Error allocating an audio frame\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame->format = sample_fmt;
|
||||||
|
av_channel_layout_copy(&frame->ch_layout, channel_layout);
|
||||||
|
frame->sample_rate = sample_rate;
|
||||||
|
frame->nb_samples = nb_samples;
|
||||||
|
|
||||||
|
if (nb_samples) {
|
||||||
|
if (av_frame_get_buffer(frame, 0) < 0) {
|
||||||
|
LogInfo("Error allocating an audio buffer\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
68
utils/MediaBase/src/FfmpegEncoder.h
Normal file
68
utils/MediaBase/src/FfmpegEncoder.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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 FFMPEG_ENCODER_H
|
||||||
|
#define FFMPEG_ENCODER_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#include <libavutil/timestamp.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
class FfmpegEncoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FfmpegEncoder(const enum AVCodecID &codecId);
|
||||||
|
virtual ~FfmpegEncoder() = default;
|
||||||
|
bool Init(int &outputFlags);
|
||||||
|
void UnInit(void);
|
||||||
|
AVRational GetTimeBase(void);
|
||||||
|
bool OpenEncoder(AVDictionary *optArg, AVStream *stream);
|
||||||
|
int EncodeData(AVFrame *frame, AVStream *stream, std::function<void(AVPacket *pkt)> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool OpenVideo(AVDictionary *optArg, AVStream *stream);
|
||||||
|
bool OpenAudio(AVDictionary *optArg, AVStream *stream);
|
||||||
|
AVFrame *ConvertAudioFrame(AVFrame *decodeFrame, struct SwrContext *swr_ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height);
|
||||||
|
static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, const AVChannelLayout *channel_layout,
|
||||||
|
int sample_rate, int nb_samples);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const enum AVCodecID mCodecId;
|
||||||
|
AVCodecContext *mCodecCtx;
|
||||||
|
AVCodec *mCodec;
|
||||||
|
AVFrame *mFrame;
|
||||||
|
AVFrame *mTmpFrame;
|
||||||
|
AVPacket *mTmpPkt;
|
||||||
|
int mSamplesCount;
|
||||||
|
struct SwrContext *mSwrCtx;
|
||||||
|
int64_t next_pts;
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -18,6 +18,7 @@
|
||||||
#include "StatusCode.h"
|
#include "StatusCode.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -30,11 +31,13 @@ extern "C" {
|
||||||
#include <libavcodec/packet.h>
|
#include <libavcodec/packet.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
#include <libavformat/avio.h>
|
#include <libavformat/avio.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
#include <libavutil/avutil.h>
|
#include <libavutil/avutil.h>
|
||||||
#include <libavutil/channel_layout.h>
|
#include <libavutil/channel_layout.h>
|
||||||
#include <libavutil/dict.h>
|
#include <libavutil/dict.h>
|
||||||
#include <libavutil/error.h>
|
#include <libavutil/error.h>
|
||||||
#include <libavutil/frame.h>
|
#include <libavutil/frame.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
#include <libavutil/opt.h>
|
#include <libavutil/opt.h>
|
||||||
#include <libavutil/pixfmt.h>
|
#include <libavutil/pixfmt.h>
|
||||||
#include <libavutil/samplefmt.h>
|
#include <libavutil/samplefmt.h>
|
||||||
|
@ -106,7 +109,7 @@ StatusCode FfmpegMuxStream::OpenOutputFile(const std::string &fileName)
|
||||||
ret = avio_open(&oc->pb, fileName.c_str(), AVIO_FLAG_WRITE);
|
ret = avio_open(&oc->pb, fileName.c_str(), AVIO_FLAG_WRITE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
LogInfo("Could not open '%s': %s\n",
|
LogError("Could not open '%s': %s\n",
|
||||||
fileName.c_str(),
|
fileName.c_str(),
|
||||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
|
@ -116,7 +119,7 @@ StatusCode FfmpegMuxStream::OpenOutputFile(const std::string &fileName)
|
||||||
ret = avformat_write_header(oc, &opt);
|
ret = avformat_write_header(oc, &opt);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
LogInfo("Error occurred when opening output file: %s\n",
|
LogError("Error occurred when opening output file: %s\n",
|
||||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +127,9 @@ StatusCode FfmpegMuxStream::OpenOutputFile(const std::string &fileName)
|
||||||
}
|
}
|
||||||
StatusCode FfmpegMuxStream::CloseOutputFile(void)
|
StatusCode FfmpegMuxStream::CloseOutputFile(void)
|
||||||
{
|
{
|
||||||
|
if (mOc && mOc->pb) {
|
||||||
av_write_trailer(mOc);
|
av_write_trailer(mOc);
|
||||||
|
}
|
||||||
if (mFrameVideo) {
|
if (mFrameVideo) {
|
||||||
av_frame_free(&mFrameVideo);
|
av_frame_free(&mFrameVideo);
|
||||||
mFrameVideo = nullptr;
|
mFrameVideo = nullptr;
|
||||||
|
@ -141,6 +146,9 @@ StatusCode FfmpegMuxStream::CloseOutputFile(void)
|
||||||
avcodec_free_context(&mCodecAudioContext);
|
avcodec_free_context(&mCodecAudioContext);
|
||||||
mCodecAudioContext = nullptr;
|
mCodecAudioContext = nullptr;
|
||||||
}
|
}
|
||||||
|
if (nullptr == mOc) {
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
||||||
close_stream(mOc, &mVideoSt);
|
close_stream(mOc, &mVideoSt);
|
||||||
close_stream(mOc, &mAudioSt);
|
close_stream(mOc, &mAudioSt);
|
||||||
memset(&mVideoSt, 0, sizeof(mVideoSt));
|
memset(&mVideoSt, 0, sizeof(mVideoSt));
|
||||||
|
@ -189,12 +197,26 @@ void FfmpegMuxStream::GetVideoStream(const void *data, const size_t &size, const
|
||||||
av_packet_unref(packet);
|
av_packet_unref(packet);
|
||||||
av_packet_free(&packet);
|
av_packet_free(&packet);
|
||||||
}
|
}
|
||||||
|
void save_code_stream_file(const void *data, const unsigned int &size)
|
||||||
|
{
|
||||||
|
FILE *file = NULL;
|
||||||
|
file = fopen("./test.g711a", "a+");
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
fwrite(data, 1, size, file);
|
||||||
|
fflush(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file)
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
void FfmpegMuxStream::GetAudioStream(const void *data, const size_t &size, const StreamInfo &streamInfo)
|
void FfmpegMuxStream::GetAudioStream(const void *data, const size_t &size, const StreamInfo &streamInfo)
|
||||||
{
|
{
|
||||||
AVPacket *packet = nullptr;
|
AVPacket *packet = nullptr;
|
||||||
packet = av_packet_alloc();
|
packet = av_packet_alloc();
|
||||||
packet->data = (unsigned char *)data;
|
packet->data = (unsigned char *)data;
|
||||||
packet->size = size;
|
packet->size = size;
|
||||||
|
// save_code_stream_file(data, size);
|
||||||
int ret = avcodec_send_packet(mCodecAudioContext, packet);
|
int ret = avcodec_send_packet(mCodecAudioContext, packet);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LogInfo("Error sending a packet for decoding\n");
|
LogInfo("Error sending a packet for decoding\n");
|
||||||
|
@ -213,7 +235,7 @@ void FfmpegMuxStream::GetAudioStream(const void *data, const size_t &size, const
|
||||||
}
|
}
|
||||||
mFrameAudio->pts = mAudioSt.next_pts;
|
mFrameAudio->pts = mAudioSt.next_pts;
|
||||||
mAudioSt.next_pts += mFrameAudio->nb_samples;
|
mAudioSt.next_pts += mFrameAudio->nb_samples;
|
||||||
ConvertAudioFrame(mFrameVideo, mAudioSt.enc, &mAudioSt);
|
ConvertAudioFrame(mFrameAudio, mAudioSt.enc, &mAudioSt);
|
||||||
write_frame(mOc, mAudioSt.enc, mAudioSt.st, mAudioSt.frame, mAudioSt.tmp_pkt);
|
write_frame(mOc, mAudioSt.enc, mAudioSt.st, mAudioSt.frame, mAudioSt.tmp_pkt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +246,7 @@ bool FfmpegMuxStream::add_stream(OutputStream *ost, AVFormatContext *oc, const A
|
||||||
{
|
{
|
||||||
AVCodecContext *c;
|
AVCodecContext *c;
|
||||||
int i;
|
int i;
|
||||||
|
LogInfo("Encoder: %s\n", avcodec_get_name(codec_id));
|
||||||
/* find the encoder */
|
/* find the encoder */
|
||||||
*codec = avcodec_find_encoder(codec_id);
|
*codec = avcodec_find_encoder(codec_id);
|
||||||
if (!(*codec)) {
|
if (!(*codec)) {
|
||||||
|
@ -264,6 +286,7 @@ bool FfmpegMuxStream::add_stream(OutputStream *ost, AVFormatContext *oc, const A
|
||||||
c->sample_rate = 44100;
|
c->sample_rate = 44100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c->sample_rate = 8000;
|
||||||
av_channel_layout_copy(&c->ch_layout, &src);
|
av_channel_layout_copy(&c->ch_layout, &src);
|
||||||
ost->st->time_base = (AVRational){1, c->sample_rate};
|
ost->st->time_base = (AVRational){1, c->sample_rate};
|
||||||
break;
|
break;
|
||||||
|
@ -273,8 +296,8 @@ bool FfmpegMuxStream::add_stream(OutputStream *ost, AVFormatContext *oc, const A
|
||||||
|
|
||||||
c->bit_rate = 400000;
|
c->bit_rate = 400000;
|
||||||
/* Resolution must be a multiple of two. */
|
/* Resolution must be a multiple of two. */
|
||||||
c->width = 352;
|
c->width = 1920;
|
||||||
c->height = 288;
|
c->height = 2160;
|
||||||
/* timebase: This is the fundamental unit of time (in seconds) in terms
|
/* timebase: This is the fundamental unit of time (in seconds) in terms
|
||||||
* of which frame timestamps are represented. For fixed-fps content,
|
* of which frame timestamps are represented. For fixed-fps content,
|
||||||
* timebase should be 1/framerate and timestamp increments should be
|
* timebase should be 1/framerate and timestamp increments should be
|
||||||
|
@ -498,6 +521,7 @@ bool FfmpegMuxStream::InitCodecAudio(enum AVCodecID codecId, AVCodec **codec, AV
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
*codec = (AVCodec *)avcodec_find_decoder(codecId);
|
*codec = (AVCodec *)avcodec_find_decoder(codecId);
|
||||||
|
// *codec = (AVCodec *)avcodec_find_decoder_by_name("libfdk_aac");
|
||||||
if (!(*codec)) {
|
if (!(*codec)) {
|
||||||
LogError("Codec not found\n");
|
LogError("Codec not found\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -509,6 +533,8 @@ bool FfmpegMuxStream::InitCodecAudio(enum AVCodecID codecId, AVCodec **codec, AV
|
||||||
}
|
}
|
||||||
/* put sample parameters */
|
/* put sample parameters */
|
||||||
(*codec_ctx)->bit_rate = 64000;
|
(*codec_ctx)->bit_rate = 64000;
|
||||||
|
// (*codec_ctx)->bit_rate = 352800;
|
||||||
|
// (*codec_ctx)->sample_rate = 8000;
|
||||||
|
|
||||||
/* check that the encoder supports s16 pcm input */
|
/* check that the encoder supports s16 pcm input */
|
||||||
(*codec_ctx)->sample_fmt = AV_SAMPLE_FMT_S16;
|
(*codec_ctx)->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||||
|
@ -529,6 +555,8 @@ bool FfmpegMuxStream::InitCodecAudio(enum AVCodecID codecId, AVCodec **codec, AV
|
||||||
LogError("Could not open codec:%s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
LogError("Could not open codec:%s\n", av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/* Set the packet timebase for the decoder. */
|
||||||
|
// (*codec_ctx)->pkt_timebase = {.num = 1, .den = 44100};
|
||||||
*frame = av_frame_alloc();
|
*frame = av_frame_alloc();
|
||||||
if (!(*frame)) {
|
if (!(*frame)) {
|
||||||
LogError("Could not allocate video frame\n");
|
LogError("Could not allocate video frame\n");
|
||||||
|
@ -572,7 +600,7 @@ int FfmpegMuxStream::write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c, AV
|
||||||
pkt->stream_index = st->index;
|
pkt->stream_index = st->index;
|
||||||
|
|
||||||
/* Write the compressed frame to the media file. */
|
/* Write the compressed frame to the media file. */
|
||||||
log_packet(fmt_ctx, pkt);
|
// log_packet(fmt_ctx, pkt);
|
||||||
ret = av_interleaved_write_frame(fmt_ctx, pkt);
|
ret = av_interleaved_write_frame(fmt_ctx, pkt);
|
||||||
/* pkt is now blank (av_interleaved_write_frame() takes ownership of
|
/* pkt is now blank (av_interleaved_write_frame() takes ownership of
|
||||||
* its contents and resets pkt), so that no unreferencing is necessary.
|
* its contents and resets pkt), so that no unreferencing is necessary.
|
||||||
|
|
137
utils/MediaBase/src/FfmpegMuxStreamV2.cpp
Normal file
137
utils/MediaBase/src/FfmpegMuxStreamV2.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* 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 "FfmpegMuxStreamV2.h"
|
||||||
|
#include "FfmpegOutputStream.h"
|
||||||
|
#include "ILog.h"
|
||||||
|
#include "MediaBase.h"
|
||||||
|
#include "StatusCode.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/codec_id.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavformat/avio.h>
|
||||||
|
#include <libavutil/dict.h>
|
||||||
|
#include <libavutil/error.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
// #include <mutex>
|
||||||
|
#include <string>
|
||||||
|
FfmpegMuxStreamV2::FfmpegMuxStreamV2() : mOutputFormat(nullptr), mOptions(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StatusCode FfmpegMuxStreamV2::OpenOutputFile(const std::string &fileName)
|
||||||
|
{
|
||||||
|
return OpenMuxOutputFile(fileName);
|
||||||
|
}
|
||||||
|
StatusCode FfmpegMuxStreamV2::CloseOutputFile(void)
|
||||||
|
{
|
||||||
|
if (mOutputFormat && mOutputFormat->pb) {
|
||||||
|
av_write_trailer(mOutputFormat);
|
||||||
|
}
|
||||||
|
if (mVideoStream) {
|
||||||
|
mVideoStream->UnInit();
|
||||||
|
}
|
||||||
|
if (mAudioStream) {
|
||||||
|
mAudioStream->UnInit();
|
||||||
|
}
|
||||||
|
if (nullptr == mOutputFormat) {
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
||||||
|
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
|
||||||
|
/* Close the output file. */
|
||||||
|
avio_closep(&mOutputFormat->pb);
|
||||||
|
}
|
||||||
|
avformat_free_context(mOutputFormat);
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
||||||
|
void FfmpegMuxStreamV2::GetStreamData(const void *data, const size_t &size, const StreamInfo &streamInfo)
|
||||||
|
{
|
||||||
|
if (streamInfo.mType == STREAM_TYPE_VIDEO_H264 && mVideoStream) {
|
||||||
|
mVideoStream->WriteSourceData(data, size);
|
||||||
|
}
|
||||||
|
if (streamInfo.mType == STREAM_TYPE_AUDIO_G711A && mAudioStream) {
|
||||||
|
mAudioStream->WriteSourceData(data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusCode FfmpegMuxStreamV2::OpenMuxOutputFile(const std::string &fileName)
|
||||||
|
{
|
||||||
|
AVDictionary *opt = nullptr;
|
||||||
|
int ret = 0;
|
||||||
|
/* allocate the output media context */
|
||||||
|
avformat_alloc_output_context2(&mOutputFormat, nullptr, "mp4", fileName.c_str());
|
||||||
|
if (!mOutputFormat) {
|
||||||
|
LogError("Could not deduce output format from file.\n");
|
||||||
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
|
}
|
||||||
|
/* Add the audio and video streams using the default format codecs
|
||||||
|
* and initialize the codecs. */
|
||||||
|
if (mOutputFormat->oformat->video_codec != AV_CODEC_ID_NONE) {
|
||||||
|
mVideoStream = AddStream(mOutputFormat, mOutputFormat->oformat->video_codec, AV_CODEC_ID_H264);
|
||||||
|
mVideoStream->SetWriteSourceDataCallback(
|
||||||
|
std::bind(&FfmpegMuxStreamV2::GetAVPacketDataCallback, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
if (mOutputFormat->oformat->audio_codec != AV_CODEC_ID_NONE) {
|
||||||
|
mAudioStream = AddStream(mOutputFormat, mOutputFormat->oformat->audio_codec, AV_CODEC_ID_PCM_ALAW);
|
||||||
|
mAudioStream->SetWriteSourceDataCallback(
|
||||||
|
std::bind(&FfmpegMuxStreamV2::GetAVPacketDataCallback, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
av_dump_format(mOutputFormat, 0, fileName.c_str(), 1);
|
||||||
|
/* open the output file, if needed */
|
||||||
|
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
|
||||||
|
ret = avio_open(&mOutputFormat->pb, fileName.c_str(), AVIO_FLAG_WRITE);
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogError("Could not open '%s': %s\n",
|
||||||
|
fileName.c_str(),
|
||||||
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Write the stream header, if any. */
|
||||||
|
ret = avformat_write_header(mOutputFormat, &opt);
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogError("Error occurred when opening output file: %s\n",
|
||||||
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
return CreateStatusCode(STATUS_CODE_NOT_OK);
|
||||||
|
}
|
||||||
|
return CreateStatusCode(STATUS_CODE_OK);
|
||||||
|
}
|
||||||
|
void FfmpegMuxStreamV2::GetAVPacketDataCallback(AVPacket *pkt)
|
||||||
|
{
|
||||||
|
// std::lock_guard<std::mutex> locker(mMutex);
|
||||||
|
int ret = 0;
|
||||||
|
ret = av_interleaved_write_frame(mOutputFormat, pkt);
|
||||||
|
/* pkt is now blank (av_interleaved_write_frame() takes ownership of
|
||||||
|
* its contents and resets pkt), so that no unreferencing is necessary.
|
||||||
|
* This would be different if one used av_write_frame(). */
|
||||||
|
if (ret < 0) {
|
||||||
|
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||||
|
LogInfo("Error while writing output packet: %s\n",
|
||||||
|
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::shared_ptr<FfmpegOutputStream> FfmpegMuxStreamV2::AddStream(AVFormatContext *outputFormat,
|
||||||
|
enum AVCodecID encodecId, enum AVCodecID decodecId)
|
||||||
|
{
|
||||||
|
auto stream = std::make_shared<FfmpegOutputStream>(encodecId, decodecId);
|
||||||
|
stream->Init(outputFormat);
|
||||||
|
return stream;
|
||||||
|
}
|
67
utils/MediaBase/src/FfmpegMuxStreamV2.h
Normal file
67
utils/MediaBase/src/FfmpegMuxStreamV2.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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 FFMPEG_MUX_STREAM_V2_H
|
||||||
|
#define FFMPEG_MUX_STREAM_V2_H
|
||||||
|
#include "FfmpegBase.h"
|
||||||
|
#include "FfmpegOutputStream.h"
|
||||||
|
#include "MediaBase.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#include <libavutil/timestamp.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
class FfmpegMuxStreamV2 : virtual public FfmpegBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FfmpegMuxStreamV2();
|
||||||
|
virtual ~FfmpegMuxStreamV2() = default;
|
||||||
|
|
||||||
|
public: // About combine file.
|
||||||
|
StatusCode OpenOutputFile(const std::string &fileName) override;
|
||||||
|
StatusCode CloseOutputFile(void) override;
|
||||||
|
void GetStreamData(const void *data, const size_t &size, const StreamInfo &streamInfo) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StatusCode OpenMuxOutputFile(const std::string &fileName);
|
||||||
|
void GetAVPacketDataCallback(AVPacket *pkt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::shared_ptr<FfmpegOutputStream> AddStream(AVFormatContext *outputFormat, enum AVCodecID encodecId,
|
||||||
|
enum AVCodecID decodecId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mMutex;
|
||||||
|
AVFormatContext *mOutputFormat;
|
||||||
|
std::shared_ptr<FfmpegOutputStream> mVideoStream;
|
||||||
|
std::shared_ptr<FfmpegOutputStream> mAudioStream;
|
||||||
|
AVDictionary *mOptions;
|
||||||
|
};
|
||||||
|
#endif
|
78
utils/MediaBase/src/FfmpegOutputStream.cpp
Normal file
78
utils/MediaBase/src/FfmpegOutputStream.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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 "FfmpegOutputStream.h"
|
||||||
|
#include "FfmpegDecoder.h"
|
||||||
|
#include "FfmpegEncoder.h"
|
||||||
|
#include "ILog.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/codec_id.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/frame.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
FfmpegOutputStream::FfmpegOutputStream(const AVCodecID &encodecId, const AVCodecID &dncodecId)
|
||||||
|
: mEncodecId(encodecId), mDeccodecId(dncodecId), mTmpPkt(nullptr), mStream(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool FfmpegOutputStream::Init(AVFormatContext *outputFormat)
|
||||||
|
{
|
||||||
|
mDecodeCallback = std::bind(&FfmpegOutputStream::GetDecodeDataCallback, this, std::placeholders::_1);
|
||||||
|
mTmpPkt = av_packet_alloc();
|
||||||
|
if (!mTmpPkt) {
|
||||||
|
LogError("Could not allocate AVPacket\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mStream = avformat_new_stream(outputFormat, nullptr);
|
||||||
|
if (!mStream) {
|
||||||
|
LogError("Could not allocate stream\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mDecoder = std::make_shared<FfmpegDecoder>(mDeccodecId);
|
||||||
|
mDecoder->Init();
|
||||||
|
mStream->id = outputFormat->nb_streams - 1;
|
||||||
|
mEncoder = std::make_shared<FfmpegEncoder>(mEncodecId);
|
||||||
|
mEncoder->Init(outputFormat->flags);
|
||||||
|
mStream->time_base = mEncoder->GetTimeBase();
|
||||||
|
mEncoder->OpenEncoder(nullptr, mStream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void FfmpegOutputStream::UnInit(void)
|
||||||
|
{
|
||||||
|
mEncoder->UnInit();
|
||||||
|
mDecoder->UnInit();
|
||||||
|
av_packet_free(&mTmpPkt);
|
||||||
|
}
|
||||||
|
void FfmpegOutputStream::WriteSourceData(const void *data, const size_t &size)
|
||||||
|
{
|
||||||
|
mDecoder->DecodeData(data, size, mDecodeCallback);
|
||||||
|
}
|
||||||
|
void FfmpegOutputStream::SetWriteSourceDataCallback(std::function<void(AVPacket *pkt)> callback)
|
||||||
|
{
|
||||||
|
mEncodeCallback = callback;
|
||||||
|
}
|
||||||
|
void FfmpegOutputStream::GetDecodeDataCallback(AVFrame *frame)
|
||||||
|
{
|
||||||
|
mEncoder->EncodeData(frame, mStream, mEncodeCallback);
|
||||||
|
}
|
||||||
|
void FfmpegOutputStream::GetEncodeDataCallback(AVPacket *pkt)
|
||||||
|
{
|
||||||
|
}
|
63
utils/MediaBase/src/FfmpegOutputStream.h
Normal file
63
utils/MediaBase/src/FfmpegOutputStream.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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 FFMPEG_OUTPUT_STREAM_H
|
||||||
|
#define FFMPEG_OUTPUT_STREAM_H
|
||||||
|
#include "FfmpegDecoder.h"
|
||||||
|
#include "FfmpegEncoder.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavcodec/packet.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avassert.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#include <libavutil/timestamp.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
class FfmpegOutputStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FfmpegOutputStream(const AVCodecID &encodecId, const AVCodecID &dncodecId);
|
||||||
|
virtual ~FfmpegOutputStream() = default;
|
||||||
|
bool Init(AVFormatContext *outputFormat);
|
||||||
|
void UnInit(void);
|
||||||
|
void WriteSourceData(const void *data, const size_t &size);
|
||||||
|
void SetWriteSourceDataCallback(std::function<void(AVPacket *pkt)> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetDecodeDataCallback(AVFrame *frame);
|
||||||
|
void GetEncodeDataCallback(AVPacket *pkt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const AVCodecID mEncodecId;
|
||||||
|
const AVCodecID mDeccodecId;
|
||||||
|
AVPacket *mTmpPkt;
|
||||||
|
std::shared_ptr<FfmpegEncoder> mEncoder;
|
||||||
|
std::shared_ptr<FfmpegDecoder> mDecoder;
|
||||||
|
AVStream *mStream;
|
||||||
|
std::function<void(AVFrame *)> mDecodeCallback;
|
||||||
|
std::function<void(AVPacket *)> mEncodeCallback;
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -123,6 +123,10 @@ void FfmpegReadFile::ReadFileThread(AVFormatContext *pFormatCtx, int mediaStream
|
||||||
pFormatCtx->streams[mediaStreamIndex]->time_base.den;
|
pFormatCtx->streams[mediaStreamIndex]->time_base.den;
|
||||||
// LogInfo("Frame data address: %p, length: %zu\n", packet.data, packet.size);
|
// LogInfo("Frame data address: %p, length: %zu\n", packet.data, packet.size);
|
||||||
// LogInfo("Play time ms:%d\n", playTimeMs);
|
// LogInfo("Play time ms:%d\n", playTimeMs);
|
||||||
|
// LogInfo("time base: num = %d, den = %d\n",
|
||||||
|
// pFormatCtx->streams[mediaStreamIndex]->time_base.num,
|
||||||
|
// pFormatCtx->streams[mediaStreamIndex]->time_base.den);
|
||||||
|
// LogInfo("pFormatCtx->bit_rate = %ld\n", pFormatCtx->bit_rate);
|
||||||
ReadFrame(&packet);
|
ReadFrame(&packet);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(playTimeMs));
|
std::this_thread::sleep_for(std::chrono::milliseconds(playTimeMs));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
#ifndef MEDIA_BASE_IMPL_H
|
#ifndef MEDIA_BASE_IMPL_H
|
||||||
#define MEDIA_BASE_IMPL_H
|
#define MEDIA_BASE_IMPL_H
|
||||||
#include "FfmpegBase.h"
|
#include "FfmpegBase.h"
|
||||||
#include "FfmpegMuxStream.h"
|
#include "FfmpegMuxStreamV2.h"
|
||||||
#include "FfmpegReadFile.h"
|
#include "FfmpegReadFile.h"
|
||||||
#include "IMediaBase.h"
|
#include "IMediaBase.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
class MediaBaseImpl : public FfmpegReadFile, public FfmpegMuxStream
|
class MediaBaseImpl : public FfmpegReadFile, public FfmpegMuxStreamV2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MediaBaseImpl(const MediaHandleType &type);
|
MediaBaseImpl(const MediaHandleType &type);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user