#include "cscreenrecorder.h"
#include <QPainter>
CScreenRecorder::CScreenRecorder()
{
}
void CScreenRecorder::Init(const QVariantMap &_map)
{
m_strFilePath = _map["filePath"].toString();
m_nWidth = _map["width"].toInt();
m_nHeight = _map["height"].toInt();
m_nFps = _map["fps"].toInt();
m_nAudioBitrate = _map["audioBitrate"].toInt();
m_strMicrophoneName = _map["MicrophoneName"].toString();
}
void CScreenRecorder::Start()
{
if (m_enState == EnRecordState::EN_STOP)
{
cout << "start record";
m_enState = EnRecordState::EN_START;
std::thread muxThread(&CScreenRecorder::muxThread, this);
muxThread.detach();
}
else if (m_enState == EnRecordState::EN_PAUSE)
{
cout << "continue record";
m_enState = EnRecordState::EN_START;
m_cvNotPause.notify_one();
}
}
void CScreenRecorder::Pause()
{
m_enState = EnRecordState::EN_PAUSE;
}
void CScreenRecorder::Stop()
{
EnRecordState state = m_enState;
m_enState = EnRecordState::EN_STOP;
if (state == EnRecordState::EN_PAUSE)
m_cvNotPause.notify_one();
}
void CScreenRecorder::muxThread()
{
cout << " start";
int nRet = -1;
bool bFinish = false;
int nVideoFrameIndex = 0;
int nAudioFrameIndex = 0;
avdevice_register_all();
if( openVideo() == ERR ||openAudio() == ERR || openOutput() == ERR)
{
release();
cout << " open device failed, exit...";
return;
}
initVideoBuffer();
initAudioBuffer();
std::thread screenRecord(&CScreenRecorder::screenRecordThread, this);
std::thread soundRecord(&CScreenRecorder::soundRecordThread, this);
screenRecord.detach();
soundRecord.detach();
QThread::msleep(200);
m_nVideoCurPts = m_nAudioCurPts = 0;
while(true)
{
AVPacket pkt;
av_init_packet(&pkt);
if(m_enState == EnRecordState::EN_STOP && !bFinish)
bFinish = true;
if(bFinish)
{
std::unique_lock<std::mutex> vBufLock(m_mtxVBuf, std::defer_lock);
std::unique_lock<std::mutex> aBufLock(m_mtxABuf, std::defer_lock);
std::lock(vBufLock, aBufLock);
if (av_fifo_size(m_pVideoFifoBuf) < m_nVideoOutFrameSize &&
av_audio_fifo_size(m_pAudioFifoBuf) < m_nbSamples )
{
cout << "video buff size:" << av_fifo_size(m_pVideoFifoBuf) << " audio buff size:" << av_audio_fifo_size(m_pAudioFifoBuf) << " both video and audio fifo buf are empty, break";
break;
}
cout << "video buff size:" << av_fifo_size(m_pVideoFifoBuf) << " audio buff size:" << av_audio_fifo_size(m_pAudioFifoBuf);
if(av_fifo_size(m_pVideoFifoBuf) >= m_nVideoOutFrameSize && m_nVideoCurPts == INT_MAX)
m_nVideoCurPts = 0;
if(av_audio_fifo_size(m_pAudioFifoBuf) >= m_nbSamples && m_nAudioCurPts == INT_MAX)
m_nAudioCurPts = 0;
}
// 比较音视频pts,大于0表示视频帧在前,音频需要连续编码。
// 小于0表示,音频帧在前,应该至少编码一帧视频
if (av_compare_ts(m_nVideoCurPts, m_pOutFmtCtx->streams[m_nVideoOutIndex]->time_base,
m_nAudioCurPts, m_pOutFmtCtx->streams[m_nAudioOutIndex]->time_base) <= 0)
{
if (bFinish)
{
std::lock_guard<std::mutex> lk(m_mtxVBuf);
if (av_fifo_size(m_pVideoFifoBuf) < m_nVideoOutFrameSize)
{
cout << "video wirte done";
m_nVideoCurPts = INT_MAX;
continue;
}
}
else
{
std::unique_lock<std::mutex> lk(m_mtxVBuf);
m_cvVBufNotEmpty.wait(lk, [this] { return av_fifo_size(m_pVideoFifoBuf) >= m_nVideoOutFrameSize; });
}
av_fifo_generic_read(m_pVideoFifoBuf, m_pVideoOutFrameBuf, m_nVideoOutFrameSize, nullptr);
m_cvVBufNotFull.notify_one();
m_pVideoOutFrame->pts = nVideoFrameIndex++;
m_pVideoOutFrame->format = m_pVideoEncodeCtx->pix_fmt;
m_pVideoOutFrame->width = m_pVideoEncodeCtx->width;
m_pVideoOutFrame->height = m_pVideoEncodeCtx->height;
nRet = avcodec_send_frame(m_pVideoEncodeCtx, m_pVideoOutFrame);
if(nRet != OK)
{
cout << "video avcodec_send_frame failed:" << getAvErrorMsg(nRet);
continue;
}
nRet = avcodec_receive_packet(m_pVideoEncodeCtx, &pkt);
if(nRet != OK)
{
cout << "video avcodec_receive_packet failed:" << getAvErrorMsg(nRet);
av_packet_unref(&pkt);
continue;
}
pkt.stream_index = m_nVideoIndex;
av_packet_rescale_ts(&pkt, m_pVideoEncodeCtx->time_base, m_pOutFmtCtx->streams[m_nVideoOutIndex]->time_base);
m_nVideoCurPts = pkt.pts;
nRet = av_interleaved_write_frame(m_pOutFmtCtx, &pkt);
if(nRet != OK)
{
cout << "video av_interleaved_write_frame failed:" << nRet;
}
cout << "video index:" << nVideoFrameIndex;
av_packet_unref(&pkt);
}
else
{
if (bFinish)
{
std::lock_guard<std::mutex> lk(m_mtxABuf);
if (av_audio_fifo_size(m_pAudioFifoBuf) < m_nbSamples)
{
cout << "audio write done";
m_nAudioCurPts = INT_MAX;
continue;
}
}
else
{
std::unique_lock<std::mutex> lk(m_mtxABuf);
m_cvABufNotEmpty.wait(lk, [this] { return av_audio_fifo_size(m_pAudioFifoBuf) >= m_nbSamples; });
}
int nRet = -1;
AVFrame *pFrame = av_frame_alloc();
pFrame->nb_samples = m_nbSamples;
pFrame->channel_layout = m_pAudioEncodeCtx->channel_layout;
pFrame->format = m_pAudioEncodeCtx->sample_fmt;
pFrame->sample_rate = m_pAudioEncodeCtx->sample_rate;
pFrame->pts = m_nbSamples * nAudioFrameIndex++;
//分配data buf
nRet = av_frame_get_buffer(pFrame, 0);
if(av_audio_fifo_read(m_pAudioFifoBuf, (void **)pFrame->data, m_nbSamples) < m_nbSamples)
{
cout << "av_audio_fifo_read failed";
continue;
}
m_cvABufNotFull.notify_one();
nRet = avcodec_send_frame(m_pAudioEncodeCtx, pFrame);
if (nRet != OK)
{
cout << "audio avcodec_send_frame failed, ret: " << nRet;
av_frame_free(&pFrame);
continue;
}
nRet = avcodec_receive_packet(m_pAudioEncodeCtx, &pkt);
if (nRet != OK)
{
cout << "audio avcodec_receive_packet failed, ret: " << nRet;
av_frame_free(&pFrame);
av_packet_unref(&pkt);
continue;
}
pkt.stream_index = m_nAudioOutIndex;
av_packet_rescale_ts(&pkt, m_pAudioEncodeCtx->time_base, m_pOutFmtCtx->streams[m_nAudioOutIndex]->time_base);
m_nAudioCurPts = pkt.pts;
nRet = av_interleaved_write_frame(m_pOutFmtCtx, &pkt);
if (nRet != OK)
cout << "audio av_interleaved_write_frame failed, ret: " << nRet;
cout << "audio index:" << nAudioFrameIndex;
av_frame_free(&pFrame);
av_packet_unref(&pkt);
}
}
flushEncoders();
av_write_trailer(m_pOutFmtCtx);
cout << " exit";
release();
}
void CScreenRecorder::screenRecordThread()
{
cout << " start";
int nRet = -1;
AVPacket pkt;
av_init_packet(&pkt);
int y_size = m_nWidth * m_nHe

onnx
- 粉丝: 1w+
最新资源
- Python期末大作业(眼底血管医学图像分割实验)+源代码+文档报告
- 工业自动化领域中三菱FX3U PLC与台达VFD变频器Modbus通讯详解及应用实例 资料
- 这是一个基于stm32f103单片机的下推式磁悬浮项目
- FPGA开发板硬件设计技术资料分享.zip
- 基于USS协议的西门子S7-1200PLC与KTP700触摸屏对MM420变频器的多段频率精确控制及显示
- 西门子200PLC控制台达伺服电机正反转与模拟量控制功能实现
- 三菱PLC控制伺服系统在锯床自动收料中的应用:含CAD电气图纸与PLC人机界面设计 - 伺服电机
- 西门子SMART触摸屏与多品牌变频器Modbus RTU通讯实现及应用
- 三菱PLC与发那科机器人基恩士侧头通过CClink现场总线连接实现的精确角度定位加工自动上下料案例程序及PLC定位模块控制
- 艾默生15kw充电桩模块:PFC+DCDC双DSP控制核心算法及全套开发资料解析 - 嵌入式系统
- 基于SVG静止无功发生器的DSP+FPGA主板源码解析与应用研究
- 留虽然发给认同感四个数上个三十多个
- 基于Simulink的二自由度车辆模型构建
- 西门子S7-1200PLC与KTP700触摸屏控制V90伺服电机的以太网通信及操作实现
- LabVIEW源码解析:基于Modbus TCP与西门子PLC通讯及研华PCI板卡数据管理
- Python100-master (3).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈


