[feat] add aom av1 decoder implementation

This commit is contained in:
dijunkun
2024-09-27 17:29:47 +08:00
parent bbd60570a1
commit 2740f31642
5 changed files with 216 additions and 8 deletions

View File

@@ -0,0 +1,153 @@
#include "aom_av1_decoder.h"
#include "log.h"
#define SAVE_RECEIVED_AV1_STREAM 0
#define SAVE_DECODED_NV12_STREAM 0
AomAv1Decoder::AomAv1Decoder() {}
AomAv1Decoder::~AomAv1Decoder() {
if (SAVE_RECEIVED_AV1_STREAM && file_av1_) {
fflush(file_av1_);
fclose(file_av1_);
file_av1_ = nullptr;
}
if (SAVE_DECODED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (nv12_frame_) {
delete nv12_frame_;
nv12_frame_ = nullptr;
}
}
int AomAv1Decoder::Init() {
aom_av1_decoder_config_.threads = 8;
aom_av1_decoder_config_.w = 2560;
aom_av1_decoder_config_.h = 1440;
aom_av1_decoder_config_.allow_lowbitdepth = 1;
extern aom_codec_iface_t my_codec;
if (AOM_CODEC_OK != aom_codec_dec_init(&aom_av1_decoder_ctx_,
aom_codec_av1_dx(),
&aom_av1_decoder_config_, 0)) {
LOG_ERROR("Failed to initialize decoder");
return -1;
}
aom_codec_control(&aom_av1_decoder_ctx_, AV1D_GET_IMG_FORMAT,
AOM_IMG_FMT_NV12);
if (SAVE_RECEIVED_AV1_STREAM) {
file_av1_ = fopen("received_av1_stream.ivf", "w+b");
if (!file_av1_) {
LOG_WARN("Fail to open received_av1_stream.ivf");
}
}
if (SAVE_DECODED_NV12_STREAM) {
file_nv12_ = fopen("decoded_nv12_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open decoded_nv12_stream.yuv");
}
}
return 0;
}
int AomAv1Decoder::Decode(
const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame) {
if (SAVE_RECEIVED_AV1_STREAM) {
fwrite((unsigned char *)data, 1, size, file_av1_);
}
LOG_ERROR("Decode size {}", size);
aom_codec_iter_t iter = nullptr;
aom_codec_err_t ret =
aom_codec_decode(&aom_av1_decoder_ctx_, data, size, nullptr);
if (AOM_CODEC_OK != ret) {
const char *error = aom_codec_error(&aom_av1_decoder_ctx_);
const char *detail = aom_codec_error_detail(&aom_av1_decoder_ctx_);
if (detail && error) {
LOG_ERROR("Failed to decode frame [{}], additional information [{}]",
error, detail);
} else {
LOG_ERROR("Failed to decode frame, ret [{}]",
aom_codec_err_to_string(ret));
}
return -1;
}
if (img_ = aom_codec_get_frame(&aom_av1_decoder_ctx_, &iter)) {
{
aom_codec_frame_flags_t flags;
ret = aom_codec_control(&aom_av1_decoder_ctx_, AOMD_GET_FRAME_FLAGS,
&flags);
if (ret == AOM_CODEC_OK) {
if (flags & AOM_FRAME_IS_KEY) {
LOG_ERROR("Key frame");
} else {
LOG_ERROR("Inter frame");
}
if (flags & (AOM_FRAME_IS_KEY | AOM_FRAME_IS_INTRAONLY)) {
LOG_ERROR("Key frame");
} else if (flags & AOM_FRAME_IS_SWITCH) {
LOG_ERROR("Switch frame");
} else {
LOG_ERROR("P frame");
}
}
}
int corrupted = 0;
int ret = aom_codec_control(&aom_av1_decoder_ctx_, AOMD_GET_FRAME_CORRUPTED,
&corrupted);
if (ret != AOM_CODEC_OK) {
LOG_ERROR("Failed to get frame corrupted");
return -1;
}
frame_width_ = img_->d_w;
frame_height_ = img_->d_h;
nv12_frame_size_ = frame_width_ * frame_height_ * 3 / 2;
if (!nv12_frame_) {
nv12_frame_capacity_ = nv12_frame_size_;
nv12_frame_ =
new VideoFrame(nv12_frame_capacity_, frame_width_, frame_height_);
}
if (nv12_frame_capacity_ < nv12_frame_size_) {
nv12_frame_capacity_ = nv12_frame_size_;
delete nv12_frame_;
nv12_frame_ =
new VideoFrame(nv12_frame_capacity_, frame_width_, frame_height_);
}
if (nv12_frame_->Size() != nv12_frame_size_ ||
nv12_frame_->Width() != frame_width_ ||
nv12_frame_->Height() != frame_height_) {
nv12_frame_->SetSize(nv12_frame_size_);
nv12_frame_->SetWidth(frame_width_);
nv12_frame_->SetHeight(frame_height_);
}
on_receive_decoded_frame(*nv12_frame_);
if (SAVE_DECODED_NV12_STREAM) {
fwrite((unsigned char *)nv12_frame_->Buffer(), 1, nv12_frame_->Size(),
file_nv12_);
}
return 0;
}
return -1;
}

View File

@@ -0,0 +1,49 @@
/*
* @Author: DI JUNKUN
* @Date: 2024-09-25
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _AOM_AV1_DECODER_H_
#define _AOM_AV1_DECODER_H_
#include <functional>
#include "aom/aom_codec.h"
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
#include "video_decoder.h"
class AomAv1Decoder : public VideoDecoder {
public:
AomAv1Decoder();
virtual ~AomAv1Decoder();
public:
int Init();
int Decode(const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame);
std::string GetDecoderName() { return "AomAv1"; }
private:
VideoFrame *nv12_frame_ = 0;
int nv12_frame_capacity_ = 0;
int nv12_frame_size_ = 0;
int frame_width_ = 0;
int frame_height_ = 0;
FILE *file_av1_ = nullptr;
FILE *file_nv12_ = nullptr;
bool first_ = false;
// aom av1 decoder
aom_codec_ctx_t aom_av1_decoder_ctx_;
aom_codec_dec_cfg_t aom_av1_decoder_config_;
aom_image_t *img_ = nullptr;
};
#endif

View File

@@ -1,13 +1,13 @@
#include "video_decoder_factory.h" #include "video_decoder_factory.h"
#if __APPLE__ #include "aom/aom_av1_decoder.h"
#include "dav1d/dav1d_av1_decoder.h" #include "dav1d/dav1d_av1_decoder.h"
#include "openh264/openh264_decoder.h" #include "openh264/openh264_decoder.h"
#if __APPLE__
#else #else
#include "dav1d/dav1d_av1_decoder.h"
#include "nvcodec/nvidia_video_decoder.h" #include "nvcodec/nvidia_video_decoder.h"
#include "nvcodec_api.h" #include "nvcodec_api.h"
#include "openh264/openh264_decoder.h"
#endif #endif
#include "log.h" #include "log.h"
@@ -21,6 +21,8 @@ std::unique_ptr<VideoDecoder> VideoDecoderFactory::CreateVideoDecoder(
if (av1_encoding) { if (av1_encoding) {
LOG_INFO("Use dav1d decoder"); LOG_INFO("Use dav1d decoder");
return std::make_unique<Dav1dAv1Decoder>(Dav1dAv1Decoder()); return std::make_unique<Dav1dAv1Decoder>(Dav1dAv1Decoder());
// LOG_INFO("Use aom decoder");
// return std::make_unique<AomAv1Decoder>(AomAv1Decoder());
} else { } else {
#if __APPLE__ #if __APPLE__
return std::make_unique<OpenH264Decoder>(OpenH264Decoder()); return std::make_unique<OpenH264Decoder>(OpenH264Decoder());

View File

@@ -129,9 +129,7 @@ int AomAv1Encoder::Init() {
aom_codec_err_t ret = aom_codec_enc_config_default( aom_codec_err_t ret = aom_codec_enc_config_default(
aom_codec_av1_cx(), &aom_av1_encoder_config_, kUsageProfile); aom_codec_av1_cx(), &aom_av1_encoder_config_, kUsageProfile);
if (ret != AOM_CODEC_OK) { if (ret != AOM_CODEC_OK) {
LOG_ERROR( LOG_ERROR("Failed to get config: {}", aom_codec_err_to_string(ret));
"AomAv1Encoder::EncodeInit returned {} on aom_codec_enc_config_default",
(int)ret);
return -1; return -1;
} }

View File

@@ -112,6 +112,7 @@ target("media")
"src/media/video/decode/openh264/*.cpp", "src/media/video/decode/openh264/*.cpp",
"src/media/video/encode/aom/*.cpp", "src/media/video/encode/aom/*.cpp",
"src/media/video/decode/dav1d/*.cpp", "src/media/video/decode/dav1d/*.cpp",
"src/media/video/decode/aom/*.cpp",
"src/media/nvcodec/*.cpp") "src/media/nvcodec/*.cpp")
add_includedirs("src/media/video/encode", add_includedirs("src/media/video/encode",
"src/media/video/decode", "src/media/video/decode",
@@ -121,6 +122,7 @@ target("media")
"src/media/video/decode/openh264", "src/media/video/decode/openh264",
"src/media/video/encode/aom", "src/media/video/encode/aom",
"src/media/video/decode/dav1d", "src/media/video/decode/dav1d",
"src/media/video/decode/aom",
"src/media/nvcodec", "src/media/nvcodec",
"thirdparty/nvcodec/interface", {public = true}) "thirdparty/nvcodec/interface", {public = true})
add_includedirs(path.join(os.getenv("CUDA_PATH"), "include"), {public = true}) add_includedirs(path.join(os.getenv("CUDA_PATH"), "include"), {public = true})
@@ -133,6 +135,7 @@ target("media")
"src/media/video/decode/openh264/*.cpp", "src/media/video/decode/openh264/*.cpp",
"src/media/video/encode/aom/*.cpp", "src/media/video/encode/aom/*.cpp",
"src/media/video/decode/dav1d/*.cpp", "src/media/video/decode/dav1d/*.cpp",
"src/media/video/decode/aom/*.cpp",
"src/media/nvcodec/*.cpp") "src/media/nvcodec/*.cpp")
add_includedirs("src/media/video/encode", add_includedirs("src/media/video/encode",
"src/media/video/decode", "src/media/video/decode",
@@ -142,6 +145,7 @@ target("media")
"src/media/video/decode/openh264", "src/media/video/decode/openh264",
"src/media/video/encode/aom", "src/media/video/encode/aom",
"src/media/video/decode/dav1d", "src/media/video/decode/dav1d",
"src/media/video/decode/aom",
"src/media/nvcodec", "src/media/nvcodec",
"thirdparty/nvcodec/interface", {public = true}) "thirdparty/nvcodec/interface", {public = true})
add_includedirs(path.join(os.getenv("CUDA_PATH"), "include"), {public = true}) add_includedirs(path.join(os.getenv("CUDA_PATH"), "include"), {public = true})
@@ -151,13 +155,15 @@ target("media")
"src/media/video/encode/openh264/*.cpp", "src/media/video/encode/openh264/*.cpp",
"src/media/video/decode/openh264/*.cpp", "src/media/video/decode/openh264/*.cpp",
"src/media/video/encode/aom/*.cpp", "src/media/video/encode/aom/*.cpp",
"src/media/video/decode/dav1d/*.cpp") "src/media/video/decode/dav1d/*.cpp",
"src/media/video/decode/aom/*.cpp")
add_includedirs("src/media/video/encode", add_includedirs("src/media/video/encode",
"src/media/video/decode", "src/media/video/decode",
"src/media/video/encode/openh264", "src/media/video/encode/openh264",
"src/media/video/decode/openh264", "src/media/video/decode/openh264",
"src/media/video/encode/aom", "src/media/video/encode/aom",
"src/media/video/decode/dav1d", {public = true}) "src/media/video/decode/dav1d",
"src/media/video/decode/aom", {public = true})
end end
add_files("src/media/audio/encode/*.cpp", add_files("src/media/audio/encode/*.cpp",
"src/media/audio/decode/*.cpp") "src/media/audio/decode/*.cpp")