1.Use libyuv instead of ffmpeg to do nv12<->yuv420p convertion;2.Use local package to build libyuv(branch stable 2021.4.28 commit eb6e7bb63738e29efd82ea3cf2a115238a89fa51)

This commit is contained in:
dijunkun
2024-05-08 16:34:53 +08:00
parent e0d2ab5a9f
commit 6bc8aaabdc
126 changed files with 98754 additions and 241 deletions

View File

@@ -2,37 +2,10 @@
#include "log.h"
#define SAVE_DECODER_STREAM 0
#define SAVE_RECEIVED_AV1_STREAM 0
#define SAVE_DECODED_NV12_STREAM 0
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
};
static int YUV420PToNV12FFmpeg(unsigned char *src_buffer, int width, int height,
unsigned char *dst_buffer) {
AVFrame *Input_pFrame = av_frame_alloc();
AVFrame *Output_pFrame = av_frame_alloc();
struct SwsContext *img_convert_ctx = sws_getContext(
width, height, AV_PIX_FMT_YUV420P, 1280, 720, AV_PIX_FMT_NV12,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer,
AV_PIX_FMT_YUV420P, width, height, 1);
av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, dst_buffer,
AV_PIX_FMT_NV12, 1280, 720, 1);
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, height, Output_pFrame->data,
Output_pFrame->linesize);
if (Input_pFrame) av_free(Input_pFrame);
if (Output_pFrame) av_free(Output_pFrame);
if (img_convert_ctx) sws_freeContext(img_convert_ctx);
return 0;
}
#include "libyuv.h"
class ScopedDav1dPicture : public std::shared_ptr<ScopedDav1dPicture> {
public:
@@ -60,10 +33,16 @@ void NullFreeCallback(const uint8_t *buffer, void *opaque) {}
Dav1dAv1Decoder::Dav1dAv1Decoder() {}
Dav1dAv1Decoder::~Dav1dAv1Decoder() {
if (SAVE_DECODER_STREAM && file_) {
fflush(file_);
fclose(file_);
file_ = nullptr;
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 (decoded_frame_yuv_) {
@@ -94,12 +73,20 @@ int Dav1dAv1Decoder::Init() {
decoded_frame_yuv_ = new VideoFrame(1280 * 720 * 3 / 2);
decoded_frame_nv12_ = new VideoFrame(1280 * 720 * 3 / 2);
if (SAVE_DECODER_STREAM) {
file_ = fopen("decode_stream.ivf", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.ivf");
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;
}
@@ -117,9 +104,10 @@ void YUV420PtoNV12(unsigned char *SrcY, unsigned char *SrcU,
int Dav1dAv1Decoder::Decode(
const uint8_t *data, int size,
std::function<void(VideoFrame)> on_receive_decoded_frame) {
// if (SAVE_DECODER_STREAM) {
// fwrite((unsigned char *)data, 1, size, file_);
// }
if (SAVE_RECEIVED_AV1_STREAM) {
fwrite((unsigned char *)data, 1, size, file_av1_);
}
ScopedDav1dData scoped_dav1d_data;
Dav1dData &dav1d_data = scoped_dav1d_data.Data();
dav1d_data_wrap(&dav1d_data, data, size,
@@ -149,44 +137,28 @@ int Dav1dAv1Decoder::Decode(
return -1;
}
uint32_t start_ts = static_cast<uint32_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count());
if (1) {
if (0) {
YUV420PtoNV12((unsigned char *)dav1d_picture.data[0],
(unsigned char *)dav1d_picture.data[1],
(unsigned char *)dav1d_picture.data[2],
decoded_frame_nv12_->GetBuffer(), dav1d_picture.p.w,
dav1d_picture.p.h);
} else {
memcpy(decoded_frame_yuv_->GetBuffer(), dav1d_picture.data[0],
dav1d_picture.p.w * dav1d_picture.p.h);
memcpy(
decoded_frame_yuv_->GetBuffer() + dav1d_picture.p.w * dav1d_picture.p.h,
dav1d_picture.data[1], dav1d_picture.p.w * dav1d_picture.p.h / 4);
memcpy(decoded_frame_yuv_->GetBuffer() +
dav1d_picture.p.w * dav1d_picture.p.h * 5 / 4,
dav1d_picture.data[2], dav1d_picture.p.w * dav1d_picture.p.h / 4);
YUV420PToNV12FFmpeg(decoded_frame_yuv_->GetBuffer(), dav1d_picture.p.w,
dav1d_picture.p.h, decoded_frame_nv12_->GetBuffer());
libyuv::I420ToNV12(
(const uint8_t *)dav1d_picture.data[0], dav1d_picture.p.w,
(const uint8_t *)dav1d_picture.data[1], dav1d_picture.p.w / 2,
(const uint8_t *)dav1d_picture.data[2], dav1d_picture.p.w / 2,
decoded_frame_nv12_->GetBuffer(), dav1d_picture.p.w,
decoded_frame_nv12_->GetBuffer() +
dav1d_picture.p.w * dav1d_picture.p.h,
dav1d_picture.p.w, dav1d_picture.p.w, dav1d_picture.p.h);
}
uint32_t end_ts = static_cast<uint32_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count());
LOG_ERROR("decode time = {}", end_ts - start_ts);
on_receive_decoded_frame(*decoded_frame_nv12_);
// if (SAVE_DECODER_STREAM) {
// fwrite((unsigned char *)decoded_frame_->Buffer(), 1,
// decoded_frame_->Size(),
// file_);
// }
if (SAVE_DECODED_NV12_STREAM) {
fwrite((unsigned char *)decoded_frame_nv12_->Buffer(), 1,
decoded_frame_nv12_->Size(), file_nv12_);
}
return 0;
}

View File

@@ -49,7 +49,9 @@ class Dav1dAv1Decoder : public VideoDecoder {
VideoFrame *decoded_frame_yuv_ = nullptr;
VideoFrame *decoded_frame_nv12_ = nullptr;
FILE *file_ = nullptr;
FILE *file_av1_ = nullptr;
FILE *file_nv12_ = nullptr;
bool first_ = false;
// dav1d

View File

@@ -2,7 +2,8 @@
#include "log.h"
#define SAVE_DECODER_STREAM 0
#define SAVE_RECEIVED_H264_STREAM 0
#define SAVE_DECODED_NV12_STREAM 0
extern "C" {
#include <libavformat/avformat.h>
@@ -13,10 +14,16 @@ extern "C" {
FfmpegVideoDecoder::FfmpegVideoDecoder() {}
FfmpegVideoDecoder::~FfmpegVideoDecoder() {
if (SAVE_DECODER_STREAM && file_) {
fflush(file_);
fclose(file_);
file_ = nullptr;
if (SAVE_RECEIVED_H264_STREAM && file_h264_) {
fflush(file_h264_);
fclose(file_h264_);
file_h264_ = nullptr;
}
if (SAVE_DECODED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (decoded_frame_) {
@@ -89,10 +96,17 @@ int FfmpegVideoDecoder::Init() {
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");
if (SAVE_RECEIVED_H264_STREAM) {
file_h264_ = fopen("received_h264_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open received_h264_stream.h264");
}
}
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;
@@ -109,6 +123,10 @@ int FfmpegVideoDecoder::Decode(
}
}
if (SAVE_RECEIVED_H264_STREAM) {
fwrite((unsigned char *)data, 1, size, file_h264_);
}
packet_->data = (uint8_t *)data;
packet_->size = size;
@@ -152,9 +170,9 @@ int FfmpegVideoDecoder::Decode(
// LOG_ERROR("cost {}", now_ts - start_ts);
on_receive_decoded_frame(*decoded_frame_);
if (SAVE_DECODER_STREAM) {
if (SAVE_DECODED_NV12_STREAM) {
fwrite((unsigned char *)decoded_frame_->Buffer(), 1,
decoded_frame_->Size(), file_);
decoded_frame_->Size(), file_nv12_);
}
}
}

View File

@@ -40,7 +40,8 @@ class FfmpegVideoDecoder : public VideoDecoder {
VideoFrame *decoded_frame_ = nullptr;
FILE *file_ = nullptr;
FILE *file_h264_ = nullptr;
FILE *file_nv12_ = nullptr;
bool first_ = false;
};

View File

@@ -2,14 +2,21 @@
#include "log.h"
#define SAVE_DECODER_STREAM 0
#define SAVE_RECEIVED_H264_STREAM 0
#define SAVE_DECODED_NV12_STREAM 0
NvidiaVideoDecoder::NvidiaVideoDecoder() {}
NvidiaVideoDecoder::~NvidiaVideoDecoder() {
if (SAVE_DECODER_STREAM && file_) {
fflush(file_);
fclose(file_);
file_ = nullptr;
if (SAVE_RECEIVED_H264_STREAM && file_h264_) {
fflush(file_h264_);
fclose(file_h264_);
file_h264_ = nullptr;
}
if (SAVE_DECODED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
}
@@ -34,12 +41,20 @@ int NvidiaVideoDecoder::Init() {
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");
if (SAVE_RECEIVED_H264_STREAM) {
file_h264_ = fopen("received_h264_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open received_h264_stream.h264");
}
}
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;
}
@@ -50,8 +65,8 @@ int NvidiaVideoDecoder::Decode(
return -1;
}
if (SAVE_DECODER_STREAM) {
fwrite((unsigned char *)data, 1, size, file_);
if (SAVE_RECEIVED_H264_STREAM) {
fwrite((unsigned char *)data, 1, size, file_h264_);
}
if ((*(data + 4) & 0x1f) == 0x07) {
@@ -71,6 +86,10 @@ int NvidiaVideoDecoder::Decode(
data, decoder->GetWidth() * decoder->GetHeight() * 3 / 2,
decoder->GetWidth(), decoder->GetHeight());
on_receive_decoded_frame(decoded_frame);
if (SAVE_DECODED_NV12_STREAM) {
fwrite((unsigned char *)decoded_frame.Buffer(), 1,
decoded_frame.Size(), file_nv12_);
}
}
}
}

View File

@@ -20,7 +20,9 @@ class NvidiaVideoDecoder : public VideoDecoder {
NvDecoder* decoder = nullptr;
bool get_first_keyframe_ = false;
bool skip_frame_ = false;
FILE* file_ = nullptr;
FILE* file_h264_ = nullptr;
FILE* file_nv12_ = nullptr;
};
#endif

View File

@@ -5,23 +5,8 @@
#include "log.h"
#ifdef __cplusplus
extern "C" {
#endif
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
};
#ifdef __cplusplus
};
#endif
#define SAVE_NV12_STREAM 0
#define SAVE_H264_STREAM 1
#define SAVE_RECEIVED_NV12_STREAM 0
#define SAVE_ENCODED_AV1_STREAM 0
#define YUV420P_BUFFER_SIZE 1280 * 720 * 3 / 2
static unsigned char yuv420p_buffer[YUV420P_BUFFER_SIZE];
@@ -45,30 +30,6 @@ constexpr double kMinimumFrameRate = 1.0;
constexpr uint8_t kObuSizePresentBit = 0b0'0000'010;
static int NV12ToYUV420PFFmpeg(unsigned char *src_buffer, int width, int height,
unsigned char *dst_buffer) {
AVFrame *Input_pFrame = av_frame_alloc();
AVFrame *Output_pFrame = av_frame_alloc();
struct SwsContext *img_convert_ctx = sws_getContext(
width, height, AV_PIX_FMT_NV12, 1280, 720, AV_PIX_FMT_YUV420P,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer,
AV_PIX_FMT_NV12, width, height, 1);
av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, dst_buffer,
AV_PIX_FMT_YUV420P, 1280, 720, 1);
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, height, Output_pFrame->data,
Output_pFrame->linesize);
if (Input_pFrame) av_free(Input_pFrame);
if (Output_pFrame) av_free(Output_pFrame);
if (img_convert_ctx) sws_freeContext(img_convert_ctx);
return 0;
}
static aom_superblock_size_t GetSuperblockSize(int width, int height,
int threads) {
int resolution = width * height;
@@ -127,16 +88,16 @@ int AomAv1Encoder::GetCpuSpeed(int width, int height) {
AomAv1Encoder::AomAv1Encoder() {}
AomAv1Encoder::~AomAv1Encoder() {
if (SAVE_NV12_STREAM && file_nv12_) {
if (SAVE_RECEIVED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (SAVE_H264_STREAM && file_ivf_) {
fflush(file_ivf_);
fclose(file_ivf_);
file_ivf_ = nullptr;
if (SAVE_ENCODED_AV1_STREAM && file_av1_) {
fflush(file_av1_);
fclose(file_av1_);
file_av1_ = nullptr;
}
delete encoded_frame_;
@@ -272,17 +233,17 @@ int AomAv1Encoder::Init() {
frame_for_encode_ = aom_img_wrap(nullptr, AOM_IMG_FMT_NV12, frame_width_,
frame_height_, 1, nullptr);
if (SAVE_H264_STREAM) {
file_ivf_ = fopen("encoded_stream.ivf", "w+b");
if (!file_ivf_) {
LOG_ERROR("Fail to open encoded_stream.ivf");
if (SAVE_RECEIVED_NV12_STREAM) {
file_nv12_ = fopen("received_nv12_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_ERROR("Fail to open received_nv12_stream.yuv");
}
}
if (SAVE_NV12_STREAM) {
file_nv12_ = fopen("raw_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_ERROR("Fail to open raw_stream.yuv");
if (SAVE_ENCODED_AV1_STREAM) {
file_av1_ = fopen("encoded_av1_stream.ivf", "w+b");
if (!file_av1_) {
LOG_ERROR("Fail to open encoded_av1_stream.ivf");
}
}
@@ -293,7 +254,7 @@ int AomAv1Encoder::Encode(const uint8_t *pData, int nSize,
std::function<int(char *encoded_packets, size_t size,
VideoFrameType frame_type)>
on_encoded_image) {
if (SAVE_NV12_STREAM) {
if (SAVE_RECEIVED_NV12_STREAM) {
fwrite(pData, 1, nSize, file_nv12_);
}
@@ -309,9 +270,6 @@ int AomAv1Encoder::Encode(const uint8_t *pData, int nSize,
frame_for_encode_->stride[AOM_PLANE_U] = frame_width_;
frame_for_encode_->stride[AOM_PLANE_V] = 0;
// NV12ToYUV420PFFmpeg((unsigned char *)pData, frame_width_, frame_height_,
// (unsigned char *)yuv420p_buffer);
VideoFrameType frame_type;
if (0 == seq_++ % 300) {
force_i_frame_flags_ = AOM_EFLAG_FORCE_KF;
@@ -347,8 +305,8 @@ int AomAv1Encoder::Encode(const uint8_t *pData, int nSize,
if (on_encoded_image) {
on_encoded_image((char *)encoded_frame_, encoded_frame_size_,
frame_type);
if (SAVE_H264_STREAM) {
fwrite(encoded_frame_, 1, encoded_frame_size_, file_ivf_);
if (SAVE_ENCODED_AV1_STREAM) {
fwrite(encoded_frame_, 1, encoded_frame_size_, file_av1_);
}
} else {
OnEncodedImage((char *)encoded_frame_, encoded_frame_size_);

View File

@@ -65,7 +65,7 @@ class AomAv1Encoder : public VideoEncoder {
std::vector<std::vector<uint8_t>> encoded_packets_;
unsigned char* encoded_image_ = nullptr;
FILE* file_ivf_ = nullptr;
FILE* file_av1_ = nullptr;
FILE* file_nv12_ = nullptr;
unsigned char* nv12_data_ = nullptr;
unsigned int seq_ = 0;

View File

@@ -4,8 +4,8 @@
#include "log.h"
#define SAVE_NV12_STREAM 0
#define SAVE_H264_STREAM 0
#define SAVE_RECEIVED_NV12_STREAM 0
#define SAVE_ENCODED_H264_STREAM 0
#define YUV420P_BUFFER_SIZE 1280 * 720 * 3 / 2
static unsigned char yuv420p_buffer[YUV420P_BUFFER_SIZE];
@@ -36,13 +36,13 @@ static int NV12ToYUV420PFFmpeg(unsigned char *src_buffer, int width, int height,
FFmpegVideoEncoder::FFmpegVideoEncoder() {}
FFmpegVideoEncoder::~FFmpegVideoEncoder() {
if (SAVE_NV12_STREAM && file_nv12_) {
if (SAVE_RECEIVED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (SAVE_H264_STREAM && file_h264_) {
if (SAVE_ENCODED_H264_STREAM && file_h264_) {
fflush(file_h264_);
fclose(file_h264_);
file_h264_ = nullptr;
@@ -130,17 +130,17 @@ int FFmpegVideoEncoder::Init() {
packet_ = av_packet_alloc();
if (SAVE_H264_STREAM) {
file_h264_ = fopen("encoded_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open encoded_stream.h264");
if (SAVE_RECEIVED_NV12_STREAM) {
file_nv12_ = fopen("received_nv12_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open received_nv12_stream.yuv");
}
}
if (SAVE_NV12_STREAM) {
file_nv12_ = fopen("raw_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open raw_stream.yuv");
if (SAVE_ENCODED_H264_STREAM) {
file_h264_ = fopen("encoded_h264_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open encoded_h264_stream.h264");
}
}
@@ -165,7 +165,7 @@ int FFmpegVideoEncoder::Encode(
frame_->data[1] = yuv420p_buffer + frame_->width * frame_->height;
frame_->data[2] = yuv420p_buffer + frame_->width * frame_->height * 5 / 4;
if (SAVE_NV12_STREAM) {
if (SAVE_RECEIVED_NV12_STREAM) {
fwrite(yuv420p_buffer, 1, nSize, file_nv12_);
}
} else {
@@ -173,7 +173,7 @@ int FFmpegVideoEncoder::Encode(
memcpy(frame_->data[1], pData + frame_->width * frame_->height,
frame_->width * frame_->height / 2);
if (SAVE_NV12_STREAM) {
if (SAVE_RECEIVED_NV12_STREAM) {
fwrite(pData, 1, nSize, file_nv12_);
}
}
@@ -208,7 +208,7 @@ int FFmpegVideoEncoder::Encode(
if (on_encoded_image) {
on_encoded_image((char *)packet_->data, packet_->size, frame_type);
if (SAVE_H264_STREAM) {
if (SAVE_ENCODED_H264_STREAM) {
fwrite(packet_->data, 1, packet_->size, file_h264_);
}
} else {

View File

@@ -4,14 +4,21 @@
#include "log.h"
#define SAVE_ENCODER_STREAM 0
#define SAVE_RECEIVED_NV12_STREAM 0
#define SAVE_ENCODED_H264_STREAM 0
NvidiaVideoEncoder::NvidiaVideoEncoder() {}
NvidiaVideoEncoder::~NvidiaVideoEncoder() {
if (SAVE_ENCODER_STREAM && file_) {
fflush(file_);
fclose(file_);
file_ = nullptr;
if (SAVE_RECEIVED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (SAVE_ENCODED_H264_STREAM && file_h264_) {
fflush(file_h264_);
fclose(file_h264_);
file_h264_ = nullptr;
}
if (nv12_data_) {
@@ -67,12 +74,20 @@ int NvidiaVideoEncoder::Init() {
encoder_->CreateEncoder(&init_params);
if (SAVE_ENCODER_STREAM) {
file_ = fopen("encode_stream.h264", "w+b");
if (!file_) {
LOG_WARN("Fail to open stream.h264");
if (SAVE_RECEIVED_NV12_STREAM) {
file_nv12_ = fopen("received_nv12_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open received_nv12_stream.yuv");
}
}
if (SAVE_ENCODED_H264_STREAM) {
file_h264_ = fopen("encoded_h264_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open encoded_h264_stream.h264");
}
}
return 0;
}
@@ -86,6 +101,10 @@ int NvidiaVideoEncoder::Encode(
return -1;
}
if (SAVE_RECEIVED_NV12_STREAM) {
fwrite(pData, 1, nSize, file_nv12_);
}
VideoFrameType frame_type;
if (0 == seq_++ % 300) {
ForceIdr();
@@ -117,16 +136,12 @@ int NvidiaVideoEncoder::Encode(
for (const auto &packet : encoded_packets_) {
if (on_encoded_image) {
on_encoded_image((char *)packet.data(), packet.size(), frame_type);
if (SAVE_ENCODER_STREAM) {
fwrite(packet.data(), 1, packet.size(), file_);
if (SAVE_ENCODED_H264_STREAM) {
fwrite((unsigned char *)packet.data(), 1, packet.size(), file_h264_);
}
} else {
OnEncodedImage((char *)packet.data(), packet.size());
}
if (SAVE_ENCODER_STREAM) {
fwrite((unsigned char *)packet.data(), 1, packet.size(), file_);
}
}
#ifdef SHOW_SUBMODULE_TIME_COST

View File

@@ -36,7 +36,8 @@ class NvidiaVideoEncoder : public VideoEncoder {
CUcontext cuda_context_ = nullptr;
std::vector<std::vector<uint8_t>> encoded_packets_;
unsigned char* encoded_image_ = nullptr;
FILE* file_ = nullptr;
FILE* file_nv12_ = nullptr;
FILE* file_h264_ = nullptr;
unsigned char* nv12_data_ = nullptr;
unsigned int seq_ = 0;
};

View File

@@ -2,63 +2,57 @@
#include <chrono>
#include "libyuv.h"
#include "log.h"
#ifdef __cplusplus
extern "C" {
#endif
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
};
#ifdef __cplusplus
};
#endif
#define SAVE_NV12_STREAM 0
#define SAVE_H264_STREAM 0
#define SAVE_RECEIVED_NV12_STREAM 0
#define SAVE_ENCODED_H264_STREAM 0
#define YUV420P_BUFFER_SIZE 1280 * 720 * 3 / 2
static unsigned char yuv420p_buffer[YUV420P_BUFFER_SIZE];
static int NV12ToYUV420PFFmpeg(unsigned char *src_buffer, int width, int height,
unsigned char *dst_buffer) {
AVFrame *Input_pFrame = av_frame_alloc();
AVFrame *Output_pFrame = av_frame_alloc();
struct SwsContext *img_convert_ctx = sws_getContext(
width, height, AV_PIX_FMT_NV12, 1280, 720, AV_PIX_FMT_YUV420P,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
void nv12ToI420(unsigned char *Src_data, int src_width, int src_height,
unsigned char *Dst_data) {
// NV12 video size
int NV12_Size = src_width * src_height * 3 / 2;
int NV12_Y_Size = src_width * src_height;
av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer,
AV_PIX_FMT_NV12, width, height, 1);
av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, dst_buffer,
AV_PIX_FMT_YUV420P, 1280, 720, 1);
// YUV420 video size
int I420_Size = src_width * src_height * 3 / 2;
int I420_Y_Size = src_width * src_height;
int I420_U_Size = (src_width >> 1) * (src_height >> 1);
int I420_V_Size = I420_U_Size;
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, height, Output_pFrame->data,
Output_pFrame->linesize);
// src: buffer address of Y channel and UV channel
unsigned char *Y_data_Src = Src_data;
unsigned char *UV_data_Src = Src_data + NV12_Y_Size;
int src_stride_y = src_width;
int src_stride_uv = src_width;
if (Input_pFrame) av_free(Input_pFrame);
if (Output_pFrame) av_free(Output_pFrame);
if (img_convert_ctx) sws_freeContext(img_convert_ctx);
// dst: buffer address of Y channel<65><6C>U channel and V channel
unsigned char *Y_data_Dst = Dst_data;
unsigned char *U_data_Dst = Dst_data + I420_Y_Size;
unsigned char *V_data_Dst = Dst_data + I420_Y_Size + I420_U_Size;
int Dst_Stride_Y = src_width;
int Dst_Stride_U = src_width >> 1;
int Dst_Stride_V = Dst_Stride_U;
return 0;
libyuv::NV12ToI420(
(const uint8_t *)Y_data_Src, src_stride_y, (const uint8_t *)UV_data_Src,
src_stride_uv, (uint8_t *)Y_data_Dst, Dst_Stride_Y, (uint8_t *)U_data_Dst,
Dst_Stride_U, (uint8_t *)V_data_Dst, Dst_Stride_V, src_width, src_height);
}
OpenH264Encoder::OpenH264Encoder() {}
OpenH264Encoder::~OpenH264Encoder() {
if (SAVE_NV12_STREAM && file_nv12_) {
if (SAVE_RECEIVED_NV12_STREAM && file_nv12_) {
fflush(file_nv12_);
fclose(file_nv12_);
file_nv12_ = nullptr;
}
if (SAVE_H264_STREAM && file_h264_) {
if (SAVE_ENCODED_H264_STREAM && file_h264_) {
fflush(file_h264_);
fclose(file_h264_);
file_h264_ = nullptr;
@@ -137,17 +131,17 @@ int OpenH264Encoder::Init() {
int video_format = EVideoFormatType::videoFormatI420;
openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, &video_format);
if (SAVE_H264_STREAM) {
file_h264_ = fopen("encoded_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open encoded_stream.h264");
if (SAVE_RECEIVED_NV12_STREAM) {
file_nv12_ = fopen("received_nv12_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open received_nv12_stream.yuv");
}
}
if (SAVE_NV12_STREAM) {
file_nv12_ = fopen("raw_stream.yuv", "w+b");
if (!file_nv12_) {
LOG_WARN("Fail to open raw_stream.yuv");
if (SAVE_ENCODED_H264_STREAM) {
file_h264_ = fopen("encoded_h264_stream.h264", "w+b");
if (!file_h264_) {
LOG_WARN("Fail to open encoded_h264_stream.h264");
}
}
@@ -163,8 +157,8 @@ int OpenH264Encoder::Encode(
return -1;
}
if (SAVE_NV12_STREAM) {
fwrite(yuv420p_buffer, 1, nSize, file_nv12_);
if (SAVE_RECEIVED_NV12_STREAM) {
fwrite(pData, 1, nSize, file_nv12_);
}
VideoFrameType frame_type;
@@ -175,8 +169,8 @@ int OpenH264Encoder::Encode(
frame_type = VideoFrameType::kVideoFrameDelta;
}
NV12ToYUV420PFFmpeg((unsigned char *)pData, frame_width_, frame_height_,
(unsigned char *)yuv420p_buffer);
nv12ToI420((unsigned char *)pData, frame_width_, frame_height_,
yuv420p_buffer);
raw_frame_ = {0};
raw_frame_.iPicWidth = frame_width_;
@@ -229,7 +223,7 @@ int OpenH264Encoder::Encode(
if (on_encoded_image) {
on_encoded_image((char *)encoded_frame_, encoded_frame_size_, frame_type);
if (SAVE_H264_STREAM) {
if (SAVE_ENCODED_H264_STREAM) {
fwrite(encoded_frame_, 1, encoded_frame_size_, file_h264_);
}
} else {
@@ -275,7 +269,7 @@ int OpenH264Encoder::Encode(
if (on_encoded_image) {
on_encoded_image((char *)encoded_frame_, frame_type);
if (SAVE_H264_STREAM) {
if (SAVE_ENCODED_H264_STREAM) {
fwrite(encoded_frame_, 1, encoded_frame_size_, file_h264_);
}
} else {