mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
Fix replay saving freeze, unable to save replay if audio is not provided
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,6 +12,7 @@ tests/compile_commands.json
|
|||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
debug-build/
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
gpu-screen-recorder
|
gpu-screen-recorder
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <libavcodec/packet.h>
|
#include <libavcodec/packet.h>
|
||||||
|
|
||||||
|
typedef struct gsr_replay_buffer gsr_replay_buffer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
int ref_counter;
|
int ref_counter;
|
||||||
@@ -15,15 +17,15 @@ gsr_av_packet* gsr_av_packet_create(const AVPacket *av_packet, double timestamp)
|
|||||||
gsr_av_packet* gsr_av_packet_ref(gsr_av_packet *self);
|
gsr_av_packet* gsr_av_packet_ref(gsr_av_packet *self);
|
||||||
void gsr_av_packet_unref(gsr_av_packet *self);
|
void gsr_av_packet_unref(gsr_av_packet *self);
|
||||||
|
|
||||||
typedef struct {
|
struct gsr_replay_buffer {
|
||||||
gsr_av_packet **packets;
|
gsr_av_packet **packets;
|
||||||
size_t capacity_num_packets;
|
size_t capacity_num_packets;
|
||||||
size_t num_packets;
|
size_t num_packets;
|
||||||
size_t index;
|
size_t index;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
bool mutex_initialized;
|
bool mutex_initialized;
|
||||||
bool owns_mutex;
|
gsr_replay_buffer *original_replay_buffer;
|
||||||
} gsr_replay_buffer;
|
};
|
||||||
|
|
||||||
bool gsr_replay_buffer_init(gsr_replay_buffer *self, size_t replay_buffer_num_packets);
|
bool gsr_replay_buffer_init(gsr_replay_buffer *self, size_t replay_buffer_num_packets);
|
||||||
void gsr_replay_buffer_deinit(gsr_replay_buffer *self);
|
void gsr_replay_buffer_deinit(gsr_replay_buffer *self);
|
||||||
@@ -32,7 +34,7 @@ bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet
|
|||||||
void gsr_replay_buffer_clear(gsr_replay_buffer *self);
|
void gsr_replay_buffer_clear(gsr_replay_buffer *self);
|
||||||
gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, size_t index);
|
gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, size_t index);
|
||||||
/* The clone has to be deinitialized before the replay buffer it clones */
|
/* The clone has to be deinitialized before the replay buffer it clones */
|
||||||
bool gsr_replay_buffer_clone(const gsr_replay_buffer *self, gsr_replay_buffer *destination);
|
bool gsr_replay_buffer_clone(gsr_replay_buffer *self, gsr_replay_buffer *destination);
|
||||||
/* Returns 0 if replay buffer is empty */
|
/* Returns 0 if replay buffer is empty */
|
||||||
size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds);
|
size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds);
|
||||||
/* Returns -1 if not found */
|
/* Returns -1 if not found */
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ static bool get_supported_video_codecs(VADisplay va_dpy, gsr_supported_video_cod
|
|||||||
int va_minor = 0;
|
int va_minor = 0;
|
||||||
if(vaInitialize(va_dpy, &va_major, &va_minor) != VA_STATUS_SUCCESS) {
|
if(vaInitialize(va_dpy, &va_major, &va_minor) != VA_STATUS_SUCCESS) {
|
||||||
fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vaapi: vaInitialize failed\n");
|
fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vaapi: vaInitialize failed\n");
|
||||||
goto fail;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_profiles = vaMaxNumProfiles(va_dpy);
|
int num_profiles = vaMaxNumProfiles(va_dpy);
|
||||||
|
|||||||
10
src/main.cpp
10
src/main.cpp
@@ -1270,13 +1270,13 @@ static void save_replay_async(AVCodecContext *video_codec_context, int video_str
|
|||||||
}
|
}
|
||||||
|
|
||||||
const size_t audio_start_index = gsr_replay_buffer_find_keyframe(replay_buffer, video_start_index, video_stream_index, true);
|
const size_t audio_start_index = gsr_replay_buffer_find_keyframe(replay_buffer, video_start_index, video_stream_index, true);
|
||||||
if(audio_start_index == (size_t)-1) {
|
// if(audio_start_index == (size_t)-1) {
|
||||||
fprintf(stderr, "gsr error: failed to save replay: failed to find an audio keyframe. perhaps replay was saved too fast, before anything has been recorded\n");
|
// fprintf(stderr, "gsr error: failed to save replay: failed to find an audio keyframe. perhaps replay was saved too fast, before anything has been recorded\n");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const int64_t video_pts_offset = gsr_replay_buffer_get_packet_at_index(replay_buffer, video_start_index)->packet.pts;
|
const int64_t video_pts_offset = gsr_replay_buffer_get_packet_at_index(replay_buffer, video_start_index)->packet.pts;
|
||||||
const int64_t audio_pts_offset = gsr_replay_buffer_get_packet_at_index(replay_buffer, audio_start_index)->packet.pts;
|
const int64_t audio_pts_offset = audio_start_index == (size_t)-1 ? 0 : gsr_replay_buffer_get_packet_at_index(replay_buffer, audio_start_index)->packet.pts;
|
||||||
|
|
||||||
gsr_replay_buffer cloned_replay_buffer;
|
gsr_replay_buffer cloned_replay_buffer;
|
||||||
if(!gsr_replay_buffer_clone(replay_buffer, &cloned_replay_buffer)) {
|
if(!gsr_replay_buffer_clone(replay_buffer, &cloned_replay_buffer)) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ bool gsr_replay_buffer_init(gsr_replay_buffer *self, size_t replay_buffer_num_pa
|
|||||||
assert(replay_buffer_num_packets > 0);
|
assert(replay_buffer_num_packets > 0);
|
||||||
memset(self, 0, sizeof(*self));
|
memset(self, 0, sizeof(*self));
|
||||||
self->mutex_initialized = false;
|
self->mutex_initialized = false;
|
||||||
self->owns_mutex = true;
|
self->original_replay_buffer = NULL;
|
||||||
if(pthread_mutex_init(&self->mutex, NULL) != 0)
|
if(pthread_mutex_init(&self->mutex, NULL) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -70,10 +70,28 @@ bool gsr_replay_buffer_init(gsr_replay_buffer *self, size_t replay_buffer_num_pa
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gsr_replay_buffer_deinit(gsr_replay_buffer *self) {
|
static void gsr_replay_buffer_lock(gsr_replay_buffer *self) {
|
||||||
|
if(self->original_replay_buffer) {
|
||||||
|
gsr_replay_buffer_lock(self->original_replay_buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(self->mutex_initialized)
|
if(self->mutex_initialized)
|
||||||
pthread_mutex_lock(&self->mutex);
|
pthread_mutex_lock(&self->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gsr_replay_buffer_unlock(gsr_replay_buffer *self) {
|
||||||
|
if(self->original_replay_buffer) {
|
||||||
|
gsr_replay_buffer_unlock(self->original_replay_buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(self->mutex_initialized)
|
||||||
|
pthread_mutex_unlock(&self->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsr_replay_buffer_deinit(gsr_replay_buffer *self) {
|
||||||
|
gsr_replay_buffer_lock(self);
|
||||||
for(size_t i = 0; i < self->num_packets; ++i) {
|
for(size_t i = 0; i < self->num_packets; ++i) {
|
||||||
if(self->packets[i]) {
|
if(self->packets[i]) {
|
||||||
gsr_av_packet_unref(self->packets[i]);
|
gsr_av_packet_unref(self->packets[i]);
|
||||||
@@ -81,9 +99,7 @@ void gsr_replay_buffer_deinit(gsr_replay_buffer *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self->num_packets = 0;
|
self->num_packets = 0;
|
||||||
|
gsr_replay_buffer_unlock(self);
|
||||||
if(self->mutex_initialized)
|
|
||||||
pthread_mutex_unlock(&self->mutex);
|
|
||||||
|
|
||||||
if(self->packets) {
|
if(self->packets) {
|
||||||
free(self->packets);
|
free(self->packets);
|
||||||
@@ -93,17 +109,19 @@ void gsr_replay_buffer_deinit(gsr_replay_buffer *self) {
|
|||||||
self->capacity_num_packets = 0;
|
self->capacity_num_packets = 0;
|
||||||
self->index = 0;
|
self->index = 0;
|
||||||
|
|
||||||
if(self->mutex_initialized && self->owns_mutex) {
|
if(self->mutex_initialized && !self->original_replay_buffer) {
|
||||||
pthread_mutex_destroy(&self->mutex);
|
pthread_mutex_destroy(&self->mutex);
|
||||||
self->mutex_initialized = false;
|
self->mutex_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->original_replay_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp) {
|
bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp) {
|
||||||
pthread_mutex_lock(&self->mutex);
|
gsr_replay_buffer_lock(self);
|
||||||
gsr_av_packet *packet = gsr_av_packet_create(av_packet, timestamp);
|
gsr_av_packet *packet = gsr_av_packet_create(av_packet, timestamp);
|
||||||
if(!packet) {
|
if(!packet) {
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,12 +136,12 @@ bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet
|
|||||||
if(self->num_packets > self->capacity_num_packets)
|
if(self->num_packets > self->capacity_num_packets)
|
||||||
self->num_packets = self->capacity_num_packets;
|
self->num_packets = self->capacity_num_packets;
|
||||||
|
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gsr_replay_buffer_clear(gsr_replay_buffer *self) {
|
void gsr_replay_buffer_clear(gsr_replay_buffer *self) {
|
||||||
pthread_mutex_lock(&self->mutex);
|
gsr_replay_buffer_lock(self);
|
||||||
for(size_t i = 0; i < self->num_packets; ++i) {
|
for(size_t i = 0; i < self->num_packets; ++i) {
|
||||||
if(self->packets[i]) {
|
if(self->packets[i]) {
|
||||||
gsr_av_packet_unref(self->packets[i]);
|
gsr_av_packet_unref(self->packets[i]);
|
||||||
@@ -132,7 +150,7 @@ void gsr_replay_buffer_clear(gsr_replay_buffer *self) {
|
|||||||
}
|
}
|
||||||
self->num_packets = 0;
|
self->num_packets = 0;
|
||||||
self->index = 0;
|
self->index = 0;
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, size_t index) {
|
gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, size_t index) {
|
||||||
@@ -147,17 +165,17 @@ gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, si
|
|||||||
return self->packets[offset];
|
return self->packets[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gsr_replay_buffer_clone(const gsr_replay_buffer *self, gsr_replay_buffer *destination) {
|
bool gsr_replay_buffer_clone(gsr_replay_buffer *self, gsr_replay_buffer *destination) {
|
||||||
pthread_mutex_lock(&destination->mutex);
|
gsr_replay_buffer_lock(self);
|
||||||
memset(destination, 0, sizeof(*destination));
|
memset(destination, 0, sizeof(*destination));
|
||||||
destination->owns_mutex = false;
|
destination->original_replay_buffer = self;
|
||||||
destination->mutex = self->mutex;
|
destination->mutex = self->mutex;
|
||||||
destination->capacity_num_packets = self->capacity_num_packets;
|
destination->capacity_num_packets = self->capacity_num_packets;
|
||||||
destination->mutex_initialized = self->mutex_initialized;
|
destination->mutex_initialized = self->mutex_initialized;
|
||||||
destination->index = self->index;
|
destination->index = self->index;
|
||||||
destination->packets = calloc(destination->capacity_num_packets, sizeof(gsr_av_packet*));
|
destination->packets = calloc(destination->capacity_num_packets, sizeof(gsr_av_packet*));
|
||||||
if(!destination->packets) {
|
if(!destination->packets) {
|
||||||
pthread_mutex_unlock(&destination->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,17 +184,17 @@ bool gsr_replay_buffer_clone(const gsr_replay_buffer *self, gsr_replay_buffer *d
|
|||||||
destination->packets[i] = gsr_av_packet_ref(self->packets[i]);
|
destination->packets[i] = gsr_av_packet_ref(self->packets[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&destination->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Binary search */
|
/* Binary search */
|
||||||
size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds) {
|
size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds) {
|
||||||
pthread_mutex_lock(&self->mutex);
|
gsr_replay_buffer_lock(self);
|
||||||
|
|
||||||
const double now = clock_get_monotonic_seconds();
|
const double now = clock_get_monotonic_seconds();
|
||||||
if(self->num_packets == 0) {
|
if(self->num_packets == 0) {
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,14 +217,14 @@ size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *sel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, size_t start_index, int stream_index, bool invert_stream_index) {
|
size_t gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, size_t start_index, int stream_index, bool invert_stream_index) {
|
||||||
assert(start_index < self->num_packets);
|
assert(start_index < self->num_packets);
|
||||||
size_t keyframe_index = (size_t)-1;
|
size_t keyframe_index = (size_t)-1;
|
||||||
pthread_mutex_lock(&self->mutex);
|
gsr_replay_buffer_lock(self);
|
||||||
for(size_t i = start_index; i < self->num_packets; ++i) {
|
for(size_t i = start_index; i < self->num_packets; ++i) {
|
||||||
const gsr_av_packet *packet = gsr_replay_buffer_get_packet_at_index(self, i);
|
const gsr_av_packet *packet = gsr_replay_buffer_get_packet_at_index(self, i);
|
||||||
if((packet->packet.flags & AV_PKT_FLAG_KEY) && (invert_stream_index ? packet->packet.stream_index != stream_index : packet->packet.stream_index == stream_index)) {
|
if((packet->packet.flags & AV_PKT_FLAG_KEY) && (invert_stream_index ? packet->packet.stream_index != stream_index : packet->packet.stream_index == stream_index)) {
|
||||||
@@ -214,6 +232,6 @@ size_t gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, size_t start_ind
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&self->mutex);
|
gsr_replay_buffer_unlock(self);
|
||||||
return keyframe_index;
|
return keyframe_index;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user