Files
SimpleRemoter/client/X264Encoder.cpp
2026-04-19 22:55:21 +02:00

156 lines
3.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "X264Encoder.h"
#include <string.h>
#include <stdio.h>
#ifdef _WIN64
#pragma comment(lib,"libyuv/libyuv_x64.lib")
#pragma comment(lib,"x264/libx264_x64.lib")
#else
#pragma comment(lib,"libyuv/libyuv.lib")
#pragma comment(lib,"x264/libx264.lib")
#endif
CX264Encoder::CX264Encoder()
{
memset(&m_Param, 0, sizeof(m_Param));
m_pCodec = NULL;
m_pPicIn = NULL;
m_pPicOut = NULL;
}
CX264Encoder::~CX264Encoder()
{
close();
}
bool CX264Encoder::open(int width, int height, int fps, int crf)
{
x264_param_t param = { 0 };
x264_param_default_preset(&param, "ultrafast", "zerolatency");
param.i_width = width & 0xfffffffe;
param.i_height = height & 0xfffffffe;
//x264_LOG_NONE
param.i_log_level = X264_LOG_NONE;
param.i_threads = 1;
param.i_frame_total = 0;
param.i_keyint_max = fps * 15; // 15秒一个IDR场景突变由scenecut自动插入
param.i_bframe = 0; //不启用b帧
param.b_open_gop = 0;
param.i_fps_num = fps;
param.i_csp = X264_CSP_I420;
// CRF: 静态画面自动降至极低码率,动态画面按质量需要分配
// 不设 VBV —— 避免 IDR/复杂帧后的质量振荡
param.rc.i_rc_method = X264_RC_CRF;
param.rc.f_rf_constant = (float)crf;
//设置profile.
if (x264_param_apply_profile(&param, x264_profile_names[0])) {
return false;
}
return open(&param);
}
bool CX264Encoder::open(x264_param_t * param)
{
m_pPicIn = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
m_pPicOut = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
//input pic.
x264_picture_init(m_pPicIn);
x264_picture_alloc(
m_pPicIn,
X264_CSP_I420,
param->i_width,
param->i_height);
//create codec instance.
m_pCodec = x264_encoder_open(param);
if (m_pCodec == NULL) {
return false;
}
memcpy(&m_Param, param, sizeof(m_Param));
return true;
}
void CX264Encoder::close()
{
if (m_pCodec) {
x264_encoder_close(m_pCodec);
m_pCodec = NULL;
}
if (m_pPicIn) {
x264_picture_clean(m_pPicIn);
free(m_pPicIn);
m_pPicIn = NULL;
}
if (m_pPicOut) {
free(m_pPicOut);
m_pPicOut = NULL;
}
}
int CX264Encoder::encode(
uint8_t * rgb,
uint8_t bpp,
uint32_t stride,
uint32_t width,
uint32_t height,
uint8_t ** lppData,
uint32_t * lpSize,
int direction)
{
int encode_size = 0;
x264_nal_t *pNal = NULL;
int iNal;
if ((width & 0xfffffffe) != m_Param.i_width ||
(height & 0xfffffffe) != m_Param.i_height) {
return -1;
}
switch (bpp) {
case 24:
libyuv::RGB24ToI420((uint8_t*)rgb, stride,
m_pPicIn->img.plane[0], m_pPicIn->img.i_stride[0],
m_pPicIn->img.plane[1], m_pPicIn->img.i_stride[1],
m_pPicIn->img.plane[2], m_pPicIn->img.i_stride[2],
m_Param.i_width, direction * m_Param.i_height);
break;
case 32:
libyuv::ARGBToI420((uint8_t*)rgb, stride,
m_pPicIn->img.plane[0], m_pPicIn->img.i_stride[0],
m_pPicIn->img.plane[1], m_pPicIn->img.i_stride[1],
m_pPicIn->img.plane[2], m_pPicIn->img.i_stride[2],
m_Param.i_width, direction * m_Param.i_height);
break;
default:
return -2;
}
encode_size = x264_encoder_encode(
m_pCodec,
&pNal,
&iNal,
m_pPicIn,
m_pPicOut);
if (encode_size < 0) {
return -3;
}
*lppData = pNal->p_payload;
*lpSize = encode_size;
return 0;
}