Commit c5e6a682 authored by Silas Della Contrada's avatar Silas Della Contrada
Browse files

Feature complete (seeking)

 - fixed AVPlayer not restarted when transcoding already finished
 - TODO: Fix seeking in paused state results in resuming playback
parent 40271a6c
......@@ -25,7 +25,7 @@ Page {
FileDialog {
id: mediaSelectionDialog
title: "Please choose a media file"
folder: "file:///Users/Silas/Videos/Captures"
folder: "file:///home/silas/"
selectMultiple: false
selectExisting: true
selectFolder: false
......
......@@ -8,6 +8,18 @@ Page {
property alias togglePlayPauseBtn: playPauseBtn
property alias positionChangeSlider: positionSlider
function msToTime(duration) {
var seconds = Math.floor((duration / 1000) % 60);
var minutes = Math.floor((duration / (1000 * 60)) % 60);
var hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return hours + ":" + minutes + ":" + seconds;
}
header: Label {
font.pixelSize: Qt.application.font.pixelSize * 2
text: qsTr("Streaming Control Panel")
......@@ -82,11 +94,18 @@ Page {
anchors.right: parent.right
anchors.rightMargin: 20
id: positionSlider
onPressedChanged: {
if (!pressed) {
backendAPI.seek(value)
}
}
onMoved: {
currentPlayPos.text = pageStreaming.msToTime(positionSlider.value)
// positionSliderPopup.label.text = msToTime(value)
}
from: 0
value: 0
to: 100
......@@ -100,29 +119,21 @@ Page {
}
Connections {
function msToTime(duration) {
var seconds = Math.floor((duration / 1000) % 60);
var minutes = Math.floor((duration / (1000 * 60)) % 60);
var hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return hours + ":" + minutes + ":" + seconds;
}
target: backendAPI
function onPlaybackPositionChanged(position) {
positionSlider.value = position
console.log("[PageStreaming] position set:" + position + "/" + positionSlider.to)
currentPlayPos.text = msToTime(position)
if (!positionSlider.pressed) {
positionSlider.value = position
console.log("[PageStreaming] position set:" + position + "/" + positionSlider.to)
currentPlayPos.text = pageStreaming.msToTime(position)
}
}
function onDurationLoaded(dur) {
positionSlider.to = dur
console.log("[PageStreaming] duration set")
duration.text = "/ " + msToTime(dur)
duration.text = "/ " + pageStreaming.msToTime(dur)
}
}
}
......
......@@ -50,10 +50,10 @@ unix {
LIBS += -lQtAV -lQtAVWidgets
QMAKE_LFLAGS_RPATH=
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\'"
copyToDestDir($$OUT_PWD/libbackend.so, $$OUT_PWD/VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1, $$OUT_PWD/VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1.0, $$OUT_PWD/VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1.0.0, $$OUT_PWD/VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so, $$OUT_PWD/../VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1, $$OUT_PWD/../VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1.0, $$OUT_PWD/../VanadiumCast/)
copyToDestDir($$OUT_PWD/libbackend.so.1.0.0, $$OUT_PWD/../VanadiumCast/)
}
......
......@@ -275,6 +275,7 @@ void NetworkAPI::streamThreadFinished() {
disconnect(streamThreadCon3);
delete streamThread;
streamThread = nullptr;
firstPositionChange = false;
}
qint64 NetworkAPI::getDuration() {
......
......@@ -42,9 +42,10 @@ bool VideoGuiLauncher::event(QEvent *event) {
break;
}
case EventAction::START_PLAYER: {
qDebug() << "[VideoGui] Starting resetted sink playback";
qDebug() << "[VideoGuiLauncher] Starting resetted sink playback";
avPlayer->play();
if (isPausedByUser) {
qDebug() << "[VideoGuiLauncher] Pausing restarted Player";
avPlayer->pause(true);
}
emit actionFinished();
......@@ -108,7 +109,7 @@ void VideoGuiLauncher::create() {
qDebug() << "[VideoGui] nVidia CUVID decoder selected";
videoCodecs << "CUDA";
} else if (vendor.compare("AMD", Qt::CaseInsensitive) == 0) {
qDebug() << "[VideoGui] VAAPI decoder selected";
qDebug() << "[VideoGui] AMD VAAPI decoder selected";
videoCodecs << "VAAPI";
}
#endif
......@@ -120,7 +121,7 @@ void VideoGuiLauncher::create() {
videoCodecs << "FFmpeg";
avPlayer->setVideoDecoderPriority(videoCodecs);
videoRenderer->setPreferredPixelFormat(QtAV::VideoFormat::Format_YUV420P10LE);
videoRenderer->setPreferredPixelFormat(QtAV::VideoFormat::Format_YUV420P);
// avPlayer->setAutoLoad();
// avPlayer->setAsyncLoad();
bufferCon1 = connect(inputDevice, &End::inputUnderrun, [&]() {
......
......@@ -157,7 +157,9 @@ bool VideoTranscoder::isPaused() {
}
bool VideoTranscoder::seek(qint64 secPos) {
if (secPos <= avPlayer->duration() && secPos >= 0) {
if (secPos <= duration && secPos >= 0) {
qDebug() << "[VideoTranscoder] Seeking AVPlayer in state:" << (avPlayer->state() == QtAV::AVPlayer::PausedState ? "Paused"
: (avPlayer->state() == QtAV::AVPlayer::StoppedState ? "Stopped" : "Playing"));
switch (avPlayer->state()) {
case QtAV::AVPlayer::PlayingState: {
pause();
......@@ -168,18 +170,30 @@ bool VideoTranscoder::seek(qint64 secPos) {
case QtAV::AVPlayer::PausedState: {
avPlayer->setPosition(secPos);
resume();
QTimer::singleShot(1500, [&]() {
QTimer::singleShot(1000, [&]() {
pause();
});
break;
}
case QtAV::AVPlayer::StoppedState: {
qDebug() << "[VideoTranscoder] Restarting finished AVTranscoder and AVPlayer";
avTranscoder->stop();
qDebug() << "[VideoTranscoder] Stopped Transcoder";
avPlayer->stop();
qDebug() << "[VideoTranscoder] Stopped Player";
avTranscoder->start();
qDebug() << "[VideoTranscoder] Started Transcoder";
avPlayer->setStartPosition(secPos);
qDebug() << "[VideoTranscoder] Set Player start position";
avPlayer->play();
avPlayer->setPosition(secPos);
qDebug() << "[VideoTranscoder] Started Player";
qDebug() << "[VideoTranscoder] Restarted finished AVTranscoder and AVPlayer";
break;
}
}
return true;
}
qDebug() << "[VideoTranscoder] Invalid position";
return false;
}
......
......@@ -106,30 +106,30 @@ private:
// High profile
HIGH.audioCodecName = "aac";
HIGH.videoCodecName = videoCodecSQ;
HIGH.videoCodecName = videoCodecHQ;
HIGH.width = 1920;
HIGH.height = 1080;
HIGH.rate = 10000000;
HIGH.rate = 15000000;
HIGH.framerate = 60;
HIGH.bytesPerColor = 1;
// Ultra profile
ULTRA.audioCodecName = "aac";
ULTRA.videoCodecName = videoCodecHQ;
ULTRA.width = 2560;
ULTRA.height = 1440;
ULTRA.rate = 15000000;
ULTRA.framerate = 60;
ULTRA.bytesPerColor = 2;
// Extreme profile
EXTREME.audioCodecName = "aac";
EXTREME.videoCodecName = videoCodecHQ;
EXTREME.width = 3840;
EXTREME.height = 2160;
EXTREME.rate = 30000000;
EXTREME.framerate = 60;
EXTREME.bytesPerColor = 2;
// // Ultra profile
// ULTRA.audioCodecName = "aac";
// ULTRA.videoCodecName = videoCodecHQ;
// ULTRA.width = 2560;
// ULTRA.height = 1440;
// ULTRA.rate = 15000000;
// ULTRA.framerate = 60;
// ULTRA.bytesPerColor = 2;
// // Extreme profile
// EXTREME.audioCodecName = "aac";
// EXTREME.videoCodecName = videoCodecHQ;
// EXTREME.width = 3840;
// EXTREME.height = 2160;
// EXTREME.rate = 30000000;
// EXTREME.framerate = 60;
// EXTREME.bytesPerColor = 2;
encodingProfilesInitialized = true;
}
......
......@@ -48,7 +48,7 @@ void NetworkSinkHandler::run() {
qDebug() << "[NetworkSinkHandler] Answered request";
if (dataConnectionServer->waitForNewConnection(30000)) {
dataConnection = dataConnectionServer->nextPendingConnection();
cachedLocalStream = new CachedLocalStream(32 * 1024 * 1024, 128, 1024);
cachedLocalStream = new CachedLocalStream(32 * 1024 * 1024, 64, 512);
controller = new SinkController(this);
videoGuiLauncher = new VideoGuiLauncher(cachedLocalStream->getEnd2());
videoGuiLauncher->moveToThread(QApplication::instance()->thread());
......
......@@ -32,7 +32,7 @@ void StreamThread::run() {
dataConnection->connectToHost(controlConnection->peerAddress(), 55556);
dataConnection->waitForConnected(1000);
cachedOutput = new CachedLocalStream(64 * 1024 * 1024, 128, 1024);
transcoder = new VideoTranscoder(inputFile, cachedOutput->getEnd2(), VideoTranscoder::MEDIUM);
transcoder = new VideoTranscoder(inputFile, cachedOutput->getEnd2(), VideoTranscoder::HIGH);
playbackController = new PlaybackController(controlConnection, transcoder, this);
qDebug() << "[StreamThread] Playback Controller lives in:" << playbackController->thread();
qDebug() << "[StreamThread] StreamThread::run() is running in:" << currentThread();
......@@ -252,7 +252,6 @@ bool PlaybackController::isPaused() {
bool PlaybackController::seek(qint64 absPos) {
streamThread->suspendControlHandling();
streamThread->transcoder->pause();
streamThread->cachedOutput->clear();
controlConnection->write(Command::SEEK);
controlConnection->readAll();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment