Загрузка данных
#include "streamingwt.h"
#include "easyav/transport/servers/mpegtsudpserver.h"
#include "easyav/transport/servers/rtptransportserver.h"
#include "easyav/transport/servers/shmemtransportserver.h"
#include "lib_qt_common/qlogtools.h"
#include "ui_streamingwt.h"
#include <QDir>
#include <QFileDialog>
#include <QTimer>
#ifdef BUILD_OPENCV_SUPPORT_EASYSTREAMER
#include "easyapi_cvadapter/cveasyframe.h"
#endif
Q_DEVELOPER_LOG_CATGS(easystreamer, StreamingWt);
StreamingWt::StreamingWt(MediaPlayerWt *player, QWidget *parent)
: QWidget(parent)
, ui(new Ui::StreamingWt)
, mPlayer(player)
, mSender()
, mRcvrStreamsModel(new StreamsModel(this))
, mSndrStreamsModel(new StreamsModel(this))
, mWtVideoConfig(new VideoEncoderConfigWt(this))
, mWtAudioConfig(new AudioEncoderConfigWt(this))
, mWtFilterHwConfig(new HwConfigWt(this))
, mWtControl(new MediaControlWt(this, false))
{
qCDebug(catgMem) << _FUNC_RAW_;
ui->setupUi(this);
setupWidgets();
setupStreamMonitor();
loadSettings();
auto defaultFilterString = "aresample=44100,aformat=sample_fmts=fltp:channel_layouts=stereo";
ui->leFilterAudio->setText(QString::fromStdString(defaultFilterString));
this->setMinimumWidth(500);
}
StreamingWt::~StreamingWt()
{
dbgMemStart(catgMem);
stopCvInput();
stopArvCamera();
mSender.stopAllPipelines();
saveSettings();
delete ui;
dbgMemFinish(catgMem);
}
void StreamingWt::onInputReady() {}
void StreamingWt::setupStreamMonitor()
{
ui->pbAddStream->setEnabled(false);
connect(mRcvrStreamsModel, &StreamsModel::selectionChanged, this, [this](const EasyAV::StreamInfo &val) {
if (val.mediaType == EasyAV::MediaType::video)
{
ui->stackedWidget->setCurrentIndex(0);
}
else if (val.mediaType == EasyAV::MediaType::audio)
{
ui->stackedWidget->setCurrentIndex(1);
}
else
ui->stackedWidget->setCurrentIndex(2);
ui->pbAddStream->setEnabled(true);
});
connect(mRcvrStreamsModel, &StreamsModel::selectionRemoved, this, [this]() { ui->pbAddStream->setEnabled(false); });
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this]() {
if (!mPlayer->reciever().pipelineExists(1))
return;
mRcvrStreamsModel->updateData(mPlayer->reciever().getStreamInfos(1));
});
timer->start(1000);
}
void StreamingWt::setupWidgets()
{
QRegularExpression ipRegex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}"
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
QRegularExpressionValidator *ipValidator = new QRegularExpressionValidator(ipRegex, this);
ui->leIpRtp->setValidator(ipValidator);
ui->sbPortRtp->setRange(1, 65535);
ui->leIpMpegUdp->setValidator(ipValidator);
ui->sbPortMpegUdp->setRange(1, 65535);
ui->leShmName->setText("test_shmem");
int memSize = 1280 * 720 * 3 / 2 /* + 100*/; // yuv420p = 3/2 bytes per pix
ui->leSizeBytes->setText(QString::number(memSize));
ui->leSizeBytes->setValidator(new QIntValidator(this));
ui->tvRcvrStreams->setModel(mRcvrStreamsModel);
ui->tvSndrStreams->setModel(mSndrStreamsModel);
ui->tvRcvrStreams->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tvRcvrStreams->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tvRcvrStreams->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->tvRcvrStreams->header()->setSectionResizeMode(1, QHeaderView::Stretch);
ui->tvSndrStreams->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tvSndrStreams->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tvSndrStreams->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->tvSndrStreams->header()->setSectionResizeMode(1, QHeaderView::Stretch);
mRcvrStreamsModel->setSelector(ui->tvRcvrStreams->selectionModel());
mSndrStreamsModel->setSelector(ui->tvSndrStreams->selectionModel());
ui->loVideoConfig->addWidget(mWtVideoConfig);
ui->loAudioConfig->addWidget(mWtAudioConfig);
ui->loFilterHwConfig->addWidget(mWtFilterHwConfig);
connect(ui->pbAddStream, &QPushButton::clicked, this, &StreamingWt::onAddStreamClicked);
connect(ui->pbAddOverlay, &QPushButton::clicked, this, &StreamingWt::onAddOverlayClicked);
// ui->cbFiltepHwStrategy->addItem("none", QVariant(static_cast<int>(EasyAV::HwStrategy::none)));
// ui->cbFilterHwStrategy->addItem("derive",
// QVariant(static_cast<int>(EasyAV::HwStrategy::derive)));
// ui->cbFilterHwStrategy->addItem("unique",
// QVariant(static_cast<int>(EasyAV::HwStrategy::unique)));
connect(ui->pbSetupRtp, &QPushButton::clicked, this, &StreamingWt::onSetupRtpClicked);
connect(ui->pbSetupMpegUdp, &QPushButton::clicked, this, &StreamingWt::onSetupMpegTsUdpClicked);
connect(ui->pbSetupShMem, &QPushButton::clicked, this, &StreamingWt::onSetupShMemClicked);
// connect(mPlayer, &MediaPlayerWt::overlayPayloadReady, this, &StreamingWt::onOverlayPayload);
connect(ui->pbAddCvCamera, &QPushButton::clicked, this, &StreamingWt::onAddCameraClicked);
connect(ui->pbAddAravisCamera, &QPushButton::clicked, this, &StreamingWt::onAddArvCameraClicked);
connect(ui->pbAddCvFile, &QPushButton::clicked, this, [this]() {
QString filter = "Video Files (*.mp4 *.avi *.mkv);;All Files (*.*)";
QString filename = QFileDialog::getOpenFileName(this, "Select a video file", "", filter);
if (filename.isEmpty())
{
qCCritical(QLoggingCategory("EasyStreamer")) << "Empty filename for OpenCV file";
return;
}
this->onAddVideoClicked(filename);
});
ui->loPlayerControls->addWidget(mWtControl);
#ifndef BUILD_OPENCV_SUPPORT_EASYSTREAMER
ui->pbAddCvCamera->hide();
ui->pbAddCvFile->hide();
#endif
mWtControl->setPlayCallback([this]() -> bool { return onPlay(); });
mWtControl->setStopCallback([this]() { return onStop(); });
}
// void StreamingWt::onOverlayPayload(const QByteArray &payload)
// {
// AVFrame *frame = av_frame_alloc();
// if (!frame)
// return;
// frame->format = -1; // custom data
// frame->buf[0] = av_buffer_alloc(payload.size());
// if (!frame->buf[0])
// {
// av_frame_free(&frame);
// return;
// }
// memcpy(frame->buf[0]->data, payload.constData(), payload.size());
// frame->data[0] = frame->buf[0]->data;
// frame->linesize[0] = static_cast<int>(payload.size());
// long long lastVideoUs = mLastVideoPtsUs.load(std::memory_order_relaxed);
// int64_t usec_ts = 0;
// static auto startTime = std::chrono::steady_clock::now();
// if (lastVideoUs > 0)
// {
// usec_ts = static_cast<int64_t>(lastVideoUs);
// }
// else
// {
// auto now = std::chrono::steady_clock::now();
// usec_ts = static_cast<int64_t>(std::chrono::duration_cast<std::chrono::microseconds>(now - startTime).count());
// }
// AVRational src_tb{1, 1000000};
// AVRational dst_tb{1, 90000}; // если твой overlay stream timebase = 1/90000
// frame->pts = av_rescale_q(usec_ts, src_tb, dst_tb);
// frame->pkt_dts = frame->pts;
// frame->duration = 1;
// auto easyFrame = EasyAV::AVEasyFrame::createFromAVFrame(frame, std::chrono::microseconds(usec_ts));
// bool ok = mSender.pushFrame(pipelineId, overlayIdx, easyFrame);
// }
void StreamingWt::loadSettings()
{
ui->leIpRtp->setText("127.0.0.1");
ui->sbPortRtp->setValue(3535);
ui->leIpMpegUdp->setText("127.0.0.1");
ui->sbPortMpegUdp->setValue(3535);
ui->leFilterVideo->setText("scale_vaapi=w=1280:h=720,hwdownload,format=yuv420p");
EasyAV::VideoEncoderConfig videoConfig;
videoConfig.video = {1280, 720, EasyAV::PixelFormat::YUV420P};
videoConfig.fps = 30;
videoConfig.bitrate = 2'500'000; // 2.5 Mbps for 720p
mWtVideoConfig->setConfig(videoConfig);
EasyAV::AudioEncoderConfig audioConfig;
mWtAudioConfig->setConfig(audioConfig);
}
void StreamingWt::saveSettings() {}
void StreamingWt::onAddArvCameraClicked()
{
#ifdef BUILD_ARAVIS_SUPPORT_EASYSTREAMER
if (mArvTimer)
{
mArvTimer->stop();
mArvTimer->deleteLater();
mArvTimer = nullptr;
}
if (mArvStream)
{
g_object_unref(mArvStream);
mArvStream = nullptr;
}
if (mArvCamera)
{
g_object_unref(mArvCamera);
mArvCamera = nullptr;
}
mArvCamera = arv_camera_new(nullptr, nullptr);
if (!mArvCamera)
{
qCCritical(QLoggingCategory("EasyStreamer")) << "Failed to open Aravis camera!";
return;
}
GError *setErr = nullptr;
arv_camera_set_pixel_format(mArvCamera, ARV_PIXEL_FORMAT_MONO_8, &setErr);
if (setErr)
{
qCWarning(QLoggingCategory("EasyStreamer")) << "Could not set format:" << setErr->message;
g_clear_error(&setErr);
}
arv_camera_set_acquisition_mode(mArvCamera, ARV_ACQUISITION_MODE_CONTINUOUS, nullptr);
arv_camera_start_acquisition(mArvCamera, nullptr);
GError *error = nullptr;
mArvStream = arv_camera_create_stream(mArvCamera, nullptr, nullptr, &error);
if (error)
{
qCCritical(QLoggingCategory("EasyStreamer")) << "Stream creation error:" << error->message;
g_error_free(error);
g_object_unref(mArvCamera);
return;
}
size_t payload_size = arv_camera_get_payload(mArvCamera, nullptr);
for (int i = 0; i < 50; i++)
{
arv_stream_push_buffer(mArvStream, arv_buffer_new(payload_size, nullptr));
}
std::string filter = ui->leFilterVideo->text().toStdString();
EasyAV::VideoEncoderConfig config = mWtVideoConfig->getConfig();
int arvWidth = 0, arvHeight = 0;
arv_camera_get_region(mArvCamera, nullptr, nullptr, &arvWidth, &arvHeight, nullptr);
config.video.width = arvWidth;
config.video.height = arvHeight;
auto optStreamIdx = mSender.makeVideoStreamInPipeline(pipelineId, config, {1, 1000}, {filter, mWtFilterHwConfig->getConfig()});
if (optStreamIdx.has_value())
{
mVideoIdx = optStreamIdx.value();
}
else
{
qCWarning(catg) << _FUNC_RAW_ << "Couldn't make video stream for Aravis";
return;
}
mArvTimer = new QTimer(this);
connect(mArvTimer, &QTimer::timeout, this, [this]() {
if (!mArvStream)
return;
ArvBuffer *buffer = arv_stream_try_pop_buffer(mArvStream);
if (!buffer)
return;
if (arv_buffer_get_status(buffer) == ARV_BUFFER_STATUS_SUCCESS)
{
auto easyFrame = std::make_shared<EasyApi::ArvEasyFrame>(buffer);
mSender.pushFrame(pipelineId, mVideoIdx, easyFrame);
}
arv_stream_push_buffer(mArvStream, buffer);
});
mArvTimer->start(30);
#endif
}
void StreamingWt::stopArvCamera()
{
#ifdef BUILD_ARAVIS_SUPPORT_EASYSTREAMER
if (mArvTimer)
{
mArvTimer->stop();
delete mArvTimer;
mArvTimer = nullptr;
}
if (mArvCamera)
{
arv_camera_stop_acquisition(mArvCamera, nullptr);
if (mArvStream)
{
ArvBuffer *buffer = nullptr;
while ((buffer = arv_stream_try_pop_buffer(mArvStream)) != nullptr)
arv_stream_push_buffer(mArvStream, buffer);
g_object_unref(mArvStream);
mArvStream = nullptr;
}
g_object_unref(mArvCamera);
mArvCamera = nullptr;
}
#endif
}
void StreamingWt::stopCvInput()
{
if (mCvTimer)
{
mCvTimer->stop();
mCvTimer->deleteLater();
mCvTimer = nullptr;
}
#ifdef BUILD_OPENCV_SUPPORT_EASYSTREAMER
mCvCapture.reset();
#endif
}
void StreamingWt::onAddCameraClicked(int index = 0)
{
#ifdef BUILD_OPENCV_SUPPORT_EASYSTREAMER
stopCvInput();
mCvCapture = std::make_unique<cv::VideoCapture>(index);
if (!mCvCapture->isOpened())
{
qCCritical(QLoggingCategory("EasyStreamer")) << "Failed to open camera:" << index;
return;
}
mCvTimer = new QTimer(this);
std::string filter = ui->leFilterVideo->text().toStdString();
EasyAV::VideoEncoderConfig config = mWtVideoConfig->getConfig();
auto optStreamIdx = mSender.makeVideoStreamInPipeline(pipelineId, config, {1, 30},
{filter, mWtFilterHwConfig->getConfig()}); // time base of recieving
if (optStreamIdx.has_value())
mVideoIdx = optStreamIdx.value();
else
{
qCWarning(catg) << _FUNC_RAW_ << "couldn't make video stream";
return;
}
connect(mCvTimer, &QTimer::timeout, this, [this]() {
cv::Mat frame;
if (!mCvCapture->read(frame))
return;
auto easyFrame = EasyApi::CVEasyFrame::createFromMat(frame);
mSender.pushFrame(pipelineId, mVideoIdx, easyFrame);
});
mCvTimer->start(30); // ~30 FPS
#endif
}
void StreamingWt::onAddVideoClicked(QString path)
{
#ifdef BUILD_OPENCV_SUPPORT_EASYSTREAMER
stopCvInput();
if (!mSender.pipelineExists(pipelineId))
{
mActiveTransportServer = std::make_shared<EasyAV::RtpTransportServer>(
"rtp://" + ui->leIpRtp->text().toStdString() + ":" + ui->sbPortRtp->text().toStdString(), nullptr);
mSender.addMediaPipeline(pipelineId, mActiveTransportServer);
}
mCvCapture = std::make_unique<cv::VideoCapture>(path.toStdString(), cv::CAP_FFMPEG);
// qCInfo(QLoggingCategory("EasyStreamer")) << "Backend:" << mCvCapture->getBackendName().c_str();
if (!mCvCapture->isOpened())
{
qCCritical(QLoggingCategory("EasyStreamer")) << "Failed to open OpenCV file:" << path;
return;
}
mCvTimer = new QTimer(this);
std::string filter = ui->leFilterVideo->text().toStdString();
EasyAV::VideoEncoderConfig config = mWtVideoConfig->getConfig();
auto optStreamIdx = mSender.makeVideoStreamInPipeline(pipelineId, config, {1, 1000},
{filter, mWtFilterHwConfig->getConfig()}); // time base of recieving
if (optStreamIdx.has_value())
mVideoIdx = optStreamIdx.value();
else
{
qCWarning(catg) << _FUNC_RAW_ << "couldn't make video stream";
return;
}
connect(mCvTimer, &QTimer::timeout, this, [this]() {
if (!mCvCapture || !mCvCapture->isOpened())
return;
cv::Mat frame;
if (!mCvCapture->read(frame) || frame.empty())
return;
auto easyFrame = EasyApi::CVEasyFrame::createFromMat(frame);
mSender.pushFrame(pipelineId, mVideoIdx, easyFrame);
});
mCvTimer->start(33);
#endif
}
void StreamingWt::onAddStreamClicked()
{
EasyAV::StreamInfo selectedStream = mRcvrStreamsModel->getSelectedStream();
auto &reciever = mPlayer->reciever();
if (selectedStream.mediaType == EasyAV::MediaType::video)
{
std::string filter = ui->leFilterVideo->text().toStdString();
EasyAV::VideoEncoderConfig config = mWtVideoConfig->getConfig();
auto optStreamIdx = mSender.makeVideoStreamInPipeline(pipelineId, config, selectedStream.streamTimebase,
{filter, mWtFilterHwConfig->getConfig()}); // time base of recieving
if (!optStreamIdx.has_value())
{
qCWarning(catg) << _FUNC_RAW_ << "couldn't make video stream";
return;
}
mVideoIdx = optStreamIdx.value();
reciever.addRenderer(
pipelineId, EasyAV::SourceIdx{selectedStream.index.value}, [this](std::shared_ptr<EasyApi::IEasyFrame> videoFrame) {
// auto avVideo = std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(videoFrame);
mSender.pushFrame(pipelineId, mVideoIdx, std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(videoFrame));
if (mOverlayIdx.value != -1)
{
auto overlayFrame = makeOverlayFrame(videoFrame);
/*int64_t videoPts = avVideo->getRawAVFrame()->pts;
int64_t overlayPts = std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(overlayFrame)->getRawAVFrame()->pts;
qCCritical(QLoggingCategory("EasyStreamer"))
<< "VIDEO pts=" << videoPts
<< " OVERLAY pts=" << overlayPts
<< " diff=" << (videoPts - overlayPts);*/
mSender.pushFrame(pipelineId, mOverlayIdx, std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(overlayFrame));
}
});
}
else if (selectedStream.mediaType == EasyAV::MediaType::audio)
{
ui->stackedWidget->setCurrentIndex(1);
std::string filter = ui->leFilterAudio->text().toStdString();
auto optStreamIdx = mSender.makeAudioStreamInPipeline(pipelineId, mWtAudioConfig->getConfig(), selectedStream.streamTimebase,
ui->leFilterAudio->text().toStdString()); // time base to codec timebase
if (!optStreamIdx.has_value())
{
qCWarning(catg) << _FUNC_RAW_ << "couldn't make audio stream";
return;
}
mAudioIdx = optStreamIdx.value();
reciever.addRenderer(1, EasyAV::SourceIdx{selectedStream.index.value}, [this](std::shared_ptr<EasyApi::IEasyFrame> frame) {
mSender.pushFrame(pipelineId, mAudioIdx, std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(frame));
});
}
else if (selectedStream.mediaType == EasyAV::MediaType::data)
{
ui->stackedWidget->setCurrentIndex(2);
}
else
ui->stackedWidget->setCurrentIndex(2);
}
void StreamingWt::onAddOverlayClicked()
{
EasyAV::StreamInfo selectedStream = mRcvrStreamsModel->getSelectedStream();
ui->stackedWidget->setCurrentIndex(2);
// 1. Создаём data-stream в sender
auto optStreamIdx = mSender.makeOverlayStreamInPipeline(pipelineId, selectedStream.streamTimebase);
if (!optStreamIdx.has_value())
return;
mOverlayIdx = optStreamIdx.value();
mPlayer->setOverlayEnabled(true);
}
void StreamingWt::onSetupRtpClicked()
{
// TODO edit format AVDictionary;
// TODO edit -> add shMem;
mActiveTransportServer = std::make_shared<EasyAV::RtpTransportServer>(
"rtp://" + ui->leIpRtp->text().toStdString() + ":" + ui->sbPortRtp->text().toStdString(), nullptr);
auto rtpServer = std::dynamic_pointer_cast<EasyAV::RtpTransportServer>(mActiveTransportServer);
if (rtpServer)
{
rtpServer->setSdpOutputFilename(QString(QDir::currentPath() + "/rtpstream.sdp").toStdString());
}
bool success = mSender.addMediaPipeline(1, mActiveTransportServer);
if (success)
{
ui->pbSetupRtp->setEnabled(false);
ui->pbSetupShMem->setEnabled(false);
ui->pbSetupMpegUdp->setEnabled(false);
}
}
void StreamingWt::onSetupMpegTsUdpClicked()
{
std::string url = "udp://" + ui->leIpMpegUdp->text().toStdString() + ":" + ui->sbPortMpegUdp->text().toStdString();
mActiveTransportServer = std::make_shared<EasyAV::MpegTsUdpServer>(url, nullptr);
bool success = mSender.addMediaPipeline(1, mActiveTransportServer);
if (success)
{
ui->pbSetupRtp->setEnabled(false);
ui->pbSetupShMem->setEnabled(false);
ui->pbSetupMpegUdp->setEnabled(false);
}
else
{
qCWarning(catg) << _FUNC_RAW_ << "couldn't setup MPEGTS UDP transport; sender pipeline already exists";
ui->pbSetupMpegUdp->setEnabled(true);
}
}
void StreamingWt::onSetupShMemClicked()
{
// auto shMemSharedServer =
// std::make_shared<EasyAV::ShMemTransportServer>(ui->leShmName->text().toStdString(), ui->leSizeBytes->text().toInt(), nullptr);
// bool success = mSender.addMediaPipeline(1, shMemSharedServer);
// ui->pbSetupRtp->setEnabled(!success);
// ui->pbSetupShMem->setEnabled(!success);
}
void StreamingWt::setupSndrStreamModel()
{
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this]() {
if (!mSender.pipelineExists(1))
return;
mSndrStreamsModel->updateData(mSender.getStreamInfos(1));
});
timer->start(1000);
}
bool StreamingWt::onPlay()
{
bool ok = mSender.playPipeline(1);
if (ok)
setupSndrStreamModel();
return ok;
}
void StreamingWt::onStop()
{
stopCvInput();
mSender.stopPipeline(1);
}
std::shared_ptr<EasyApi::IEasyFrame> StreamingWt::makeOverlayFrame(std::shared_ptr<EasyApi::IEasyFrame> videoFrame)
{
auto avEasy = std::dynamic_pointer_cast<EasyApi::AVEasyFrame>(videoFrame);
if (!avEasy)
return {};
AVFrame *videoAv = avEasy->getRawAVFrame();
if (!videoAv || videoAv->pts == AV_NOPTS_VALUE)
return {};
auto payload = mPlayer->getOverlayData();
AVFrame *frame = av_frame_alloc();
if (!frame)
return {};
frame->format = AV_PIX_FMT_NONE;
frame->pts = videoAv->pts;
frame->pkt_dts = videoAv->pts;
frame->duration = frame->duration = videoAv->duration > 0 ? videoAv->duration : 1;
frame->buf[0] = av_buffer_alloc(payload.size());
if (!frame->buf[0])
{
av_frame_free(&frame);
return {};
}
frame->data[0] = frame->buf[0]->data;
frame->linesize[0] = payload.size();
memcpy(frame->data[0], payload.constData(), payload.size());
auto easyFrame = EasyAV::AVEasyFrame::createFromAVFrame(frame, std::chrono::microseconds(0));
if (!easyFrame)
return nullptr;
return easyFrame;
}
#pragma once
#include "audioencoderconfigwt.h"
#include "easyapi_avadapter/codecsettings.h"
#include "easyav/reciever/mediareciever.h"
#include "easyav/sender/mediasender.h"
#include <QTreeView>
#include <QWidget>
#ifdef BUILD_ARAVIS_SUPPORT_EASYSTREAMER
#include "easyapi_arvadapter/arveasyframe.h"
#endif
#include "mediaplayerwt.h"
#include "streamsmodel.h"
#include "videoencoderconfigwt.h"
namespace Ui
{
class StreamingWt;
}
class StreamingWt : public QWidget
{
Q_OBJECT
public:
explicit StreamingWt(MediaPlayerWt *player, QWidget *parent = nullptr);
~StreamingWt();
public slots:
void onInputReady();
void onSetupRtpClicked();
void onSetupShMemClicked();
void onSetupMpegTsUdpClicked();
private slots:
// void onOverlayPayload(const QByteArray &payload);
private:
bool mOverlayListed = false;
std::atomic<long long> mLastVideoPtsUs{0};
// bool mOverlayAdded = 0;
static constexpr int pipelineId{1};
Ui::StreamingWt *ui;
MediaPlayerWt *mPlayer;
EasyAV::MediaSender mSender;
StreamsModel *mRcvrStreamsModel;
StreamsModel *mSndrStreamsModel;
QTimer *mCvTimer = nullptr;
void onAddArvCameraClicked(); // Слот для кнопки
#ifdef BUILD_ARAVIS_SUPPORT_EASYSTREAMER
ArvCamera* mArvCamera = nullptr;
ArvStream* mArvStream = nullptr;
#endif
QTimer* mArvTimer = nullptr;
std::shared_ptr<EasyAV::ITransportServer> mActiveTransportServer;
#ifdef BUILD_OPENCV_SUPPORT_EASYSTREAMER
std::unique_ptr<cv::VideoCapture> mCvCapture;
#endif
EasyAV::VideoEncoderConfig mCurVideoConfig;
VideoEncoderConfigWt *mWtVideoConfig;
AudioEncoderConfigWt *mWtAudioConfig;
HwConfigWt *mWtFilterHwConfig;
MediaControlWt *mWtControl;
EasyAV::SourceIdx mVideoIdx{-1};
EasyAV::SourceIdx mAudioIdx{-1};
EasyAV::SourceIdx mOverlayIdx{-1};
void setupStreamMonitor();
void setupSndrStreamModel();
void setupWidgets();
void loadSettings();
void saveSettings();
void stopCvInput();
void stopArvCamera();
void onAddStreamClicked();
void onAddOverlayClicked();
void onAddCameraClicked(int index);
void onAddVideoClicked(QString path);
bool onFrameImported(EasyAV::MediaReciever::PipelineId pipeId, int32_t streamIdx, EasyAV::MediaType mt, AVFrame *frame);
bool onPlay();
void onStop();
std::shared_ptr<EasyApi::IEasyFrame> makeOverlayFrame(std::shared_ptr<EasyApi::IEasyFrame> videoFrame);
};