static void rtmp_stream_data(void *data, struct encoder_packet *packet) { struct rtmp_stream *stream = data; struct encoder_packet new_packet; bool added_packet = false; if (disconnected(stream)) return; if (packet->type == OBS_ENCODER_VIDEO) obs_parse_avc_packet(&new_packet, packet); else obs_duplicate_encoder_packet(&new_packet, packet); pthread_mutex_lock(&stream->packets_mutex); if (!disconnected(stream)) { added_packet = (packet->type == OBS_ENCODER_VIDEO) ? add_video_packet(stream, &new_packet) : add_packet(stream, &new_packet); } pthread_mutex_unlock(&stream->packets_mutex); if (added_packet) os_sem_post(stream->send_sem); else obs_free_encoder_packet(&new_packet); }
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 bool prepare_interleaved_packet(struct obs_output *output, struct encoder_packet *out, struct encoder_packet *in) { int64_t offset; /* audio and video need to start at timestamp 0, and the encoders * may not currently be at 0 when we get data. so, we store the * current dts as offset and subtract that value from the dts/pts * of the output packet. */ if (in->type == OBS_ENCODER_VIDEO) { if (!output->received_video) { output->first_video_ts = in->dts_usec; output->video_offset = in->dts; output->received_video = true; } offset = output->video_offset; } else{ /* don't accept audio that's before the first video timestamp */ if (!output->received_video || in->dts_usec < output->first_video_ts) return false; if (!output->received_audio) { output->audio_offset = in->dts; output->received_audio = true; } offset = output->audio_offset; } obs_duplicate_encoder_packet(out, in); out->dts -= offset; out->pts -= offset; /* convert the newly adjusted dts to relative dts time to ensure proper * interleaving. if we're using an audio encoder that's already been * started on another output, then the first audio packet may not be * quite perfectly synced up in terms of system time (and there's * nothing we can really do about that), but it will always at least be * within a 23ish millisecond threshold (at least for AAC) */ out->dts_usec = packet_dts_usec(out); return true; }
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); }