diff --git a/utils/MediaBase/include/MediaBase.h b/utils/MediaBase/include/MediaBase.h index 13d4d81..d8a607b 100644 --- a/utils/MediaBase/include/MediaBase.h +++ b/utils/MediaBase/include/MediaBase.h @@ -53,6 +53,7 @@ typedef struct output_file_info { char mFileName[OUTPUT_FILE_NAME_MAX]; ///< Name of the output file. Must be an absolute path. char mThumbnailFileName[OUTPUT_FILE_NAME_MAX]; ///< Name of the thumbnail file. Must be an absolute path. + const bool mTakePicture; ///< Whether to take a picture. const unsigned int mDuration_ms; ///< Duration of the output file in milliseconds. int *const mFinished; ///< Whether the output file is finished. See OutputFileStatus. } OutputFileInfo; @@ -72,6 +73,10 @@ StatusCode ICloseOutputFile(void *object); void IGetStreamData(void *object, const void *data, const size_t size, const StreamInfo streamInfo); OutputFileInfo IGetOutputFileInfo(void *object); +StatusCode IOpenJpegFile(void *object, const OutputFileInfo *info); +StatusCode ICloseJpegFile(void *object); +StatusCode IWriteJpegData(void *object, const void *data, const size_t size); + void IMediaBaseFree(void *object); #ifdef __cplusplus } diff --git a/utils/MediaBase/src/FfmpegOriginalPicture.cpp b/utils/MediaBase/src/FfmpegOriginalPicture.cpp new file mode 100644 index 0000000..74d2b77 --- /dev/null +++ b/utils/MediaBase/src/FfmpegOriginalPicture.cpp @@ -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. + */ +#include "FfmpegOriginalPicture.h" +#include "ILog.h" +original_info::original_info(const int &srouceWidth, const int &srouceHeight) + : mSrouceWidth(srouceWidth), mSrouceHeight(srouceHeight) +{ +} +FfmpegOriginalPicture::FfmpegOriginalPicture(const AVCodecID &encodecId, const AVCodecID &decodecId) + : FfmpegThumbnail(encodecId, decodecId) +{ +} +void FfmpegOriginalPicture::Init(const OriginalInfo &originalInfo) +{ + ThumbnailInfo thumbnailInfo(originalInfo.mSrouceWidth, originalInfo.mSrouceHeight, 192, 216); + FfmpegThumbnail::Init(thumbnailInfo); +} +void FfmpegOriginalPicture::UnInit(void) +{ + FfmpegThumbnail::UnInit(); + if (mEncoder) { + mEncoder->UnInit(); + mEncoder.reset(); + } +} +bool FfmpegOriginalPicture::CreateOriginalPicture(const std::string &outputFile, const void *data, const size_t &size) +{ + mEncodeCallback = + std::bind(&FfmpegOriginalPicture::GetEncodeDataCallback, this, std::placeholders::_1, "./test_original.jpg"); + return FfmpegThumbnail::CreateThumbnail(outputFile, data, size); +} +void FfmpegOriginalPicture::EncodeDataToPicture(AVFrame *frame) +{ + LogInfo("EncodeDataToPicture.\n"); + if (!mStream) { + LogError("mStream = nullptr.\n"); + return; + } + mEncoder = std::make_shared(mEncodecId, mSrouceWidth, mSrouceHeight); + if (!mEncoder) { + LogError("mEncoder = nullptr.\n"); + } + constexpr int NO_FLAGS = 0; + mEncoder->Init(NO_FLAGS); + mStream->time_base = mEncoder->GetTimeBase(); + mEncoder->OpenEncoder(nullptr, mStream); + if (mEncoder) { + mEncoder->EncodeData(frame, mStream, mEncodeCallback); + } + FfmpegThumbnail::EncodeDataToPicture(frame); +} +void FfmpegOriginalPicture::GetEncodeDataCallback(AVPacket *pkt, const std::string &fileName) +{ + FfmpegThumbnail::SaveThumbnailFile(fileName, pkt->data, pkt->size); +} \ No newline at end of file diff --git a/utils/MediaBase/src/FfmpegOriginalPicture.h b/utils/MediaBase/src/FfmpegOriginalPicture.h new file mode 100644 index 0000000..555ef68 --- /dev/null +++ b/utils/MediaBase/src/FfmpegOriginalPicture.h @@ -0,0 +1,60 @@ +/* + * 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_ORIGINAL_PICTURE_H +#define FFMPEG_ORIGINAL_PICTURE_H +#include "FfmpegEncoder.h" +#include "FfmpegThumbnail.h" +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +} +#endif +typedef struct original_info +{ + original_info(const int &srouceWidth, const int &srouceHeight); + const int mSrouceWidth; + const int mSrouceHeight; +} OriginalInfo; +class FfmpegOriginalPicture : public FfmpegThumbnail +{ +public: + FfmpegOriginalPicture(const AVCodecID &encodecId, const AVCodecID &decodecId); + virtual ~FfmpegOriginalPicture() = default; + void Init(const OriginalInfo &originalInfo); + void UnInit(void); + bool CreateOriginalPicture(const std::string &outputFile, const void *data, const size_t &size); + +private: + void EncodeDataToPicture(AVFrame *frame) override; + void GetEncodeDataCallback(AVPacket *pkt, const std::string &fileName); + +private: + std::shared_ptr mEncoder; + std::function mEncodeCallback; +}; +#endif \ No newline at end of file diff --git a/utils/MediaBase/src/FfmpegOutputStream.cpp b/utils/MediaBase/src/FfmpegOutputStream.cpp index 7b053c6..21fadd8 100644 --- a/utils/MediaBase/src/FfmpegOutputStream.cpp +++ b/utils/MediaBase/src/FfmpegOutputStream.cpp @@ -15,6 +15,7 @@ #include "FfmpegOutputStream.h" #include "FfmpegDecoder.h" #include "FfmpegEncoder.h" +#include "FfmpegOriginalPicture.h" #include "FfmpegThumbnail.h" #include "ILog.h" #include @@ -204,4 +205,10 @@ void FfmpegOutputStream::CreateThumbnailFileThread(const void *frame, const size thumbnail.CreateThumbnail(mThumbnailFileName, frame, size); thumbnail.UnInit(); LogInfo("CreateThumbnailFile end.\n"); + // FfmpegOriginalPicture thumbnail(AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264); + // OriginalInfo info(1920, 2160); // TODO: + // thumbnail.Init(info); + // thumbnail.CreateOriginalPicture(mThumbnailFileName, frame, size); + // thumbnail.UnInit(); + // LogInfo("CreateThumbnailFile end.\n"); } \ No newline at end of file diff --git a/utils/MediaBase/src/FfmpegTakePicture.cpp b/utils/MediaBase/src/FfmpegTakePicture.cpp new file mode 100644 index 0000000..69e891e --- /dev/null +++ b/utils/MediaBase/src/FfmpegTakePicture.cpp @@ -0,0 +1,43 @@ +/* + * 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 "FfmpegTakePicture.h" +#include "FfmpegOriginalPicture.h" +#include "ILog.h" +StatusCode FfmpegTakePicture::OpenJpegFile(const OutputFileInfo &fileInfo) +{ + return CreateStatusCode(STATUS_CODE_OK); +} +StatusCode FfmpegTakePicture::CloseJpegFile(void) +{ + return CreateStatusCode(STATUS_CODE_OK); +} +StatusCode FfmpegTakePicture::WriteJpegData(const void *data, const size_t &size) +{ + char *pData = (char *)data; + for (size_t i = 0; i < size; i++) { + if ((0x00 == pData[i]) && (0x00 == pData[i + 1]) && (0x00 == pData[i + 2]) && (0x01 == pData[i + 3]) && + (0x5 == (pData[i + 4] & 0x1F))) { + LogInfo("Found extradata\n"); + FfmpegOriginalPicture picture(AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264); + OriginalInfo info(1920, 2160); // TODO: + picture.Init(info); + picture.CreateOriginalPicture("mThumbnailFileName", data, size); + picture.UnInit(); + LogInfo("CreateThumbnailFile end.\n"); + return CreateStatusCode(STATUS_CODE_OK); + } + } + return CreateStatusCode(STATUS_CODE_NOT_OK); +} \ No newline at end of file diff --git a/utils/MediaBase/src/FfmpegTakePicture.h b/utils/MediaBase/src/FfmpegTakePicture.h new file mode 100644 index 0000000..2c9c684 --- /dev/null +++ b/utils/MediaBase/src/FfmpegTakePicture.h @@ -0,0 +1,45 @@ +/* + * 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_TAKE_PICTURE_H +#define FFMPEG_TAKE_PICTURE_H +#include "FfmpegBase.h" +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +} +#endif +class FfmpegTakePicture : virtual public FfmpegBase +{ +public: + FfmpegTakePicture() = default; + virtual ~FfmpegTakePicture() = default; + virtual StatusCode OpenJpegFile(const OutputFileInfo &fileInfo) override; + virtual StatusCode CloseJpegFile(void) override; + virtual StatusCode WriteJpegData(const void *data, const size_t &size) override; +}; +#endif \ No newline at end of file diff --git a/utils/MediaBase/src/FfmpegThumbnail.cpp b/utils/MediaBase/src/FfmpegThumbnail.cpp index c650de9..04df442 100644 --- a/utils/MediaBase/src/FfmpegThumbnail.cpp +++ b/utils/MediaBase/src/FfmpegThumbnail.cpp @@ -133,6 +133,14 @@ bool FfmpegThumbnail::CreateThumbnail(const std::string &outputFile, const void return false; } void FfmpegThumbnail::GetDecodeDataCallback(AVFrame *frame) +{ + EncodeDataToPicture(frame); +} +void FfmpegThumbnail::GetEncodeDataCallback(AVPacket *pkt, const std::string &fileName) +{ + SaveThumbnailFile(fileName, pkt->data, pkt->size); +} +void FfmpegThumbnail::EncodeDataToPicture(AVFrame *frame) { LogInfo("Decode frame->width = %d, frame->height=%d\n", frame->width, frame->height); AVFrame *thumbnailFrame = av_frame_alloc(); @@ -168,7 +176,7 @@ void FfmpegThumbnail::GetDecodeDataCallback(AVFrame *frame) LogError("mSwsCtx = nullptr.\n"); goto END; } - system("echo 1 > /proc/sys/vm/drop_caches"); + fx_system_v2("echo 1 > /proc/sys/vm/drop_caches"); /** * @brief Perform pixel format conversion. * NOTE: This function will crash when the chip does not have enough memory. @@ -187,10 +195,6 @@ END: } return; } -void FfmpegThumbnail::GetEncodeDataCallback(AVPacket *pkt, const std::string &fileName) -{ - SaveThumbnailFile(fileName, pkt->data, pkt->size); -} bool FfmpegThumbnail::SaveThumbnailFile(const std::string &fileName, const void *data, const size_t &size) { FILE *file = nullptr; diff --git a/utils/MediaBase/src/FfmpegThumbnail.h b/utils/MediaBase/src/FfmpegThumbnail.h index 12d2b18..8262d03 100644 --- a/utils/MediaBase/src/FfmpegThumbnail.h +++ b/utils/MediaBase/src/FfmpegThumbnail.h @@ -57,14 +57,19 @@ private: void GetDecodeDataCallback(AVFrame *frame); void GetEncodeDataCallback(AVPacket *pkt, const std::string &fileName); -private: +protected: + virtual void EncodeDataToPicture(AVFrame *frame); + +protected: static bool SaveThumbnailFile(const std::string &fileName, const void *data, const size_t &size); private: - std::function mDecodeCallback; - std::function mEncodeCallback; std::shared_ptr mEncoder; std::shared_ptr mDecoder; + std::function mDecodeCallback; + std::function mEncodeCallback; + +protected: AVFormatContext *mOutputFormat; AVStream *mStream; struct SwsContext *mSwsCtx; diff --git a/utils/MediaBase/src/IMediaBase.cpp b/utils/MediaBase/src/IMediaBase.cpp index da75d40..0418f0a 100644 --- a/utils/MediaBase/src/IMediaBase.cpp +++ b/utils/MediaBase/src/IMediaBase.cpp @@ -60,6 +60,21 @@ OutputFileInfo IMediaBase::GetOutputFileInfo(void) OutputFileInfo info = {.mFileName = {0}, .mDuration_ms = 0, .mFinished = nullptr}; return info; } +StatusCode IMediaBase::OpenJpegFile(const OutputFileInfo &fileInfo) +{ + LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n"); + return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); +} +StatusCode IMediaBase::CloseJpegFile(void) +{ + LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n"); + return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); +} +StatusCode IMediaBase::WriteJpegData(const void *data, const size_t &size) +{ + LogWarning("STATUS_CODE_VIRTUAL_FUNCTION\n"); + return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); +} static const char *MEDIA_BASE_NAME = "media_adapter"; const char *GetMediaBaseModuleName(void) { diff --git a/utils/MediaBase/src/IMediaBase.h b/utils/MediaBase/src/IMediaBase.h index d0f4aef..50808a8 100644 --- a/utils/MediaBase/src/IMediaBase.h +++ b/utils/MediaBase/src/IMediaBase.h @@ -33,6 +33,11 @@ public: // About combine file. virtual StatusCode CloseOutputFile(void); virtual void GetStreamData(const void *data, const size_t &size, const StreamInfo &streamInfo); virtual OutputFileInfo GetOutputFileInfo(void); + +public: // About take picture. + virtual StatusCode OpenJpegFile(const OutputFileInfo &fileInfo); + virtual StatusCode CloseJpegFile(void); + virtual StatusCode WriteJpegData(const void *data, const size_t &size); }; typedef struct media_base_header { diff --git a/utils/MediaBase/src/MediaBase.cpp b/utils/MediaBase/src/MediaBase.cpp index 01f979e..8b6e112 100644 --- a/utils/MediaBase/src/MediaBase.cpp +++ b/utils/MediaBase/src/MediaBase.cpp @@ -41,42 +41,42 @@ StatusCode ISetReadVideoCallback(void *object, ReadVideoFileCallback callback, v if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->SetReadVideoCallback(callback, context); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } StatusCode ISetReadAudioCallback(void *object, ReadVideoFileCallback callback, void *context) { if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->SetReadAudioCallback(callback, context); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } StatusCode IStartReadFile(void *object, const char *path) { if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->StartReadFile(path); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } StatusCode IStopReadFile(void *object) { if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->StopReadFile(); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } StatusCode IOpenOutputFile(void *object, const OutputFileInfo *info) { if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->OpenOutputFile(*info); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } StatusCode ICloseOutputFile(void *object) { if (ObjectCheck(object) == true) { return (*(std::shared_ptr *)object)->CloseOutputFile(); } - return CreateStatusCode(STATUS_CODE_OK); + return CreateStatusCode(STATUS_CODE_NOT_OK); } void IGetStreamData(void *object, const void *data, const size_t size, const StreamInfo streamInfo) { @@ -92,6 +92,27 @@ OutputFileInfo IGetOutputFileInfo(void *object) OutputFileInfo info = {.mFileName = {0}, .mDuration_ms = 0, .mFinished = nullptr}; return info; } +StatusCode IOpenJpegFile(void *object, const OutputFileInfo *info) +{ + if (ObjectCheck(object) == true) { + return (*(std::shared_ptr *)object)->OpenJpegFile(*info); + } + return CreateStatusCode(STATUS_CODE_NOT_OK); +} +StatusCode ICloseJpegFile(void *object) +{ + if (ObjectCheck(object) == true) { + return (*(std::shared_ptr *)object)->CloseJpegFile(); + } + return CreateStatusCode(STATUS_CODE_NOT_OK); +} +StatusCode IWriteJpegData(void *object, const void *data, const size_t size) +{ + if (ObjectCheck(object) == true) { + return (*(std::shared_ptr *)object)->WriteJpegData(data, size); + } + return CreateStatusCode(STATUS_CODE_NOT_OK); +} void IMediaBaseFree(void *object) { if (ObjectCheck(object) == true) {