Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/waylandrecord/avoutputstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ void CAVOutputStream::SetVideoCodecProp(AVCodecID codec_id, int framerate, int b
m_gopsize = gopsize;
}

bool CAVOutputStream::shouldUseSingleThread(int width, int height)
{
const qint64 pixelCount = static_cast<qint64>(width) * height;
const qint64 fullHdPixelCount = static_cast<qint64>(1920) * 1080;
return m_boardVendorType != 0 && width > 0 && height > 0 && pixelCount <= fullHdPixelCount;
}

//初始化音频编码器
void CAVOutputStream::SetAudioCodecProp(AVCodecID codec_id, int samplerate, int channels, int layout, int bitrate)
{
Expand Down Expand Up @@ -502,7 +509,10 @@ bool CAVOutputStream::open(QString path)
// Set H264 preset and tune
avlibInterface::m_av_dict_set(&param, "preset", "ultrafast", 0);
avlibInterface::m_av_dict_set(&param, "tune", "zerolatency", 0);
avlibInterface::m_av_dict_set(&param, "crf", "30", 0); // 质量较低,文件较大但编码更快
avlibInterface::m_av_dict_set(&param, "crf", "30", 0);
if (shouldUseSingleThread(pCodecCtx->width, pCodecCtx->height)) {
avlibInterface::m_av_dict_set(&param, "threads", "1", 0);
}
}

if (avlibInterface::m_avcodec_open2(pCodecCtx, pCodec, &param) < 0) {
Expand Down Expand Up @@ -734,16 +744,11 @@ int CAVOutputStream::writeVideoFrame(WaylandIntegration::WaylandIntegrationPriva
//qDebug() << "stride-src: " << pRgbFrame->linesize[0] << pRgbFrame->width*4 << pRgbFrame->linesize[2] <<
// "stride-dst: " << pFrameYUV->linesize[0] << pFrameYUV->linesize[1] << pFrameYUV->linesize[2];
//qDebug() << "pYUVFrame -w h" << pFrameYUV->width << pFrameYUV->height ;
qint64 time2 = QDateTime::currentMSecsSinceEpoch();
avlibInterface::m_sws_scale(m_pVideoSwsContext, pRgbFrame->data, pRgbFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);


qint64 time3 = QDateTime::currentMSecsSinceEpoch();
qDebug() << "time3 - time2: sws_scale : " << time3-time2;
if (pRgbFrame->height != pCodecCtx->height && pRgbFrame->width != pCodecCtx->width) {
pFrameYUV->width = pCodecCtx->width;
pFrameYUV->height = pCodecCtx->height;
qDebug() << "the frame maybe cropped. the frame mybe not be encode. use the codectx as encode frame size";
} else {
pFrameYUV->width = pRgbFrame->width;
pFrameYUV->height = pRgbFrame->height;
Expand All @@ -753,8 +758,6 @@ int CAVOutputStream::writeVideoFrame(WaylandIntegration::WaylandIntegrationPriva
pFrameYUV->width = pCodecCtx->width;
pFrameYUV->height = pCodecCtx->height;

qint64 time2 = QDateTime::currentMSecsSinceEpoch();

convertARGB2YUV420(pCodecCtx->width,
pCodecCtx->height,
frame._frame + (m_top * frame._stride + m_left * 4),
Expand Down Expand Up @@ -791,10 +794,8 @@ int CAVOutputStream::writeVideoFrame(WaylandIntegration::WaylandIntegrationPriva
return ret;
}
}
qint64 time4 = QDateTime::currentMSecsSinceEpoch();
// qDebug() << "time4 - time1: writeVideoFrame : " << time4-time1;
avlibInterface::m_av_free_packet(&packet);
fflush(stdout);
return 0;
}

Expand Down Expand Up @@ -1205,7 +1206,6 @@ void CAVOutputStream::writeMixAudio()
printf("Mixer: failed to call av_buffersink_get_frame_flags ret : %d \n", ret);
break;
}
fflush(stdout);
if (pFrame_out->data[0] != nullptr) {
AVPacket packet_out;
avlibInterface::m_av_init_packet(&packet_out);
Expand Down
2 changes: 2 additions & 0 deletions src/waylandrecord/avoutputstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ class CAVOutputStream
*/
bool isNotAudioFifoEmty();
private:
bool shouldUseSingleThread(int width, int height);

/**
* @brief 电脑类型
*/
Expand Down
85 changes: 39 additions & 46 deletions src/waylandrecord/waylandintegration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::onDeviceChanged(quint32 name

void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland::Client::RemoteBuffer *rbuf, const QRect rect)
{
qInfo() << __FUNCTION__ << __LINE__ << "开始处理buffer...";
qDebug() << ">>>>>> open fd!" << rbuf->fd();
// QScopedPointer<const KWayland::Client::RemoteBuffer> guard(rbuf);
auto dma_fd = rbuf->fd();
quint32 width = rbuf->width();
Expand Down Expand Up @@ -562,8 +560,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland

void WaylandIntegration::WaylandIntegrationPrivate::processBufferHw(const KWayland::Client::RemoteBuffer *rbuf, const QRect rect, int screenId)
{
qInfo() << __FUNCTION__ << __LINE__ << "开始处理buffer...";
qDebug() << ">>>>>> open fd!" << rbuf->fd();
// QScopedPointer<const KWayland::Client::RemoteBuffer> guard(rbuf);
auto dma_fd = rbuf->fd();
quint32 width = rbuf->width();
Expand Down Expand Up @@ -714,7 +710,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::processBufferHw(const KWayla
}
#endif
munmap(mapData, stride * height);
qInfo() << __FUNCTION__ << __LINE__ << "已处理buffer";
}

//拷贝数据,当远程buffer没有数据传过来时,调用此接口,将上一次的屏幕数据做为当前的屏幕数据
Expand Down Expand Up @@ -765,28 +760,20 @@ QImage::Format WaylandIntegration::WaylandIntegrationPrivate::getImageFormat(qui
{
switch (format) {
case GBM_FORMAT_XRGB8888: //GBM_FORMAT_XRGB8888 = 875713112
qDebug() << "fd 图片格式: XRGB" << GBM_FORMAT_XRGB8888 << " -> " << "QImage::Format_RGB32";
return QImage::Format_RGB32;
case GBM_FORMAT_XBGR8888: //GBM_FORMAT_XBGR8888 = 875709016
qDebug() << "fd 图片格式: XBGR" << GBM_FORMAT_XBGR8888 << " -> " << "QImage::Format_RGB32";
return QImage::Format_RGB32;
case GBM_FORMAT_RGBX8888: //GBM_FORMAT_RGBX8888 = 875714642
qDebug() << "fd 图片格式: RGBX" << GBM_FORMAT_RGBX8888 << " -> " << "QImage::Format_RGBX8888";
return QImage::Format_RGBX8888;
case GBM_FORMAT_BGRX8888: //GBM_FORMAT_BGRX8888 = 875714626
qDebug() << "fd 图片格式: BGRX" << GBM_FORMAT_BGRX8888 << " -> " << "QImage::Format_BGR30";
return QImage::Format_BGR30;
case GBM_FORMAT_ARGB8888: //GBM_FORMAT_ARGB8888 = 875713089
qDebug() << "fd 图片格式: ARGB" << GBM_FORMAT_ARGB8888 << " -> " << "QImage::Format_ARGB32";
return QImage::Format_ARGB32;
case GBM_FORMAT_ABGR8888: //GBM_FORMAT_ABGR8888 = 875708993
qDebug() << "fd 图片格式: ABGR" << GBM_FORMAT_ABGR8888 << " -> " << "QImage::Format_ARGB32";
return QImage::Format_ARGB32;
case GBM_FORMAT_RGBA8888: //GBM_FORMAT_RGBA8888 = 875708754
qDebug() << "fd 图片格式: RGBA" << GBM_FORMAT_RGBA8888 << " -> " << "QImage::Format_RGBA8888";
return QImage::Format_RGBA8888;
case GBM_FORMAT_BGRA8888: //GBM_FORMAT_BGRA8888 = 875708738
qDebug() << "fd 图片格式: BGRA" << GBM_FORMAT_BGRA8888 << " -> " << "QImage::Format_BGR30";
return QImage::Format_BGR30;
default:
qDebug() << "fd 图片格式未知: " << format << " -> " << "QImage::Format_RGB32";
Expand All @@ -796,8 +783,6 @@ QImage::Format WaylandIntegration::WaylandIntegrationPrivate::getImageFormat(qui

void WaylandIntegration::WaylandIntegrationPrivate::processBufferX86(const KWayland::Client::RemoteBuffer *rbuf, const QRect rect)
{
qInfo() << __FUNCTION__ << __LINE__ << "开始处理buffer...";
qDebug() << ">>>>>> open fd!" << rbuf->fd();
//QScopedPointer<const KWayland::Client::RemoteBuffer> guard(rbuf);
auto dma_fd = rbuf->fd();
quint32 width = rbuf->width();
Expand Down Expand Up @@ -901,25 +886,42 @@ void WaylandIntegration::WaylandIntegrationPrivate::appendFrameToList()
#else

QVector<QPair<QRect, QImage>> tempImageVec;
bool frameReady = false;
{
QMutexLocker locker(&m_bGetScreenImageMutex);
if (m_boardVendorType) {
if (!m_curNewImageScreenFrames[0]._flag || !m_curNewImageScreenFrames[1]._flag) continue;
for (int i = 0 ; i < 2 ; i++) {
QImage tempImage = QImage(m_curNewImageScreenFrames[i]._frame,
static_cast<int>(m_curNewImageScreenFrames[i]._width),
static_cast<int>(m_curNewImageScreenFrames[i]._height),
m_curNewImageScreenFrames[i]._format).copy();
tempImageVec.append(QPair<QRect, QImage>(m_curNewImageScreenFrames[i]._rect, tempImage));
m_curNewImageScreenFrames[i]._flag = false;
frameReady = isScreenFrameReady(true,
m_screenCount,
m_curNewImageScreenFrames[0]._flag,
m_curNewImageScreenFrames[1]._flag,
m_curNewImageScreen.size());
if (frameReady) {
for (int i = 0 ; i < 2 ; i++) {
QImage tempImage = QImage(m_curNewImageScreenFrames[i]._frame,
static_cast<int>(m_curNewImageScreenFrames[i]._width),
static_cast<int>(m_curNewImageScreenFrames[i]._height),
m_curNewImageScreenFrames[i]._format).copy();
tempImageVec.append(QPair<QRect, QImage>(m_curNewImageScreenFrames[i]._rect, tempImage));
m_curNewImageScreenFrames[i]._flag = false;
}
}
} else {
if (m_curNewImageScreen.size() != m_screenCount) continue;
for (auto itr = m_curNewImageScreen.begin(); itr != m_curNewImageScreen.end(); ++itr) {
tempImageVec.append(*itr);
frameReady = isScreenFrameReady(false,
m_screenCount,
false,
false,
m_curNewImageScreen.size());
if (frameReady) {
for (auto itr = m_curNewImageScreen.begin(); itr != m_curNewImageScreen.end(); ++itr) {
tempImageVec.append(*itr);
}
}
}
}
if (!frameReady) {
QThread::msleep(static_cast<unsigned long>(delayTime));
continue;
}
QImage img(m_screenSize, QImage::Format_RGBA8888);
if (m_boardVendorType) {
img = img.convertToFormat(QImage::Format_RGB32);
Expand Down Expand Up @@ -1055,7 +1057,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
//qDebug() << "screenGeometry: " << screenGeometry;
//qDebug() << "rbuf->isValid(): " << rbuf->isValid();
connect(rbuf, &KWayland::Client::RemoteBuffer::parametersObtained, this, [this, rbuf, screenGeometry] {
qDebug() << "正在处理buffer..." << "fd:" << rbuf->fd() << "frameCount: " << frameCount ;
if(frameCount == 0)
{
qDebug() << "Current number of screens: " << m_screenCount;
Expand All @@ -1071,7 +1072,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
}

#ifdef KWAYLAND_REMOTE_BUFFER_RELEASE_FLAGE_ON
qDebug()<< "m_screenCount: "<< m_screenCount << "m_isScreenExtension: " << m_isScreenExtension << screenGeometry << "m_currentScreenBufs[0]->" << (m_currentScreenBufs[0] ? "true":"false") << "m_currentScreenBufs[1]->" << (m_currentScreenBufs[1] ? "true":"false");;
if (m_screenCount == 1 || !m_isScreenExtension)
{
if(m_currentScreenBufs[0] == nullptr)
Expand Down Expand Up @@ -1193,7 +1193,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry()
rbuf->release();
#endif
}
qDebug() << "buffer已处理" << "fd:" << rbuf->fd() << "frameCount: " << frameCount;
});
//qDebug() << "buffer已接收";
});
Expand Down Expand Up @@ -1256,13 +1255,9 @@ void WaylandIntegration::WaylandIntegrationPrivate::initEgl()
}
void WaylandIntegration::WaylandIntegrationPrivate::appendBuffer(unsigned char *frame, int width, int height, int stride, int64_t time)
{
static int f_count = 0;
bool res = false;
if (res = !bGetFrame() || nullptr == frame || width <= 0 || height <= 0) {
qDebug() << "drop ...." << res << frame << width << height;
if (!bGetFrame() || nullptr == frame || width <= 0 || height <= 0) {
return;
}
qDebug() << "append frame index:" << ++f_count;
int size = height * stride;
unsigned char *ch = nullptr;
if (m_bInit) {
Expand All @@ -1282,7 +1277,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::appendBuffer(unsigned char *
//先进先出
//取队首
waylandFrame wFrame = m_waylandList.first();
memset(wFrame._frame, 0, static_cast<size_t>(size));
//拷贝当前帧
memcpy(wFrame._frame, frame, static_cast<size_t>(size));
wFrame._time = time;
Expand All @@ -1306,7 +1300,6 @@ void WaylandIntegration::WaylandIntegrationPrivate::appendBuffer(unsigned char *
wFrame._index = 0;
//分配空闲内存
wFrame._frame = m_freeList.first();
memset(wFrame._frame, 0, static_cast<size_t>(size));
//拷贝wayland推送的视频帧
memcpy(wFrame._frame, frame, static_cast<size_t>(size));
m_waylandList.append(wFrame);
Expand Down Expand Up @@ -1367,6 +1360,10 @@ void WaylandIntegration::WaylandIntegrationPrivate::appendRemoteBuffer()
copyScreenData(1);
}
}
if (m_currentScreenBufs[0] == nullptr
&& (m_screenCount != 2 || !m_isScreenExtension || m_currentScreenBufs[1] == nullptr)) {
QThread::msleep(2);
}
}
qInfo() << "Stop append remote buffer" ;
}
Expand Down Expand Up @@ -1453,14 +1450,10 @@ int WaylandIntegration::WaylandIntegrationPrivate::getPadStride(int width, int d

void WaylandIntegration::WaylandIntegrationPrivate::copyBuffer(unsigned char *tmpDst, unsigned char * tmpSrc, const KWayland::Client::RemoteBuffer *rbuf)
{
unsigned char *dst = tmpDst;
unsigned char *buf = tmpSrc;
int srcStride = getPadStride(rbuf->width(),4,32);
qDebug()<<"current strade"<<srcStride;

for (int i = 0; i < rbuf->height(); i++) {
memcpy(dst, buf, srcStride);
buf += rbuf->stride();
dst += srcStride;
}
const int rowBytes = getPadStride(rbuf->width(), 4, 32);
copyImageRows(tmpDst,
tmpSrc,
rowBytes,
static_cast<int>(rbuf->height()),
static_cast<int>(rbuf->stride()));
}
31 changes: 30 additions & 1 deletion src/waylandrecord/waylandintegration_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <epoxy/gl.h>
#include <QMutex>
#include <EGL/egl.h>
#include <cstring>

enum audioType {
//麦克风
Expand Down Expand Up @@ -214,6 +215,35 @@ protected Q_SLOTS:
* @brief appendRemoteBuffer 在线程中拷贝远程buffer(remoteaccess传过来的屏幕buffer)的数据
*/
void appendRemoteBuffer();

static void copyImageRows(unsigned char *destination,
const unsigned char *source,
int rowBytes,
int height,
int sourceStride)
{
if (sourceStride == rowBytes) {
std::memcpy(destination, source, static_cast<size_t>(rowBytes) * height);
return;
}

for (int row = 0; row < height; ++row) {
std::memcpy(destination, source, static_cast<size_t>(rowBytes));
source += sourceStride;
destination += rowBytes;
}
}

static bool isScreenFrameReady(bool boardVendorType,
int screenCount,
bool firstScreenReady,
bool secondScreenReady,
int availableImageCount)
{
return boardVendorType
? firstScreenReady && secondScreenReady
: availableImageCount == screenCount;
}
public:
/**
* @ 内存由getFrame函数内部申请
Expand Down Expand Up @@ -367,4 +397,3 @@ protected Q_SLOTS:

#endif // XDG_DESKTOP_PORTAL_KDE_WAYLAND_INTEGRATION_P_H


2 changes: 2 additions & 0 deletions src/waylandrecord/writeframethread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ void WriteFrameThread::run()
while (m_context->isWriteVideo()) {
if (m_context->getFrame(frame)) {
m_context->m_recordAdmin->m_pOutputStream->writeVideoFrame(frame);
} else {
QThread::msleep(5);
}
}
m_context->m_recordAdmin->m_cacheMutex.unlock();
Expand Down
29 changes: 29 additions & 0 deletions tests/ut_screen_shot_recorder/waylandrecord/ut_avoutputstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,35 @@ ACCESS_PRIVATE_FIELD(CAVOutputStream, uint8_t *, m_out_buffer);
ACCESS_PRIVATE_FIELD(CAVOutputStream, AVFilterGraph *, filter_graph);
ACCESS_PRIVATE_FIELD(CAVOutputStream, AVFrame *, mMic_frame);
ACCESS_PRIVATE_FIELD(CAVOutputStream, AVFrame *, mSpeaker_frame);
ACCESS_PRIVATE_FUN(CAVOutputStream, bool(int, int), shouldUseSingleThread);

TEST_F(CAVOutputStreamTest, shouldUseSingleThreadForHuaweiFullHD)
{
m_avOutputStream->setBoardVendor(1);

EXPECT_TRUE(call_private_fun::CAVOutputStreamshouldUseSingleThread(*m_avOutputStream, 1920, 1080));
}

TEST_F(CAVOutputStreamTest, shouldNotUseSingleThreadForHuawei4K)
{
m_avOutputStream->setBoardVendor(1);

EXPECT_FALSE(call_private_fun::CAVOutputStreamshouldUseSingleThread(*m_avOutputStream, 3840, 2160));
}

TEST_F(CAVOutputStreamTest, shouldNotUseSingleThreadForOtherVendors)
{
m_avOutputStream->setBoardVendor(0);

EXPECT_FALSE(call_private_fun::CAVOutputStreamshouldUseSingleThread(*m_avOutputStream, 1920, 1080));
}

TEST_F(CAVOutputStreamTest, shouldNotUseSingleThreadForInvalidSize)
{
m_avOutputStream->setBoardVendor(1);

EXPECT_FALSE(call_private_fun::CAVOutputStreamshouldUseSingleThread(*m_avOutputStream, 0, 1080));
}

TEST_F(CAVOutputStreamTest, SetVideoCodecProp)
{
Expand Down
Loading
Loading