mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 21:13:12 -07:00
Move Chiaki Session to StreamSession
This commit is contained in:
parent
c5bb81c015
commit
49e7143de9
5 changed files with 157 additions and 123 deletions
|
@ -18,21 +18,45 @@
|
||||||
#ifndef CHIAKI_STREAMSESSION_H
|
#ifndef CHIAKI_STREAMSESSION_H
|
||||||
#define CHIAKI_STREAMSESSION_H
|
#define CHIAKI_STREAMSESSION_H
|
||||||
|
|
||||||
|
#include "videodecoder.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QGamepad>
|
#include <QImage>
|
||||||
|
|
||||||
|
#include <chiaki/session.h>
|
||||||
|
|
||||||
|
class QGamepad;
|
||||||
|
class QAudioOutput;
|
||||||
|
class QIODevice;
|
||||||
|
|
||||||
class StreamSession : public QObject
|
class StreamSession : public QObject
|
||||||
{
|
{
|
||||||
|
friend class StreamSessionPrivate;
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ChiakiSession session;
|
||||||
|
|
||||||
QGamepad *gamepad;
|
QGamepad *gamepad;
|
||||||
|
|
||||||
|
VideoDecoder video_decoder;
|
||||||
|
|
||||||
|
QAudioOutput *audio_output;
|
||||||
|
QIODevice *audio_io;
|
||||||
|
|
||||||
|
void PushAudioFrame(int16_t *buf, size_t samples_count);
|
||||||
|
void PushVideoSample(uint8_t *buf, size_t buf_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StreamSession(QObject *parent = nullptr);
|
explicit StreamSession(const QString &host, const QString ®istkey, const QString &ostype, const QString &auth, const QString &morning, const QString &did, QObject *parent = nullptr);
|
||||||
~StreamSession();
|
~StreamSession();
|
||||||
|
|
||||||
QGamepad *GetGamepad() { return gamepad; }
|
QGamepad *GetGamepad() { return gamepad; }
|
||||||
|
VideoDecoder *GetVideoDecoder() { return &video_decoder; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void CurrentImageUpdated();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void UpdateGamepads();
|
void UpdateGamepads();
|
||||||
|
|
|
@ -21,19 +21,25 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
class StreamSession;
|
||||||
|
|
||||||
class StreamWindow: public QMainWindow
|
class StreamWindow: public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StreamWindow(QWidget *parent = nullptr);
|
explicit StreamWindow(StreamSession *session, QWidget *parent = nullptr);
|
||||||
~StreamWindow();
|
~StreamWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
StreamSession *session;
|
||||||
|
|
||||||
|
QLabel *imageLabel;
|
||||||
|
|
||||||
void SetImage(const QImage &image);
|
void SetImage(const QImage &image);
|
||||||
|
|
||||||
private:
|
private slots:
|
||||||
QLabel *imageLabel;
|
void FramesAvailable();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHIAKI_GUI_STREAMWINDOW_H
|
#endif // CHIAKI_GUI_STREAMWINDOW_H
|
||||||
|
|
117
gui/src/main.cpp
117
gui/src/main.cpp
|
@ -86,127 +86,16 @@ int RunMain(QApplication &app)
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAudioOutput *audio_out;
|
|
||||||
QIODevice *audio_io;
|
|
||||||
|
|
||||||
VideoDecoder video_decoder;
|
|
||||||
|
|
||||||
|
|
||||||
void audio_frame_cb(int16_t *buf, size_t samples_count, void *user)
|
|
||||||
{
|
|
||||||
audio_io->write((const char *)buf, static_cast<qint64>(samples_count * 2 * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
void video_sample_cb(uint8_t *buf, size_t buf_size, void *user)
|
|
||||||
{
|
|
||||||
video_decoder.PutFrame(buf, buf_size);
|
|
||||||
/*if(!video_out_file)
|
|
||||||
return;
|
|
||||||
printf("writing %#zx to file, start: %#zx\n", buf_size, file_size);
|
|
||||||
chiaki_log_hexdump(nullptr, CHIAKI_LOG_DEBUG, buf, buf_size);
|
|
||||||
file_size += buf_size;
|
|
||||||
video_out_file->write((const char *)buf, buf_size);*/
|
|
||||||
//StreamRelayIODevice *io_device = reinterpret_cast<StreamRelayIODevice *>(user);
|
|
||||||
//io_device->PushSample(buf, buf_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RunStream(QApplication &app, const QString &host, const QString ®istkey, const QString &ostype, const QString &auth, const QString &morning, const QString &did)
|
int RunStream(QApplication &app, const QString &host, const QString ®istkey, const QString &ostype, const QString &auth, const QString &morning, const QString &did)
|
||||||
{
|
{
|
||||||
StreamSession stream_session;
|
StreamSession stream_session(host, registkey, ostype, auth, morning, did);
|
||||||
|
|
||||||
QByteArray host_str = host.toUtf8();
|
StreamWindow window(&stream_session);
|
||||||
QByteArray registkey_str = registkey.toUtf8();
|
|
||||||
QByteArray ostype_str = ostype.toUtf8();
|
|
||||||
|
|
||||||
ChiakiConnectInfo connect_info;
|
|
||||||
connect_info.host = host_str.constData();
|
|
||||||
connect_info.regist_key = registkey_str.constData();
|
|
||||||
connect_info.ostype = ostype_str.constData();
|
|
||||||
|
|
||||||
QByteArray auth_str = auth.toUtf8();
|
|
||||||
size_t auth_len = auth_str.length();
|
|
||||||
if(auth_len > sizeof(connect_info.auth))
|
|
||||||
auth_len = sizeof(connect_info.auth);
|
|
||||||
memcpy(connect_info.auth, auth_str.constData(), auth_len);
|
|
||||||
if(auth_len < sizeof(connect_info.auth))
|
|
||||||
memset(connect_info.auth + auth_len, 0, sizeof(connect_info.auth) - auth_len);
|
|
||||||
|
|
||||||
size_t morning_size = sizeof(connect_info.morning);
|
|
||||||
QByteArray morning_str = morning.toUtf8();
|
|
||||||
ChiakiErrorCode err = chiaki_base64_decode(morning_str.constData(), morning_str.length(), connect_info.morning, &morning_size);
|
|
||||||
if(err != CHIAKI_ERR_SUCCESS || morning_size != sizeof(connect_info.morning))
|
|
||||||
{
|
|
||||||
printf("morning invalid.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t did_size = sizeof(connect_info.did);
|
|
||||||
QByteArray did_str = did.toUtf8();
|
|
||||||
err = chiaki_base64_decode(did_str.constData(), did_str.length(), connect_info.did, &did_size);
|
|
||||||
if(err != CHIAKI_ERR_SUCCESS || did_size != sizeof(connect_info.did))
|
|
||||||
{
|
|
||||||
printf("did invalid.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamWindow window;
|
|
||||||
window.resize(640, 360);
|
window.resize(640, 360);
|
||||||
window.show();
|
window.show();
|
||||||
|
|
||||||
|
|
||||||
QAudioFormat audio_format;
|
|
||||||
audio_format.setSampleRate(48000);
|
|
||||||
audio_format.setChannelCount(2);
|
|
||||||
audio_format.setSampleSize(16);
|
|
||||||
audio_format.setCodec("audio/pcm");
|
|
||||||
audio_format.setSampleType(QAudioFormat::SignedInt);
|
|
||||||
|
|
||||||
QAudioDeviceInfo audio_device_info(QAudioDeviceInfo::defaultOutputDevice());
|
|
||||||
if(!audio_device_info.isFormatSupported(audio_format))
|
|
||||||
{
|
|
||||||
printf("audio output format not supported\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_out = new QAudioOutput(audio_format);
|
|
||||||
audio_io = audio_out->start();
|
|
||||||
|
|
||||||
|
|
||||||
//video_out_file = nullptr;
|
|
||||||
//video_out_file->open(QFile::ReadWrite);
|
|
||||||
|
|
||||||
QObject::connect(&video_decoder, &VideoDecoder::FramesAvailable, &window, [&window]() {
|
|
||||||
QImage prev;
|
|
||||||
QImage image;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
prev = image;
|
|
||||||
image = video_decoder.PullFrame();
|
|
||||||
} while(!image.isNull());
|
|
||||||
|
|
||||||
if(!prev.isNull())
|
|
||||||
{
|
|
||||||
window.SetImage(prev);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ChiakiSession session;
|
|
||||||
chiaki_session_init(&session, &connect_info);
|
|
||||||
chiaki_session_set_audio_frame_cb(&session, audio_frame_cb, nullptr);
|
|
||||||
chiaki_session_set_video_sample_cb(&session, video_sample_cb, nullptr);
|
|
||||||
chiaki_session_start(&session);
|
|
||||||
|
|
||||||
app.setQuitOnLastWindowClosed(true);
|
app.setQuitOnLastWindowClosed(true);
|
||||||
|
return app.exec();
|
||||||
int ret = app.exec();
|
|
||||||
|
|
||||||
//video_out_file->close();
|
|
||||||
|
|
||||||
//printf("CLOSED!!! filesize: %zu\n", file_size);
|
|
||||||
|
|
||||||
chiaki_session_join(&session);
|
|
||||||
chiaki_session_fini(&session);
|
|
||||||
|
|
||||||
delete audio_out;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,85 @@
|
||||||
|
|
||||||
#include <streamsession.h>
|
#include <streamsession.h>
|
||||||
|
|
||||||
|
#include <chiaki/base64.h>
|
||||||
|
|
||||||
#include <QGamepadManager>
|
#include <QGamepadManager>
|
||||||
|
#include <QAudioOutput>
|
||||||
|
#include <QGamepad>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
StreamSession::StreamSession(QObject *parent)
|
|
||||||
|
static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user);
|
||||||
|
static void VideoSampleCb(uint8_t *buf, size_t buf_size, void *user);
|
||||||
|
|
||||||
|
StreamSession::StreamSession(const QString &host, const QString ®istkey, const QString &ostype, const QString &auth, const QString &morning, const QString &did, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
gamepad(nullptr)
|
gamepad(nullptr)
|
||||||
{
|
{
|
||||||
|
QByteArray host_str = host.toUtf8();
|
||||||
|
QByteArray registkey_str = registkey.toUtf8();
|
||||||
|
QByteArray ostype_str = ostype.toUtf8();
|
||||||
|
|
||||||
|
ChiakiConnectInfo connect_info;
|
||||||
|
connect_info.host = host_str.constData();
|
||||||
|
connect_info.regist_key = registkey_str.constData();
|
||||||
|
connect_info.ostype = ostype_str.constData();
|
||||||
|
|
||||||
|
QByteArray auth_str = auth.toUtf8();
|
||||||
|
size_t auth_len = auth_str.length();
|
||||||
|
if(auth_len > sizeof(connect_info.auth))
|
||||||
|
auth_len = sizeof(connect_info.auth);
|
||||||
|
memcpy(connect_info.auth, auth_str.constData(), auth_len);
|
||||||
|
if(auth_len < sizeof(connect_info.auth))
|
||||||
|
memset(connect_info.auth + auth_len, 0, sizeof(connect_info.auth) - auth_len);
|
||||||
|
|
||||||
|
size_t morning_size = sizeof(connect_info.morning);
|
||||||
|
QByteArray morning_str = morning.toUtf8();
|
||||||
|
ChiakiErrorCode err = chiaki_base64_decode(morning_str.constData(), morning_str.length(), connect_info.morning, &morning_size);
|
||||||
|
if(err != CHIAKI_ERR_SUCCESS || morning_size != sizeof(connect_info.morning))
|
||||||
|
{
|
||||||
|
printf("morning invalid.\n");
|
||||||
|
throw std::exception(); // TODO: proper exception
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t did_size = sizeof(connect_info.did);
|
||||||
|
QByteArray did_str = did.toUtf8();
|
||||||
|
err = chiaki_base64_decode(did_str.constData(), did_str.length(), connect_info.did, &did_size);
|
||||||
|
if(err != CHIAKI_ERR_SUCCESS || did_size != sizeof(connect_info.did))
|
||||||
|
{
|
||||||
|
printf("did invalid.\n");
|
||||||
|
throw std::exception(); // TODO: proper exception
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudioFormat audio_format;
|
||||||
|
audio_format.setSampleRate(48000);
|
||||||
|
audio_format.setChannelCount(2);
|
||||||
|
audio_format.setSampleSize(16);
|
||||||
|
audio_format.setCodec("audio/pcm");
|
||||||
|
audio_format.setSampleType(QAudioFormat::SignedInt);
|
||||||
|
|
||||||
|
QAudioDeviceInfo audio_device_info(QAudioDeviceInfo::defaultOutputDevice());
|
||||||
|
if(!audio_device_info.isFormatSupported(audio_format))
|
||||||
|
{
|
||||||
|
printf("audio output format not supported\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_output = new QAudioOutput(audio_format, this);
|
||||||
|
audio_io = audio_output->start();
|
||||||
|
|
||||||
|
chiaki_session_init(&session, &connect_info);
|
||||||
|
chiaki_session_set_audio_frame_cb(&session, AudioFrameCb, this);
|
||||||
|
chiaki_session_set_video_sample_cb(&session, VideoSampleCb, this);
|
||||||
|
chiaki_session_start(&session);
|
||||||
|
|
||||||
connect(QGamepadManager::instance(), &QGamepadManager::connectedGamepadsChanged, this, &StreamSession::UpdateGamepads);
|
connect(QGamepadManager::instance(), &QGamepadManager::connectedGamepadsChanged, this, &StreamSession::UpdateGamepads);
|
||||||
UpdateGamepads();
|
UpdateGamepads();
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSession::~StreamSession()
|
StreamSession::~StreamSession()
|
||||||
{
|
{
|
||||||
|
chiaki_session_join(&session);
|
||||||
|
chiaki_session_fini(&session);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamSession::UpdateGamepads()
|
void StreamSession::UpdateGamepads()
|
||||||
|
@ -50,3 +116,32 @@ void StreamSession::UpdateGamepads()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StreamSession::PushAudioFrame(int16_t *buf, size_t samples_count)
|
||||||
|
{
|
||||||
|
audio_io->write((const char *)buf, static_cast<qint64>(samples_count * 2 * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamSession::PushVideoSample(uint8_t *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
video_decoder.PutFrame(buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
class StreamSessionPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void PushAudioFrame(StreamSession *session, int16_t *buf, size_t samples_count) { session->PushAudioFrame(buf, samples_count); }
|
||||||
|
static void PushVideoSample(StreamSession *session, uint8_t *buf, size_t buf_size) { session->PushVideoSample(buf, buf_size); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user)
|
||||||
|
{
|
||||||
|
auto session = reinterpret_cast<StreamSession *>(user);
|
||||||
|
StreamSessionPrivate::PushAudioFrame(session, buf, samples_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void VideoSampleCb(uint8_t *buf, size_t buf_size, void *user)
|
||||||
|
{
|
||||||
|
auto session = reinterpret_cast<StreamSession *>(user);
|
||||||
|
StreamSessionPrivate::PushVideoSample(session, buf, buf_size);
|
||||||
|
}
|
|
@ -16,11 +16,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <streamwindow.h>
|
#include <streamwindow.h>
|
||||||
|
#include <streamsession.h>
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
StreamWindow::StreamWindow(QWidget *parent)
|
StreamWindow::StreamWindow(StreamSession *session, QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent),
|
||||||
|
session(session)
|
||||||
{
|
{
|
||||||
imageLabel = new QLabel(this);
|
imageLabel = new QLabel(this);
|
||||||
setCentralWidget(imageLabel);
|
setCentralWidget(imageLabel);
|
||||||
|
@ -29,6 +31,8 @@ StreamWindow::StreamWindow(QWidget *parent)
|
||||||
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||||
imageLabel->setScaledContents(true);
|
imageLabel->setScaledContents(true);
|
||||||
|
|
||||||
|
connect(session->GetVideoDecoder(), &VideoDecoder::FramesAvailable, this, &StreamWindow::FramesAvailable);
|
||||||
|
FramesAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamWindow::~StreamWindow()
|
StreamWindow::~StreamWindow()
|
||||||
|
@ -39,3 +43,19 @@ void StreamWindow::SetImage(const QImage &image)
|
||||||
{
|
{
|
||||||
imageLabel->setPixmap(QPixmap::fromImage(image));
|
imageLabel->setPixmap(QPixmap::fromImage(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StreamWindow::FramesAvailable()
|
||||||
|
{
|
||||||
|
QImage prev;
|
||||||
|
QImage image;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
prev = image;
|
||||||
|
image = session->GetVideoDecoder()->PullFrame();
|
||||||
|
} while(!image.isNull());
|
||||||
|
|
||||||
|
if(!prev.isNull())
|
||||||
|
{
|
||||||
|
SetImage(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue