92 lines
3.2 KiB
C++
92 lines
3.2 KiB
C++
#include "VideoReceiver.h"
|
|
#include <QDebug>
|
|
|
|
VideoReceiver::VideoReceiver(QObject *parent)
|
|
: QThread(parent) {
|
|
}
|
|
|
|
VideoReceiver::~VideoReceiver() {
|
|
}
|
|
|
|
void VideoReceiver::run() {
|
|
QTcpSocket socket;
|
|
socket.connectToHost("127.0.0.1", 27183);
|
|
if (!socket.waitForConnected(3000)) {
|
|
qWarning() << "Unable to connect to scrcpy stream";
|
|
return;
|
|
} else {
|
|
qDebug() << "Connected to scrcpy stream";
|
|
}
|
|
|
|
// No need for explicit avcodec_register_all() with modern FFmpeg
|
|
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
|
if (!codec) {
|
|
qCritical() << "H264 codec not found";
|
|
return;
|
|
}
|
|
m_codecCtx = avcodec_alloc_context3(codec);
|
|
if (avcodec_open2(m_codecCtx, codec, nullptr) < 0) {
|
|
qCritical() << "Failed to open codec";
|
|
return;
|
|
}
|
|
|
|
m_parser = av_parser_init(AV_CODEC_ID_H264);
|
|
AVPacket *pkt = av_packet_alloc();
|
|
AVFrame *frame = av_frame_alloc();
|
|
|
|
// Delay determining width/height until after first frame if unknown
|
|
SwsContext *swsCtx = nullptr;
|
|
uint8_t *rgbData[4] = {nullptr};
|
|
int rgbLinesize[4] = {0};
|
|
|
|
QByteArray buffer;
|
|
while (socket.waitForReadyRead()) {
|
|
buffer.append(socket.readAll());
|
|
const uint8_t *data = reinterpret_cast<const uint8_t *>(buffer.constData());
|
|
int dataSize = buffer.size();
|
|
while (dataSize > 0) {
|
|
int len = av_parser_parse2(m_parser, m_codecCtx,
|
|
&pkt->data, &pkt->size,
|
|
data, dataSize,
|
|
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
|
|
if (len < 0) break;
|
|
data += len;
|
|
dataSize -= len;
|
|
if (pkt->size > 0) {
|
|
avcodec_send_packet(m_codecCtx, pkt);
|
|
while (avcodec_receive_frame(m_codecCtx, frame) == 0) {
|
|
// Initialize scaler and buffers when frame size known
|
|
if (!swsCtx) {
|
|
m_dstWidth = frame->width;
|
|
m_dstHeight = frame->height;
|
|
swsCtx = sws_getContext(
|
|
m_dstWidth, m_dstHeight, m_codecCtx->pix_fmt,
|
|
m_dstWidth, m_dstHeight, AV_PIX_FMT_RGB24,
|
|
SWS_BILINEAR, nullptr, nullptr, nullptr
|
|
);
|
|
av_image_alloc(rgbData, rgbLinesize,
|
|
m_dstWidth, m_dstHeight,
|
|
AV_PIX_FMT_RGB24, 1);
|
|
}
|
|
// Convert to RGB
|
|
sws_scale(swsCtx, frame->data, frame->linesize, 0,
|
|
m_dstHeight, rgbData, rgbLinesize);
|
|
QImage img(rgbData[0], m_dstWidth, m_dstHeight,
|
|
rgbLinesize[0], QImage::Format_RGB888);
|
|
emit frameReady(img.copy());
|
|
}
|
|
}
|
|
}
|
|
buffer.clear();
|
|
}
|
|
|
|
if (rgbData[0])
|
|
av_freep(&rgbData[0]);
|
|
if (swsCtx)
|
|
sws_freeContext(swsCtx);
|
|
av_frame_free(&frame);
|
|
av_packet_free(&pkt);
|
|
av_parser_close(m_parser);
|
|
avcodec_free_context(&m_codecCtx);
|
|
}
|