Make sure the first frame is pts 0

This commit is contained in:
dec05eba
2026-04-21 18:12:41 +02:00
parent 9a6b345bac
commit 1e1da80d74
3 changed files with 22 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ typedef struct {
AVFormatContext *format_context;
AVStream *stream;
int64_t start_pts;
int64_t first_pts;
bool has_received_keyframe;
char *first_frame_ts_filepath;
bool first_frame_ts_written;
@@ -26,6 +27,7 @@ typedef struct {
typedef struct {
gsr_replay_buffer *replay_buffer;
int64_t first_pts;
pthread_mutex_t file_write_mutex;
bool file_write_mutex_created;

View File

@@ -38,6 +38,7 @@ bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size
memset(self, 0, sizeof(*self));
self->num_recording_destinations = 0;
self->recording_destination_id_counter = 0;
self->first_pts = -1;
if(pthread_mutex_init(&self->file_write_mutex, NULL) != 0) {
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->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) {
@@ -107,9 +109,12 @@ void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_contex
av_packet->size = 0;
int res = avcodec_receive_packet(codec_context, av_packet);
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->pts = pts;
av_packet->dts = pts;
av_packet->pts = pts - self->first_pts;
av_packet->dts = av_packet->pts;
if(self->replay_buffer) {
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;
}
av_packet->pts = pts - recording_destination->start_pts;
av_packet->dts = pts - recording_destination->start_pts;
if(recording_destination->first_pts == -1)
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);
// 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->stream = stream;
recording_destination->start_pts = start_pts;
recording_destination->first_pts = -1;
recording_destination->has_received_keyframe = false;
recording_destination->first_frame_ts_filepath = NULL;
recording_destination->first_frame_ts_written = false;

View File

@@ -898,6 +898,7 @@ static AVStream* create_stream(AVFormatContext *av_format_context, AVCodecContex
stream->id = av_format_context->nb_streams - 1;
stream->time_base = codec_context->time_base;
stream->avg_frame_rate = codec_context->framerate;
//stream->r_frame_rate = codec_context->framerate;
return stream;
}
@@ -1084,6 +1085,9 @@ static RecordingStartResult start_recording_create_streams(const char *filename,
AVFormatContext *av_format_context;
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);
avcodec_parameters_from_context(video_stream->codecpar, video_codec_context);
@@ -3785,6 +3789,9 @@ int main(int argc, char **argv) {
_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;
std::string file_extension = output_format->extensions ? output_format->extensions : "";