Add LockThreadDetector, integrate soon...
This commit is contained in:
rock88 2021-02-23 15:34:09 +03:00
parent 1be75b0c93
commit 24436ad841
7 changed files with 87 additions and 106 deletions

View file

@ -44,7 +44,7 @@ APP_AUTHOR := port by rock88
APP_VERSION := 1.1.0
BUILD := build
SOURCES := src src/libgamestream src/switch src/nanogui_resources src/streaming src/streaming/ffmpeg \
src/crypto src/streaming/video src/crypto src/streaming/audio src/ui/windows src/ui/buttons src/ui src/helpers src/controls\
src/crypto src/streaming/video src/crypto src/streaming/audio src/ui/windows src/ui/buttons src/ui src/utils src/controls\
third_party/moonlight-common-c/enet third_party/moonlight-common-c/reedsolomon third_party/moonlight-common-c/src \
third_party/nanogui/ext/nanovg/src third_party/nanogui/src
DATA := data
@ -65,7 +65,7 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
M_INCLUDES := \
-I$(TOPDIR)/src -I$(TOPDIR)/src/switch -I$(TOPDIR)/src/streaming -I$(TOPDIR)/src/crypto -I$(TOPDIR)/src/crypto/keys \
-I$(TOPDIR)/src/streaming/ffmpeg -I$(TOPDIR)/src/streaming/video -I$(TOPDIR)/src/streaming/audio \
-I$(TOPDIR)/src/nanogui_resources -I$(TOPDIR)/src/helpers -I$(TOPDIR)/src/controls \
-I$(TOPDIR)/src/nanogui_resources -I$(TOPDIR)/src/utils -I$(TOPDIR)/src/controls \
-I$(TOPDIR)/src/ui -I$(TOPDIR)/src/ui/buttons -I$(TOPDIR)/src/ui/windows \
-I$(TOPDIR)/src/libgamestream \
-I$(TOPDIR)/third_party/moonlight-common-c/reedsolomon \

View file

@ -106,6 +106,7 @@
36A0C0372461DBA30083289C /* AddHostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A0C0352461DBA30083289C /* AddHostButton.cpp */; };
36A0C03A2461E4C00083289C /* SettingsWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A0C0382461E4C00083289C /* SettingsWindow.cpp */; };
36A0C03D2461F03C0083289C /* Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A0C03B2461F03C0083289C /* Settings.cpp */; };
36BD0AFE25E5251300DD1B86 /* LockThreadDetector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36BD0AFC25E5251300DD1B86 /* LockThreadDetector.cpp */; };
36BFCCF12479723E00245D40 /* xml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36BFCCEA2479723E00245D40 /* xml.cpp */; };
36BFCCF22479723E00245D40 /* client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36BFCCEC2479723E00245D40 /* client.cpp */; };
36BFCCF32479723E00245D40 /* http.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36BFCCF02479723E00245D40 /* http.cpp */; };
@ -320,6 +321,8 @@
36A0C0392461E4C00083289C /* SettingsWindow.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SettingsWindow.hpp; sourceTree = "<group>"; };
36A0C03B2461F03C0083289C /* Settings.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Settings.cpp; sourceTree = "<group>"; };
36A0C03C2461F03C0083289C /* Settings.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Settings.hpp; sourceTree = "<group>"; };
36BD0AFC25E5251300DD1B86 /* LockThreadDetector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LockThreadDetector.cpp; sourceTree = "<group>"; };
36BD0AFD25E5251300DD1B86 /* LockThreadDetector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LockThreadDetector.hpp; sourceTree = "<group>"; };
36BFCCEA2479723E00245D40 /* xml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xml.cpp; sourceTree = "<group>"; };
36BFCCEB2479723E00245D40 /* client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = client.h; sourceTree = "<group>"; };
36BFCCEC2479723E00245D40 /* client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = client.cpp; sourceTree = "<group>"; };
@ -432,12 +435,14 @@
path = controls;
sourceTree = "<group>";
};
3620419025D7FDCC00D21EE3 /* helpers */ = {
3620419025D7FDCC00D21EE3 /* utils */ = {
isa = PBXGroup;
children = (
3620419125D7FDDB00D21EE3 /* Singleton.hpp */,
36BD0AFC25E5251300DD1B86 /* LockThreadDetector.cpp */,
36BD0AFD25E5251300DD1B86 /* LockThreadDetector.hpp */,
);
path = helpers;
path = utils;
sourceTree = "<group>";
};
3652ECC3245B3AFF001FABF3 /* nanogui */ = {
@ -684,7 +689,7 @@
36B406932459F41E005BD903 /* src */ = {
isa = PBXGroup;
children = (
3620419025D7FDCC00D21EE3 /* helpers */,
3620419025D7FDCC00D21EE3 /* utils */,
36BFCCE92479723E00245D40 /* libgamestream */,
36E63789246FFFDC0032F5FB /* crypto */,
36DFE0CA2459FA3F00FC51CE /* nanogui_resources */,
@ -1008,6 +1013,7 @@
3652EFE8245B3B00001FABF3 /* opengl.cpp in Sources */,
3652EFD7245B3B00001FABF3 /* screen.cpp in Sources */,
3652EFE1245B3B00001FABF3 /* progressbar.cpp in Sources */,
36BD0AFE25E5251300DD1B86 /* LockThreadDetector.cpp in Sources */,
3652EFF5245B3B00001FABF3 /* popupbutton.cpp in Sources */,
3652EFF0245B3B00001FABF3 /* colorwheel.cpp in Sources */,
3652F068245C292B001FABF3 /* unix.c in Sources */,

View file

@ -10,77 +10,9 @@
#define DECODER_BUFFER_SIZE 92 * 1024 * 2
#include <switch.h>
#include <unistd.h>
FFmpegVideoDecoder::FFmpegVideoDecoder() {}
class ThreadLockWatcher {
public:
void start() {
std::lock_guard<std::mutex> lock(m_mutex);
is_alive = true;
prev = current = 0;
pthread_create(&thread, NULL, entry, this);
}
void stop() {
std::lock_guard<std::mutex> lock(m_mutex);
is_alive = false;
}
void enter(int line) {
std::lock_guard<std::mutex> lock(m_mutex);
last_line = line;
prev = current;
current++;
}
private:
bool is_alive = false;
u64 prev = 0;
u64 current = 0;
int last_line = 0;
static void* entry(void* context) {
while (true) {
if (auto watcher = static_cast<ThreadLockWatcher *>(context)) {
if (watcher->is_alive) {
if (watcher->current != 0) {
std::lock_guard<std::mutex> lock(watcher->m_mutex);
if (watcher->prev > watcher->current) {
Logger::error("ThreadLockWatcher", "Thread Lock Detected on a line: %i", watcher->last_line);
} else {
watcher->prev++;
}
}
usleep(500'000);
} else {
return NULL;
}
} else {
return NULL;
}
}
return NULL;
}
std::mutex m_mutex;
pthread_t thread;
};
static ThreadLockWatcher watcher;
#define DBG() watcher.enter(__LINE__);
FFmpegVideoDecoder::FFmpegVideoDecoder() {
//pthread_mutex_init(&m_mutex, NULL);
watcher.start();
}
FFmpegVideoDecoder::~FFmpegVideoDecoder() {
watcher.stop();
//pthread_mutex_destroy(&m_mutex);
}
FFmpegVideoDecoder::~FFmpegVideoDecoder() {}
int FFmpegVideoDecoder::setup(int video_format, int width, int height, int redraw_rate, void *context, int dr_flags) {
m_stream_fps = redraw_rate;
@ -200,26 +132,22 @@ void FFmpegVideoDecoder::cleanup() {
}
int FFmpegVideoDecoder::submit_decode_unit(PDECODE_UNIT decode_unit) {
DBG();
if (decode_unit->fullLength < DECODER_BUFFER_SIZE) {
PLENTRY entry = decode_unit->bufferList;
DBG();
if (!m_last_frame) {
m_video_decode_stats.measurement_start_timestamp = LiGetMillis();
m_last_frame = decode_unit->frameNumber;
DBG();
}
else {
// Any frame number greater than m_LastFrameNumber + 1 represents a dropped frame
m_video_decode_stats.network_dropped_frames += decode_unit->frameNumber - (m_last_frame + 1);
m_video_decode_stats.total_frames += decode_unit->frameNumber - (m_last_frame + 1);
m_last_frame = decode_unit->frameNumber;
DBG();
}
m_video_decode_stats.received_frames++;
m_video_decode_stats.total_frames++;
DBG();
int length = 0;
while (entry != NULL) {
@ -227,14 +155,11 @@ int FFmpegVideoDecoder::submit_decode_unit(PDECODE_UNIT decode_unit) {
Logger::error("FFmpeg", "Big buffer to decode... !");
}
DBG();
memcpy(m_ffmpeg_buffer + length, entry->data, entry->length);
length += entry->length;
entry = entry->next;
DBG();
}
DBG();
m_video_decode_stats.total_reassembly_time += LiGetMillis() - decode_unit->receiveTimeMs;
m_frames_in++;
@ -245,24 +170,17 @@ int FFmpegVideoDecoder::submit_decode_unit(PDECODE_UNIT decode_unit) {
Logger::error("FFmpeg", "Big buffer to decode...");
}
DBG();
if (decode(m_ffmpeg_buffer, length) == 0) {
m_frames_out++;
DBG();
m_video_decode_stats.total_decode_time += LiGetMillis() - before_decode;
// Also count the frame-to-frame delay if the decoder is delaying frames
// until a subsequent frame is submitted.
m_video_decode_stats.total_decode_time += (m_frames_in - m_frames_out) * (1000 / m_stream_fps);
m_video_decode_stats.decoded_frames++;
DBG();
//if (pthread_mutex_lock(&m_mutex) == 0) {
m_frame = get_frame(true);
AVFrameHolder::instance().push(m_frame);
DBG();//
// Push event!!
//pthread_mutex_unlock(&m_mutex);
//}
m_frame = get_frame(true);
AVFrameHolder::instance().push(m_frame);
}
} else {
Logger::error("FFmpeg", "Big buffer to decode... 2");
@ -277,36 +195,28 @@ int FFmpegVideoDecoder::capabilities() const {
int FFmpegVideoDecoder::decode(char* indata, int inlen) {
m_packet.data = (uint8_t *)indata;
m_packet.size = inlen;
DBG();
int err = avcodec_send_packet(m_decoder_context, &m_packet);
DBG();
if (err != 0) {
DBG();
char error[512];
av_strerror(err, error, sizeof(error));
Logger::error("FFmpeg", "Decode failed - %s", error);
DBG();
}
DBG();
return err != 0 ? err : 0;
}
AVFrame* FFmpegVideoDecoder::get_frame(bool native_frame) {
DBG();
int err = avcodec_receive_frame(m_decoder_context, m_frames[m_next_frame]);
DBG();
if (err == 0) {
DBG();
m_current_frame = m_next_frame;
m_next_frame = (m_current_frame + 1) % m_frames_count;
DBG();
if (/*ffmpeg_decoder == SOFTWARE ||*/ native_frame)
return m_frames[m_current_frame];
} else if (err != AVERROR(EAGAIN)) {
DBG();
char error[512];
av_strerror(err, error, sizeof(error));
DBG();
Logger::error("FFmpeg", "Receive failed - %d/%s", err, error);
}
return NULL;

View file

@ -1,5 +1,4 @@
#include "IFFmpegVideoDecoder.hpp"
#include <pthread.h>
#pragma once
class FFmpegVideoDecoder: public IFFmpegVideoDecoder {
@ -34,5 +33,4 @@ private:
char* m_ffmpeg_buffer = nullptr;
AVFrame* m_frame = nullptr;
pthread_mutex_t m_mutex;
};

View file

@ -0,0 +1,42 @@
#include "LockThreadDetector.hpp"
#include "Logger.hpp"
void* LockThreadDetector::entry(void* context) {
while (true) {
if (auto detector = static_cast<LockThreadDetector *>(context)) {
if (detector->m_is_running) {
if (detector->m_current != 0) {
std::lock_guard<std::mutex> lock(detector->m_mutex);
if (detector->m_prev > detector->m_current) {
Logger::error("LockThreadDetector", "Thread Lock Detected on a line: %i", detector->m_last_line);
} else {
detector->m_prev++;
}
}
usleep(500'000);
} else {
return NULL;
}
} else {
return NULL;
}
}
return NULL;
}
LockThreadDetector::LockThreadDetector(std::string file_name) {
m_file_name = file_name;
}
void LockThreadDetector::start() {
}
void LockThreadDetector::stop() {
}
void LockThreadDetector::enter(int line) {
}

View file

@ -0,0 +1,25 @@
#include <stdio.h>
#include <mutex>
#include <switch.h>
#pragma once
class LockThreadDetector {
LockThreadDetector(std::string file_name);
void start();
void stop();
void enter(int line);
private:
static void* entry(void* context);
std::string m_file_name;
bool m_is_running = false;
u64 m_prev = 0;
u64 m_current = 0;
int m_last_line = 0;
std::mutex m_mutex;
pthread_t m_thread;
};