提交 cd699daf 编写于 作者: L ling990

modify testcases Signed-off-by: ling990 <liling96@huawei.com>

Signed-off-by: Nling990 <ling990@qq.com>
上级 1dae22cc
/*
* Copyright (C) 2022 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 VIDEODECENC_NDK_SAMPLE_H
#define VIDEODECENC_NDK_SAMPLE_H
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <atomic>
#include <fstream>
#include <thread>
#include <mutex>
#include <queue>
#include <string>
#include "securec.h"
#include "nocopyable.h"
#include "ndktest_log.h"
#include "native_avmagic.h"
#include "surface.h"
#include "native_avcodec_videodecoder.h"
#include "native_avcodec_videoencoder.h"
namespace OHOS {
namespace Media {
class VDecEncSignal {
public:
std::mutex inMutexDec_;
std::mutex outMutexDec_;
std::condition_variable inCondDec_;
std::condition_variable outCondDec_;
std::queue<uint32_t> inQueueDec_;
std::queue<uint32_t> outQueueDec_;
std::queue<uint32_t> flagQueueDec_;
std::queue<OH_AVMemory *> inBufferQueueDec_;
std::queue<OH_AVMemory *> outBufferQueueDec_;
std::mutex outMutexEnc_;
std::condition_variable outCondEnc_;
std::queue<uint32_t> inQueueEnc_;
std::queue<uint32_t> outQueueEnc_;
std::queue<uint32_t> sizeQueueEnc_;
std::queue<uint32_t> flagQueueEnc_;
std::queue<OH_AVMemory *> inBufferQueueEnc_;
std::queue<OH_AVMemory *> outBufferQueueEnc_;
int32_t errorNum_ = 0;
std::atomic<bool> isVdecFlushing_ = false;
std::atomic<bool> isVencFlushing_ = false;
};
class VDecEncNdkSample : public NoCopyable {
public:
VDecEncNdkSample() = default;
~VDecEncNdkSample();
void SetEosState(bool needSetEos);
struct OH_AVCodec* CreateVideoDecoderByMime(std::string mimetype);
struct OH_AVCodec* CreateVideoDecoderByName(std::string name);
int32_t ConfigureDec(struct OH_AVFormat *format);
int32_t SetOutputSurface();
int32_t PrepareDec();
int32_t StartDec();
int32_t StopDec();
int32_t FlushDec();
int32_t ResetDec();
int32_t ReleaseDec();
struct OH_AVCodec* CreateVideoEncoderByMime(std::string mimetype);
struct OH_AVCodec* CreateVideoEncoderByName(std::string name);
int32_t ConfigureEnc(struct OH_AVFormat *format);
int32_t GetSurface();
int32_t PrepareEnc();
int32_t StartEnc();
int32_t StopEnc();
int32_t FlushEnc();
int32_t ResetEnc();
int32_t ReleaseEnc();
int32_t CalcuError();
void SetReadPath(std::string filepath);
void SetSavePath(std::string filepath);
void ReRead();
void ResetDecParam();
void ResetEncParam();
int32_t GetFrameCount();
bool GetEncEosState();
bool GetDecEosState();
void PopInqueueDec();
void PopOutqueueDec();
void PopOutqueueEnc();
void SendEncEos();
int32_t PushInbufferDec(uint32_t index, uint32_t bufferSize);
VDecEncSignal* vcodecSignal_ = nullptr;
bool isDecInputEOS = false;
bool isEncInputEOS = false;
bool isDecOutputEOS = false;
bool isEncOutputEOS = false;
bool setEos = true;
private:
OHNativeWindow *nativeWindow_;
struct OH_AVCodec* vdec_;
void InputFuncDec();
void OutputFuncDec();
int32_t WriteToFile();
std::atomic<bool> isDecRunning_ = false;
std::unique_ptr<std::ifstream> testFile_;
std::unique_ptr<std::thread> inputLoopDec_;
std::unique_ptr<std::thread> outputLoopDec_;
struct OH_AVCodecAsyncCallback cbDec_;
int64_t timeStampDec_ = 0;
uint32_t decInCnt_ = 0;
uint32_t decOutCnt_ = 0;
struct OH_AVCodec* venc_;
void OutputFuncEnc();
std::atomic<bool> isEncRunning_ = false;
std::unique_ptr<std::thread> outputLoopEnc_;
struct OH_AVCodecAsyncCallback cbEnc_;
bool isFirstDecFrame_ = true;
uint32_t encOutCnt_ = 0;
std::string inFile_ = "/data/media/out_320_240_10s.h264";
std::string outFile_ = "/data/media/video_out.es";
};
}
}
#endif // VIDEODECENC_NDK_SAMPLE_H
/*
* Copyright (c) 2022 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 <string>
#include "gtest/gtest.h"
#include "native_avcodec_videodecoder.h"
#include "native_avcodec_videoencoder.h"
#include "native_avcodec_base.h"
#include "native_avformat.h"
#include "ActsVideoDecEncNdkTest.h"
using namespace std;
using namespace testing::ext;
using namespace OHOS;
using namespace OHOS::Media;
namespace {
const string MIME_TYPE_AVC = "video/avc";
const string MIME_TYPE_MPEG4 = "video/mp4v-es";
constexpr uint32_t DEFAULT_WIDTH = 320;
constexpr uint32_t DEFAULT_HEIGHT = 240;
constexpr uint32_t DEFAULT_PIXELFORMAT = 2;
constexpr uint32_t DEFAULT_FRAMERATE = 60;
const char* READPATH = "/data/media/out_320_240_10s.h264";
bool CheckDecDesc(map<string, int> InDesc, OH_AVFormat* OutDesc)
{
int32_t out ;
for (const auto& t: InDesc) {
bool res = OH_AVFormat_GetIntValue(OutDesc, t.first.c_str(), &out);
cout << "key: " << t.first << "; out: " << out <<endl;
if (!res) {
cout << "OH_AVFormat_GetIntValue Fail. key:" << t.first << endl;
return false;
}
if (out != t.second) {
cout << "OH_AVFormat_GetIntValue error. key: " << t.first
<< "; expect: "<< t.second
<< ", actual: "<< out << endl;
return false;
}
out = 0;
}
return true;
}
bool SetFormat(struct OH_AVFormat *format, map<string, int> mediaDescription)
{
const char *key;
for (const auto& t: mediaDescription) {
key = t.first.c_str();
if (not OH_AVFormat_SetIntValue(format, key, t.second)) {
cout << "OH_AV_FormatPutIntValue Fail. format key: " << t.first
<< ", value: "<< t.second << endl;
return false;
}
}
return true;
}
struct OH_AVFormat* createFormat()
{
OH_AVFormat *DefaultFormat = OH_AVFormat_Create();
OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAMERATE);
return DefaultFormat;
}
}
/**
* @tc.number : ActsVideoDecEncNdkTest001
* @tc.name : stop at end of stream
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest001, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetSavePath("/data/media/video_001.es");
OH_AVFormat *VideoFormat = OH_AVFormat_Create();
ASSERT_NE(nullptr, VideoFormat);
map<string, int> VideoParam = {
{OH_MD_KEY_WIDTH, DEFAULT_WIDTH},
{OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT},
{OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT},
{OH_MD_KEY_FRAME_RATE, DEFAULT_FRAMERATE},
};
ASSERT_EQ(true, SetFormat(VideoFormat, VideoParam));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
OH_AVFormat *OutDescDec = OH_VideoDecoder_GetOutputDescription(videoDec);
ASSERT_NE(nullptr, OutDescDec);
ASSERT_EQ(true, CheckDecDesc(VideoParam, OutDescDec));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
OH_AVFormat *OutDescEnc = OH_VideoEncoder_GetOutputDescription(videoEnc);
ASSERT_NE(nullptr, OutDescEnc);
ASSERT_EQ(true, CheckDecDesc(VideoParam, OutDescEnc));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest002
* @tc.name : reset at end of stream
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest002, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetSavePath("/data/media/video_002.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest003
* @tc.name : release at end of stream
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest003, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetSavePath("/data/media/video_003.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest004
* @tc.name : flush at running
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest004, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetEosState(false);
vDecEncSample->SetSavePath("/data/media/video_004.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (vDecEncSample->GetFrameCount() < 100) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
vDecEncSample->SetEosState(true);
vDecEncSample->SetSavePath("/data/media/video_004_2.es");
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest005
* @tc.name : flush dec at eos and restart
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest005, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetEosState(false);
vDecEncSample->SetSavePath("/data/media/video_005.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetDecEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
vDecEncSample->SetSavePath("/data/media/video_005_2.es");
vDecEncSample->SetEosState(true);
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest006
* @tc.name : stop at running and restart to eos
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest006, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetEosState(false);
vDecEncSample->SetSavePath("/data/media/video_006.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (vDecEncSample->GetFrameCount() < 100) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
vDecEncSample->SetEosState(true);
vDecEncSample->SetSavePath("/data/media/video_006_2.es");
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest007
* @tc.name : stop dec at eos and restart to eos
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest007, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetEosState(false);
vDecEncSample->SetSavePath("/data/media/video_007.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetDecEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
vDecEncSample->SetSavePath("/data/media/video_007_2.es");
vDecEncSample->SetEosState(true);
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest008
* @tc.name : reset at eos and restart to eos
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest008, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetSavePath("/data/media/video_008.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
vDecEncSample->SetSavePath("/data/media/video_008_2.es");
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
/**
* @tc.number : ActsVideoDecEncNdkTest009
* @tc.name : release at eos and restart to eos
* @tc.desc : Basic function test
*/
HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest009, Function | MediumTest | Level1)
{
VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample();
struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec);
struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc);
vDecEncSample->SetReadPath(READPATH);
vDecEncSample->SetSavePath("/data/media/video_009.es");
OH_AVFormat *VideoFormat = createFormat();
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec());
while (!vDecEncSample->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec());
videoDec = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc());
videoEnc = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
vDecEncSample->ReRead();
vDecEncSample->ResetDecParam();
vDecEncSample->ResetEncParam();
VDecEncNdkSample *vDecEncSample2 = new VDecEncNdkSample();
struct OH_AVCodec* videoDec2 = vDecEncSample2->CreateVideoDecoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoDec2);
struct OH_AVCodec* videoEnc2 = vDecEncSample2->CreateVideoEncoderByMime(MIME_TYPE_AVC);
ASSERT_NE(nullptr, videoEnc2);
vDecEncSample2->SetReadPath(READPATH);
vDecEncSample2->SetSavePath("/data/media/video_009_2.es");
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ConfigureDec(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ConfigureEnc(VideoFormat));
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->GetSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->SetOutputSurface());
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->PrepareEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->PrepareDec());
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->StartEnc());
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->StartDec());
while (!vDecEncSample2->GetEncEosState()) {};
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ReleaseDec());
videoDec2 = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ReleaseEnc());
videoEnc2 = nullptr;
OH_AVFormat_Destroy(VideoFormat);
VideoFormat = nullptr;
ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError());
}
\ No newline at end of file
/*
* Copyright (C) 2022 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 "gtest/gtest.h"
#include "audio_info.h"
#include "av_common.h"
#include "avcodec_video_encoder.h"
#include "avcodec_video_decoder.h"
#include "native_avmemory.h"
#include "VDecEncNdkSample.h"
using namespace OHOS;
using namespace OHOS::Media;
using namespace std;
namespace {
constexpr uint32_t SAMPLE_DURATION_US = 23000;
constexpr uint32_t ES[] = {
2106, 11465, 321, 72, 472, 68, 76, 79, 509, 90, 677, 88, 956, 99, 347, 77, 452, 681, 81, 1263, 94, 106, 97,
998, 97, 797, 93, 1343, 150, 116, 117, 926, 1198, 128, 110, 78, 1582, 158, 135, 112, 1588, 165, 132,
128, 1697, 168, 149, 117, 1938, 170, 141, 142, 1830, 106, 161, 122, 1623, 160, 154, 156, 1998, 230,
177, 139, 1650, 186, 128, 134, 1214, 122, 1411, 120, 1184, 128, 1591, 195, 145, 105, 1587, 169, 140,
118, 1952, 177, 150, 161, 1437, 159, 123, 1758, 180, 165, 144, 1936, 214, 191, 175, 2122, 180, 179,
160, 1927, 161, 184, 119, 1973, 218, 210, 129, 1962, 196, 127, 154, 2308, 173, 127, 1572, 142, 122,
2065, 262, 159, 206, 2251, 269, 179, 170, 2056, 308, 168, 191, 2090, 303, 191, 110, 1932, 272, 162,
122, 1877, 245, 167, 141, 1908, 294, 162, 118, 1493, 132, 1782, 273, 184, 133, 1958, 274, 180, 149,
2070, 216, 169, 143, 1882, 224, 149, 139, 1749, 277, 184, 139, 2141, 197, 170, 140, 2002, 269, 162,
140, 1862, 202, 179, 131, 1868, 214, 164, 140, 1546, 226, 150, 130, 1707, 162, 146, 1824, 181, 147,
130, 1898, 209, 143, 131, 1805, 180, 148, 106, 1776, 147, 141, 1572, 177, 130, 105, 1776, 178, 144,
122, 1557, 142, 124, 114, 1436, 143, 126, 1326, 127, 1755, 169, 127, 105, 1807, 177, 131, 134, 1613,
187, 137, 136, 1314, 134, 118, 2005, 194, 129, 147, 1566, 185, 132, 131, 1236, 174, 137, 106, 11049,
574, 126, 1242, 188, 130, 119, 1450, 187, 137, 141, 1116, 124, 1848, 138, 122, 1605, 186, 127, 140,
1798, 170, 124, 121, 1666, 157, 128, 130, 1678, 135, 118, 1804, 169, 135, 125, 1837, 168, 124, 124};
constexpr uint32_t ES_LENGTH = sizeof(ES) / sizeof(uint32_t);
constexpr int32_t STOPNUM = 10000;
void VdecAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
cout << "DEC Error errorCode=" << errorCode << endl;
VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
vcodecSignal_->errorNum_ += 1;
}
void VdecAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
cout << "DEC Format Changed" << endl;
}
void VdecAsyncNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
{
VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
if (vcodecSignal_->isVdecFlushing_.load()) {
cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl;
return;
}
vcodecSignal_->inQueueDec_.push(index);
vcodecSignal_->inBufferQueueDec_.push(data);
vcodecSignal_->inCondDec_.notify_all();
}
void VdecAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data,
OH_AVCodecBufferAttr *attr, void *userData)
{
VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
if (vcodecSignal_->isVdecFlushing_.load()) {
cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl;
return;
}
vcodecSignal_->outQueueDec_.push(index);
vcodecSignal_->flagQueueDec_.push(attr->flags);
vcodecSignal_->outCondDec_.notify_all();
}
void VencAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
cout << "ENC Error errorCode=" << errorCode << endl;
VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
vcodecSignal_->errorNum_ += 1;
}
void VencAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
cout << "ENC Format Changed" << endl;
}
void VencAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data,
OH_AVCodecBufferAttr *attr, void *userData)
{
VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
if (vcodecSignal_->isVencFlushing_.load()) {
cout << "VdecAsyncNeedInputData isVencFlushing_ is true, return" << endl;
return;
}
vcodecSignal_->outQueueEnc_.push(index);
vcodecSignal_->sizeQueueEnc_.push(attr->size);
vcodecSignal_->flagQueueEnc_.push(attr->flags);
vcodecSignal_->outBufferQueueEnc_.push(data);
vcodecSignal_->outCondEnc_.notify_all();
}
void clearIntqueue (std::queue<uint32_t>& q)
{
std::queue<uint32_t> empty;
swap(empty, q);
}
void clearBufferqueue (std::queue<OH_AVMemory *>& q)
{
std::queue<OH_AVMemory *> empty;
swap(empty, q);
}
}
VDecEncNdkSample::~VDecEncNdkSample()
{
OH_VideoDecoder_Destroy(vdec_);
OH_VideoEncoder_Destroy(venc_);
delete vcodecSignal_;
vcodecSignal_ = nullptr;
}
void VDecEncNdkSample::SetReadPath(std::string filepath)
{
inFile_ = filepath;
if (testFile_ == nullptr) {
testFile_ = std::make_unique<std::ifstream>();
}
testFile_->open(inFile_, std::ios::in | std::ios::binary);
}
void VDecEncNdkSample::SetSavePath(std::string filepath)
{
outFile_ = filepath;
}
void VDecEncNdkSample::SetEosState(bool needSetEos)
{
setEos = needSetEos;
}
void VDecEncNdkSample::ReRead()
{
if (testFile_ != nullptr) {
testFile_->close();
cout << "ReRead close before file success " << endl;
}
cout << "ReRead inFile is " << inFile_ << endl;
testFile_->open(inFile_, std::ios::in | std::ios::binary);
if (testFile_ != nullptr) {
cout << "testFile open success" << endl;
}
decInCnt_ = 0;
isFirstDecFrame_ = true;
timeStampDec_ = 0;
}
void VDecEncNdkSample::ResetDecParam()
{
decInCnt_ = 0;
decOutCnt_ = 0;
isDecInputEOS = false;
isDecOutputEOS = false;
unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
clearIntqueue(vcodecSignal_->inQueueDec_);
clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
vcodecSignal_->inCondDec_.notify_all();
unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
clearIntqueue(vcodecSignal_->outQueueDec_);
clearIntqueue(vcodecSignal_->flagQueueDec_);
clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
vcodecSignal_->outCondDec_.notify_all();
isDecRunning_.store(true);
cout << "isDecRunning_.load() is " << isDecRunning_.load() << endl;
}
void VDecEncNdkSample::ResetEncParam()
{
encOutCnt_ = 0;
isEncInputEOS = false;
isEncOutputEOS = false;
unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
clearIntqueue(vcodecSignal_->outQueueEnc_);
clearIntqueue(vcodecSignal_->sizeQueueEnc_);
clearIntqueue(vcodecSignal_->flagQueueEnc_);
clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
vcodecSignal_->outCondEnc_.notify_all();
isEncRunning_.store(true);
cout << "isEncRunning_.load() is " << isEncRunning_.load() << endl;
}
struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByMime(std::string mimetype)
{
vdec_ = OH_VideoDecoder_CreateByMime(mimetype.c_str());
NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByMime");
if (vcodecSignal_ == nullptr) {
vcodecSignal_ = new VDecEncSignal();
NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
}
cbDec_.onError = VdecAsyncError;
cbDec_.onStreamChanged = VdecAsyncStreamChanged;
cbDec_.onNeedInputData = VdecAsyncNeedInputData;
cbDec_.onNeedOutputData = VdecAsyncNewOutputData;
int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast<void *>(vcodecSignal_));
NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback");
return vdec_;
}
struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByName(std::string name)
{
vdec_ = OH_VideoDecoder_CreateByName(name.c_str());
NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByName");
if (vcodecSignal_ == nullptr) {
vcodecSignal_ = new VDecEncSignal();
NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
}
cbDec_.onError = VdecAsyncError;
cbDec_.onStreamChanged = VdecAsyncStreamChanged;
cbDec_.onNeedInputData = VdecAsyncNeedInputData;
cbDec_.onNeedOutputData = VdecAsyncNewOutputData;
int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast<void *>(vcodecSignal_));
NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback");
return vdec_;
}
int32_t VDecEncNdkSample::ConfigureDec(struct OH_AVFormat *format)
{
return OH_VideoDecoder_Configure(vdec_, format);
}
int32_t VDecEncNdkSample::PrepareDec()
{
return OH_VideoDecoder_Prepare(vdec_);
}
int32_t VDecEncNdkSample::StartDec()
{
cout << "Enter dec start" << endl;
isDecRunning_.store(true);
if (inputLoopDec_ == nullptr) {
inputLoopDec_ = make_unique<thread>(&VDecEncNdkSample::InputFuncDec, this);
NDK_CHECK_AND_RETURN_RET_LOG(inputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
}
if (outputLoopDec_ == nullptr) {
outputLoopDec_ = make_unique<thread>(&VDecEncNdkSample::OutputFuncDec, this);
NDK_CHECK_AND_RETURN_RET_LOG(outputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
}
cout << "Exit dec start" << endl;
return OH_VideoDecoder_Start(vdec_);
}
int32_t VDecEncNdkSample::StopDec()
{
cout << "ENTER DEC stop" << endl;
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
vcodecSignal_->isVdecFlushing_.store(true);
lock.unlock();
lock2.unlock();
int32_t ret = OH_VideoDecoder_Stop(vdec_);
unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
clearIntqueue(vcodecSignal_->inQueueDec_);
clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
vcodecSignal_->inCondDec_.notify_all();
lockIn.unlock();
unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
clearIntqueue(vcodecSignal_->outQueueDec_);
clearIntqueue(vcodecSignal_->flagQueueDec_);
clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
vcodecSignal_->outCondDec_.notify_all();
lockOut.unlock();
vcodecSignal_->isVdecFlushing_.store(false);
cout << "EXIT DEC stop" << endl;
return ret;
}
int32_t VDecEncNdkSample::FlushDec()
{
cout << "ENTER DEC FLUSH" << endl;
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
vcodecSignal_->isVdecFlushing_.store(true);
lock.unlock();
lock2.unlock();
int32_t ret = OH_VideoDecoder_Flush(vdec_);
unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
clearIntqueue(vcodecSignal_->inQueueDec_);
clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
vcodecSignal_->inCondDec_.notify_all();
lockIn.unlock();
unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
clearIntqueue(vcodecSignal_->outQueueDec_);
clearIntqueue(vcodecSignal_->flagQueueDec_);
clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
vcodecSignal_->outCondDec_.notify_all();
lockOut.unlock();
vcodecSignal_->isVdecFlushing_.store(false);
cout << "EXIT DEC FLUSH" << endl;
return ret;
}
int32_t VDecEncNdkSample::ResetDec()
{
cout << "Enter DEC reset" << endl;
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
vcodecSignal_->isVdecFlushing_.store(true);
lock.unlock();
lock2.unlock();
int32_t ret = OH_VideoDecoder_Reset(vdec_);
unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
clearIntqueue(vcodecSignal_->inQueueDec_);
clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
vcodecSignal_->inCondDec_.notify_all();
lockIn.unlock();
unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
clearIntqueue(vcodecSignal_->outQueueDec_);
clearIntqueue(vcodecSignal_->flagQueueDec_);
clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
vcodecSignal_->outCondDec_.notify_all();
lockOut.unlock();
vcodecSignal_->isVdecFlushing_.store(false);
cout << "Exit DEC reset" << endl;
return ret;
}
int32_t VDecEncNdkSample::ReleaseDec()
{
cout << "Enter DEC release" << endl;
isDecRunning_.store(false);
if (inputLoopDec_ != nullptr && inputLoopDec_->joinable()) {
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
vcodecSignal_->inQueueDec_.push(STOPNUM);
vcodecSignal_->inCondDec_.notify_all();
lock.unlock();
inputLoopDec_->join();
inputLoopDec_.reset();
}
if (outputLoopDec_ != nullptr && outputLoopDec_->joinable()) {
unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
vcodecSignal_->outQueueDec_.push(STOPNUM);
vcodecSignal_->outCondDec_.notify_all();
lock.unlock();
outputLoopDec_->join();
outputLoopDec_.reset();
}
OH_VideoDecoder_Destroy(vdec_);
cout << "Exit DEC release" << endl;
return AV_ERR_OK;
}
void VDecEncNdkSample::PopInqueueDec()
{
if (vcodecSignal_ == nullptr) {
return;
}
vcodecSignal_->inQueueDec_.pop();
vcodecSignal_->inBufferQueueDec_.pop();
}
int32_t VDecEncNdkSample::PushInbufferDec(uint32_t index, uint32_t bufferSize)
{
if (vdec_ == nullptr) {
return AV_ERR_INVALID_VAL;
}
struct OH_AVCodecBufferAttr attr;
attr.offset = 0;
if (decInCnt_ == ES_LENGTH) {
attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
attr.pts = 0;
attr.size = 0;
cout << "EOS Frame, frameCount = " << decInCnt_ << endl;
isDecInputEOS = true;
} else {
attr.pts = timeStampDec_;
attr.size = bufferSize;
if (isFirstDecFrame_) {
attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
isFirstDecFrame_ = false;
} else {
attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
}
}
return OH_VideoDecoder_PushInputData(vdec_, index, attr);
}
void VDecEncNdkSample::InputFuncDec()
{
while (true) {
cout << "ENTER DEC IN" << endl;
if (!isDecRunning_.load()) {
break;
}
unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
vcodecSignal_->inCondDec_.wait(lock, [this]() { return vcodecSignal_->inQueueDec_.size() > 0; });
if (!isDecRunning_.load()) {
break;
}
uint32_t index = vcodecSignal_->inQueueDec_.front();
OH_AVMemory *buffer = reinterpret_cast<OH_AVMemory *>(vcodecSignal_->inBufferQueueDec_.front());
if (vcodecSignal_->isVdecFlushing_.load() || isDecInputEOS || buffer == nullptr) {
PopInqueueDec();
continue;
}
NDK_CHECK_AND_RETURN_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
uint32_t bufferSize = 0;
if (decInCnt_ < ES_LENGTH) {
bufferSize = ES[decInCnt_];
char *fileBuffer = (char *)malloc(sizeof(char) * bufferSize + 1);
NDK_CHECK_AND_RETURN_LOG(fileBuffer != nullptr, "Fatal: malloc fail");
(void)testFile_->read(fileBuffer, bufferSize);
if (testFile_->eof()) {
free(fileBuffer);
cout << "Finish" << endl;
break;
}
if (memcpy_s(OH_AVMemory_GetAddr(buffer), OH_AVMemory_GetSize(buffer), fileBuffer, bufferSize) != EOK
|| buffer == nullptr) {
free(fileBuffer);
PopInqueueDec();
continue;
}
free(fileBuffer);
}
if (PushInbufferDec(index, bufferSize) != AV_ERR_OK) {
cout << "Fatal: OH_VideoDecoder_PushInputData fail, exit" << endl;
vcodecSignal_->errorNum_ += 1;
} else {
decInCnt_++;
}
timeStampDec_ += SAMPLE_DURATION_US;
PopInqueueDec();
}
}
void VDecEncNdkSample::PopOutqueueDec()
{
if (vcodecSignal_ == nullptr) {
return;
}
vcodecSignal_->outQueueDec_.pop();
vcodecSignal_->flagQueueDec_.pop();
}
void VDecEncNdkSample::SendEncEos()
{
if (vcodecSignal_ == nullptr || venc_== nullptr) {
return;
}
if (setEos) {
int32_t ret = OH_VideoEncoder_NotifyEndOfStream(venc_);
if (ret == 0) {
cout << "ENC IN: input EOS " << endl;
isEncInputEOS = true;
} else {
cout << "ENC IN: input EOS fail" << endl;
vcodecSignal_->errorNum_ += 1;
}
}
}
void VDecEncNdkSample::OutputFuncDec()
{
while (true) {
if (!isDecRunning_.load()) {
break;
}
unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
vcodecSignal_->outCondDec_.wait(lock, [this]() { return vcodecSignal_->outQueueDec_.size() > 0; });
if (!isDecRunning_.load()) {
break;
}
if (vcodecSignal_->isVdecFlushing_.load() || vcodecSignal_->isVencFlushing_.load() || isEncInputEOS) {
PopOutqueueDec();
continue;
}
uint32_t index = vcodecSignal_->outQueueDec_.front();
uint32_t outflag = vcodecSignal_->flagQueueDec_.front();
if (outflag == 0) {
uint32_t ret = OH_VideoDecoder_RenderOutputData(vdec_, index);
if (ret == 0) {
decOutCnt_ += 1;
cout << "DEC OUT.: render output success, decOutCnt_ is " << decOutCnt_ << endl;
} else {
cout << "DEC OUT. Fatal: ReleaseOutputBuffer fail" << endl;
vcodecSignal_->errorNum_ += 1;
break;
}
} else {
cout << "DEC OUT.: output EOS" << endl;
isDecOutputEOS = true;
SendEncEos();
}
PopOutqueueDec();
}
}
struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByMime(std::string mimetype)
{
venc_ = OH_VideoEncoder_CreateByMime(mimetype.c_str());
NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByMime");
if (vcodecSignal_ == nullptr) {
vcodecSignal_ = new VDecEncSignal();
NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
}
cbEnc_.onError = VencAsyncError;
cbEnc_.onStreamChanged = VencAsyncStreamChanged;
cbEnc_.onNeedOutputData = VencAsyncNewOutputData;
int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast<void *>(vcodecSignal_));
NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback");
return venc_;
}
struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByName(std::string name)
{
venc_ = OH_VideoEncoder_CreateByName(name.c_str());
NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByName");
if (vcodecSignal_ == nullptr) {
vcodecSignal_ = new VDecEncSignal();
NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
}
cbEnc_.onError = VencAsyncError;
cbEnc_.onStreamChanged = VencAsyncStreamChanged;
cbEnc_.onNeedOutputData = VencAsyncNewOutputData;
int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast<void *>(vcodecSignal_));
NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback");
return venc_;
}
int32_t VDecEncNdkSample::ConfigureEnc(struct OH_AVFormat *format)
{
return OH_VideoEncoder_Configure(venc_, format);
}
struct VEncObject : public OH_AVCodec {
explicit VEncObject(const std::shared_ptr<AVCodecVideoEncoder> &encoder)
: OH_AVCodec(AVMagic::MEDIA_MAGIC_VIDEO_ENCODER), videoEncoder_(encoder) {}
~VEncObject() = default;
const std::shared_ptr<AVCodecVideoEncoder> videoEncoder_;
};
int32_t VDecEncNdkSample::GetSurface()
{
return OH_VideoEncoder_GetSurface(venc_, &nativeWindow_);
}
struct VDecObject : public OH_AVCodec {
explicit VDecObject(const std::shared_ptr<AVCodecVideoDecoder> &decoder)
: OH_AVCodec(AVMagic::MEDIA_MAGIC_VIDEO_DECODER), videoDecoder_(decoder) {}
~VDecObject() = default;
const std::shared_ptr<AVCodecVideoDecoder> videoDecoder_;
};
int32_t VDecEncNdkSample::SetOutputSurface()
{
return OH_VideoDecoder_SetSurface(vdec_, nativeWindow_);
}
int32_t VDecEncNdkSample::PrepareEnc()
{
return OH_VideoEncoder_Prepare(venc_);
}
int32_t VDecEncNdkSample::StartEnc()
{
cout << "Enter enc start" << endl;
isEncRunning_.store(true);
if (outputLoopEnc_ == nullptr) {
outputLoopEnc_ = make_unique<thread>(&VDecEncNdkSample::OutputFuncEnc, this);
NDK_CHECK_AND_RETURN_RET_LOG(outputLoopEnc_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
}
cout << "Exit enc start" << endl;
return OH_VideoEncoder_Start(venc_);
}
int32_t VDecEncNdkSample::StopEnc()
{
cout << "Enter enc stop" << endl;
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
vcodecSignal_->isVencFlushing_.store(true);
lock.unlock();
int32_t ret = OH_VideoEncoder_Stop(venc_);
unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
clearIntqueue(vcodecSignal_->outQueueEnc_);
clearIntqueue(vcodecSignal_->sizeQueueEnc_);
clearIntqueue(vcodecSignal_->flagQueueEnc_);
clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
vcodecSignal_->outCondEnc_.notify_all();
lockOut.unlock();
vcodecSignal_->isVencFlushing_.store(false);
cout << "Exit enc stop" << endl;
return ret;
}
int32_t VDecEncNdkSample::FlushEnc()
{
cout << "Enter enc flush" << endl;
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
vcodecSignal_->isVencFlushing_.store(true);
lock.unlock();
int32_t ret = OH_VideoEncoder_Flush(venc_);
unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
clearIntqueue(vcodecSignal_->outQueueEnc_);
clearIntqueue(vcodecSignal_->sizeQueueEnc_);
clearIntqueue(vcodecSignal_->flagQueueEnc_);
clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
vcodecSignal_->outCondEnc_.notify_all();
lockOut.unlock();
vcodecSignal_->isVencFlushing_.store(false);
cout << "Exit enc flush" << endl;
return ret;
}
int32_t VDecEncNdkSample::ResetEnc()
{
cout << "Enter enc reset" << endl;
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
vcodecSignal_->isVencFlushing_.store(true);
lock.unlock();
int32_t ret = OH_VideoEncoder_Reset(venc_);
unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
clearIntqueue(vcodecSignal_->outQueueEnc_);
clearIntqueue(vcodecSignal_->sizeQueueEnc_);
clearIntqueue(vcodecSignal_->flagQueueEnc_);
clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
vcodecSignal_->outCondEnc_.notify_all();
lockOut.unlock();
vcodecSignal_->isVencFlushing_.store(false);
cout << "exit enc reset" << endl;
return ret;
}
int32_t VDecEncNdkSample::ReleaseEnc()
{
cout << "Enter enc release" << endl;
isEncRunning_.store(false);
if (outputLoopEnc_ != nullptr && outputLoopEnc_->joinable()) {
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
vcodecSignal_->outQueueEnc_.push(STOPNUM);
vcodecSignal_->outCondEnc_.notify_all();
lock.unlock();
outputLoopEnc_->join();
outputLoopEnc_.reset();
}
cout << "exit enc release" << endl;
OH_VideoEncoder_Destroy(venc_);
cout << "exit enc destroy" << endl;
return AV_ERR_OK;
}
void VDecEncNdkSample::PopOutqueueEnc()
{
if (vcodecSignal_ == nullptr) {
return;
}
vcodecSignal_->outQueueEnc_.pop();
vcodecSignal_->sizeQueueEnc_.pop();
vcodecSignal_->flagQueueEnc_.pop();
vcodecSignal_->outBufferQueueEnc_.pop();
}
int32_t VDecEncNdkSample::WriteToFile()
{
auto buffer = vcodecSignal_->outBufferQueueEnc_.front();
uint32_t size = vcodecSignal_->sizeQueueEnc_.front();
if (buffer == nullptr) {
cout << "getOutPut Buffer fail" << endl;
return AV_ERR_INVALID_VAL;
}
FILE *outFile = fopen(outFile_.c_str(), "a");
if (outFile == nullptr) {
cout << "dump data fail" << endl;
return AV_ERR_INVALID_VAL;
} else {
fwrite(OH_AVMemory_GetAddr(buffer), 1, size, outFile);
}
return fclose(outFile);
}
void VDecEncNdkSample::OutputFuncEnc()
{
while (true) {
if (!isEncRunning_.load()) {
break;
}
unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
vcodecSignal_->outCondEnc_.wait(lock, [this]() { return vcodecSignal_->outQueueEnc_.size() > 0; });
if (!isEncRunning_.load()) {
break;
}
if (vcodecSignal_->isVencFlushing_.load() || isEncOutputEOS) {
PopOutqueueEnc();
continue;
}
uint32_t index = vcodecSignal_->outQueueEnc_.front();
uint32_t encOutflag = vcodecSignal_->flagQueueEnc_.front();
if (encOutflag == 1) {
cout << "ENC get output EOS" << endl;
isEncOutputEOS = true;
} else {
if (WriteToFile() != 0) {
PopOutqueueEnc();
continue;
}
uint32_t ret = OH_VideoEncoder_FreeOutputData(venc_, index);
if (ret != 0) {
cout << "Fatal: ReleaseOutputBuffer fail" << endl;
vcodecSignal_->errorNum_ += 1;
} else {
encOutCnt_ += 1;
cout << "ENC OUT.: output success, encOutCnt_ is " << encOutCnt_ << endl;
}
}
PopOutqueueEnc();
}
}
int32_t VDecEncNdkSample::CalcuError()
{
cout << "errorNum_ is :" << vcodecSignal_->errorNum_ << endl;
cout << "decInCnt_ is :" << decInCnt_ << endl;
cout << "decOutCnt_ is :" << decOutCnt_ << endl;
cout << "encOutCnt_ is :" << encOutCnt_ << endl;
cout << "DEC inQueueDec_.size() is " << vcodecSignal_->inQueueDec_.size() << endl;
cout << "DEC outQueueDec_.size() is " << vcodecSignal_->outQueueDec_.size() << endl;
cout << "DEC outBufferQueueDec_.size() is " << vcodecSignal_->outBufferQueueDec_.size() << endl;
cout << "DEC outQueueEnc_.size() is " << vcodecSignal_->outQueueEnc_.size() << endl;
return vcodecSignal_->errorNum_ ;
}
int32_t VDecEncNdkSample::GetFrameCount()
{
return encOutCnt_;
}
bool VDecEncNdkSample::GetEncEosState()
{
return isEncOutputEOS;
}
bool VDecEncNdkSample::GetDecEosState()
{
return isDecOutputEOS;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册