From 1ea4ecf40a8d12bbe7334c64d30a9459c5a30bb5 Mon Sep 17 00:00:00 2001 From: qijinquan Date: Thu, 3 Nov 2022 16:35:58 +0800 Subject: [PATCH] feat: Add the extends of vp9 decoder, and the demo for mpeg4,vp9 decoder and hevc encoder. Signed-off-by: qijinquan --- .../interfaces/include/codec_component_type.h | 2 + codec/interfaces/include/codec_omx_ext.h | 2 + codec/test/demo/v2.0/BUILD.gn | 1 + .../test/demo/v2.0/include/codec_hdi_decode.h | 12 +- .../test/demo/v2.0/include/codec_hdi_encode.h | 11 +- .../demo/v2.0/include/codec_packet_reader.h | 59 +++++++ codec/test/demo/v2.0/include/command_parse.h | 18 +- codec/test/demo/v2.0/src/codec_hdi_decode.cpp | 159 +++++++++--------- codec/test/demo/v2.0/src/codec_hdi_encode.cpp | 123 ++++++++++---- .../demo/v2.0/src/codec_packet_reader.cpp | 137 +++++++++++++++ codec/test/demo/v2.0/src/command_parse.cpp | 41 +++-- .../unittest/hdi_omx/codec_hdi_omx_test.cpp | 3 + 12 files changed, 424 insertions(+), 144 deletions(-) create mode 100644 codec/test/demo/v2.0/include/codec_packet_reader.h create mode 100644 codec/test/demo/v2.0/src/codec_packet_reader.cpp diff --git a/codec/interfaces/include/codec_component_type.h b/codec/interfaces/include/codec_component_type.h index 48bbc37242..b7f6b043a6 100644 --- a/codec/interfaces/include/codec_component_type.h +++ b/codec/interfaces/include/codec_component_type.h @@ -67,6 +67,8 @@ typedef enum { MEDIA_ROLETYPE_VIDEO_HEVC, /** MPEG4 video */ MEDIA_ROLETYPE_VIDEO_MPEG4, + /** VP9 video */ + MEDIA_ROLETYPE_VIDEO_VP9, /** Audio codec */ MEDIA_ROLETYPE_AUDIO_FIRST = 0x10000, /** Advanced Audio Coding (AAC) */ diff --git a/codec/interfaces/include/codec_omx_ext.h b/codec/interfaces/include/codec_omx_ext.h index 7748c6b798..18226f89a8 100644 --- a/codec/interfaces/include/codec_omx_ext.h +++ b/codec/interfaces/include/codec_omx_ext.h @@ -25,6 +25,7 @@ extern "C" { * @brief Enumerates the extended codec codingtyps. */ enum CodecVideoExType { + CODEC_OMX_VIDEO_CodingVP9 = 10, /** VP9 Index in Codec HDI */ CODEC_OMX_VIDEO_CodingHEVC = 11, /** HEVC Index in Codec HDI */ }; @@ -136,6 +137,7 @@ struct CodecVideoPortFormatParam { uint32_t size; /** Size of the structure */ union OMX_VERSIONTYPE version; /** Component version */ uint32_t portIndex; /** Port index */ + uint32_t codecColorIndex; /** Color format index */ uint32_t codecColorFormat; /** Color format defined in Display */ uint32_t codecCompressFormat; /** See */ uint32_t framerate; /** Q16 format */ diff --git a/codec/test/demo/v2.0/BUILD.gn b/codec/test/demo/v2.0/BUILD.gn index 5ee20966b7..3d9f863c60 100644 --- a/codec/test/demo/v2.0/BUILD.gn +++ b/codec/test/demo/v2.0/BUILD.gn @@ -26,6 +26,7 @@ ohos_executable("codec_hdi_omx_decode") { sources = [ "src/codec_hdi_decode.cpp", + "src/codec_packet_reader.cpp", "src/command_parse.cpp", ] diff --git a/codec/test/demo/v2.0/include/codec_hdi_decode.h b/codec/test/demo/v2.0/include/codec_hdi_decode.h index 96b4edd331..fd952a0567 100644 --- a/codec/test/demo/v2.0/include/codec_hdi_decode.h +++ b/codec/test/demo/v2.0/include/codec_hdi_decode.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -30,9 +31,9 @@ #include "codec_callback_type_stub.h" #include "codec_component_manager.h" #include "codec_component_type.h" +#include "codec_packet_reader.h" #include "codec_types.h" #include "command_parse.h" - enum class PortIndex { PORT_INDEX_INPUT = 0, PORT_INDEX_OUTPUT = 1 }; class CodecHdiDecode { @@ -103,7 +104,6 @@ public: } void WaitForStatusChanged(); void OnStatusChanged(); - bool ReadOnePacket(FILE *fp, char *buf, uint32_t &filledCount); private: int32_t UseBufferOnPort(PortIndex portIndex); @@ -120,10 +120,11 @@ private: { return (((width) + alignment_ - 1) & (~(alignment_ - 1))); } + int32_t GetComponent(); private: - FILE *fpIn_; // input file - FILE *fpOut_; + std::ifstream ioIn_; + std::ofstream ioOut_; uint32_t width_; uint32_t height_; uint32_t stride_; @@ -138,10 +139,11 @@ private: std::condition_variable statusCondition_; std::mutex statusLock_; bool exit_; - codecMime codecMime_; + CodecMime codecMime_; bool useBufferHandle_; int count_; static constexpr uint32_t alignment_ = 16; static OHOS::HDI::Display::V1_0::IDisplayGralloc *gralloc_; + CodecPacketReader::Ptr reader_; }; #endif /* CODEC_HDI_DECODE_H */ \ No newline at end of file diff --git a/codec/test/demo/v2.0/include/codec_hdi_encode.h b/codec/test/demo/v2.0/include/codec_hdi_encode.h index eec001ecb3..01e0ad4ef0 100644 --- a/codec/test/demo/v2.0/include/codec_hdi_encode.h +++ b/codec/test/demo/v2.0/include/codec_hdi_encode.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -95,7 +96,7 @@ public: } void WaitForStatusChanged(); void OnStatusChanged(); - bool ReadOneFrame(FILE *fp, char *buf, uint32_t &filledCount); + bool ReadOneFrame(char *buf, uint32_t &filledCount); private: uint32_t GetInputBufferSize(); @@ -114,10 +115,12 @@ private: { return (((width) + alignment_ - 1) & (~(alignment_ - 1))); } + int32_t GetComponent(); + OMX_VIDEO_CODINGTYPE GetCompressFormat(); private: - FILE *fpIn_; // input file - FILE *fpOut_; + std::ifstream ioIn_; + std::ofstream ioOut_; uint32_t width_; uint32_t height_; uint32_t stride_; @@ -138,6 +141,8 @@ private: static constexpr uint32_t alignment_ = 16; static OHOS::HDI::Display::V1_0::IDisplayGralloc *gralloc_; ColorFormat color_; + int count_; + CodecMime codecMime_; OMX_COLOR_FORMATTYPE omxColorFormat_; }; diff --git a/codec/test/demo/v2.0/include/codec_packet_reader.h b/codec/test/demo/v2.0/include/codec_packet_reader.h new file mode 100644 index 0000000000..a1b3a1da10 --- /dev/null +++ b/codec/test/demo/v2.0/include/codec_packet_reader.h @@ -0,0 +1,59 @@ +/* + * Copyright 2022 Shenzhen Kaihong DID Co., Ltd. + * 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 CODEC_PACKET_READER_H +#define CODEC_PACKET_READER_H +#include +#include +#include +#include +#include "command_parse.h" +class CodecPacketReader { +public: + using Ptr = std::shared_ptr; + CodecPacketReader() = default; + virtual ~CodecPacketReader() = default; + + virtual bool ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) = 0; + + static Ptr GetPacketReader(const CodecMime &mime); +}; + +class CodecH264Reader : public CodecPacketReader { +public: + using Ptr = std::shared_ptr; + CodecH264Reader(); + ~CodecH264Reader() = default; + + bool ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) override; +}; + +class CodecMpeg4Reader : public CodecPacketReader { +public: + using Ptr = std::shared_ptr; + CodecMpeg4Reader(); + ~CodecMpeg4Reader() = default; + + bool ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) override; +}; + +class CodecVp9Reader : public CodecPacketReader { +public: + using Ptr = std::shared_ptr; + CodecVp9Reader(); + ~CodecVp9Reader() = default; + + bool ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) override; +}; +#endif \ No newline at end of file diff --git a/codec/test/demo/v2.0/include/command_parse.h b/codec/test/demo/v2.0/include/command_parse.h index f2b360041e..0afb5fd547 100644 --- a/codec/test/demo/v2.0/include/command_parse.h +++ b/codec/test/demo/v2.0/include/command_parse.h @@ -16,15 +16,28 @@ #define PARSE_COMMAND_H #include #include -enum class codecMime { AVC, HEVC }; +enum class CodecMime { AVC, HEVC, MPEG4, VP9 }; enum class ColorFormat { YUV420SP = 0, RGBA8888, BGRA8888 }; +enum class MyOptIndex { + OPT_INDEX_UNKONWN = 0, + OPT_INDEX_BUFFER_HANDLE, + OPT_INDEX_HEVC, + OPT_INDEX_MPEG4, + OPT_INDEX_VP9, + OPT_INDEX_HELP, + OPT_INDEX_HEIGHT = 'h', + OPT_INDEX_INPUT = 'i', + OPT_INDEX_OUTPUT = 'o', + OPT_INDEX_WIDTH = 'w', + OPT_INDEX_COLOR = 'c' +}; struct CommandOpt { std::string fileInput = ""; std::string fileOutput = ""; uint32_t width = 0; uint32_t height = 0; bool useBuffer = false; - codecMime codec = codecMime::AVC; + CodecMime codec = CodecMime::AVC; ColorFormat colorForamt = ColorFormat::YUV420SP; }; @@ -38,5 +51,6 @@ public: private: void ShowUsage(); + void ParseCodingType(const MyOptIndex index, CommandOpt &opt); }; #endif \ No newline at end of file diff --git a/codec/test/demo/v2.0/src/codec_hdi_decode.cpp b/codec/test/demo/v2.0/src/codec_hdi_decode.cpp index c53ef8c4fd..8964b6f95f 100644 --- a/codec/test/demo/v2.0/src/codec_hdi_decode.cpp +++ b/codec/test/demo/v2.0/src/codec_hdi_decode.cpp @@ -22,26 +22,18 @@ OHOS::HDI::Display::V1_0::IDisplayGralloc *CodecHdiDecode::gralloc_ = nullptr; using namespace std; using namespace OHOS; namespace { - constexpr int32_t FD_SIZE = sizeof(int); - constexpr int32_t FRAME = 30 << 16; - constexpr int32_t DENOMINATOR = 2; - constexpr int32_t NUMERATOR = 3; - constexpr int32_t START_CODE_OFFSET_ONE = -1; - constexpr int32_t START_CODE_OFFSET_SEC = -2; - constexpr int32_t START_CODE_OFFSET_THIRD = -3; - constexpr int32_t START_CODE_SIZE_FRAME = 4; - constexpr int32_t START_CODE_SIZE_SLICE = 3; - constexpr char START_CODE = 0x1; - constexpr const char *DECODER_AVC = "OMX.rk.video_decoder.avc"; - constexpr const char *DECODER_HEVC = "OMX.rk.video_decoder.avc"; -} +constexpr uint32_t FD_SIZE = sizeof(int); +constexpr uint32_t FRAME = 30 << 16; +constexpr uint32_t DENOMINATOR = 2; +constexpr uint32_t NUMERATOR = 3; +} // namespace #define HDF_LOG_TAG codec_omx_hdi_dec #define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar static CodecHdiDecode *g_core = nullptr; -CodecHdiDecode::CodecHdiDecode() : fpIn_(nullptr), fpOut_(nullptr) +CodecHdiDecode::CodecHdiDecode() { client_ = nullptr; callback_ = nullptr; @@ -49,22 +41,20 @@ CodecHdiDecode::CodecHdiDecode() : fpIn_(nullptr), fpOut_(nullptr) exit_ = false; width_ = 0; height_ = 0; - codecMime_ = codecMime::AVC; + codecMime_ = CodecMime::AVC; count_ = 0; useBufferHandle_ = false; componentId_ = 0; + reader_ = nullptr; } CodecHdiDecode::~CodecHdiDecode() { - if (fpOut_ != nullptr) { - fclose(fpOut_); - fpOut_ = nullptr; + if (ioOut_.is_open()) { + ioOut_.close(); } - - if (fpIn_ != nullptr) { - fclose(fpIn_); - fpIn_ = nullptr; + if (ioIn_.is_open()) { + ioIn_.close(); } } @@ -84,39 +74,6 @@ int CodecHdiDecode::GetYuvSize() return width_ * height_ * NUMERATOR / DENOMINATOR; } -bool CodecHdiDecode::ReadOnePacket(FILE *fp, char *buf, uint32_t &filledCount) -{ - // read start code first - size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp); - if (t < START_CODE_SIZE_FRAME) { - return true; - } - char *temp = buf; - temp += START_CODE_SIZE_FRAME; - bool ret = true; - while (!feof(fp)) { - t = fread(temp, 1, 1, fp); - if (*temp == START_CODE) { - // check start code - if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) && - (temp[START_CODE_OFFSET_THIRD] == 0)) { - fseek(fp, -START_CODE_SIZE_FRAME, SEEK_CUR); - temp -= (START_CODE_SIZE_FRAME - 1); - ret = false; - break; - } else if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) { - fseek(fp, -START_CODE_SIZE_SLICE, SEEK_CUR); - temp -= (START_CODE_SIZE_SLICE - 1); - ret = false; - break; - } - } - temp++; - } - filledCount = (temp - buf); - return ret; -} - bool CodecHdiDecode::Init(CommandOpt &opt) { this->width_ = opt.width; @@ -129,9 +86,10 @@ bool CodecHdiDecode::Init(CommandOpt &opt) // gralloc init gralloc_ = OHOS::HDI::Display::V1_0::IDisplayGralloc::Get(); - fpIn_ = fopen(opt.fileInput.c_str(), "rb"); - fpOut_ = fopen(opt.fileOutput.c_str(), "wb+"); - if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) { + reader_ = CodecPacketReader::GetPacketReader(opt.codec); + ioIn_.open(opt.fileInput, std::ios_base::binary); + ioOut_.open(opt.fileOutput, std::ios_base::binary | std::ios_base::trunc); + if (!ioOut_.is_open() || !ioIn_.is_open()) { HDF_LOGE("%{public}s failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(), opt.fileOutput.c_str()); return false; @@ -148,15 +106,7 @@ bool CodecHdiDecode::Init(CommandOpt &opt) callback_->EventHandler = &CodecHdiDecode::OnEvent; callback_->EmptyBufferDone = &CodecHdiDecode::OnEmptyBufferDone; callback_->FillBufferDone = &CodecHdiDecode::OnFillBufferDone; - int32_t err = HDF_SUCCESS; - if (codecMime_ == codecMime::AVC) { - err = omxMgr_->CreateComponent(&client_, &componentId_, const_cast(DECODER_AVC), - reinterpret_cast(this), callback_); - } else { - err = omxMgr_->CreateComponent(&client_, &componentId_, const_cast(DECODER_HEVC), - reinterpret_cast(this), callback_); - } - + int32_t err = GetComponent(); if (err != HDF_SUCCESS) { HDF_LOGE("%{public}s failed to CreateComponent", __func__); return false; @@ -242,10 +192,21 @@ bool CodecHdiDecode::Configure() HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", param.eCompressionFormat, param.eColorFormat); param.xFramerate = FRAME; // 30fps,Q16 format - if (codecMime_ == codecMime::AVC) { - param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 - } else { - param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; // H265 + switch (codecMime_) { + case CodecMime::AVC: + param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 + break; + case CodecMime::HEVC: + param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; // H265 + break; + case CodecMime::MPEG4: + param.eCompressionFormat = OMX_VIDEO_CodingMPEG4; // H264 + break; + case CodecMime::VP9: + param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingVP9; // H264 + break; + default: + break; } err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, reinterpret_cast(¶m), @@ -295,9 +256,8 @@ int32_t CodecHdiDecode::CheckAndUseBufferHandle() usage.portIndex = static_cast(PortIndex::PORT_INDEX_OUTPUT); err = client_->GetParameter(client_, OMX_IndexParamGetBufferHandleUsage, reinterpret_cast(&usage), sizeof(usage)); - HDF_LOGI( - "OMX_GetParameter:GetBufferHandleUsage:kPortIndexOutput, err [%{public}x], usage[%{public}" PRIu64 "]", - err, usage.usage); + HDF_LOGI("OMX_GetParameter:GetBufferHandleUsage:kPortIndexOutput, err [%{public}x], usage[%{public}" PRIu64 "]", + err, usage.usage); if (err != HDF_SUCCESS) { return err; } @@ -463,7 +423,7 @@ int32_t CodecHdiDecode::UseBufferHandle(int bufferCount, int bufferSize) .height = this->height_, .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, .format = PIXEL_FMT_YCBCR_420_SP}; - + for (int i = 0; i < bufferCount; i++) { int32_t ret = HDF_SUCCESS; std::shared_ptr omxBuffer = std::make_shared(); @@ -579,6 +539,40 @@ int CodecHdiDecode::GetFreeBufferId() return bufferID; } +int32_t CodecHdiDecode::GetComponent() +{ + int32_t count = omxMgr_->GetComponentNum(); + if (count <= 0) { + HDF_LOGE("%{public}s: GetComponentNum ret %{public}d", __func__, count); + return HDF_FAILURE; + } + auto caps = std::make_unique(count); + auto err = omxMgr_->GetComponentCapabilityList(caps.get(), count); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s: GetComponentCapabilityList ret %{public}d", __func__, err); + return err; + } + std::string compName(""); + for (int32_t i = 0; i < count; i++) { + if (caps[i].type != VIDEO_DECODER) { + continue; + } + if (((caps[i].role == MEDIA_ROLETYPE_VIDEO_AVC) && (codecMime_ == CodecMime::AVC)) || + ((caps[i].role == MEDIA_ROLETYPE_VIDEO_HEVC) && (codecMime_ == CodecMime::HEVC)) || + ((caps[i].role == MEDIA_ROLETYPE_VIDEO_VP9) && (codecMime_ == CodecMime::VP9)) || + ((caps[i].role == MEDIA_ROLETYPE_VIDEO_MPEG4) && (codecMime_ == CodecMime::MPEG4))) { + compName = caps[i].compName; + break; + } + } + if (compName.empty()) { + HDF_LOGE("%{public}s: role is unexpected ", __func__); + return HDF_FAILURE; + } + return omxMgr_->CreateComponent(&client_, &componentId_, compName.data(), reinterpret_cast(this), + callback_); +} + void CodecHdiDecode::Run() { HDF_LOGI("...command to OMX_StateExecuting...."); @@ -611,7 +605,7 @@ void CodecHdiDecode::Run() } auto bufferInfo = iter->second; const char *sharedAddr = static_cast(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0)); - eosFlag = this->ReadOnePacket(fpIn_, const_cast(sharedAddr), bufferInfo->omxBuffer->filledLen); + eosFlag = reader_->ReadOnePacket(ioIn_, const_cast(sharedAddr), bufferInfo->omxBuffer->filledLen); bufferInfo->omxBuffer->offset = 0; if (eosFlag) { bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; @@ -628,7 +622,7 @@ void CodecHdiDecode::Run() } auto t2 = std::chrono::system_clock::now(); std::chrono::duration diff = t2 - t1; - HDF_LOGI("cost %{public}f, count=%{public}d", diff.count(), count_); + HDF_LOGI("decoder costtime %{public}f, count=%{public}d", diff.count(), count_); // command to IDLE (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); return; @@ -689,17 +683,16 @@ int32_t CodecHdiDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer) // read buffer auto bufferInfo = iter->second; if (bufferInfo->avSharedPtr != nullptr) { - const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset); - (void)fwrite(addr, 1, buffer.filledLen, fpOut_); + void *addr = const_cast(bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset)); + ioOut_.write(static_cast(addr), buffer.filledLen); } else if (bufferInfo->bufferHandle != nullptr && gralloc_ != nullptr) { gralloc_->Mmap(*bufferInfo->bufferHandle); - (void)fwrite(bufferInfo->bufferHandle->virAddr, 1, - bufferInfo->bufferHandle->width * bufferInfo->bufferHandle->height * NUMERATOR / DENOMINATOR, - fpOut_); + ioOut_.write(static_cast(bufferInfo->bufferHandle->virAddr), + bufferInfo->bufferHandle->width * bufferInfo->bufferHandle->height * NUMERATOR / DENOMINATOR); gralloc_->Unmap(*bufferInfo->bufferHandle); } - (void)fflush(fpOut_); + ioOut_.flush(); if (buffer.flag == OMX_BUFFERFLAG_EOS) { // end exit_ = true; diff --git a/codec/test/demo/v2.0/src/codec_hdi_encode.cpp b/codec/test/demo/v2.0/src/codec_hdi_encode.cpp index bb853aa5d4..dd4e1662b6 100644 --- a/codec/test/demo/v2.0/src/codec_hdi_encode.cpp +++ b/codec/test/demo/v2.0/src/codec_hdi_encode.cpp @@ -30,13 +30,12 @@ namespace { constexpr int32_t BUFFER_COUNT = 10; constexpr int32_t BITRATE = 3000000; constexpr int32_t FD_SIZE = sizeof(int); - constexpr const char *ENCODER_AVC = "OMX.rk.video_encoder.avc"; } -#define AV_COLOR_FORMAT (OMX_COLOR_FORMATTYPE)CODEC_COLOR_FORMAT_RGBA8888 +#define AV_COLOR_FORMAT (OMX_COLOR_FORMATTYPE) CODEC_COLOR_FORMAT_RGBA8888 static CodecHdiEncode *g_core = nullptr; -CodecHdiEncode::CodecHdiEncode() : fpIn_(nullptr), fpOut_(nullptr) +CodecHdiEncode::CodecHdiEncode() { client_ = nullptr; callback_ = nullptr; @@ -45,20 +44,20 @@ CodecHdiEncode::CodecHdiEncode() : fpIn_(nullptr), fpOut_(nullptr) useBufferHandle_ = false; width_ = 0; height_ = 0; + count_ = 0; componentId_ = 0; color_ = ColorFormat::YUV420SP; + codecMime_ = CodecMime::AVC; omxColorFormat_ = OMX_COLOR_FormatYUV420SemiPlanar; } CodecHdiEncode::~CodecHdiEncode() { - if (fpOut_ != nullptr) { - fclose(fpOut_); - fpOut_ = nullptr; + if (ioOut_.is_open()) { + ioOut_.close(); } - if (fpIn_ != nullptr) { - fclose(fpIn_); - fpIn_ = nullptr; + if (ioIn_.is_open()) { + ioIn_.close(); } } @@ -73,11 +72,11 @@ void CodecHdiEncode::OnStatusChanged() statusCondition_.notify_one(); } -bool CodecHdiEncode::ReadOneFrame(FILE *fp, char *buf, uint32_t &filledCount) +bool CodecHdiEncode::ReadOneFrame(char *buf, uint32_t &filledCount) { bool ret = false; - filledCount = fread(buf, 1, GetInputBufferSize(), fp); - if (feof(fp)) { + ioIn_.read(buf, GetInputBufferSize()); + if (ioIn_.eof()) { ret = true; } return ret; @@ -91,6 +90,8 @@ bool CodecHdiEncode::Init(CommandOpt &opt) this->useBufferHandle_ = opt.useBuffer; HDF_LOGI("width[%{public}d], height[%{public}d]", width_, height_); // gralloc init + codecMime_ = opt.codec; + gralloc_ = OHOS::HDI::Display::V1_0::IDisplayGralloc::Get(); color_ = opt.colorForamt; if (color_ == ColorFormat::RGBA8888) { @@ -98,9 +99,9 @@ bool CodecHdiEncode::Init(CommandOpt &opt) } else if (color_ == ColorFormat::BGRA8888) { omxColorFormat_ = OMX_COLOR_Format32bitBGRA8888; } - fpIn_ = fopen(opt.fileInput.c_str(), "rb"); - fpOut_ = fopen(opt.fileOutput.c_str(), "wb+"); - if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) { + ioIn_.open(opt.fileInput, std::ios_base::binary); + ioOut_.open(opt.fileOutput, std::ios_base::binary | std::ios_base::trunc); + if (!ioOut_.is_open() || !ioIn_.is_open()) { HDF_LOGE("%{public}s:failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(), opt.fileOutput.c_str()); return false; @@ -118,8 +119,7 @@ bool CodecHdiEncode::Init(CommandOpt &opt) callback_->FillBufferDone = &CodecHdiEncode::OnFillBufferDone; // create a component - auto err = omxMgr_->CreateComponent(&client_, &componentId_, const_cast(ENCODER_AVC), - reinterpret_cast(this), callback_); + auto err = GetComponent(); if (err != HDF_SUCCESS) { HDF_LOGE("%{public}s failed to CreateComponent", __func__); return false; @@ -191,9 +191,8 @@ int32_t CodecHdiEncode::CheckAndUseBufferHandle() usage.portIndex = static_cast(PortIndex::PORT_INDEX_INPUT); err = client_->GetParameter(client_, OMX_IndexParamGetBufferHandleUsage, reinterpret_cast(&usage), sizeof(usage)); - HDF_LOGI( - "OMX_GetParameter:GetBufferHandleUsage:PORT_INDEX_INPUT, err [%{public}x], usage[%{public}" PRIu64 "]", - err, usage.usage); + HDF_LOGI("OMX_GetParameter:GetBufferHandleUsage:PORT_INDEX_INPUT, err [%{public}x], usage[%{public}" PRIu64 "]", + err, usage.usage); if (err != HDF_SUCCESS) { return err; } @@ -262,8 +261,8 @@ int32_t CodecHdiEncode::UseBufferOnPort(PortIndex portIndex) OMX_PARAM_PORTDEFINITIONTYPE param; InitParam(param); param.nPortIndex = static_cast(portIndex); - auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast(¶m), - sizeof(param)); + auto err = + client_->GetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast(¶m), sizeof(param)); if (err != HDF_SUCCESS) { HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]", __func__, portIndex); @@ -468,6 +467,7 @@ void CodecHdiEncode::Run() HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__); return; } + auto t1 = std::chrono::system_clock::now(); if (!FillAllTheBuffer()) { HDF_LOGE("%{public}s FillAllTheBuffer error", __func__); return; @@ -500,6 +500,9 @@ void CodecHdiEncode::Run() usleep(10000); // 10000: sleep time 10ms } (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); + auto t2 = std::chrono::system_clock::now(); + std::chrono::duration diff = t2 - t1; + HDF_LOGI("encoder costtime %{public}f, count=%{public}d", diff.count(), count_); return; } @@ -520,8 +523,8 @@ bool CodecHdiEncode::FillCodecBuffer(std::shared_ptr bufferInfo, boo BufferHandle *bufferHandle = bufferHandles_[bufferHandleId]; if (bufferHandle != nullptr) { gralloc_->Mmap(*bufferHandle); - endFlag = this->ReadOneFrame(fpIn_, reinterpret_cast(bufferHandle->virAddr), - bufferInfo->omxBuffer->filledLen); + endFlag = + this->ReadOneFrame(reinterpret_cast(bufferHandle->virAddr), bufferInfo->omxBuffer->filledLen); bufferInfo->omxBuffer->filledLen = bufferHandle->stride * bufferHandle->height; gralloc_->Unmap(*bufferHandle); bufferInfo->omxBuffer->buffer = reinterpret_cast(bufferHandle); @@ -531,7 +534,7 @@ bool CodecHdiEncode::FillCodecBuffer(std::shared_ptr bufferInfo, boo } else { // read data from ashmem void *sharedAddr = const_cast(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0)); - endFlag = this->ReadOneFrame(fpIn_, reinterpret_cast(sharedAddr), bufferInfo->omxBuffer->filledLen); + endFlag = this->ReadOneFrame(reinterpret_cast(sharedAddr), bufferInfo->omxBuffer->filledLen); } bufferInfo->omxBuffer->offset = 0; if (endFlag) { @@ -553,7 +556,7 @@ int32_t CodecHdiEncode::CreateBufferHandle() } else if (color_ == ColorFormat::BGRA8888) { pixForamt = PIXEL_FMT_BGRA_8888; } - + AllocInfo alloc = {.width = this->stride_, .height = this->height_, .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, @@ -611,9 +614,9 @@ int32_t CodecHdiEncode::OnFillBufferDone(struct CodecCallbackType *self, int64_t uint32_t CodecHdiEncode::GetInputBufferSize() { if (color_ == ColorFormat::YUV420SP) { - return (width_ * height_ * 3 / 2); // 3:byte alignment, 2:byte alignment + return (width_ * height_ * 3 / 2); // 3:byte alignment, 2:byte alignment } else { - return (width_ * height_ * 4); // 4: byte alignment for RGBA or BGRA + return (width_ * height_ * 4); // 4: byte alignment for RGBA or BGRA } } @@ -641,11 +644,11 @@ int32_t CodecHdiEncode::OnFillBufferDone(const struct OmxCodecBuffer &buffer) } auto bufferInfo = iter->second; - const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset); + void *addr = const_cast(bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset)); // save to file - (void)fwrite(addr, 1, buffer.filledLen, fpOut_); - (void)fflush(fpOut_); - + ioOut_.write(static_cast(addr), buffer.filledLen); + ioOut_.flush(); + count_++; if (buffer.flag == OMX_BUFFERFLAG_EOS) { exit_ = true; HDF_LOGI("OnFillBufferDone the END coming"); @@ -677,7 +680,7 @@ int32_t CodecHdiEncode::ConfigPortDefine() param.format.video.nFrameHeight = height_; param.format.video.nStride = stride_; param.format.video.nSliceHeight = height_; - + param.format.video.eColorFormat = omxColorFormat_; err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast(¶m), sizeof(param)); @@ -711,7 +714,59 @@ int32_t CodecHdiEncode::ConfigPortDefine() } return HDF_SUCCESS; } +int32_t CodecHdiEncode::GetComponent() +{ + int32_t count = omxMgr_->GetComponentNum(); + if (count <= 0) { + HDF_LOGE("%{public}s: GetComponentNum ret %{public}d", __func__, count); + return HDF_FAILURE; + } + auto caps = std::make_unique(count); + auto err = omxMgr_->GetComponentCapabilityList(caps.get(), count); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s: GetComponentCapabilityList ret %{public}d", __func__, err); + return err; + } + std::string compName(""); + for (int32_t i = 0; i < count; i++) { + if (caps[i].type != VIDEO_ENCODER) { + continue; + } + if (((caps[i].role == MEDIA_ROLETYPE_VIDEO_AVC) && (codecMime_ == CodecMime::AVC)) || + ((caps[i].role == MEDIA_ROLETYPE_VIDEO_HEVC) && (codecMime_ == CodecMime::HEVC))) { + compName = caps[i].compName; + break; + } + } + if (compName.empty()) { + HDF_LOGE("%{public}s: role is unexpected ", __func__); + return HDF_FAILURE; + } + return omxMgr_->CreateComponent(&client_, &componentId_, compName.data(), reinterpret_cast(this), + callback_); +} +OMX_VIDEO_CODINGTYPE CodecHdiEncode::GetCompressFormat() +{ + OMX_VIDEO_CODINGTYPE compressFmt = OMX_VIDEO_CodingAVC; + switch (codecMime_) { + case CodecMime::AVC: + compressFmt = OMX_VIDEO_CodingAVC; + break; + case CodecMime::HEVC: + compressFmt = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; + break; + case CodecMime::MPEG4: + compressFmt = OMX_VIDEO_CodingMPEG4; + break; + case CodecMime::VP9: + compressFmt = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingVP9; + break; + default: + break; + } + return compressFmt; +} int32_t CodecHdiEncode::ConfigBitMode() { OMX_VIDEO_PARAM_PORTFORMATTYPE param; @@ -726,7 +781,7 @@ int32_t CodecHdiEncode::ConfigBitMode() HDF_LOGI("set Format PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", param.eCompressionFormat, param.eColorFormat); param.xFramerate = FRAME; - param.eCompressionFormat = OMX_VIDEO_CodingAVC; + param.eCompressionFormat = GetCompressFormat(); err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, reinterpret_cast(¶m), sizeof(param)); if (err != HDF_SUCCESS) { diff --git a/codec/test/demo/v2.0/src/codec_packet_reader.cpp b/codec/test/demo/v2.0/src/codec_packet_reader.cpp new file mode 100644 index 0000000000..c1362a2dba --- /dev/null +++ b/codec/test/demo/v2.0/src/codec_packet_reader.cpp @@ -0,0 +1,137 @@ +/* + * Copyright 2022 Shenzhen Kaihong DID Co., Ltd. + * 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 "codec_packet_reader.h" +#include +#include +namespace { +constexpr int32_t START_CODE_OFFSET_ONE = -1; +constexpr int32_t START_CODE_OFFSET_SEC = -2; +constexpr int32_t START_CODE_OFFSET_THIRD = -3; +constexpr int32_t START_CODE_SIZE_FRAME = 4; +constexpr int32_t START_CODE_SIZE_SLICE = 3; +constexpr char START_CODE = 0x1; +constexpr char VOP_START = 0xB6; +} // namespace + +CodecPacketReader::Ptr CodecPacketReader::GetPacketReader(const CodecMime &mime) +{ + CodecPacketReader::Ptr reader = nullptr; + switch (mime) { + case CodecMime::AVC: + case CodecMime::HEVC: + reader = std::make_shared(); + break; + case CodecMime::MPEG4: + reader = std::make_shared(); + break; + case CodecMime::VP9: + reader = std::make_shared(); + break; + default: + break; + } + return reader; +} + +CodecH264Reader::CodecH264Reader() : CodecPacketReader() +{} + +bool CodecH264Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) +{ + // read start code first + ioIn.read(buf, START_CODE_SIZE_FRAME); + if (ioIn.eof()) { + return true; + } + + char *temp = buf; + temp += START_CODE_SIZE_FRAME; + bool ret = true; + while (!ioIn.eof()) { + ioIn.read(temp, 1); + if (*temp == START_CODE) { + // check start code + if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) && + (temp[START_CODE_OFFSET_THIRD] == 0)) { + ioIn.seekg(-START_CODE_SIZE_FRAME, std::ios_base::cur); + temp -= (START_CODE_SIZE_FRAME - 1); + ret = false; + break; + } else if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) { + ioIn.seekg(-START_CODE_SIZE_SLICE, std::ios_base::cur); + temp -= (START_CODE_SIZE_SLICE - 1); + ret = false; + break; + } + } + temp++; + } + filledCount = (temp - buf); + return ret; +} + +CodecMpeg4Reader::CodecMpeg4Reader() : CodecPacketReader() +{} + +bool CodecMpeg4Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) +{ + ioIn.read(buf, START_CODE_SIZE_SLICE); + if (ioIn.eof()) { + return true; + } + + char *temp = buf; + temp += START_CODE_SIZE_SLICE; + bool ret = true; + bool findVop = false; + while (!ioIn.eof()) { + ioIn.read(temp, 1); + // check start code + if ((*temp == VOP_START) && (temp[START_CODE_OFFSET_ONE] == START_CODE) && (temp[START_CODE_OFFSET_SEC] == 0) && + (temp[START_CODE_OFFSET_THIRD] == 0)) { + findVop = true; + } + if (findVop && (*temp == START_CODE) && (temp[START_CODE_OFFSET_ONE] == 0) && + (temp[START_CODE_OFFSET_SEC] == 0)) { + temp -= START_CODE_SIZE_SLICE - 1; + ioIn.seekg(START_CODE_OFFSET_THIRD, std::ios_base::cur); + ret = false; + break; + } + temp++; + } + filledCount = (temp - buf); + return ret; +} + +CodecVp9Reader::CodecVp9Reader() : CodecPacketReader() +{} + +bool CodecVp9Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) +{ + // vp9 saved in trunk, use ffmpeg to save vp9 to .vp9 file, the format like this: + // len(4 bytes, little-end, length of vp9 data) + vp9 data + filledCount = 0; + ioIn.read(reinterpret_cast(&filledCount), sizeof(filledCount)); + if (ioIn.eof()) { + return true; + } + filledCount = ntohl(filledCount); + ioIn.read(buf, filledCount); + if (ioIn.eof()) { + return true; + } + return false; +} \ No newline at end of file diff --git a/codec/test/demo/v2.0/src/command_parse.cpp b/codec/test/demo/v2.0/src/command_parse.cpp index 599b432a09..ccad3fc70a 100644 --- a/codec/test/demo/v2.0/src/command_parse.cpp +++ b/codec/test/demo/v2.0/src/command_parse.cpp @@ -16,18 +16,6 @@ #include #include namespace { -enum class MyOptIndex { - OPT_INDEX_UNKONWN = 0, - OPT_INDEX_BUFFER_HANDLE, - OPT_INDEX_HEVC, - OPT_INDEX_HELP, - OPT_INDEX_HEIGHT = 'h', - OPT_INDEX_INPUT = 'i', - OPT_INDEX_OUTPUT = 'o', - OPT_INDEX_WIDTH = 'w', - OPT_INDEX_COLOR = 'c' -}; - static struct option g_longOptions[] = { {"width", required_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_WIDTH)}, {"height", required_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_HEIGHT)}, @@ -36,10 +24,30 @@ static struct option g_longOptions[] = { {"color", optional_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_COLOR)}, {"nocopy", no_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_BUFFER_HANDLE)}, {"HEVC", no_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_HEVC)}, + {"MPEG4", no_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_MPEG4)}, + {"VP9", no_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_VP9)}, {"help", no_argument, nullptr, static_cast(MyOptIndex::OPT_INDEX_HELP)}, {nullptr, 0, nullptr, static_cast(MyOptIndex::OPT_INDEX_UNKONWN)}}; } // namespace +void CommandParse::ParseCodingType(const MyOptIndex index, CommandOpt &opt) +{ + MyOptIndex optIndex = static_cast(index); + switch (optIndex) { + case MyOptIndex::OPT_INDEX_HEVC: + opt.codec = CodecMime::HEVC; + break; + case MyOptIndex::OPT_INDEX_VP9: + opt.codec = CodecMime::VP9; + break; + case MyOptIndex::OPT_INDEX_MPEG4: + opt.codec = CodecMime::MPEG4; + break; + default: + ShowUsage(); + break; + } +} bool CommandParse::Parse(int argc, char *argv[], CommandOpt &opt) { while (1) { @@ -53,9 +61,6 @@ bool CommandParse::Parse(int argc, char *argv[], CommandOpt &opt) case MyOptIndex::OPT_INDEX_BUFFER_HANDLE: opt.useBuffer = true; break; - case MyOptIndex::OPT_INDEX_HEVC: - opt.codec = codecMime::HEVC; - break; case MyOptIndex::OPT_INDEX_HELP: ShowUsage(); break; @@ -77,7 +82,7 @@ bool CommandParse::Parse(int argc, char *argv[], CommandOpt &opt) } break; default: - ShowUsage(); + ParseCodingType(index, opt); break; } } @@ -97,7 +102,9 @@ void CommandParse::ShowUsage() std::cout << " -cN, --color=N The color format in the file. 0 is YUV420SP, 1 is RGBA888, 2 is BGRA888, " "the default is 0." << std::endl; - std::cout << " --HEVC HEVC decode or HEVC encode, AVC for default." << std::endl; + std::cout << " --HEVC HEVC decode or encode, AVC for default." << std::endl; + std::cout << " --MPEG4 MPEG4 decode or encode, AVC for default." << std::endl; + std::cout << " --VP9 VP9 decode or encode, AVC for default." << std::endl; std::cout << " --nocopy Support BufferHandle." << std::endl; std::cout << " --help The help info." << std::endl; } diff --git a/codec/test/unittest/hdi_omx/codec_hdi_omx_test.cpp b/codec/test/unittest/hdi_omx/codec_hdi_omx_test.cpp index 84f7fc26e5..c8e10a7044 100644 --- a/codec/test/unittest/hdi_omx/codec_hdi_omx_test.cpp +++ b/codec/test/unittest/hdi_omx/codec_hdi_omx_test.cpp @@ -255,6 +255,7 @@ HWTEST_F(CodecHdiOmxTest, HdfCodecHdiGetParameterTest_001, TestSize.Level1) CodecVideoPortFormatParam pixFormat; InitExtParam(pixFormat); pixFormat.portIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT; + pixFormat.codecColorIndex = 0; auto ret = component_->GetParameter(component_, OMX_IndexCodecVideoPortFormat, reinterpret_cast(&pixFormat), sizeof(pixFormat)); ASSERT_EQ(ret, HDF_SUCCESS); @@ -266,6 +267,7 @@ HWTEST_F(CodecHdiOmxTest, HdfCodecHdiGetParameterTest_002, TestSize.Level1) CodecVideoPortFormatParam pixFormat; InitExtParam(pixFormat); pixFormat.portIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; + pixFormat.codecColorIndex = 0; auto ret = component_->GetParameter(component_, OMX_IndexCodecVideoPortFormat, reinterpret_cast(&pixFormat), sizeof(pixFormat)); ASSERT_EQ(ret, HDF_SUCCESS); @@ -382,6 +384,7 @@ HWTEST_F(CodecHdiOmxTest, HdfCodecHdiSetParameterTest_006, TestSize.Level1) CodecVideoPortFormatParam pixFormat; InitExtParam(pixFormat); pixFormat.portIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; + pixFormat.codecColorIndex = 0; auto ret = component_->GetParameter(component_, OMX_IndexCodecVideoPortFormat, reinterpret_cast(&pixFormat), sizeof(pixFormat)); ASSERT_EQ(ret, HDF_SUCCESS); -- Gitee