Use factory to create encoder/decoder

This commit is contained in:
dijunkun
2023-09-20 17:44:29 +08:00
parent 3d4e1effe9
commit a794cd43b9
17 changed files with 173 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
#include "ffmpeg_decoder.h" #include "ffmpeg_video_decoder.h"
#include "log.h" #include "log.h"
@@ -10,7 +10,7 @@ extern "C" {
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
}; };
VideoDecoder::VideoDecoder() { FfmpegVideoDecoder::FfmpegVideoDecoder() {
if (SAVE_ENCODER_STREAM) { if (SAVE_ENCODER_STREAM) {
file_ = fopen("decode_stream.yuv", "w+b"); file_ = fopen("decode_stream.yuv", "w+b");
if (!file_) { if (!file_) {
@@ -19,7 +19,7 @@ VideoDecoder::VideoDecoder() {
} }
} }
VideoDecoder::~VideoDecoder() { FfmpegVideoDecoder::~FfmpegVideoDecoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
@@ -38,7 +38,7 @@ VideoDecoder::~VideoDecoder() {
av_free(codec_ctx_); av_free(codec_ctx_);
} }
int VideoDecoder::Init() { int FfmpegVideoDecoder::Init() {
// av_log_set_level(AV_LOG_DEBUG); // av_log_set_level(AV_LOG_DEBUG);
codec_id_ = AV_CODEC_ID_H264; codec_id_ = AV_CODEC_ID_H264;
@@ -80,7 +80,7 @@ int VideoDecoder::Init() {
return 0; return 0;
} }
int VideoDecoder::Decode( int FfmpegVideoDecoder::Decode(
const uint8_t *data, int size, const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame) { std::function<void(VideoFrame)> on_receive_decoded_frame) {
if (!first_) { if (!first_) {

View File

@@ -1,5 +1,5 @@
#ifndef _FFMPEG_DECODER_H_ #ifndef _FFMPEG_VIDEO_DECODER_H_
#define _FFMPEG_DECODER_H_ #define _FFMPEG_VIDEO_DECODER_H_
#ifdef _WIN32 #ifdef _WIN32
extern "C" { extern "C" {
@@ -17,12 +17,12 @@ extern "C" {
#include <functional> #include <functional>
#include "frame.h" #include "video_decoder.h"
class VideoDecoder { class FfmpegVideoDecoder : public VideoDecoder {
public: public:
VideoDecoder(); FfmpegVideoDecoder();
~VideoDecoder(); ~FfmpegVideoDecoder();
public: public:
int Init(); int Init();

View File

@@ -1,10 +1,10 @@
#include "nv_decoder.h" #include "nvidia_video_decoder.h"
#include "log.h" #include "log.h"
#define SAVE_ENCODER_STREAM 0 #define SAVE_ENCODER_STREAM 0
VideoDecoder::VideoDecoder() { NvidiaVideoDecoder::NvidiaVideoDecoder() {
if (SAVE_ENCODER_STREAM) { if (SAVE_ENCODER_STREAM) {
file_ = fopen("decode_stream.h264", "w+b"); file_ = fopen("decode_stream.h264", "w+b");
if (!file_) { if (!file_) {
@@ -12,7 +12,7 @@ VideoDecoder::VideoDecoder() {
} }
} }
} }
VideoDecoder::~VideoDecoder() { NvidiaVideoDecoder::~NvidiaVideoDecoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
@@ -20,7 +20,7 @@ VideoDecoder::~VideoDecoder() {
} }
} }
int VideoDecoder::Init() { int NvidiaVideoDecoder::Init() {
ck(cuInit(0)); ck(cuInit(0));
int nGpu = 0; int nGpu = 0;
int iGpu = 0; int iGpu = 0;
@@ -43,7 +43,7 @@ int VideoDecoder::Init() {
return 0; return 0;
} }
int VideoDecoder::Decode( int NvidiaVideoDecoder::Decode(
const uint8_t *data, int size, const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame) { std::function<void(VideoFrame)> on_receive_decoded_frame) {
if (!decoder) { if (!decoder) {

View File

@@ -1,15 +1,15 @@
#ifndef _NV_DECODER_H_ #ifndef _NVIDIA_VIDEO_DECODER_H_
#define _NV_DECODER_H_ #define _NVIDIA_VIDEO_DECODER_H_
#include <functional> #include <functional>
#include "NvDecoder.h" #include "NvDecoder.h"
#include "frame.h" #include "video_decoder.h"
class VideoDecoder { class NvidiaVideoDecoder : public VideoDecoder {
public: public:
VideoDecoder(); NvidiaVideoDecoder();
~VideoDecoder(); ~NvidiaVideoDecoder();
public: public:
int Init(); int Init();

View File

@@ -0,0 +1,16 @@
#ifndef _VIDEO_DECODER_H_
#define _VIDEO_DECODER_H_
#include <functional>
#include "frame.h"
class VideoDecoder {
public:
virtual int Init() = 0;
virtual int Decode(
const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame) = 0;
};
#endif

View File

@@ -0,0 +1,17 @@
#include "video_decoder_factory.h"
#include "ffmpeg/ffmpeg_video_decoder.h"
#include "nvcodec/nvidia_video_decoder.h"
VideoDecoderFactory::VideoDecoderFactory() {}
VideoDecoderFactory::~VideoDecoderFactory() {}
VideoDecoder *VideoDecoderFactory::CreateVideoDecoder(
bool hardware_acceleration) {
if (hardware_acceleration) {
return new NvidiaVideoDecoder();
} else {
return new FfmpegVideoDecoder();
}
}

View File

@@ -0,0 +1,16 @@
#ifndef _VIDEO_DECODER_FACTORY_H_
#define _VIDEO_DECODER_FACTORY_H_
#include "video_decoder.h"
class VideoDecoderFactory {
public:
VideoDecoderFactory();
~VideoDecoderFactory();
static VideoDecoder *CreateVideoDecoder(bool hardware_acceleration);
private:
bool hardware_acceleration_ = false;
};
#endif

View File

@@ -1,4 +1,4 @@
#include "ffmpeg_encoder.h" #include "ffmpeg_video_encoder.h"
#include <chrono> #include <chrono>
@@ -6,7 +6,7 @@
#define SAVE_ENCODER_STREAM 0 #define SAVE_ENCODER_STREAM 0
VideoEncoder::VideoEncoder() { FFmpegVideoEncoder::FFmpegVideoEncoder() {
if (SAVE_ENCODER_STREAM) { if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b"); file_ = fopen("encode_stream.h264", "w+b");
if (!file_) { if (!file_) {
@@ -14,7 +14,7 @@ VideoEncoder::VideoEncoder() {
} }
} }
} }
VideoEncoder::~VideoEncoder() { FFmpegVideoEncoder::~FFmpegVideoEncoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
@@ -29,7 +29,7 @@ VideoEncoder::~VideoEncoder() {
} }
} }
int VideoEncoder::Init() { int FFmpegVideoEncoder::Init() {
av_log_set_level(AV_LOG_ERROR); av_log_set_level(AV_LOG_ERROR);
codec_ = avcodec_find_encoder(AV_CODEC_ID_H264); codec_ = avcodec_find_encoder(AV_CODEC_ID_H264);
@@ -85,7 +85,7 @@ int VideoEncoder::Init() {
return 0; return 0;
} }
int VideoEncoder::Encode( int FFmpegVideoEncoder::Encode(
const uint8_t *pData, int nSize, const uint8_t *pData, int nSize,
std::function<int(char *encoded_packets, size_t size)> on_encoded_image) { std::function<int(char *encoded_packets, size_t size)> on_encoded_image) {
if (!codec_ctx_) { if (!codec_ctx_) {
@@ -132,9 +132,9 @@ int VideoEncoder::Encode(
return 0; return 0;
} }
int VideoEncoder::OnEncodedImage(char *encoded_packets, size_t size) { int FFmpegVideoEncoder::OnEncodedImage(char *encoded_packets, size_t size) {
LOG_INFO("OnEncodedImage not implemented"); LOG_INFO("OnEncodedImage not implemented");
return 0; return 0;
} }
void VideoEncoder::ForceIdr() {} void FFmpegVideoEncoder::ForceIdr() {}

View File

@@ -1,5 +1,5 @@
#ifndef _FFMPEG_ENCODER_H_ #ifndef _FFMPEG_VIDEO_ENCODER_H_
#define _FFMPEG_ENCODER_H_ #define _FFMPEG_VIDEO_ENCODER_H_
#ifdef _WIN32 #ifdef _WIN32
extern "C" { extern "C" {
@@ -24,10 +24,12 @@ extern "C" {
#endif #endif
#include <functional> #include <functional>
class VideoEncoder { #include "video_encoder.h"
class FFmpegVideoEncoder : public VideoEncoder {
public: public:
VideoEncoder(); FFmpegVideoEncoder();
~VideoEncoder(); ~FFmpegVideoEncoder();
int Init(); int Init();
int Encode( int Encode(

View File

@@ -1,4 +1,4 @@
#include "nv_encoder.h" #include "nvidia_video_encoder.h"
#include <chrono> #include <chrono>
@@ -6,7 +6,7 @@
#define SAVE_ENCODER_STREAM 0 #define SAVE_ENCODER_STREAM 0
VideoEncoder::VideoEncoder() { NvidiaVideoEncoder::NvidiaVideoEncoder() {
if (SAVE_ENCODER_STREAM) { if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b"); file_ = fopen("encode_stream.h264", "w+b");
if (!file_) { if (!file_) {
@@ -14,7 +14,7 @@ VideoEncoder::VideoEncoder() {
} }
} }
} }
VideoEncoder::~VideoEncoder() { NvidiaVideoEncoder::~NvidiaVideoEncoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
@@ -27,7 +27,7 @@ VideoEncoder::~VideoEncoder() {
} }
} }
int VideoEncoder::Init() { int NvidiaVideoEncoder::Init() {
// Init cuda context // Init cuda context
int num_of_GPUs = 0; int num_of_GPUs = 0;
CUdevice cuda_device; CUdevice cuda_device;
@@ -73,7 +73,7 @@ int VideoEncoder::Init() {
return 0; return 0;
} }
int VideoEncoder::Encode( int NvidiaVideoEncoder::Encode(
const uint8_t *pData, int nSize, const uint8_t *pData, int nSize,
std::function<int(char *encoded_packets, size_t size)> on_encoded_image) { std::function<int(char *encoded_packets, size_t size)> on_encoded_image) {
if (!encoder_) { if (!encoder_) {
@@ -130,12 +130,12 @@ int VideoEncoder::Encode(
return 0; return 0;
} }
int VideoEncoder::OnEncodedImage(char *encoded_packets, size_t size) { int NvidiaVideoEncoder::OnEncodedImage(char *encoded_packets, size_t size) {
LOG_INFO("OnEncodedImage not implemented"); LOG_INFO("OnEncodedImage not implemented");
return 0; return 0;
} }
void VideoEncoder::ForceIdr() { void NvidiaVideoEncoder::ForceIdr() {
NV_ENC_RECONFIGURE_PARAMS reconfig_params; NV_ENC_RECONFIGURE_PARAMS reconfig_params;
reconfig_params.version = NV_ENC_RECONFIGURE_PARAMS_VER; reconfig_params.version = NV_ENC_RECONFIGURE_PARAMS_VER;

View File

@@ -1,14 +1,15 @@
#ifndef _NV_ENCODER_H_ #ifndef _NVIDIA_VIDEO_ENCODER_H_
#define _NV_ENCODER_H_ #define _NVIDIA_VIDEO_ENCODER_H_
#include <functional> #include <functional>
#include "NvEncoderCuda.h" #include "NvEncoderCuda.h"
#include "video_encoder.h"
class VideoEncoder { class NvidiaVideoEncoder : public VideoEncoder {
public: public:
VideoEncoder(); NvidiaVideoEncoder();
~VideoEncoder(); ~NvidiaVideoEncoder();
int Init(); int Init();
int Encode( int Encode(

View File

@@ -0,0 +1,16 @@
#ifndef _VIDEO_ENCODER_H_
#define _VIDEO_ENCODER_H_
#include <functional>
class VideoEncoder {
public:
virtual int Init() = 0;
virtual int Encode(const uint8_t* pData, int nSize,
std::function<int(char* encoded_packets, size_t size)>
on_encoded_image) = 0;
virtual int OnEncodedImage(char* encoded_packets, size_t size) = 0;
virtual void ForceIdr() = 0;
};
#endif

View File

@@ -0,0 +1,17 @@
#include "video_encoder_factory.h"
#include "ffmpeg/ffmpeg_video_encoder.h"
#include "nvcodec/nvidia_video_encoder.h"
VideoEncoderFactory::VideoEncoderFactory() {}
VideoEncoderFactory::~VideoEncoderFactory() {}
VideoEncoder *VideoEncoderFactory::CreateVideoEncoder(
bool hardware_acceleration) {
if (hardware_acceleration) {
return new NvidiaVideoEncoder();
} else {
return new FFmpegVideoEncoder();
}
}

View File

@@ -0,0 +1,16 @@
#ifndef _VIDEO_ENCODER_FACTORY_H_
#define _VIDEO_ENCODER_FACTORY_H_
#include "video_encoder.h"
class VideoEncoderFactory {
public:
VideoEncoderFactory();
~VideoEncoderFactory();
static VideoEncoder *CreateVideoEncoder(bool hardware_acceleration);
private:
bool hardware_acceleration_ = false;
};
#endif

View File

@@ -60,7 +60,7 @@ int PeerConnection::Init(PeerConnectionParams params,
on_receive_video_ = [this](const char *data, size_t size, const char *user_id, on_receive_video_ = [this](const char *data, size_t size, const char *user_id,
size_t user_id_size) { size_t user_id_size) {
int num_frame_returned = Decode( int num_frame_returned = video_decoder->Decode(
(uint8_t *)data, size, (uint8_t *)data, size,
[this, user_id, user_id_size](VideoFrame video_frame) { [this, user_id, user_id_size](VideoFrame video_frame) {
if (on_receive_video_buffer_) { if (on_receive_video_buffer_) {
@@ -101,8 +101,15 @@ int PeerConnection::Init(PeerConnectionParams params,
do { do {
} while (SignalStatus::Connected != GetSignalStatus()); } while (SignalStatus::Connected != GetSignalStatus());
VideoEncoder::Init();
VideoDecoder::Init(); video_encoder =
VideoEncoderFactory::CreateVideoEncoder(hardware_accelerated_encode_);
video_encoder->Init();
video_decoder =
VideoDecoderFactory::CreateVideoDecoder(hardware_accelerated_decode_);
video_decoder->Init();
// VideoEncoder::Init();
// VideoDecoder::Init();
nv12_data_ = new char[1280 * 720 * 3 / 2]; nv12_data_ = new char[1280 * 720 * 3 / 2];
return 0; return 0;
@@ -302,7 +309,7 @@ int PeerConnection::SendVideoData(const char *data, size_t size) {
return -1; return -1;
} }
int ret = Encode( int ret = video_encoder->Encode(
(uint8_t *)data, size, [this](char *encoded_frame, size_t size) -> int { (uint8_t *)data, size, [this](char *encoded_frame, size_t size) -> int {
for (auto &ice_trans : ice_transmission_list_) { for (auto &ice_trans : ice_transmission_list_) {
// LOG_ERROR("H264 frame size: [{}]", size); // LOG_ERROR("H264 frame size: [{}]", size);

View File

@@ -8,10 +8,8 @@
#include "ice_transmission.h" #include "ice_transmission.h"
#ifdef _WIN32 #ifdef _WIN32
#include "ffmpeg_decoder.h" #include "video_decoder_factory.h"
#include "ffmpeg_encoder.h" #include "video_encoder_factory.h"
// #include "nv_decoder.h"
// #include "nv_encoder.h"
#endif #endif
#include "ws_transmission.h" #include "ws_transmission.h"
@@ -31,7 +29,7 @@ typedef struct {
NetStatusReport net_status_report; NetStatusReport net_status_report;
} PeerConnectionParams; } PeerConnectionParams;
class PeerConnection : public VideoEncoder, VideoDecoder { class PeerConnection {
public: public:
PeerConnection(); PeerConnection();
~PeerConnection(); ~PeerConnection();
@@ -100,6 +98,12 @@ class PeerConnection : public VideoEncoder, VideoDecoder {
OnReceiveBuffer on_receive_audio_buffer_; OnReceiveBuffer on_receive_audio_buffer_;
OnReceiveBuffer on_receive_data_buffer_; OnReceiveBuffer on_receive_data_buffer_;
char *nv12_data_ = nullptr; char *nv12_data_ = nullptr;
private:
VideoEncoder *video_encoder = nullptr;
VideoDecoder *video_decoder = nullptr;
bool hardware_accelerated_encode_ = true;
bool hardware_accelerated_decode_ = true;
}; };
#endif #endif

View File

@@ -104,12 +104,16 @@ target("media")
add_deps("log", "frame") add_deps("log", "frame")
if is_os("windows") or is_os(("linux")) then if is_os("windows") or is_os(("linux")) then
add_packages("cuda") add_packages("cuda")
add_files("src/media/video/encode/nvcodec/*.cpp", add_files("src/media/video/encode/*.cpp",
"src/media/video/decode/*.cpp",
"src/media/video/encode/nvcodec/*.cpp",
"src/media/video/decode/nvcodec/*.cpp", "src/media/video/decode/nvcodec/*.cpp",
"src/media/video/encode/ffmpeg/*.cpp", "src/media/video/encode/ffmpeg/*.cpp",
"src/media/video/decode/ffmpeg/*.cpp" "src/media/video/decode/ffmpeg/*.cpp"
) )
add_includedirs("src/media/video/encode/nvcodec", add_includedirs("src/media/video/encode",
"src/media/video/decode",
"src/media/video/encode/nvcodec",
"src/media/video/decode/nvcodec", "src/media/video/decode/nvcodec",
"src/media/video/encode/ffmpeg", "src/media/video/encode/ffmpeg",
"src/media/video/decode/ffmpeg", "src/media/video/decode/ffmpeg",