!3637 新增h265的fuzz用例

Merge pull request !3637 from 刘鹏鹏/master
This commit is contained in:
openharmony_ci 2024-10-16 03:39:42 +00:00 committed by Gitee
commit fd5811bd8c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
17 changed files with 1788 additions and 0 deletions

View File

@ -134,6 +134,9 @@ group("av_codec_fuzz_test") {
"fuzztest/encoderapi11_fuzzer:EncoderAPI11FuzzTest", "fuzztest/encoderapi11_fuzzer:EncoderAPI11FuzzTest",
"fuzztest/encoderconfigure_fuzzer:EncoderConfigureFuzzTest", "fuzztest/encoderconfigure_fuzzer:EncoderConfigureFuzzTest",
"fuzztest/encodersetparameter_fuzzer:EncoderSetParameterFuzzTest", "fuzztest/encodersetparameter_fuzzer:EncoderSetParameterFuzzTest",
"fuzztest/hevcswdecoderapi11_fuzzer:HevcSwdecoderApi11FuzzTest",
"fuzztest/hevcswdecoderconfigure_fuzzer:HevcSwdecoderConfigureFuzzTest",
"fuzztest/hevcswdecodersetparameter_fuzzer:HevcSwdecoderSetParameterFuzzTest",
"fuzztest/hwdecoder_fuzzer:HwdecoderFuzzTest", "fuzztest/hwdecoder_fuzzer:HwdecoderFuzzTest",
"fuzztest/hwdecoderapi11_fuzzer:HwdecoderApi11FuzzTest", "fuzztest/hwdecoderapi11_fuzzer:HwdecoderApi11FuzzTest",
"fuzztest/swdecoderconfigure_fuzzer:SwdecoderConfigureFuzzTest", "fuzztest/swdecoderconfigure_fuzzer:SwdecoderConfigureFuzzTest",

View File

@ -0,0 +1,69 @@
# Copyright (c) 2024 Huawei Device 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.
#####################hydra-fuzz###################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "av_codec/av_codec"
MEDIA_ROOT_DIR = "//foundation/multimedia/av_codec/"
##############################fuzztest##########################################
ohos_fuzztest("HevcSwdecoderApi11FuzzTest") {
module_out_path = module_output_path
fuzz_config_file = "$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderapi11_fuzzer"
include_dirs = [
"$MEDIA_ROOT_DIR/interfaces/kits/c",
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderapi11_fuzzer/include",
"$MEDIA_ROOT_DIR/../../graphic/graphic_2d/interfaces/inner_api",
]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"hevcswdecoderapi11_fuzzer.cpp",
"videodec_api11_sample.cpp",
]
external_deps = [
"c_utils:utils",
"graphic_2d:libgraphic_utils",
"graphic_2d:librender_service_client",
"graphic_surface:surface",
"graphic_surface:sync_fence",
"hilog:libhilog",
"ipc:ipc_core",
"media_foundation:media_foundation",
"media_foundation:native_media_core",
"window_manager:libwm",
]
deps = [
"$MEDIA_ROOT_DIR/interfaces/inner_api/native:av_codec_client",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_codecbase",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_vdec",
]
resource_config_file =
"$MEDIA_ROOT_DIR/test/moduletest/resources/ohos_test.xml"
}
group("fuzztest") {
testonly = true
deps = []
deps += [
# deps file
":HevcSwdecoderApi11FuzzTest", #引用测试套
]
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2024 Huawei Device 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.
*/
FUZZ

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2024 Huawei Device 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 <cstddef>
#include <cstdint>
#include "native_avcodec_videodecoder.h"
#include "native_averrors.h"
#include "native_avcodec_base.h"
#include "videodec_api11_sample.h"
using namespace std;
using namespace OHOS;
using namespace OHOS::Media;
#define FUZZ_PROJECT_NAME "hevcswdecoderapi11_fuzzer"
static VDecApi11FuzzSample *g_vDecSample = nullptr;
constexpr uint32_t DEFAULT_WIDTH = 1920;
constexpr uint32_t DEFAULT_HEIGHT = 1080;
constexpr double DEFAULT_FRAME_RATE = 30.0;
constexpr uint32_t SPS_SIZE = 0x19;
constexpr uint32_t PPS_SIZE = 0x05;
constexpr uint32_t START_CODE_SIZE = 4;
constexpr uint8_t SPS[SPS_SIZE + START_CODE_SIZE] = {0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x28, 0xAC,
0xB4, 0x03, 0xC0, 0x11, 0x3F, 0x2E, 0x02, 0x20, 0x00,
0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x07, 0x81, 0xE3,
0x06, 0x54};
constexpr uint8_t PPS[PPS_SIZE + START_CODE_SIZE] = {0x00, 0x00, 0x00, 0x01, 0x68, 0xEF, 0x0F, 0x2C, 0x8B};
bool g_isSurfMode = true;
namespace OHOS {
void RunNormalDecoder()
{
VDecApi11FuzzSample *vDecSample = new VDecApi11FuzzSample();
vDecSample->defaultWidth = DEFAULT_WIDTH;
vDecSample->defaultHeight = DEFAULT_HEIGHT;
vDecSample->defaultFrameRate = DEFAULT_FRAME_RATE;
vDecSample->CreateVideoDecoder();
vDecSample->ConfigureVideoDecoder();
vDecSample->SetVideoDecoderCallback();
vDecSample->StartVideoDecoder();
vDecSample->WaitForEOS();
delete vDecSample;
vDecSample = new VDecApi11FuzzSample();
vDecSample->isSurfMode = true;
vDecSample->defaultWidth = DEFAULT_WIDTH;
vDecSample->defaultHeight = DEFAULT_HEIGHT;
vDecSample->defaultFrameRate = DEFAULT_FRAME_RATE;
vDecSample->CreateVideoDecoder();
vDecSample->ConfigureVideoDecoder();
vDecSample->SetVideoDecoderCallback();
vDecSample->StartVideoDecoder();
vDecSample->WaitForEOS();
delete vDecSample;
}
bool g_needRunNormalDecoder = true;
bool HwdecoderApi11FuzzTest(const uint8_t *data, size_t size)
{
if (size < sizeof(int32_t)) {
return false;
}
if (g_needRunNormalDecoder) {
g_needRunNormalDecoder = false;
RunNormalDecoder();
}
int32_t data_ = *reinterpret_cast<const int32_t *>(data);
if (!g_vDecSample) {
g_vDecSample = new VDecApi11FuzzSample();
g_vDecSample->defaultWidth = DEFAULT_WIDTH;
g_vDecSample->defaultHeight = DEFAULT_HEIGHT;
g_vDecSample->defaultFrameRate = DEFAULT_FRAME_RATE;
g_vDecSample->CreateVideoDecoder();
g_vDecSample->ConfigureVideoDecoder();
g_vDecSample->SetVideoDecoderCallback();
g_vDecSample->Start();
g_vDecSample->InputFuncFUZZ(SPS, SPS_SIZE + START_CODE_SIZE);
g_vDecSample->InputFuncFUZZ(PPS, PPS_SIZE + START_CODE_SIZE);
}
OH_AVErrCode ret = g_vDecSample->InputFuncFUZZ(data, size);
g_vDecSample->SetParameter(data_);
if (ret == AV_ERR_NO_MEMORY) {
g_vDecSample->Flush();
g_vDecSample->Stop();
g_vDecSample->Reset();
delete g_vDecSample;
g_vDecSample = nullptr;
return false;
}
return true;
}
} // namespace OHOS
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::HwdecoderApi11FuzzTest(data, size);
return 0;
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2024 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>100000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>180</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>

View File

@ -0,0 +1,472 @@
/*
* Copyright (C) 2024 Huawei Device 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 <arpa/inet.h>
#include <sys/time.h>
#include <utility>
#include "videodec_api11_sample.h"
#include "native_avcapability.h"
using namespace OHOS;
using namespace OHOS::Media;
using namespace std;
namespace {
const string MIME_TYPE = "video/hevc";
constexpr int64_t NANOS_IN_SECOND = 1000000000L;
constexpr int64_t NANOS_IN_MICRO = 1000L;
constexpr uint32_t START_CODE_SIZE = 4;
constexpr uint8_t SPS = 7;
constexpr uint8_t PPS = 8;
constexpr int32_t EIGHT = 8;
constexpr int32_t SIXTEEN = 16;
constexpr int32_t TWENTY_FOUR = 24;
constexpr uint8_t H264_NALU_TYPE = 0x1f;
constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
VDecApi11FuzzSample *g_decSample = nullptr;
void clearIntqueue(std::queue<uint32_t> &q)
{
std::queue<uint32_t> empty;
swap(empty, q);
}
void clearAvBufferQueue(std::queue<OH_AVBuffer *> &q)
{
std::queue<OH_AVBuffer *> empty;
swap(empty, q);
}
} // namespace
class TestConsumerListener : public IBufferConsumerListener {
public:
TestConsumerListener(sptr<Surface> cs) : cs(cs) {};
~TestConsumerListener() {}
void OnBufferAvailable() override
{
sptr<SurfaceBuffer> buffer;
int32_t flushFence;
cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
cs->ReleaseBuffer(buffer, -1);
}
private:
int64_t timestamp = 0;
Rect damage = {};
sptr<Surface> cs {nullptr};
};
VDecApi11FuzzSample::~VDecApi11FuzzSample()
{
Release();
}
void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
cout << "Error errorCode=" << errorCode << endl;
}
void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
cout << "Format Changed" << endl;
int32_t currentWidth = 0;
int32_t currentHeight = 0;
OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
g_decSample->defaultWidth = currentWidth;
g_decSample->defaultHeight = currentHeight;
}
void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
{
VDecSignal *signal = static_cast<VDecSignal *>(userData);
if (signal == nullptr) {
return;
}
unique_lock<mutex> lock(signal->inMutex_);
signal->inIdxQueue_.push(index);
signal->inBufferQueue_.push(buffer);
signal->inCond_.notify_all();
}
void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
{
int32_t ret = 0;
if (g_decSample->isSurfMode) {
ret = OH_VideoDecoder_RenderOutputBuffer(codec, index);
} else {
ret = OH_VideoDecoder_FreeOutputBuffer(codec, index);
}
if (ret != AV_ERR_OK) {
g_decSample->Flush();
g_decSample->Start();
}
}
int64_t VDecApi11FuzzSample::GetSystemTimeUs()
{
struct timespec now;
(void)clock_gettime(CLOCK_BOOTTIME, &now);
int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
return nanoTime / NANOS_IN_MICRO;
}
int32_t VDecApi11FuzzSample::ConfigureVideoDecoder()
{
OH_AVFormat *format = OH_AVFormat_Create();
if (format == nullptr) {
cout << "Fatal: Failed to create format" << endl;
return AV_ERR_UNKNOWN;
}
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
(void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, 0);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
int ret = OH_VideoDecoder_Configure(vdec_, format);
OH_AVFormat_Destroy(format);
if (isSurfMode) {
cs = Surface::CreateSurfaceAsConsumer();
sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs);
cs->RegisterConsumerListener(listener);
auto p = cs->GetProducer();
ps = Surface::CreateSurfaceAsProducer(p);
nativeWindow = CreateNativeWindowFromSurface(&ps);
OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
}
return ret;
}
int32_t VDecApi11FuzzSample::SetVideoDecoderCallback()
{
signal_ = new VDecSignal();
if (signal_ == nullptr) {
cout << "Failed to new VDecSignal" << endl;
return AV_ERR_UNKNOWN;
}
cb_.onError = VdecError;
cb_.onStreamChanged = VdecFormatChanged;
cb_.onNeedInputBuffer = VdecInputDataReady;
cb_.onNewOutputBuffer = VdecOutputDataReady;
OH_VideoDecoder_RegisterCallback(vdec_, cb_, static_cast<void *>(signal_));
return OH_VideoDecoder_RegisterCallback(vdec_, cb_, static_cast<void *>(signal_));
}
int32_t VDecApi11FuzzSample::CreateVideoDecoder()
{
OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, false, SOFTWARE);
string codecName = OH_AVCapability_GetName(cap);
vdec_ = OH_VideoDecoder_CreateByName("aabbcc");
if (vdec_) {
OH_VideoDecoder_Destroy(vdec_);
vdec_ = nullptr;
}
OH_AVCodec *tmpDec = OH_VideoDecoder_CreateByMime("aabbcc");
if (tmpDec) {
OH_VideoDecoder_Destroy(tmpDec);
tmpDec = nullptr;
}
tmpDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
if (tmpDec) {
OH_VideoDecoder_Destroy(tmpDec);
tmpDec = nullptr;
}
vdec_ = OH_VideoDecoder_CreateByName(codecName.c_str());
g_decSample = this;
return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
}
void VDecApi11FuzzSample::WaitForEOS()
{
if (inputLoop_ && inputLoop_->joinable()) {
inputLoop_->join();
}
}
OH_AVErrCode VDecApi11FuzzSample::InputFuncFUZZ(const uint8_t *data, size_t size)
{
uint32_t index;
unique_lock<mutex> lock(signal_->inMutex_);
if (!isRunning_.load()) {
return AV_ERR_NO_MEMORY;
}
signal_->inCond_.wait(lock, [this]() {
if (!isRunning_.load()) {
return true;
}
return signal_->inIdxQueue_.size() > 0;
});
if (!isRunning_.load()) {
return AV_ERR_NO_MEMORY;
}
index = signal_->inIdxQueue_.front();
auto buffer = signal_->inBufferQueue_.front();
lock.unlock();
int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
uint8_t *bufferAddr = OH_AVBuffer_GetAddr(buffer);
if (size > bufferSize - START_CODE_SIZE) {
cout << "Fatal: memcpy fail" << endl;
return AV_ERR_NO_MEMORY;
}
if (memcpy_s(bufferAddr, bufferSize, START_CODE, START_CODE_SIZE) != EOK) {
cout << "Fatal: memcpy fail" << endl;
return AV_ERR_NO_MEMORY;
}
if (memcpy_s(bufferAddr + START_CODE_SIZE, bufferSize - START_CODE_SIZE, data, size) != EOK) {
cout << "Fatal: memcpy fail" << endl;
return AV_ERR_NO_MEMORY;
}
OH_AVCodecBufferAttr attr;
attr.pts = GetSystemTimeUs();
attr.size = size;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
OH_AVBuffer_SetBufferAttr(buffer, &attr);
OH_AVErrCode ret = OH_VideoDecoder_PushInputBuffer(vdec_, index);
signal_->inIdxQueue_.pop();
signal_->inBufferQueue_.pop();
return ret;
}
void VDecApi11FuzzSample::SetEOS(OH_AVBuffer *buffer, uint32_t index)
{
OH_AVCodecBufferAttr attr;
attr.pts = 0;
attr.size = 0;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
OH_AVBuffer_SetBufferAttr(buffer, &attr);
int32_t res = OH_VideoDecoder_PushInputBuffer(vdec_, index);
cout << "OH_VideoDecoder_PushInputData EOS res: " << res << endl;
}
int32_t VDecApi11FuzzSample::Flush()
{
unique_lock<mutex> inLock(signal_->inMutex_);
clearIntqueue(signal_->inIdxQueue_);
clearAvBufferQueue(signal_->inBufferQueue_);
signal_->inCond_.notify_all();
inLock.unlock();
unique_lock<mutex> outLock(signal_->outMutex_);
clearIntqueue(signal_->outIdxQueue_);
signal_->outCond_.notify_all();
isRunning_.store(false);
outLock.unlock();
return OH_VideoDecoder_Flush(vdec_);
}
int32_t VDecApi11FuzzSample::Reset()
{
isRunning_.store(false);
return OH_VideoDecoder_Reset(vdec_);
}
int32_t VDecApi11FuzzSample::Release()
{
int ret = 0;
if (vdec_ != nullptr) {
ret = OH_VideoDecoder_Destroy(vdec_);
vdec_ = nullptr;
}
if (signal_ != nullptr) {
clearAvBufferQueue(signal_->inBufferQueue_);
delete signal_;
signal_ = nullptr;
}
return ret;
}
int32_t VDecApi11FuzzSample::Stop()
{
clearIntqueue(signal_->outIdxQueue_);
isRunning_.store(false);
return OH_VideoDecoder_Stop(vdec_);
}
int32_t VDecApi11FuzzSample::Start()
{
int32_t ret = OH_VideoDecoder_Start(vdec_);
if (ret == AV_ERR_OK) {
isRunning_.store(true);
}
return ret;
}
void VDecApi11FuzzSample::SetParameter(int32_t data)
{
OH_AVFormat *format = OH_AVFormat_Create();
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
OH_VideoDecoder_SetParameter(vdec_, format);
OH_AVFormat_Destroy(format);
}
void VDecApi11FuzzSample::StopInloop()
{
if (inputLoop_ != nullptr && inputLoop_->joinable()) {
unique_lock<mutex> lock(signal_->inMutex_);
clearIntqueue(signal_->inIdxQueue_);
isRunning_.store(false);
signal_->inCond_.notify_all();
lock.unlock();
inputLoop_->join();
inputLoop_.reset();
}
}
void VDecApi11FuzzSample::ReleaseInFile()
{
if (inFile_ != nullptr) {
if (inFile_->is_open()) {
inFile_->close();
}
inFile_.reset();
inFile_ = nullptr;
}
}
int32_t VDecApi11FuzzSample::StartVideoDecoder()
{
isRunning_.store(true);
int ret = OH_VideoDecoder_Start(vdec_);
if (ret != AV_ERR_OK) {
isRunning_.store(false);
ReleaseInFile();
Release();
cout << "Failed to start codec" << endl;
return ret;
}
inFile_ = make_unique<ifstream>();
if (inFile_ == nullptr) {
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
return AV_ERR_UNKNOWN;
}
inFile_->open(inpDir, ios::in | ios::binary);
if (!inFile_->is_open()) {
cout << "open input file failed" << endl;
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
inFile_->close();
inFile_.reset();
inFile_ = nullptr;
return AV_ERR_UNKNOWN;
}
inputLoop_ = make_unique<thread>(&VDecApi11FuzzSample::InputFuncTest, this);
if (inputLoop_ == nullptr) {
cout << "Failed to create input loop" << endl;
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
ReleaseInFile();
return AV_ERR_UNKNOWN;
}
return AV_ERR_OK;
}
void VDecApi11FuzzSample::InputFuncTest()
{
while (isRunning_.load()) {
uint32_t index;
unique_lock<mutex> lock(signal_->inMutex_);
signal_->inCond_.wait(lock, [this]() {
if (!isRunning_.load()) {
return true;
}
return signal_->inIdxQueue_.size() > 0;
});
if (!isRunning_.load()) {
break;
}
index = signal_->inIdxQueue_.front();
auto buffer = signal_->inBufferQueue_.front();
signal_->inIdxQueue_.pop();
signal_->inBufferQueue_.pop();
lock.unlock();
if (!inFile_->eof()) {
int ret = PushData(index, buffer);
if (ret == 1) {
break;
}
}
}
}
int32_t VDecApi11FuzzSample::PushData(uint32_t index, OH_AVBuffer *buffer)
{
char ch[4] = {};
(void)inFile_->read(ch, START_CODE_SIZE);
if (inFile_->eof()) {
SetEOS(buffer, index);
return 1;
}
uint32_t bufferSize = static_cast<uint32_t>(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) |
((ch[1] & 0xFF) << SIXTEEN) | ((ch[0] & 0xFF) << TWENTY_FOUR));
return SendData(bufferSize, index, buffer);
}
uint32_t VDecApi11FuzzSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVBuffer *buffer)
{
OH_AVCodecBufferAttr attr;
uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
if (fileBuffer == nullptr) {
delete[] fileBuffer;
return 0;
}
if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
cout << "Fatal: memory copy failed" << endl;
}
(void)inFile_->read((char *)fileBuffer + START_CODE_SIZE, bufferSize);
if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
(fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
} else {
attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
}
int32_t size = OH_AVBuffer_GetCapacity(buffer);
if (size < bufferSize + START_CODE_SIZE) {
delete[] fileBuffer;
return 0;
}
uint8_t *avBuffer = OH_AVBuffer_GetAddr(buffer);
if (avBuffer == nullptr) {
cout << "avBuffer == nullptr" << endl;
inFile_->clear();
inFile_->seekg(0, ios::beg);
delete[] fileBuffer;
return 0;
}
if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
delete[] fileBuffer;
return 0;
}
int64_t startPts = GetSystemTimeUs();
attr.pts = startPts;
attr.size = bufferSize + START_CODE_SIZE;
attr.offset = 0;
OH_AVBuffer_SetBufferAttr(buffer, &attr);
if (isRunning_.load()) {
OH_VideoDecoder_PushInputBuffer(vdec_, index) == AV_ERR_OK ? (0) : (errCount++);
frameCount_ = frameCount_ + 1;
}
delete[] fileBuffer;
return 0;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2024 Huawei Device 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 VIDEODEC_API11_SAMPLE_H
#define VIDEODEC_API11_SAMPLE_H
#include <atomic>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <mutex>
#include <queue>
#include <string>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include "native_avcodec_videodecoder.h"
#include "native_averrors.h"
#include "native_avformat.h"
#include "native_avbuffer.h"
#include "nocopyable.h"
#include "securec.h"
#include "surface/window.h"
#include "iconsumer_surface.h"
namespace OHOS {
namespace Media {
class VDecSignal {
public:
std::mutex inMutex_;
std::mutex outMutex_;
std::condition_variable inCond_;
std::condition_variable outCond_;
std::queue<uint32_t> inIdxQueue_;
std::queue<uint32_t> outIdxQueue_;
std::queue<OH_AVBuffer *> inBufferQueue_;
};
class VDecApi11FuzzSample : public NoCopyable {
public:
VDecApi11FuzzSample() = default;
~VDecApi11FuzzSample();
int32_t RunVideoDec(std::string codeName = "");
const char *inpDir = "/data/test/media/1920_1080_30.h265";
const char *outDir = "/data/test/media/VDecTest.yuv";
uint32_t defaultWidth = 1920;
uint32_t defaultHeight = 1080;
uint32_t defaultFrameRate = 30;
uint32_t defaultRotation = 0;
uint32_t defaultPixelFormat = AV_PIXEL_FORMAT_NV12;
uint32_t frameCount_ = 0;
int32_t Start();
int32_t Stop();
int32_t Flush();
int32_t Reset();
void SetEOS(OH_AVBuffer *buffer, uint32_t index);
void WaitForEOS();
int32_t ConfigureVideoDecoder();
int32_t StartVideoDecoder();
int64_t GetSystemTimeUs();
int32_t CreateVideoDecoder();
int32_t SetVideoDecoderCallback();
int32_t Release();
void InputFuncTest();
void OutputFuncTest();
void ReleaseInFile();
void StopInloop();
int32_t PushData(uint32_t index, OH_AVBuffer *buffer);
uint32_t SendData(uint32_t bufferSize, uint32_t index, OH_AVBuffer *buffer);
void SetParameter(int32_t data);
OH_AVErrCode InputFuncFUZZ(const uint8_t *data, size_t size);
void ReleaseSignal();
VDecSignal *signal_;
uint32_t errCount = 0;
bool isSurfMode = false;
bool setParameters = false;
OH_AVCodec *vdec_;
OHNativeWindow *nativeWindow = nullptr;
sptr<Surface> cs = nullptr;
sptr<Surface> ps = nullptr;
private:
std::atomic<bool> isRunning_ { false };
std::unique_ptr<std::ifstream> inFile_;
std::unique_ptr<std::thread> inputLoop_;
std::unordered_map<uint32_t, OH_AVBuffer *> inBufferMap_;
std::unordered_map<uint32_t, OH_AVBuffer *> outBufferMap_;
OH_AVCodecCallback cb_;
int64_t timeStamp_ { 0 };
int64_t lastRenderedTimeUs_ { 0 };
bool isFirstFrame_ = true;
};
} // namespace Media
} // namespace OHOS
void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData);
void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData);
void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData);
void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData);
#endif // VIDEODEC_SAMPLE_H

View File

@ -0,0 +1,64 @@
# Copyright (c) 2024 Huawei Device 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.
#####################hydra-fuzz###################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "av_codec/av_codec"
MEDIA_ROOT_DIR = "//foundation/multimedia/av_codec/"
##############################fuzztest##########################################
ohos_fuzztest("HevcSwdecoderConfigureFuzzTest") {
module_out_path = module_output_path
fuzz_config_file =
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderconfigure_fuzzer"
include_dirs = [
"$MEDIA_ROOT_DIR/interfaces/kits/c",
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderconfigure_fuzzer/include",
]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"hevcswdecoderconfigure_fuzzer.cpp",
"videodec_sample.cpp",
]
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_core",
"media_foundation:native_media_core",
"window_manager:libwm",
]
deps = [
"$MEDIA_ROOT_DIR/interfaces/inner_api/native:av_codec_client",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_codecbase",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_vdec",
]
resource_config_file =
"$MEDIA_ROOT_DIR/test/moduletest/resources/ohos_test.xml"
}
group("fuzztest") {
testonly = true
deps = []
deps += [
# deps file
":HevcSwdecoderConfigureFuzzTest", #引用测试套
]
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2024 Huawei Device 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.
*/
FUZZ

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2024 Huawei Device 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 <cstddef>
#include <cstdint>
#include "native_avcodec_videodecoder.h"
#include "native_averrors.h"
#include "native_avcodec_base.h"
#include "videodec_sample.h"
using namespace std;
using namespace OHOS;
using namespace OHOS::Media;
#define FUZZ_PROJECT_NAME "hevcswdecoderconfigure_fuzzer"
namespace OHOS {
bool SwdecoderConfigureFuzzTest(const uint8_t *data, size_t size)
{
if (size < sizeof(int32_t)) {
return false;
}
bool result = false;
int32_t data_ = *reinterpret_cast<const int32_t *>(data);
VDecFuzzSample *vDecSample = new VDecFuzzSample();
vDecSample->inpDir = "/data/test/media/1920_1080_30.h265";
vDecSample->defaultWidth = data_;
vDecSample->defaultHeight = data_;
vDecSample->defaultFrameRate = data_;
vDecSample->defaultRotation = data_;
vDecSample->defaultPixelFormat = data_;
vDecSample->CreateVideoDecoder("OH.Media.Codec.Decoder.Video.HEVC");
vDecSample->ConfigureVideoDecoder();
vDecSample->SetVideoDecoderCallback();
vDecSample->StartVideoDecoder();
vDecSample->WaitForEOS();
vDecSample->Release();
delete vDecSample;
return result;
}
} // namespace OHOS
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::SwdecoderConfigureFuzzTest(data, size);
return 0;
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2024 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>180</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>

View File

@ -0,0 +1,520 @@
/*
* Copyright (C) 2024 Huawei Device 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 <arpa/inet.h>
#include <sys/time.h>
#include <utility>
#include "videodec_sample.h"
using namespace OHOS;
using namespace OHOS::Media;
using namespace std;
namespace {
const string MIME_TYPE = "video/hevc";
constexpr int64_t NANOS_IN_SECOND = 1000000000L;
constexpr int64_t NANOS_IN_MICRO = 1000L;
constexpr int32_t EIGHT = 8;
constexpr int32_t SIXTEEN = 16;
constexpr int32_t TWENTY_FOUR = 24;
constexpr uint8_t SEI = 6;
constexpr uint8_t SPS = 7;
constexpr uint8_t PPS = 8;
constexpr uint32_t START_CODE_SIZE = 4;
constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
VDecFuzzSample *g_decSample = nullptr;
constexpr uint8_t H264_NALU_TYPE = 0x1f;
bool g_fuzzError = false;
void clearIntqueue(std::queue<uint32_t> &q)
{
std::queue<uint32_t> empty;
swap(empty, q);
}
void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
{
std::queue<OH_AVCodecBufferAttr> empty;
swap(empty, q);
}
void clearAvBufferQueue(std::queue<OH_AVMemory *> &q)
{
std::queue<OH_AVMemory *> empty;
swap(empty, q);
}
} // namespace
class TestConsumerListener : public IBufferConsumerListener {
public:
TestConsumerListener(sptr<Surface> cs) : cs(cs) {};
~TestConsumerListener() {}
void OnBufferAvailable() override
{
sptr<SurfaceBuffer> buffer;
int32_t flushFence;
cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
cs->ReleaseBuffer(buffer, -1);
}
private:
int64_t timestamp = 0;
Rect damage = {};
sptr<Surface> cs {nullptr};
};
VDecFuzzSample::~VDecFuzzSample()
{
Release();
}
void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
VDecSignal *signal = static_cast<VDecSignal *>(userData);
if (signal == nullptr) {
return;
}
cout << "Error errorCode=" << errorCode << endl;
g_fuzzError = true;
signal->inCond_.notify_all();
}
void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
cout << "Format Changed" << endl;
int32_t currentWidth = 0;
int32_t currentHeight = 0;
OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
g_decSample->defaultWidth = currentWidth;
g_decSample->defaultHeight = currentHeight;
}
void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
{
VDecSignal *signal = static_cast<VDecSignal *>(userData);
if (signal == nullptr) {
return;
}
unique_lock<mutex> lock(signal->inMutex_);
signal->inIdxQueue_.push(index);
signal->inBufferQueue_.push(data);
signal->inCond_.notify_all();
}
void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
void *userData)
{
VDecSignal *signal = static_cast<VDecSignal *>(userData);
if (signal == nullptr) {
return;
}
unique_lock<mutex> lock(signal->outMutex_);
signal->outIdxQueue_.push(index);
signal->attrQueue_.push(*attr);
signal->outBufferQueue_.push(data);
signal->outCond_.notify_all();
if (g_decSample->isSurfMode) {
OH_VideoDecoder_RenderOutputData(codec, index);
} else {
OH_VideoDecoder_FreeOutputData(codec, index);
}
}
int64_t VDecFuzzSample::GetSystemTimeUs()
{
struct timespec now;
(void)clock_gettime(CLOCK_BOOTTIME, &now);
int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
return nanoTime / NANOS_IN_MICRO;
}
int32_t VDecFuzzSample::ConfigureVideoDecoder()
{
if (isSurfMode) {
cs = Surface::CreateSurfaceAsConsumer();
sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs);
cs->RegisterConsumerListener(listener);
auto p = cs->GetProducer();
ps = Surface::CreateSurfaceAsProducer(p);
nativeWindow = CreateNativeWindowFromSurface(&ps);
OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
}
OH_AVFormat *format = OH_AVFormat_Create();
if (format == nullptr) {
cout << "Fatal: Failed to create format" << endl;
return AV_ERR_UNKNOWN;
}
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
(void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, defaultRotation);
(void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixelFormat);
int ret = OH_VideoDecoder_Configure(vdec_, format);
OH_AVFormat_Destroy(format);
return ret;
}
int32_t VDecFuzzSample::RunVideoDec(string codeName)
{
int err = CreateVideoDecoder(codeName);
if (err != AV_ERR_OK) {
cout << "Failed to create video decoder" << endl;
return err;
}
err = ConfigureVideoDecoder();
if (err != AV_ERR_OK) {
cout << "Failed to configure video decoder" << endl;
Release();
return err;
}
err = SetVideoDecoderCallback();
if (err != AV_ERR_OK) {
cout << "Failed to setCallback" << endl;
Release();
return err;
}
err = StartVideoDecoder();
if (err != AV_ERR_OK) {
cout << "Failed to start video decoder" << endl;
Release();
return err;
}
return err;
}
int32_t VDecFuzzSample::SetVideoDecoderCallback()
{
signal_ = new VDecSignal();
if (signal_ == nullptr) {
cout << "Failed to new VDecSignal" << endl;
return AV_ERR_UNKNOWN;
}
cb_.onError = VdecError;
cb_.onStreamChanged = VdecFormatChanged;
cb_.onNeedInputData = VdecInputDataReady;
cb_.onNeedOutputData = VdecOutputDataReady;
return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
}
void VDecFuzzSample::ReleaseInFile()
{
if (inFile_ != nullptr) {
if (inFile_->is_open()) {
inFile_->close();
}
inFile_.reset();
inFile_ = nullptr;
}
}
void VDecFuzzSample::StopInloop()
{
if (inputLoop_ != nullptr && inputLoop_->joinable()) {
unique_lock<mutex> lock(signal_->inMutex_);
clearIntqueue(signal_->inIdxQueue_);
signal_->inCond_.notify_all();
lock.unlock();
inputLoop_->join();
inputLoop_.reset();
}
}
int32_t VDecFuzzSample::StartVideoDecoder()
{
int ret = OH_VideoDecoder_Start(vdec_);
if (ret != AV_ERR_OK) {
cout << "Failed to start codec" << endl;
return ret;
}
isRunning_.store(true);
inFile_ = make_unique<ifstream>();
if (inFile_ == nullptr) {
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
return AV_ERR_UNKNOWN;
}
inFile_->open(inpDir, ios::in | ios::binary);
if (!inFile_->is_open()) {
cout << "open input file failed" << endl;
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
inFile_->close();
inFile_.reset();
inFile_ = nullptr;
return AV_ERR_UNKNOWN;
}
inputLoop_ = make_unique<thread>(&VDecFuzzSample::InputFuncAVCC, this);
if (inputLoop_ == nullptr) {
cout << "Failed to create input loop" << endl;
isRunning_.store(false);
(void)OH_VideoDecoder_Stop(vdec_);
ReleaseInFile();
return AV_ERR_UNKNOWN;
}
return AV_ERR_OK;
}
int32_t VDecFuzzSample::CreateVideoDecoder(string codeName)
{
vdec_ = OH_VideoDecoder_CreateByName("aabbcc");
if (vdec_) {
OH_VideoDecoder_Destroy(vdec_);
vdec_ = nullptr;
}
OH_AVCodec *tmpDec = OH_VideoDecoder_CreateByMime("aabbcc");
if (tmpDec) {
OH_VideoDecoder_Destroy(tmpDec);
tmpDec = nullptr;
}
tmpDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
if (tmpDec) {
OH_VideoDecoder_Destroy(tmpDec);
tmpDec = nullptr;
}
vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
g_decSample = this;
return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
}
void VDecFuzzSample::WaitForEOS()
{
if (inputLoop_ && inputLoop_->joinable()) {
inputLoop_->join();
}
}
void VDecFuzzSample::CopyStartCode(uint8_t *frameBuffer, uint32_t bufferSize, OH_AVCodecBufferAttr &attr)
{
switch (frameBuffer[START_CODE_SIZE] & H264_NALU_TYPE) {
case SPS:
case PPS:
case SEI:
if (memcpy_s(frameBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
cout << "Fatal: memory copy failed" << endl;
}
attr.pts = GetSystemTimeUs();
attr.size = bufferSize + START_CODE_SIZE;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
break;
default: {
if (memcpy_s(frameBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
cout << "Fatal: memory copy failed" << endl;
}
attr.pts = GetSystemTimeUs();
attr.size = bufferSize + START_CODE_SIZE;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
}
}
}
int32_t VDecFuzzSample::ReadData(uint32_t index, OH_AVMemory *buffer)
{
uint8_t ch[4] = {};
(void)inFile_->read(reinterpret_cast<char *>(ch), START_CODE_SIZE);
if (repeatRun && inFile_->eof()) {
inFile_->clear();
inFile_->seekg(0, ios::beg);
cout << "repeat" << endl;
return 0;
} else if (inFile_->eof()) {
SetEOS(index);
return 1;
}
uint32_t bufferSize = static_cast<uint32_t>(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) |
((ch[1] & 0xFF) << SIXTEEN) | ((ch[0] & 0xFF) << TWENTY_FOUR));
return SendData(bufferSize, index, buffer);
}
uint32_t VDecFuzzSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
{
OH_AVCodecBufferAttr attr;
uint8_t *frameBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
(void)inFile_->read(reinterpret_cast<char *>(frameBuffer + START_CODE_SIZE), bufferSize);
CopyStartCode(frameBuffer, bufferSize, attr);
int32_t size = OH_AVMemory_GetSize(buffer);
if (size < attr.size) {
delete[] frameBuffer;
cout << "ERROR:AVMemory not enough, buffer size" << attr.size << " AVMemory Size " << size << endl;
isRunning_.store(false);
return 1;
}
uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
if (memcpy_s(bufferAddr, size, frameBuffer, attr.size) != EOK) {
delete[] frameBuffer;
cout << "Fatal: memcpy fail" << endl;
isRunning_.store(false);
return 1;
}
delete[] frameBuffer;
int32_t ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
if (ret != AV_ERR_OK) {
errCount++;
cout << "push input data failed, error:" << ret << endl;
}
frameCount_ = frameCount_ + 1;
if (inFile_->eof()) {
isRunning_.store(false);
}
return 0;
}
void VDecFuzzSample::InputFuncAVCC()
{
frameCount_ = 1;
errCount = 0;
while (true) {
if (!isRunning_.load()) {
break;
}
unique_lock<mutex> lock(signal_->inMutex_);
signal_->inCond_.wait(lock, [this]() {
if (!isRunning_.load()) {
cout << "quit signal" << endl;
return true;
}
return signal_->inIdxQueue_.size() > 0;
});
if (!isRunning_.load()) {
break;
}
uint32_t index = signal_->inIdxQueue_.front();
auto buffer = signal_->inBufferQueue_.front();
signal_->inIdxQueue_.pop();
signal_->inBufferQueue_.pop();
lock.unlock();
if (!inFile_->eof()) {
int ret = ReadData(index, buffer);
if (ret == 1) {
break;
}
}
}
}
OH_AVErrCode VDecFuzzSample::InputFuncFUZZ(const uint8_t *data, size_t size)
{
uint32_t index;
unique_lock<mutex> lock(signal_->inMutex_);
signal_->inCond_.wait(lock, [this]() {
if (!isRunning_.load() && g_fuzzError) {
return true;
}
return signal_->inIdxQueue_.size() > 0;
});
if (g_fuzzError)
return AV_ERR_TIMEOUT;
index = signal_->inIdxQueue_.front();
auto buffer = signal_->inBufferQueue_.front();
lock.unlock();
int32_t bufferSize = OH_AVMemory_GetSize(buffer);
uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
if (memcpy_s(bufferAddr, bufferSize, data, size) != EOK) {
cout << "Fatal: memcpy fail" << endl;
return AV_ERR_NO_MEMORY;
}
OH_AVCodecBufferAttr attr;
attr.pts = GetSystemTimeUs();
attr.size = bufferSize;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
OH_AVErrCode ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
signal_->inIdxQueue_.pop();
signal_->inBufferQueue_.pop();
return ret;
}
void VDecFuzzSample::SetEOS(uint32_t index)
{
OH_AVCodecBufferAttr attr;
attr.pts = 0;
attr.size = 0;
attr.offset = 0;
attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
cout << "OH_VideoDecoder_PushInputData EOS res: " << res << endl;
}
int32_t VDecFuzzSample::Flush()
{
unique_lock<mutex> inLock(signal_->inMutex_);
clearIntqueue(signal_->inIdxQueue_);
signal_->inCond_.notify_all();
inLock.unlock();
unique_lock<mutex> outLock(signal_->outMutex_);
clearIntqueue(signal_->outIdxQueue_);
clearBufferqueue(signal_->attrQueue_);
signal_->outCond_.notify_all();
isRunning_.store(false);
outLock.unlock();
return OH_VideoDecoder_Flush(vdec_);
}
int32_t VDecFuzzSample::Reset()
{
isRunning_.store(false);
StopInloop();
ReleaseInFile();
return OH_VideoDecoder_Reset(vdec_);
}
int32_t VDecFuzzSample::Release()
{
int ret = 0;
if (vdec_ != nullptr) {
ret = OH_VideoDecoder_Destroy(vdec_);
vdec_ = nullptr;
}
if (signal_ != nullptr) {
clearAvBufferQueue(signal_->inBufferQueue_);
clearAvBufferQueue(signal_->outBufferQueue_);
delete signal_;
signal_ = nullptr;
}
return ret;
}
int32_t VDecFuzzSample::Stop()
{
StopInloop();
clearIntqueue(signal_->outIdxQueue_);
clearBufferqueue(signal_->attrQueue_);
ReleaseInFile();
return OH_VideoDecoder_Stop(vdec_);
}
int32_t VDecFuzzSample::Start()
{
int32_t ret = 0;
ret = OH_VideoDecoder_Start(vdec_);
if (ret == AV_ERR_OK) {
isRunning_.store(true);
}
return ret;
}
int32_t VDecFuzzSample::SetParameter(OH_AVFormat *format)
{
return OH_VideoDecoder_SetParameter(vdec_, format);
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2024 Huawei Device 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 VIDEODEC_SAMPLE_H
#define VIDEODEC_SAMPLE_H
#include <atomic>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <mutex>
#include <queue>
#include <string>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include "native_avcodec_videodecoder.h"
#include "native_averrors.h"
#include "native_avformat.h"
#include "native_avmemory.h"
#include "nocopyable.h"
#include "securec.h"
#include "surface/window.h"
#include "iconsumer_surface.h"
namespace OHOS {
namespace Media {
class VDecSignal {
public:
std::mutex inMutex_;
std::mutex outMutex_;
std::condition_variable inCond_;
std::condition_variable outCond_;
std::queue<uint32_t> inIdxQueue_;
std::queue<uint32_t> outIdxQueue_;
std::queue<OH_AVCodecBufferAttr> attrQueue_;
std::queue<OH_AVMemory *> inBufferQueue_;
std::queue<OH_AVMemory *> outBufferQueue_;
};
class VDecFuzzSample : public NoCopyable {
public:
VDecFuzzSample() = default;
~VDecFuzzSample();
int32_t RunVideoDec(std::string codeName = "");
const char *inpDir = "/data/test/media/1920_1080_30.h265";
const char *outDir = "/data/test/media/VDecTest.yuv";
uint32_t defaultWidth = 1920;
uint32_t defaultHeight = 1080;
uint32_t defaultFrameRate = 30;
uint32_t defaultRotation = 0;
uint32_t defaultPixelFormat = 1;
uint32_t frameCount_ = 0;
const char *fileSourcesha256[64] = {"27", "6D", "A2", "D4", "18", "21", "A5", "CD", "50", "F6", "DD", "CA", "46",
"32", "C3", "FE", "58", "FC", "BC", "51", "FD", "70", "C7", "D4", "E7", "4D",
"5C", "76", "E7", "71", "8A", "B3", "C0", "51", "84", "0A", "FA", "AF", "FA",
"DC", "7B", "C5", "26", "D1", "9A", "CA", "00", "DE", "FC", "C8", "4E", "34",
"C5", "9A", "43", "59", "85", "DC", "AC", "97", "A3", "FB", "23", "51"};
int32_t Start();
int32_t Stop();
int32_t Flush();
int32_t Reset();
void SetEOS(uint32_t index);
uint32_t SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer);
void CopyStartCode(uint8_t *frameBuffer, uint32_t bufferSize, OH_AVCodecBufferAttr &attr);
int32_t ReadData(uint32_t index, OH_AVMemory *buffer);
void WaitForEOS();
int32_t ConfigureVideoDecoder();
int32_t StartVideoDecoder();
int64_t GetSystemTimeUs();
int32_t CreateVideoDecoder(std::string codeName);
int32_t SetVideoDecoderCallback();
int32_t Release();
int32_t SetParameter(OH_AVFormat *format);
void OutputFunc();
void WriteOutputFrame(uint32_t index, OH_AVMemory *buffer, OH_AVCodecBufferAttr attr, FILE *outFile);
void InputFuncAVCC();
OH_AVErrCode InputFuncFUZZ(const uint8_t *data, size_t size);
void ReleaseSignal();
void ReleaseInFile();
void StopInloop();
VDecSignal *signal_;
uint32_t errCount = 0;
uint32_t outCount = 0;
int64_t outTimeArray[2000] = {};
bool sleepOnFPS = false;
bool repeatRun = false;
bool isSurfMode = false;
bool setParameters = false;
OH_AVCodec *vdec_;
OHNativeWindow *nativeWindow = nullptr;
sptr<Surface> cs = nullptr;
sptr<Surface> ps = nullptr;
private:
std::atomic<bool> isRunning_ { false };
std::unique_ptr<std::ifstream> inFile_;
std::unique_ptr<std::thread> inputLoop_;
std::unordered_map<uint32_t, OH_AVMemory *> inBufferMap_;
std::unordered_map<uint32_t, OH_AVMemory *> outBufferMap_;
OH_AVCodecAsyncCallback cb_;
int64_t timeStamp_ { 0 };
int64_t lastRenderedTimeUs_ { 0 };
bool isFirstFrame_ = true;
};
} // namespace Media
} // namespace OHOS
void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData);
void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData);
void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData);
void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
void *userData);
#endif // VIDEODEC_SAMPLE_H

View File

@ -0,0 +1,62 @@
# Copyright (c) 2024 Huawei Device 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.
#####################hydra-fuzz###################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "av_codec/av_codec"
MEDIA_ROOT_DIR = "//foundation/multimedia/av_codec/"
##############################fuzztest##########################################
ohos_fuzztest("HevcSwdecoderSetParameterFuzzTest") {
module_out_path = module_output_path
fuzz_config_file =
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecodersetparameter_fuzzer"
include_dirs = [
"$MEDIA_ROOT_DIR/interfaces/kits/c",
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderconfigure_fuzzer/",
]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"$MEDIA_ROOT_DIR/test/fuzztest/hevcswdecoderconfigure_fuzzer/videodec_sample.cpp",
"hevcswdecodersetparameter_fuzzer.cpp",
]
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_core",
"media_foundation:native_media_core",
"window_manager:libwm",
]
deps = [
"$MEDIA_ROOT_DIR/interfaces/inner_api/native:av_codec_client",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_codecbase",
"$MEDIA_ROOT_DIR/interfaces/kits/c:native_media_vdec",
]
}
###############################################################################
group("fuzztest") {
testonly = true
deps = []
deps += [
# deps file
":HevcSwdecoderSetParameterFuzzTest", #引用测试套
]
}
###############################################################################

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2024 Huawei Device 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.
*/
FUZZ

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2024 Huawei Device 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 <cstddef>
#include <cstdint>
#include "native_avcodec_base.h"
#include "native_avformat.h"
#include "videodec_sample.h"
#define FUZZ_PROJECT_NAME "hevcswdecodersetparameter_fuzzer"
using namespace std;
using namespace OHOS;
using namespace OHOS::Media;
static VDecFuzzSample *vDecSample = nullptr;
constexpr uint32_t DEFAULT_WIDTH = 1920;
constexpr uint32_t DEFAULT_HEIGHT = 1080;
constexpr double DEFAULT_FRAME_RATE = 30.0;
namespace OHOS {
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
if (size < sizeof(int64_t)) {
return false;
}
if (!vDecSample) {
vDecSample = new VDecFuzzSample();
vDecSample->defaultWidth = DEFAULT_WIDTH;
vDecSample->defaultHeight = DEFAULT_HEIGHT;
vDecSample->defaultFrameRate = DEFAULT_FRAME_RATE;
vDecSample->CreateVideoDecoder("OH.Media.Codec.Decoder.Video.HEVC");
vDecSample->ConfigureVideoDecoder();
vDecSample->SetVideoDecoderCallback();
vDecSample->Start();
}
OH_AVFormat *format = OH_AVFormat_CreateVideoFormat("video/hevc", DEFAULT_WIDTH, DEFAULT_HEIGHT);
int32_t intData = *reinterpret_cast<const int32_t *>(data);
int64_t longData = *reinterpret_cast<const int64_t *>(data);
double doubleData = *reinterpret_cast<const double *>(data);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITRATE, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, intData);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, intData);
OH_AVFormat_SetLongValue(format, OH_MD_KEY_DURATION, longData);
OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, doubleData);
vDecSample->SetParameter(format);
OH_AVFormat_Destroy(format);
return true;
}
} // namespace OHOS
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2024 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>180</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>