obs中使用libx264编码的例子,包含了动态设置码率。

#include "Main.h"#include <inttypes.h>
#include <ws2tcpip.h>extern "C"
{
#include "../x264/x264.h"
}void get_x264_log(void *param, int i_level, const char *psz, va_list argptr)
{String chi(psz);chi.FindReplace(TEXT("%s"), TEXT("%S"));OSDebugOutva(chi, argptr);Logva(chi, argptr);
}struct VideoPacket
{List<BYTE> Packet;inline void FreeData() {Packet.Clear();}
};const float baseCRF = 20.0f;class X264Encoder : public VideoEncoder
{x264_param_t paramData;x264_t *x264;x264_picture_t picOut;int cur_pts_time;x264_nal_t *pp_nal;int pi_nal;int fps_ms;UINT width, height;String curPreset;bool bFirstFrameProcessed;bool bUseCBR;List<VideoPacket> CurrentPackets;List<BYTE> HeaderPacket;int delayOffset;inline void ClearPackets(){for(UINT i=0; i<CurrentPackets.Num(); i++)CurrentPackets[i].FreeData();CurrentPackets.Clear();}public:X264Encoder(int fps, int width, int height, int quality, CTSTR preset, bool bUse444, int maxBitRate, int bufferSize){fps_ms = 1000/fps;zero(¶mData, sizeof(paramData));curPreset = preset;LPSTR lpPreset = curPreset.CreateUTF8String();x264_param_default_preset(¶mData, lpPreset, NULL);Free(lpPreset);this->width  = width;this->height = height;//warning: messing with x264 settings without knowing what they do can seriously screw things up//ratetol//qcomp//paramData.i_frame_reference     = 1; //ref=1//paramData.i_threads             = 4;bUseCBR = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCBR")) != 0;if(bUseCBR){paramData.rc.i_bitrate          = maxBitRate;paramData.rc.i_vbv_max_bitrate  = maxBitRate; //vbv-maxrateparamData.rc.i_vbv_buffer_size  = bufferSize; //vbv-bufsizeparamData.i_nal_hrd             = X264_NAL_HRD_CBR;paramData.rc.i_rc_method        = X264_RC_ABR;paramData.rc.f_rf_constant      = 0.0f;}else{paramData.rc.i_vbv_max_bitrate  = maxBitRate; //vbv-maxrateparamData.rc.i_vbv_buffer_size  = bufferSize; //vbv-bufsizeparamData.rc.i_rc_method        = X264_RC_CRF;paramData.rc.f_rf_constant      = baseCRF+float(10-quality);}paramData.b_vfr_input           = 1;paramData.i_keyint_max          = fps*5;      //keyframe every 5 sec, should make this an optionparamData.i_width               = width;paramData.i_height              = height;paramData.vui.b_fullrange       = 0;          //specify full range input levels//paramData.i_frame_reference//paramData.b_inparamData.i_fps_num = fps;paramData.i_fps_den = 1;paramData.i_timebase_num = 1;paramData.i_timebase_den = 1000;//paramData.pf_log                = get_x264_log;//paramData.i_log_level           = X264_LOG_INFO;BOOL bUseCustomParams = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCustomSettings"));if(bUseCustomParams){String strCustomParams = AppConfig->GetString(TEXT("Video Encoding"), TEXT("CustomSettings"));strCustomParams.KillSpaces();if(strCustomParams.IsValid()){Log(TEXT("Using custom x264 settings: \"%s\""), strCustomParams.Array());StringList paramList;strCustomParams.GetTokenList(paramList, ' ', FALSE);for(UINT i=0; i<paramList.Num(); i++){String &strParam = paramList[i];if(!schr(strParam, '='))continue;String strParamName = strParam.GetToken(0, '=');String strParamVal  = strParam.GetTokenOffset(1, '=');if( strParamName.CompareI(TEXT("fps")) /*|| strParamName.CompareI(TEXT("force-cfr"))*/){continue;}LPSTR lpParam = strParamName.CreateUTF8String();LPSTR lpVal   = strParamVal.CreateUTF8String();x264_param_parse(¶mData, lpParam, lpVal);Free(lpParam);Free(lpVal);}}}if(bUse444) paramData.i_csp = X264_CSP_I444;x264 = x264_encoder_open(¶mData);if(!x264)CrashError(TEXT("Could not initialize x264"));Log(TEXT("------------------------------------------"));Log(TEXT("%s"), GetInfoString().Array());Log(TEXT("------------------------------------------"));DataPacket packet;GetHeaders(packet);}~X264Encoder(){ClearPackets();x264_encoder_close(x264);}bool Encode(LPVOID picInPtr, List<DataPacket> &packets, List<PacketType> &packetTypes, DWORD outputTimestamp, int &ctsOffset){x264_picture_t *picIn = (x264_picture_t*)picInPtr;x264_nal_t *nalOut;int nalNum;packets.Clear();ClearPackets();if(x264_encoder_encode(x264, &nalOut, &nalNum, picIn, &picOut) < 0){AppWarning(TEXT("x264 encode failed"));return false;}if(!bFirstFrameProcessed && nalNum){if(picOut.i_dts < 0)delayOffset = int(-picOut.i_dts);//Log(TEXT("cts: %u, timestamp: %u"), ctsOffset, outputTimestamp);bFirstFrameProcessed = true;}INT64 ts = INT64(outputTimestamp);int timeOffset = int(picOut.i_pts+INT64(delayOffset)-ts);timeOffset += ctsOffset;//dynamically adjust the CTS for the stream if it gets lower than the current value//(thanks to cyrus for suggesting to do this instead of a single shift)if(nalNum && timeOffset < 0){ctsOffset -= timeOffset;timeOffset = 0;}//Log(TEXT("dts: %d, pts: %d, timestamp: %d, offset: %d"), picOut.i_dts, picOut.i_pts, outputTimestamp, timeOffset);timeOffset = htonl(timeOffset);BYTE *timeOffsetAddr = ((BYTE*)&timeOffset)+1;for(int i=0; i<nalNum; i++){x264_nal_t &nal = nalOut[i];if(nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SLICE || nal.i_type == NAL_SEI){VideoPacket *newPacket = CurrentPackets.CreateNew();BYTE *skip = nal.p_payload;while(*(skip++) != 0x1);int skipBytes = (int)(skip-nal.p_payload);int newPayloadSize = (nal.i_payload-skipBytes);newPacket->Packet.SetSize(9+newPayloadSize);newPacket->Packet[0] = ((nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SEI) ? 0x17 : 0x27);newPacket->Packet[1] = 1;mcpy(newPacket->Packet+2, timeOffsetAddr, 3);*(DWORD*)(newPacket->Packet+5) = htonl(newPayloadSize);mcpy(newPacket->Packet+9, nal.p_payload+skipBytes, newPayloadSize);}else if(nal.i_type == NAL_SPS){VideoPacket *newPacket = CurrentPackets.CreateNew();BufferOutputSerializer headerOut(newPacket->Packet);headerOut.OutputByte(0x17);headerOut.OutputByte(0);headerOut.Serialize(timeOffsetAddr, 3);headerOut.OutputByte(1);headerOut.Serialize(nal.p_payload+5, 3);headerOut.OutputByte(0xff);headerOut.OutputByte(0xe1);headerOut.OutputWord(htons(nal.i_payload-4));headerOut.Serialize(nal.p_payload+4, nal.i_payload-4);x264_nal_t &pps = nalOut[i+1]; //the PPS always comes after the SPSheaderOut.OutputByte(1);headerOut.OutputWord(htons(pps.i_payload-4));headerOut.Serialize(pps.p_payload+4, pps.i_payload-4);}elsecontinue;switch(nal.i_ref_idc){case NAL_PRIORITY_DISPOSABLE:   packetTypes << PacketType_VideoDisposable;  break;case NAL_PRIORITY_LOW:          packetTypes << PacketType_VideoLow;         break;case NAL_PRIORITY_HIGH:         packetTypes << PacketType_VideoHigh;        break;case NAL_PRIORITY_HIGHEST:      packetTypes << PacketType_VideoHighest;     break;}}packets.SetSize(CurrentPackets.Num());for(UINT i=0; i<packets.Num(); i++){packets[i].lpPacket = CurrentPackets[i].Packet.Array();packets[i].size     = CurrentPackets[i].Packet.Num();}return true;}void GetHeaders(DataPacket &packet){if(!HeaderPacket.Num()){x264_nal_t *nalOut;int nalNum;x264_encoder_headers(x264, &nalOut, &nalNum);for(int i=0; i<nalNum; i++){x264_nal_t &nal = nalOut[i];if(nal.i_type == NAL_SPS){BufferOutputSerializer headerOut(HeaderPacket);headerOut.OutputByte(0x17);headerOut.OutputByte(0);headerOut.OutputByte(0);headerOut.OutputByte(0);headerOut.OutputByte(0);headerOut.OutputByte(1);headerOut.Serialize(nal.p_payload+5, 3);headerOut.OutputByte(0xff);headerOut.OutputByte(0xe1);headerOut.OutputWord(htons(nal.i_payload-4));headerOut.Serialize(nal.p_payload+4, nal.i_payload-4);x264_nal_t &pps = nalOut[i+1]; //the PPS always comes after the SPSheaderOut.OutputByte(1);headerOut.OutputWord(htons(pps.i_payload-4));headerOut.Serialize(pps.p_payload+4, pps.i_payload-4);}}}packet.lpPacket = HeaderPacket.Array();packet.size     = HeaderPacket.Num();}int GetBitRate() const {return paramData.rc.i_vbv_max_bitrate;}String GetInfoString() const{String strInfo;strInfo << TEXT("Video Encoding: x264")  <<TEXT("\r\n    fps: ")         << IntString(paramData.i_fps_num) <<TEXT("\r\n    width: ")       << IntString(width) << TEXT(", height: ") << IntString(height) <<TEXT("\r\n    preset: ")      << curPreset <<TEXT("\r\n    CBR: ")         << CTSTR((bUseCBR) ? TEXT("yes") : TEXT("no")) <<TEXT("\r\n    max bitrate: ") << IntString(paramData.rc.i_vbv_max_bitrate);if(!bUseCBR){strInfo << TEXT("\r\n    buffer size: ") << IntString(paramData.rc.i_vbv_buffer_size) << TEXT("\r\n    quality: ")     << IntString(10-int(paramData.rc.f_rf_constant-baseCRF));}return strInfo;}virtual bool DynamicBitrateSupported() const{return true;}virtual bool SetBitRate(DWORD maxBitrate, DWORD bufferSize){if(bUseCBR){paramData.rc.i_bitrate          = maxBitrate;paramData.rc.i_vbv_max_bitrate  = maxBitrate; //vbv-maxrateparamData.rc.i_vbv_buffer_size  = bufferSize; //vbv-bufsize}else{paramData.rc.i_vbv_max_bitrate = maxBitrate;paramData.rc.i_vbv_buffer_size = bufferSize;}int retVal = x264_encoder_reconfig(x264, ¶mData);if(retVal < 0)Log(TEXT("Could not set new encoder bitrate, error value %u"), retVal);return retVal == 0;}
};VideoEncoder* CreateX264Encoder(int fps, int width, int height, int quality, CTSTR preset, bool bUse444, int maxBitRate, int bufferSize)
{return new X264Encoder(fps, width, height, quality, preset, bUse444, maxBitRate, bufferSize);
}

obs之libx264编码相关推荐

  1. obs之lame编码

    obs之lame编码. #include "Main.h"#include "../lame/include/lame.h"const int audioBlo ...

  2. obs自定义编码设置_通过7个步骤设置OBS进行实时编码

    obs自定义编码设置 by Wesley McCann 韦斯利·麦肯(Wesley McCann) 通过7个步骤设置OBS进行实时编码 (Setting up OBS for Live Coding ...

  3. obs之libfaac编码

    obs源码之libaac编码. #include "Main.h"#include "../libfaac/include/faac.h"//AAC is pr ...

  4. libx264编码过程中修改码率踩坑记录

    问题来源于项目中的一个需求,根据当前网络环境实时调整libx264的码率参数,从而让视频播放更加流畅. 1.设置码率调整算法为ABR. 2.初始化,并提供一个接口供探测网络环境的线程调用.写法大概类似 ...

  5. 【obs-studio开源项目从入门到放弃】video_thread 视频编码线程理解

    文章目录 前言 1.视频编码线程的创建时机 video_output_open函数创建视频编码线程 2.视频编码线程的工作内容 video_output_cur_frame 线程真正的工作函数 详细解 ...

  6. Tesla T4视频编码性能分析

    Tesla T4视频编码性能分析 从开普勒开始的所有 NVIDIA GPUs 都支持完全加速的硬件视频编码: GPUs 支持完全加速的硬件视频解码.最近发布的图灵硬件提供了张量核心和更好的机器学习性能 ...

  7. FFmpeg与libx264接口源代码简单分析

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  8. ffmpeg Unknown encoder ‘libx264‘

    原因:恰好下载的是lgpl,ffmpeg缺少依赖项,自身不带libx264编码类型 安装好了ffmpeg后,如果使用ffmpeg命令去把某个视频文件转成h264视频编码.mp3音频编码或者其他ffmp ...

  9. 【obs】转载:OBS直播严重延迟和卡顿怎么办?

    大神们对rtmp推流做了讨论和分享 GOP设置2秒 保利威 的知乎专栏 保利威 从推流到播放,会引入延迟的环节有编码延迟.网络丢包和网络抖动.视频的分段传输.节点.播放器的缓存等等. 由于RTMP基于 ...

最新文章

  1. 关于LDD3 setconsole.c Alesssandro Rubini 的邮件回复
  2. CTF web题总结--任意文件下载
  3. 云间来客 --- Java 目录大纲
  4. PyQt5 技术篇-plainTextEdit控件获得文本内容方法、设置文本内容方法。
  5. 全国计算机等级考试题库二级C操作题100套(第84套)
  6. C语言中sizeof详解——面试C/C++
  7. suse查看mysql内存使用情况_MySQL 慢查询日志(Slow Query Log)
  8. 计算机数据结构英语作文,数据结构学习心得英语作文
  9. Netty工作笔记0044---Netty案例源码分析
  10. 在MongoDB的MapReduce上踩过的坑
  11. Jenkins可持续集成
  12. kvm virtio功能配置
  13. fir.im Weekly - 从零开始创建 Android 新项目
  14. 资管新规这样规定,我的货基该怎么办?
  15. mumu 模拟器连不上adb
  16. 在MonthCalendar控件中选中日期
  17. 服务器机柜可放多大显示器,一个标准服务器机柜究竟能够放多少服务器
  18. 51单片机WIFI手机APP智能窗户窗帘控制系统手动自动定时
  19. 查看各类系统端口占用情况
  20. 运行中的程序突然出现Killed原因

热门文章

  1. CentOS-6.4 安装 Memcached
  2. Javascript第六章prototype原型向构造器中添加属性,实现构造器共享,节约空间第五课
  3. 5工程添加emwin库_手把手教你打造专属自己的远程私有库——上
  4. 计算机国三网络技术,计算机国三网络技术.doc
  5. 新增磁盘,创建分区,分区挂载
  6. 洛谷 P1400 塔
  7. UWP开发随笔——UWP新控件!AutoSuggestBox!
  8. Keil如何生成bin文件【Keil生成Bin文件的方法】
  9. 记一次 nginx 504 Gateway Time-out
  10. 找出Java进程中大量消耗CPU