mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-05-07 15:19:55 +09:00
Make sure the first frame is pts 0
This commit is contained in:
@@ -19,6 +19,7 @@ typedef struct {
|
|||||||
AVFormatContext *format_context;
|
AVFormatContext *format_context;
|
||||||
AVStream *stream;
|
AVStream *stream;
|
||||||
int64_t start_pts;
|
int64_t start_pts;
|
||||||
|
int64_t first_pts;
|
||||||
bool has_received_keyframe;
|
bool has_received_keyframe;
|
||||||
char *first_frame_ts_filepath;
|
char *first_frame_ts_filepath;
|
||||||
bool first_frame_ts_written;
|
bool first_frame_ts_written;
|
||||||
@@ -26,6 +27,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gsr_replay_buffer *replay_buffer;
|
gsr_replay_buffer *replay_buffer;
|
||||||
|
int64_t first_pts;
|
||||||
|
|
||||||
pthread_mutex_t file_write_mutex;
|
pthread_mutex_t file_write_mutex;
|
||||||
bool file_write_mutex_created;
|
bool file_write_mutex_created;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size
|
|||||||
memset(self, 0, sizeof(*self));
|
memset(self, 0, sizeof(*self));
|
||||||
self->num_recording_destinations = 0;
|
self->num_recording_destinations = 0;
|
||||||
self->recording_destination_id_counter = 0;
|
self->recording_destination_id_counter = 0;
|
||||||
|
self->first_pts = -1;
|
||||||
|
|
||||||
if(pthread_mutex_init(&self->file_write_mutex, NULL) != 0) {
|
if(pthread_mutex_init(&self->file_write_mutex, NULL) != 0) {
|
||||||
fprintf(stderr, "gsr error: gsr_encoder_init: failed to create mutex\n");
|
fprintf(stderr, "gsr error: gsr_encoder_init: failed to create mutex\n");
|
||||||
@@ -95,6 +96,7 @@ void gsr_encoder_deinit(gsr_encoder *self) {
|
|||||||
|
|
||||||
self->num_recording_destinations = 0;
|
self->num_recording_destinations = 0;
|
||||||
self->recording_destination_id_counter = 0;
|
self->recording_destination_id_counter = 0;
|
||||||
|
self->first_pts = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_context, int64_t pts, int stream_index) {
|
void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_context, int64_t pts, int stream_index) {
|
||||||
@@ -107,9 +109,12 @@ void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_contex
|
|||||||
av_packet->size = 0;
|
av_packet->size = 0;
|
||||||
int res = avcodec_receive_packet(codec_context, av_packet);
|
int res = avcodec_receive_packet(codec_context, av_packet);
|
||||||
if(res == 0) { // we have a packet, send the packet to the muxer
|
if(res == 0) { // we have a packet, send the packet to the muxer
|
||||||
|
if(self->first_pts == -1)
|
||||||
|
self->first_pts = pts;
|
||||||
|
|
||||||
av_packet->stream_index = stream_index;
|
av_packet->stream_index = stream_index;
|
||||||
av_packet->pts = pts;
|
av_packet->pts = pts - self->first_pts;
|
||||||
av_packet->dts = pts;
|
av_packet->dts = av_packet->pts;
|
||||||
|
|
||||||
if(self->replay_buffer) {
|
if(self->replay_buffer) {
|
||||||
pthread_mutex_lock(&self->replay_mutex);
|
pthread_mutex_lock(&self->replay_mutex);
|
||||||
@@ -136,8 +141,11 @@ void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_contex
|
|||||||
recording_destination->first_frame_ts_written = true;
|
recording_destination->first_frame_ts_written = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_packet->pts = pts - recording_destination->start_pts;
|
if(recording_destination->first_pts == -1)
|
||||||
av_packet->dts = pts - recording_destination->start_pts;
|
recording_destination->first_pts = pts;
|
||||||
|
|
||||||
|
av_packet->pts = (pts - recording_destination->first_pts) - recording_destination->start_pts;
|
||||||
|
av_packet->dts = av_packet->pts;
|
||||||
|
|
||||||
av_packet_rescale_ts(av_packet, codec_context->time_base, recording_destination->stream->time_base);
|
av_packet_rescale_ts(av_packet, codec_context->time_base, recording_destination->stream->time_base);
|
||||||
// TODO: Is av_interleaved_write_frame needed?. Answer: might be needed for mkv but dont use it! it causes frames to be inconsistent, skipping frames and duplicating frames.
|
// TODO: Is av_interleaved_write_frame needed?. Answer: might be needed for mkv but dont use it! it causes frames to be inconsistent, skipping frames and duplicating frames.
|
||||||
@@ -189,6 +197,7 @@ size_t gsr_encoder_add_recording_destination(gsr_encoder *self, AVCodecContext *
|
|||||||
recording_destination->format_context = format_context;
|
recording_destination->format_context = format_context;
|
||||||
recording_destination->stream = stream;
|
recording_destination->stream = stream;
|
||||||
recording_destination->start_pts = start_pts;
|
recording_destination->start_pts = start_pts;
|
||||||
|
recording_destination->first_pts = -1;
|
||||||
recording_destination->has_received_keyframe = false;
|
recording_destination->has_received_keyframe = false;
|
||||||
recording_destination->first_frame_ts_filepath = NULL;
|
recording_destination->first_frame_ts_filepath = NULL;
|
||||||
recording_destination->first_frame_ts_written = false;
|
recording_destination->first_frame_ts_written = false;
|
||||||
|
|||||||
@@ -898,6 +898,7 @@ static AVStream* create_stream(AVFormatContext *av_format_context, AVCodecContex
|
|||||||
stream->id = av_format_context->nb_streams - 1;
|
stream->id = av_format_context->nb_streams - 1;
|
||||||
stream->time_base = codec_context->time_base;
|
stream->time_base = codec_context->time_base;
|
||||||
stream->avg_frame_rate = codec_context->framerate;
|
stream->avg_frame_rate = codec_context->framerate;
|
||||||
|
//stream->r_frame_rate = codec_context->framerate;
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,6 +1085,9 @@ static RecordingStartResult start_recording_create_streams(const char *filename,
|
|||||||
AVFormatContext *av_format_context;
|
AVFormatContext *av_format_context;
|
||||||
avformat_alloc_output_context2(&av_format_context, nullptr, arg_parser.container_format, filename);
|
avformat_alloc_output_context2(&av_format_context, nullptr, arg_parser.container_format, filename);
|
||||||
|
|
||||||
|
av_opt_set(av_format_context->priv_data, "use_editlist", "1", 0);
|
||||||
|
//av_opt_set(av_format_context->priv_data, "movflags", "+frag_keyframe+empty_moov+delay_moov", 0);
|
||||||
|
|
||||||
AVStream *video_stream = create_stream(av_format_context, video_codec_context);
|
AVStream *video_stream = create_stream(av_format_context, video_codec_context);
|
||||||
avcodec_parameters_from_context(video_stream->codecpar, video_codec_context);
|
avcodec_parameters_from_context(video_stream->codecpar, video_codec_context);
|
||||||
|
|
||||||
@@ -3785,6 +3789,9 @@ int main(int argc, char **argv) {
|
|||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av_opt_set(av_format_context->priv_data, "use_editlist", "1", 0);
|
||||||
|
//av_opt_set(av_format_context->priv_data, "movflags", "+frag_keyframe+empty_moov+delay_moov", 0);
|
||||||
|
|
||||||
const AVOutputFormat *output_format = av_format_context->oformat;
|
const AVOutputFormat *output_format = av_format_context->oformat;
|
||||||
|
|
||||||
std::string file_extension = output_format->extensions ? output_format->extensions : "";
|
std::string file_extension = output_format->extensions ? output_format->extensions : "";
|
||||||
|
|||||||
Reference in New Issue
Block a user