diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 8eca9fb0c..40e4befa7 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -1301,7 +1301,7 @@ static bool initialize_interleaved_packets(struct obs_output *output) } /* get new offsets */ - output->video_offset = video->dts; + output->video_offset = video->pts; for (size_t i = 0; i < audio_mixes; i++) output->audio_offsets[i] = audio[i]->dts; diff --git a/plugins/obs-outputs/flv-mux.c b/plugins/obs-outputs/flv-mux.c index e74b2daf8..6d4063fb5 100644 --- a/plugins/obs-outputs/flv-mux.c +++ b/plugins/obs-outputs/flv-mux.c @@ -177,11 +177,11 @@ bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size, static int32_t last_time = 0; #endif -static void flv_video(struct serializer *s, struct encoder_packet *packet, - bool is_header) +static void flv_video(struct serializer *s, int32_t dts_offset, + struct encoder_packet *packet, bool is_header) { int64_t offset = packet->pts - packet->dts; - int32_t time_ms = get_ms_time(packet, packet->dts); + int32_t time_ms = get_ms_time(packet, packet->dts) - dts_offset; if (!packet->data || !packet->size) return; @@ -212,10 +212,10 @@ static void flv_video(struct serializer *s, struct encoder_packet *packet, s_wb32(s, (uint32_t)serializer_get_pos(s) + 4 - 1); } -static void flv_audio(struct serializer *s, struct encoder_packet *packet, - bool is_header) +static void flv_audio(struct serializer *s, int32_t dts_offset, + struct encoder_packet *packet, bool is_header) { - int32_t time_ms = get_ms_time(packet, packet->dts); + int32_t time_ms = get_ms_time(packet, packet->dts) - dts_offset; if (!packet->data || !packet->size) return; @@ -245,7 +245,7 @@ static void flv_audio(struct serializer *s, struct encoder_packet *packet, s_wb32(s, (uint32_t)serializer_get_pos(s) + 4 - 1); } -void flv_packet_mux(struct encoder_packet *packet, +void flv_packet_mux(struct encoder_packet *packet, int32_t dts_offset, uint8_t **output, size_t *size, bool is_header) { struct array_output_data data; @@ -254,9 +254,9 @@ void flv_packet_mux(struct encoder_packet *packet, array_output_serializer_init(&s, &data); if (packet->type == OBS_ENCODER_VIDEO) - flv_video(&s, packet, is_header); + flv_video(&s, dts_offset, packet, is_header); else - flv_audio(&s, packet, is_header); + flv_audio(&s, dts_offset, packet, is_header); *output = data.bytes.array; *size = data.bytes.num; diff --git a/plugins/obs-outputs/flv-mux.h b/plugins/obs-outputs/flv-mux.h index e4c655e5a..50c37e22b 100644 --- a/plugins/obs-outputs/flv-mux.h +++ b/plugins/obs-outputs/flv-mux.h @@ -21,14 +21,14 @@ #define MILLISECOND_DEN 1000 -static uint32_t get_ms_time(struct encoder_packet *packet, int64_t val) +static int32_t get_ms_time(struct encoder_packet *packet, int64_t val) { - return (uint32_t)(val * MILLISECOND_DEN / packet->timebase_den); + return (int32_t)(val * MILLISECOND_DEN / packet->timebase_den); } extern void write_file_info(FILE *file, int64_t duration_ms, int64_t size); extern bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size, bool write_header, size_t audio_idx); -extern void flv_packet_mux(struct encoder_packet *packet, +extern void flv_packet_mux(struct encoder_packet *packet, int32_t dts_offset, uint8_t **output, size_t *size, bool is_header); diff --git a/plugins/obs-outputs/flv-output.c b/plugins/obs-outputs/flv-output.c index 1bdae92d2..99a1c4e6b 100644 --- a/plugins/obs-outputs/flv-output.c +++ b/plugins/obs-outputs/flv-output.c @@ -32,12 +32,15 @@ #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) struct flv_output { - obs_output_t *output; - struct dstr path; - FILE *file; - bool active; - bool sent_headers; - int64_t last_packet_ts; + obs_output_t *output; + struct dstr path; + FILE *file; + volatile bool active; + bool sent_headers; + int64_t last_packet_ts; + + bool got_first_video; + int32_t start_dts_offset; }; static const char *flv_output_getname(void *unused) @@ -98,7 +101,8 @@ static int write_packet(struct flv_output *stream, stream->last_packet_ts = get_ms_time(packet, packet->dts); - flv_packet_mux(packet, &data, &size, is_header); + flv_packet_mux(packet, is_header ? 0 : stream->start_dts_offset, + &data, &size, is_header); fwrite(data, 1, size, stream->file); bfree(data); obs_encoder_packet_release(packet); @@ -168,6 +172,8 @@ static bool flv_output_start(void *data) if (!obs_output_initialize_encoders(stream->output, 0)) return false; + stream->got_first_video = false; + /* get path */ settings = obs_output_get_settings(stream->output); path = obs_data_get_string(settings, "path"); @@ -199,6 +205,12 @@ static void flv_output_data(void *data, struct encoder_packet *packet) } if (packet->type == OBS_ENCODER_VIDEO) { + if (!stream->got_first_video) { + stream->start_dts_offset = + get_ms_time(packet, packet->dts); + stream->got_first_video = true; + } + obs_parse_avc_packet(&parsed_packet, packet); write_packet(stream, &parsed_packet, false); obs_encoder_packet_release(&parsed_packet); diff --git a/plugins/obs-outputs/rtmp-stream.c b/plugins/obs-outputs/rtmp-stream.c index d343031ef..7147f20d3 100644 --- a/plugins/obs-outputs/rtmp-stream.c +++ b/plugins/obs-outputs/rtmp-stream.c @@ -347,7 +347,8 @@ static int send_packet(struct rtmp_stream *stream, } } - flv_packet_mux(packet, &data, &size, is_header); + flv_packet_mux(packet, is_header ? 0 : stream->start_dts_offset, + &data, &size, is_header); #ifdef TEST_FRAMEDROPS droptest_cap_data_rate(stream, size); @@ -876,6 +877,7 @@ static bool init_connect(struct rtmp_stream *stream) stream->total_bytes_sent = 0; stream->dropped_frames = 0; stream->min_priority = 0; + stream->got_first_video = false; settings = obs_output_get_settings(stream->output); dstr_copy(&stream->path, obs_service_get_url(service)); @@ -1089,10 +1091,17 @@ static void rtmp_stream_data(void *data, struct encoder_packet *packet) if (disconnected(stream) || !active(stream)) return; - if (packet->type == OBS_ENCODER_VIDEO) + if (packet->type == OBS_ENCODER_VIDEO) { + if (!stream->got_first_video) { + stream->start_dts_offset = + get_ms_time(packet, packet->dts); + stream->got_first_video = true; + } + obs_parse_avc_packet(&new_packet, packet); - else + } else { obs_encoder_packet_ref(&new_packet, packet); + } pthread_mutex_lock(&stream->packets_mutex); diff --git a/plugins/obs-outputs/rtmp-stream.h b/plugins/obs-outputs/rtmp-stream.h index 863eda619..1c4715acd 100644 --- a/plugins/obs-outputs/rtmp-stream.h +++ b/plugins/obs-outputs/rtmp-stream.h @@ -51,6 +51,9 @@ struct rtmp_stream { struct circlebuf packets; bool sent_headers; + bool got_first_video; + int64_t start_dts_offset; + volatile bool connecting; pthread_t connect_thread;