Add global hardware acceleration codec switch

This commit is contained in:
dijunkun
2023-09-21 10:42:16 +08:00
parent a794cd43b9
commit b4318cc8d6
17 changed files with 113 additions and 85 deletions

View File

@@ -10,4 +10,7 @@ port = 3478
ip = 120.77.216.215 ip = 120.77.216.215
port = 3478 port = 3478
username = dijunkun username = dijunkun
password = dijunkunpw password = dijunkunpw
[hardware acceleration]
turn_on = true

View File

@@ -24,7 +24,6 @@ int IceAgent::CreateIceAgent(juice_cb_state_changed_t on_state_changed,
juice_cb_recv_t on_recv, void *user_ptr) { juice_cb_recv_t on_recv, void *user_ptr) {
// juice_set_log_level(JUICE_LOG_LEVEL_DEBUG); // juice_set_log_level(JUICE_LOG_LEVEL_DEBUG);
LOG_ERROR("{} {} {} {}", stun_ip_, stun_port_, turn_ip_, turn_port_);
juice_config_t config; juice_config_t config;
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));

View File

@@ -2,7 +2,7 @@
#include "log.h" #include "log.h"
#define SAVE_ENCODER_STREAM 1 #define SAVE_DECODER_STREAM 1
extern "C" { extern "C" {
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
@@ -10,17 +10,10 @@ extern "C" {
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
}; };
FfmpegVideoDecoder::FfmpegVideoDecoder() { FfmpegVideoDecoder::FfmpegVideoDecoder() {}
if (SAVE_ENCODER_STREAM) {
file_ = fopen("decode_stream.yuv", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.yuv");
}
}
}
FfmpegVideoDecoder::~FfmpegVideoDecoder() { FfmpegVideoDecoder::~FfmpegVideoDecoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_DECODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
file_ = nullptr; file_ = nullptr;
@@ -31,11 +24,26 @@ FfmpegVideoDecoder::~FfmpegVideoDecoder() {
decoded_frame_ = nullptr; decoded_frame_ = nullptr;
} }
av_frame_free(&frame_); if (packet_) {
av_frame_free(&frame_nv12_); av_packet_free(&packet_);
sws_freeContext(img_convert_ctx); }
avcodec_close(codec_ctx_);
av_free(codec_ctx_); if (frame_) {
av_frame_free(&frame_);
}
if (frame_nv12_) {
av_frame_free(&frame_nv12_);
}
if (img_convert_ctx) {
sws_freeContext(img_convert_ctx);
}
if (codec_ctx_) {
avcodec_close(codec_ctx_);
}
if (codec_ctx_) {
av_free(codec_ctx_);
}
} }
int FfmpegVideoDecoder::Init() { int FfmpegVideoDecoder::Init() {
@@ -71,12 +79,20 @@ int FfmpegVideoDecoder::Init() {
frame_ = av_frame_alloc(); frame_ = av_frame_alloc();
frame_nv12_ = av_frame_alloc(); frame_nv12_ = av_frame_alloc();
packet_ = av_packet_alloc();
img_convert_ctx = img_convert_ctx =
sws_getContext(1280, 720, AV_PIX_FMT_YUV420P, 1280, 720, AV_PIX_FMT_NV12, sws_getContext(1280, 720, AV_PIX_FMT_YUV420P, 1280, 720, AV_PIX_FMT_NV12,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
decoded_frame_ = new VideoFrame(1280 * 720 * 3 / 2); decoded_frame_ = new VideoFrame(1280 * 720 * 3 / 2);
if (SAVE_DECODER_STREAM) {
file_ = fopen("decode_stream.yuv", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.yuv");
}
}
return 0; return 0;
} }
@@ -93,10 +109,11 @@ int FfmpegVideoDecoder::Decode(
} }
} }
packet_.data = (uint8_t *)data; packet_->data = (uint8_t *)data;
packet_.size = size; packet_->size = size;
int ret = avcodec_send_packet(codec_ctx_, &packet_); int ret = avcodec_send_packet(codec_ctx_, packet_);
av_packet_unref(packet_);
while (ret >= 0) { while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx_, frame_); ret = avcodec_receive_frame(codec_ctx_, frame_);
@@ -135,9 +152,9 @@ int FfmpegVideoDecoder::Decode(
LOG_ERROR("cost {}", now_ts - start_ts); LOG_ERROR("cost {}", now_ts - start_ts);
on_receive_decoded_frame(*decoded_frame_); on_receive_decoded_frame(*decoded_frame_);
if (SAVE_ENCODER_STREAM) { if (SAVE_DECODER_STREAM) {
fwrite((unsigned char *)frame_->data, 1, fwrite((unsigned char *)decoded_frame_->Buffer(), 1,
frame_->width * frame_->height * 3 / 2, file_); decoded_frame_->Size(), file_);
} }
} }
} }

View File

@@ -22,7 +22,7 @@ extern "C" {
class FfmpegVideoDecoder : public VideoDecoder { class FfmpegVideoDecoder : public VideoDecoder {
public: public:
FfmpegVideoDecoder(); FfmpegVideoDecoder();
~FfmpegVideoDecoder(); virtual ~FfmpegVideoDecoder();
public: public:
int Init(); int Init();
@@ -33,7 +33,7 @@ class FfmpegVideoDecoder : public VideoDecoder {
AVCodecID codec_id_; AVCodecID codec_id_;
const AVCodec *codec_; const AVCodec *codec_;
AVCodecContext *codec_ctx_ = nullptr; AVCodecContext *codec_ctx_ = nullptr;
AVPacket packet_; AVPacket *packet_ = nullptr;
AVFrame *frame_ = nullptr; AVFrame *frame_ = nullptr;
AVFrame *frame_nv12_ = nullptr; AVFrame *frame_nv12_ = nullptr;
struct SwsContext *img_convert_ctx = nullptr; struct SwsContext *img_convert_ctx = nullptr;

View File

@@ -2,18 +2,11 @@
#include "log.h" #include "log.h"
#define SAVE_ENCODER_STREAM 0 #define SAVE_DECODER_STREAM 1
NvidiaVideoDecoder::NvidiaVideoDecoder() { NvidiaVideoDecoder::NvidiaVideoDecoder() {}
if (SAVE_ENCODER_STREAM) {
file_ = fopen("decode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
}
NvidiaVideoDecoder::~NvidiaVideoDecoder() { NvidiaVideoDecoder::~NvidiaVideoDecoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_DECODER_STREAM && file_) {
fflush(file_); fflush(file_);
fclose(file_); fclose(file_);
file_ = nullptr; file_ = nullptr;
@@ -40,6 +33,13 @@ int NvidiaVideoDecoder::Init() {
} }
decoder = new NvDecoder(cuContext, false, cudaVideoCodec_H264, true); decoder = new NvDecoder(cuContext, false, cudaVideoCodec_H264, true);
if (SAVE_DECODER_STREAM) {
file_ = fopen("decode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
return 0; return 0;
} }
@@ -54,10 +54,6 @@ int NvidiaVideoDecoder::Decode(
// LOG_WARN("Receive key frame"); // LOG_WARN("Receive key frame");
} }
if (SAVE_ENCODER_STREAM) {
fwrite((unsigned char *)data, 1, size, file_);
}
int num_frame_returned = decoder->Decode(data, size); int num_frame_returned = decoder->Decode(data, size);
for (size_t i = 0; i < num_frame_returned; ++i) { for (size_t i = 0; i < num_frame_returned; ++i) {
@@ -71,6 +67,10 @@ int NvidiaVideoDecoder::Decode(
data, decoder->GetWidth() * decoder->GetHeight() * 3 / 2, data, decoder->GetWidth() * decoder->GetHeight() * 3 / 2,
decoder->GetWidth(), decoder->GetHeight()); decoder->GetWidth(), decoder->GetHeight());
on_receive_decoded_frame(decoded_frame); on_receive_decoded_frame(decoded_frame);
if (SAVE_DECODER_STREAM) {
fwrite((unsigned char *)decoded_frame.Buffer(), 1,
decoded_frame.Size(), file_);
}
} }
} }
} }

View File

@@ -9,7 +9,7 @@
class NvidiaVideoDecoder : public VideoDecoder { class NvidiaVideoDecoder : public VideoDecoder {
public: public:
NvidiaVideoDecoder(); NvidiaVideoDecoder();
~NvidiaVideoDecoder(); virtual ~NvidiaVideoDecoder();
public: public:
int Init(); int Init();

View File

@@ -7,11 +7,11 @@ VideoDecoderFactory::VideoDecoderFactory() {}
VideoDecoderFactory::~VideoDecoderFactory() {} VideoDecoderFactory::~VideoDecoderFactory() {}
VideoDecoder *VideoDecoderFactory::CreateVideoDecoder( std::unique_ptr<VideoDecoder> VideoDecoderFactory::CreateVideoDecoder(
bool hardware_acceleration) { bool hardware_acceleration) {
if (hardware_acceleration) { if (hardware_acceleration) {
return new NvidiaVideoDecoder(); return std::make_unique<NvidiaVideoDecoder>(NvidiaVideoDecoder());
} else { } else {
return new FfmpegVideoDecoder(); return std::make_unique<FfmpegVideoDecoder>(FfmpegVideoDecoder());
} }
} }

View File

@@ -7,10 +7,8 @@ class VideoDecoderFactory {
VideoDecoderFactory(); VideoDecoderFactory();
~VideoDecoderFactory(); ~VideoDecoderFactory();
static VideoDecoder *CreateVideoDecoder(bool hardware_acceleration); static std::unique_ptr<VideoDecoder> CreateVideoDecoder(
bool hardware_acceleration);
private:
bool hardware_acceleration_ = false;
}; };
#endif #endif

View File

@@ -4,16 +4,9 @@
#include "log.h" #include "log.h"
#define SAVE_ENCODER_STREAM 0 #define SAVE_ENCODER_STREAM 1
FFmpegVideoEncoder::FFmpegVideoEncoder() { FFmpegVideoEncoder::FFmpegVideoEncoder() {}
if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
}
FFmpegVideoEncoder::~FFmpegVideoEncoder() { FFmpegVideoEncoder::~FFmpegVideoEncoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
@@ -21,12 +14,14 @@ FFmpegVideoEncoder::~FFmpegVideoEncoder() {
file_ = nullptr; file_ = nullptr;
} }
av_packet_free(&packet_);
if (nv12_data_) { if (nv12_data_) {
free(nv12_data_); free(nv12_data_);
nv12_data_ = nullptr; nv12_data_ = nullptr;
} }
if (packet_) {
av_packet_free(&packet_);
}
} }
int FFmpegVideoEncoder::Init() { int FFmpegVideoEncoder::Init() {
@@ -82,6 +77,13 @@ int FFmpegVideoEncoder::Init() {
packet_ = av_packet_alloc(); packet_ = av_packet_alloc();
if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
return 0; return 0;
} }

View File

@@ -29,7 +29,7 @@ extern "C" {
class FFmpegVideoEncoder : public VideoEncoder { class FFmpegVideoEncoder : public VideoEncoder {
public: public:
FFmpegVideoEncoder(); FFmpegVideoEncoder();
~FFmpegVideoEncoder(); virtual ~FFmpegVideoEncoder();
int Init(); int Init();
int Encode( int Encode(
@@ -57,7 +57,7 @@ class FFmpegVideoEncoder : public VideoEncoder {
const AVCodec* codec_ = nullptr; const AVCodec* codec_ = nullptr;
AVCodecContext* codec_ctx_ = nullptr; AVCodecContext* codec_ctx_ = nullptr;
AVFrame* frame_ = nullptr; AVFrame* frame_ = nullptr;
AVPacket* packet_; AVPacket* packet_ = nullptr;
bool got_output_ = false; bool got_output_ = false;
uint32_t pts_ = 0; uint32_t pts_ = 0;
}; };

View File

@@ -4,16 +4,9 @@
#include "log.h" #include "log.h"
#define SAVE_ENCODER_STREAM 0 #define SAVE_ENCODER_STREAM 1
NvidiaVideoEncoder::NvidiaVideoEncoder() { NvidiaVideoEncoder::NvidiaVideoEncoder() {}
if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
}
NvidiaVideoEncoder::~NvidiaVideoEncoder() { NvidiaVideoEncoder::~NvidiaVideoEncoder() {
if (SAVE_ENCODER_STREAM && file_) { if (SAVE_ENCODER_STREAM && file_) {
fflush(file_); fflush(file_);
@@ -70,6 +63,13 @@ int NvidiaVideoEncoder::Init() {
max_payload_size_; max_payload_size_;
encoder_->CreateEncoder(&init_params); encoder_->CreateEncoder(&init_params);
if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
}
}
return 0; return 0;
} }

View File

@@ -9,7 +9,7 @@
class NvidiaVideoEncoder : public VideoEncoder { class NvidiaVideoEncoder : public VideoEncoder {
public: public:
NvidiaVideoEncoder(); NvidiaVideoEncoder();
~NvidiaVideoEncoder(); virtual ~NvidiaVideoEncoder();
int Init(); int Init();
int Encode( int Encode(

View File

@@ -11,6 +11,9 @@ class VideoEncoder {
on_encoded_image) = 0; on_encoded_image) = 0;
virtual int OnEncodedImage(char* encoded_packets, size_t size) = 0; virtual int OnEncodedImage(char* encoded_packets, size_t size) = 0;
virtual void ForceIdr() = 0; virtual void ForceIdr() = 0;
VideoEncoder() = default;
virtual ~VideoEncoder() {}
}; };
#endif #endif

View File

@@ -7,11 +7,11 @@ VideoEncoderFactory::VideoEncoderFactory() {}
VideoEncoderFactory::~VideoEncoderFactory() {} VideoEncoderFactory::~VideoEncoderFactory() {}
VideoEncoder *VideoEncoderFactory::CreateVideoEncoder( std::unique_ptr<VideoEncoder> VideoEncoderFactory::CreateVideoEncoder(
bool hardware_acceleration) { bool hardware_acceleration) {
if (hardware_acceleration) { if (hardware_acceleration) {
return new NvidiaVideoEncoder(); return std::make_unique<NvidiaVideoEncoder>(NvidiaVideoEncoder());
} else { } else {
return new FFmpegVideoEncoder(); return std::make_unique<FFmpegVideoEncoder>(FFmpegVideoEncoder());
} }
} }

View File

@@ -7,10 +7,8 @@ class VideoEncoderFactory {
VideoEncoderFactory(); VideoEncoderFactory();
~VideoEncoderFactory(); ~VideoEncoderFactory();
static VideoEncoder *CreateVideoEncoder(bool hardware_acceleration); static std::unique_ptr<VideoEncoder> CreateVideoEncoder(
bool hardware_acceleration);
private:
bool hardware_acceleration_ = false;
}; };
#endif #endif

View File

@@ -33,6 +33,9 @@ int PeerConnection::Init(PeerConnectionParams params,
cfg_turn_server_port_ = reader.Get("turn server", "port", "-1"); cfg_turn_server_port_ = reader.Get("turn server", "port", "-1");
cfg_turn_server_username_ = reader.Get("turn server", "username", ""); cfg_turn_server_username_ = reader.Get("turn server", "username", "");
cfg_turn_server_password_ = reader.Get("turn server", "password", ""); cfg_turn_server_password_ = reader.Get("turn server", "password", "");
cfg_hardware_acceleration_ =
reader.Get("hardware acceleration", "turn_on", "false");
std::regex regex("\n"); std::regex regex("\n");
LOG_INFO("Read config success"); LOG_INFO("Read config success");
@@ -52,6 +55,10 @@ int PeerConnection::Init(PeerConnectionParams params,
cfg_turn_server_password_); cfg_turn_server_password_);
} }
hardware_acceleration_ = cfg_hardware_acceleration_ == "true" ? true : false;
LOG_INFO("Hardware accelerated codec [{}]",
hardware_acceleration_ ? "ON" : "OFF");
on_receive_video_buffer_ = params.on_receive_video_buffer; on_receive_video_buffer_ = params.on_receive_video_buffer;
on_receive_audio_buffer_ = params.on_receive_audio_buffer; on_receive_audio_buffer_ = params.on_receive_audio_buffer;
on_receive_data_buffer_ = params.on_receive_data_buffer; on_receive_data_buffer_ = params.on_receive_data_buffer;
@@ -103,13 +110,12 @@ int PeerConnection::Init(PeerConnectionParams params,
} while (SignalStatus::Connected != GetSignalStatus()); } while (SignalStatus::Connected != GetSignalStatus());
video_encoder = video_encoder =
VideoEncoderFactory::CreateVideoEncoder(hardware_accelerated_encode_); VideoEncoderFactory::CreateVideoEncoder(hardware_acceleration_);
video_encoder->Init(); video_encoder->Init();
video_decoder = video_decoder =
VideoDecoderFactory::CreateVideoDecoder(hardware_accelerated_decode_); VideoDecoderFactory::CreateVideoDecoder(hardware_acceleration_);
video_decoder->Init(); 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;

View File

@@ -68,9 +68,11 @@ class PeerConnection {
std::string cfg_turn_server_port_; std::string cfg_turn_server_port_;
std::string cfg_turn_server_username_; std::string cfg_turn_server_username_;
std::string cfg_turn_server_password_; std::string cfg_turn_server_password_;
std::string cfg_hardware_acceleration_;
int signal_server_port_ = 0; int signal_server_port_ = 0;
int stun_server_port_ = 0; int stun_server_port_ = 0;
int turn_server_port_ = 0; int turn_server_port_ = 0;
bool hardware_acceleration_ = false;
private: private:
std::shared_ptr<WsTransmission> ws_transport_ = nullptr; std::shared_ptr<WsTransmission> ws_transport_ = nullptr;
@@ -100,10 +102,10 @@ class PeerConnection {
char *nv12_data_ = nullptr; char *nv12_data_ = nullptr;
private: private:
VideoEncoder *video_encoder = nullptr; std::unique_ptr<VideoEncoder> video_encoder = nullptr;
VideoDecoder *video_decoder = nullptr; std::unique_ptr<VideoDecoder> video_decoder = nullptr;
bool hardware_accelerated_encode_ = true; bool hardware_accelerated_encode_ = false;
bool hardware_accelerated_decode_ = true; bool hardware_accelerated_decode_ = false;
}; };
#endif #endif