static bool initialize_interleaved_packets(struct obs_output *output) { struct encoder_packet *video; struct encoder_packet *audio[MAX_AUDIO_MIXES]; struct encoder_packet *last_audio[MAX_AUDIO_MIXES]; size_t audio_mixes = num_audio_mixes(output); size_t start_idx; if (!get_audio_and_video_packets(output, &video, audio, audio_mixes)) return false; for (size_t i = 0; i < audio_mixes; i++) last_audio[i] = find_last_packet_type(output, OBS_ENCODER_AUDIO, i); /* ensure that there is audio past the first video packet */ for (size_t i = 0; i < audio_mixes; i++) { if (last_audio[i]->dts_usec < video->dts_usec) { output->received_audio = false; return false; } } /* clear out excess starting audio if it hasn't been already */ start_idx = get_interleaved_start_idx(output); if (start_idx) { discard_to_idx(output, start_idx); if (!get_audio_and_video_packets(output, &video, audio, audio_mixes)) return false; } /* get new offsets */ output->video_offset = video->dts; for (size_t i = 0; i < audio_mixes; i++) output->audio_offsets[i] = audio[i]->dts; #if DEBUG_STARTING_PACKETS == 1 int64_t v = video->dts_usec; int64_t a = audio[0]->dts_usec; int64_t diff = v - a; blog(LOG_DEBUG, "output '%s' offset for video: %lld, audio: %lld, " "diff: %lldms", output->context.name, v, a, diff / 1000LL); #endif /* subtract offsets from highest TS offset variables */ output->highest_audio_ts -= audio[0]->dts_usec; output->highest_video_ts -= video->dts_usec; /* apply new offsets to all existing packet DTS/PTS values */ for (size_t i = 0; i < output->interleaved_packets.num; i++) { struct encoder_packet *packet = &output->interleaved_packets.array[i]; apply_interleaved_packet_offset(output, packet); } return true; }
static void interleave_packets(void *data, struct encoder_packet *packet) { struct obs_output *output = data; struct encoder_packet out; bool was_started; pthread_mutex_lock(&output->interleaved_mutex); was_started = output->received_audio && output->received_video; obs_duplicate_encoder_packet(&out, packet); apply_interleaved_packet_offset(output, &out); insert_interleaved_packet(output, &out); set_higher_ts(output, &out); /* when both video and audio have been received, we're ready * to start sending out packets (one at a time) */ if (output->received_audio && output->received_video) { if (!was_started) { prune_interleaved_packets(output); initialize_interleaved_packets(output); resort_interleaved_packets(output); } send_interleaved(output); } pthread_mutex_unlock(&output->interleaved_mutex); }
static void interleave_packets(void *data, struct encoder_packet *packet) { struct obs_output *output = data; struct encoder_packet out; bool was_started; if (!active(output)) return; if (packet->type == OBS_ENCODER_AUDIO) packet->track_idx = get_track_index(output, packet); pthread_mutex_lock(&output->interleaved_mutex); /* if first video frame is not a keyframe, discard until received */ if (!output->received_video && packet->type == OBS_ENCODER_VIDEO && !packet->keyframe) { discard_unused_audio_packets(output, packet->dts_usec); pthread_mutex_unlock(&output->interleaved_mutex); if (output->active_delay_ns) obs_free_encoder_packet(packet); return; } was_started = output->received_audio && output->received_video; if (output->active_delay_ns) out = *packet; else obs_duplicate_encoder_packet(&out, packet); if (was_started) apply_interleaved_packet_offset(output, &out); else check_received(output, packet); insert_interleaved_packet(output, &out); set_higher_ts(output, &out); /* when both video and audio have been received, we're ready * to start sending out packets (one at a time) */ if (output->received_audio && output->received_video) { if (!was_started) { if (prune_interleaved_packets(output)) { if (initialize_interleaved_packets(output)) { resort_interleaved_packets(output); send_interleaved(output); } } } else { send_interleaved(output); } } pthread_mutex_unlock(&output->interleaved_mutex); }
static void interleave_packets(void *data, struct encoder_packet *packet) { struct obs_output *output = data; struct encoder_packet out; bool was_started; if (packet->type == OBS_ENCODER_AUDIO) packet->track_idx = get_track_index(output, packet); pthread_mutex_lock(&output->interleaved_mutex); was_started = output->received_audio && output->received_video; if (output->active_delay_ns) out = *packet; else obs_duplicate_encoder_packet(&out, packet); if (was_started) apply_interleaved_packet_offset(output, &out); else check_received(output, packet); insert_interleaved_packet(output, &out); set_higher_ts(output, &out); /* when both video and audio have been received, we're ready * to start sending out packets (one at a time) */ if (output->received_audio && output->received_video) { if (!was_started) { prune_interleaved_packets(output); if (initialize_interleaved_packets(output)) { resort_interleaved_packets(output); send_interleaved(output); } } else { send_interleaved(output); } } pthread_mutex_unlock(&output->interleaved_mutex); }
static bool initialize_interleaved_packets(struct obs_output *output) { struct encoder_packet *video; struct encoder_packet *audio[MAX_AUDIO_MIXES]; size_t audio_mixes = num_audio_mixes(output); video = find_first_packet_type(output, OBS_ENCODER_VIDEO, 0); if (!video) output->received_video = false; for (size_t i = 0; i < audio_mixes; i++) { audio[i] = find_first_packet_type(output, OBS_ENCODER_AUDIO, i); if (!audio[i]) { output->received_audio = false; return false; } } if (!video) { return false; } /* get new offsets */ output->video_offset = video->dts; for (size_t i = 0; i < audio_mixes; i++) output->audio_offsets[i] = audio[i]->dts; /* subtract offsets from highest TS offset variables */ output->highest_audio_ts -= audio[0]->dts_usec; output->highest_video_ts -= video->dts_usec; /* apply new offsets to all existing packet DTS/PTS values */ for (size_t i = 0; i < output->interleaved_packets.num; i++) { struct encoder_packet *packet = &output->interleaved_packets.array[i]; apply_interleaved_packet_offset(output, packet); } return true; }
static void initialize_interleaved_packets(struct obs_output *output) { struct encoder_packet *video; struct encoder_packet *audio; video = find_first_packet_type(output, OBS_ENCODER_VIDEO); audio = find_first_packet_type(output, OBS_ENCODER_AUDIO); /* get new offsets */ output->video_offset = video->dts; output->audio_offset = audio->dts; /* subtract offsets from highest TS offset variables */ output->highest_audio_ts -= audio->dts_usec; output->highest_video_ts -= video->dts_usec; /* apply new offsets to all existing packet DTS/PTS values */ for (size_t i = 0; i < output->interleaved_packets.num; i++) { struct encoder_packet *packet = &output->interleaved_packets.array[i]; apply_interleaved_packet_offset(output, packet); } }