Feature: Implement H.264 and AV1 hardware encoding for remote control
Remark: Need to update FFmpeg static libraries to take effort
This commit is contained in:
@@ -13,8 +13,11 @@
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <emmintrin.h> // SSE2
|
||||
#include "X264Encoder.h"
|
||||
#include "common/config.h"
|
||||
#include "VideoEncoderBase.h"
|
||||
#include "EncoderFactory.h"
|
||||
#include "ScrollDetector.h"
|
||||
#include "common/file_upload.h"
|
||||
|
||||
@@ -126,6 +129,7 @@ public:
|
||||
ULONG* m_BlockSizes; // 分块差异像素数
|
||||
int m_BlockNum; // 分块个数
|
||||
int m_SendQuality; // 发送质量
|
||||
int m_EncodeLevel; // 编码级别
|
||||
|
||||
LPBITMAPINFO m_BitmapInfor_Full; // BMP信息
|
||||
LPBITMAPINFO m_BitmapInfor_Send; // 发送的BMP信息
|
||||
@@ -145,7 +149,7 @@ public:
|
||||
int m_FrameID; // 帧序号
|
||||
int m_GOP; // 关键帧间隔
|
||||
bool m_SendKeyFrame; // 发送关键帧
|
||||
CX264Encoder *m_encoder; // 编码器
|
||||
std::unique_ptr<VideoEncoderBase> m_encoder; // 编码器,ensureEncoder() lazy 创建,走 EncoderFactory 探测
|
||||
int m_nScreenCount; // 屏幕数量
|
||||
BOOL m_bEnableMultiScreen;// 多显示器支持
|
||||
|
||||
@@ -182,14 +186,14 @@ protected:
|
||||
int m_nVScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
|
||||
public:
|
||||
ScreenCapture(int n = 32, BYTE algo = ALGORITHM_DIFF, BOOL all = FALSE) :
|
||||
ScreenCapture(int n = 32, BYTE algo = ALGORITHM_DIFF, BOOL all = FALSE, int level = LEVEL_H264_SOFT) :
|
||||
m_ThreadPool(nullptr), m_FirstBuffer(nullptr), m_RectBuffer(nullptr),
|
||||
m_BitmapInfor_Full(nullptr), m_bAlgorithm(algo), m_SendQuality(100),
|
||||
m_ulFullWidth(0), m_ulFullHeight(0), m_bZoomed(false), m_wZoom(1), m_hZoom(1),
|
||||
m_FrameID(0), m_GOP(DEFAULT_GOP), m_iScreenX(0), m_iScreenY(0), m_biBitCount(n),
|
||||
m_SendKeyFrame(false), m_encoder(nullptr),
|
||||
m_pScrollDetector(nullptr), m_bEnableScrollDetect(false), m_bServerSupportsScroll(false),
|
||||
m_bLastFrameWasScroll(false), m_nScrollDetectInterval(1)
|
||||
m_bLastFrameWasScroll(false), m_nScrollDetectInterval(1), m_EncodeLevel(level)
|
||||
{
|
||||
SetAlgorithm(algo);
|
||||
m_BitmapInfor_Send = nullptr;
|
||||
@@ -256,7 +260,6 @@ public:
|
||||
SAFE_DELETE_ARRAY(m_BlockSizes);
|
||||
|
||||
SAFE_DELETE(m_ThreadPool);
|
||||
SAFE_DELETE(m_encoder);
|
||||
SAFE_DELETE(m_pScrollDetector);
|
||||
}
|
||||
|
||||
@@ -839,6 +842,19 @@ public:
|
||||
return bmpInfo;
|
||||
}
|
||||
|
||||
// 编码器 lazy 创建。委托 EncoderFactory 完成"硬编探测 + 软编 fallback"。
|
||||
void ensureEncoder(int width, int height)
|
||||
{
|
||||
if (m_encoder) return;
|
||||
EncoderRequest req;
|
||||
req.width = width;
|
||||
req.height = height;
|
||||
req.fps = 20;
|
||||
req.bitrate_kbps = (m_nBitRate > 0) ? m_nBitRate : (width * height / 1266);
|
||||
req.encodeLevel = m_EncodeLevel;
|
||||
m_encoder = CreateEncoder(req);
|
||||
}
|
||||
|
||||
// 算法+光标位置+光标类型
|
||||
virtual LPBYTE GetNextScreenData(ULONG* ulNextSendLength)
|
||||
{
|
||||
@@ -923,13 +939,12 @@ public:
|
||||
uint8_t* encoded_data = nullptr;
|
||||
uint32_t encoded_size = 0;
|
||||
int width = m_BitmapInfor_Send->bmiHeader.biWidth, height = m_BitmapInfor_Send->bmiHeader.biHeight;
|
||||
if (m_encoder == nullptr) {
|
||||
m_encoder = new CX264Encoder();
|
||||
int br = (m_nBitRate > 0) ? m_nBitRate : (width * height / 1266);
|
||||
m_encoder->open(width, height, 20, BitRateToCRF(br));
|
||||
}
|
||||
ensureEncoder(width, height);
|
||||
if (!m_encoder) return nullptr;
|
||||
m_encoder->forceIDR(); // 协议层 keyframe → 编码器强制 IDR,与 TOKEN_KEYFRAME 语义对齐
|
||||
int err = m_encoder->encode(nextData, 32, 4 * width, width, height, &encoded_data, &encoded_size);
|
||||
if (err) {
|
||||
// encoded_size == 0:硬编首帧延迟(avcodec_receive_packet 返回 EAGAIN),本帧无码流,按失败跳过
|
||||
if (err || encoded_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
*ulNextSendLength = 1 + offset + encoded_size;
|
||||
@@ -953,13 +968,11 @@ public:
|
||||
uint8_t* encoded_data = nullptr;
|
||||
uint32_t encoded_size = 0;
|
||||
int width = m_BitmapInfor_Send->bmiHeader.biWidth, height = m_BitmapInfor_Send->bmiHeader.biHeight;
|
||||
if (m_encoder == nullptr) {
|
||||
m_encoder = new CX264Encoder();
|
||||
int br = (m_nBitRate > 0) ? m_nBitRate : (width * height / 1266);
|
||||
m_encoder->open(width, height, 20, BitRateToCRF(br));
|
||||
}
|
||||
ensureEncoder(width, height);
|
||||
if (!m_encoder) return nullptr;
|
||||
int err = m_encoder->encode(nextData, 32, 4 * width, width, height, &encoded_data, &encoded_size);
|
||||
if (err) {
|
||||
// encoded_size == 0:硬编首帧延迟,本帧无码流,按失败跳过
|
||||
if (err || encoded_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
*ulNextSendLength = 1 + offset + encoded_size;
|
||||
|
||||
Reference in New Issue
Block a user