static void drop_frames(struct rtmp_stream *stream, const char *name, int highest_priority, int64_t *p_min_dts_usec) { struct circlebuf new_buf = {0}; uint64_t last_drop_dts_usec = 0; int num_frames_dropped = 0; #ifdef _DEBUG int start_packets = (int)num_buffered_packets(stream); #else UNUSED_PARAMETER(name); #endif circlebuf_reserve(&new_buf, sizeof(struct encoder_packet) * 8); while (stream->packets.size) { struct encoder_packet packet; circlebuf_pop_front(&stream->packets, &packet, sizeof(packet)); last_drop_dts_usec = packet.dts_usec; /* do not drop audio data or video keyframes */ if (packet.type == OBS_ENCODER_AUDIO || packet.drop_priority >= highest_priority) { circlebuf_push_back(&new_buf, &packet, sizeof(packet)); } else { num_frames_dropped++; obs_free_encoder_packet(&packet); } } circlebuf_free(&stream->packets); stream->packets = new_buf; if (stream->min_priority < highest_priority) stream->min_priority = highest_priority; *p_min_dts_usec = last_drop_dts_usec; stream->dropped_frames += num_frames_dropped; #ifdef _DEBUG debug("Dropped %s, prev packet count: %d, new packet count: %d", name, start_packets, (int)num_buffered_packets(stream)); #endif }
static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes) { struct encoder_packet first; int64_t buffer_duration_usec; size_t num_packets = num_buffered_packets(stream); const char *name = pframes ? "p-frames" : "b-frames"; int priority = pframes ? OBS_NAL_PRIORITY_HIGHEST : OBS_NAL_PRIORITY_HIGH; int64_t *p_min_dts_usec = pframes ? &stream->pframe_min_drop_dts_usec : &stream->min_drop_dts_usec; int64_t drop_threshold = pframes ? stream->pframe_drop_threshold_usec : stream->drop_threshold_usec; if (num_packets < 5) return; circlebuf_peek_front(&stream->packets, &first, sizeof(first)); /* do not drop frames if frames were just dropped within this time */ if (first.dts_usec < *p_min_dts_usec) return; /* if the amount of time stored in the buffered packets waiting to be * sent is higher than threshold, drop frames */ buffer_duration_usec = stream->last_dts_usec - first.dts_usec; if (buffer_duration_usec > drop_threshold) { debug("buffer_duration_usec: %lld", buffer_duration_usec); drop_frames(stream, name, priority, p_min_dts_usec); } }
static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes) { struct encoder_packet first; int64_t buffer_duration_usec; size_t num_packets = num_buffered_packets(stream); const char *name = pframes ? "p-frames" : "b-frames"; int priority = pframes ? OBS_NAL_PRIORITY_HIGHEST : OBS_NAL_PRIORITY_HIGH; int64_t drop_threshold = pframes ? stream->pframe_drop_threshold_usec : stream->drop_threshold_usec; if (num_packets < 5) { if (!pframes) stream->congestion = 0.0f; return; } if (!find_first_video_packet(stream, &first)) return; /* if the amount of time stored in the buffered packets waiting to be * sent is higher than threshold, drop frames */ buffer_duration_usec = stream->last_dts_usec - first.dts_usec; if (!pframes) { stream->congestion = (float)buffer_duration_usec / (float)drop_threshold; } if (buffer_duration_usec > drop_threshold) { debug("buffer_duration_usec: %" PRId64, buffer_duration_usec); drop_frames(stream, name, priority, pframes); } }
static void drop_frames(struct rtmp_stream *stream) { struct circlebuf new_buf = {0}; int drop_priority = 0; uint64_t last_drop_dts_usec = 0; int num_frames_dropped = 0; debug("Previous packet count: %d", (int)num_buffered_packets(stream)); circlebuf_reserve(&new_buf, sizeof(struct encoder_packet) * 8); while (stream->packets.size) { struct encoder_packet packet; circlebuf_pop_front(&stream->packets, &packet, sizeof(packet)); last_drop_dts_usec = packet.dts_usec; /* do not drop audio data or video keyframes */ if (packet.type == OBS_ENCODER_AUDIO || packet.drop_priority == OBS_NAL_PRIORITY_HIGHEST) { circlebuf_push_back(&new_buf, &packet, sizeof(packet)); } else { if (drop_priority < packet.drop_priority) drop_priority = packet.drop_priority; num_frames_dropped++; obs_free_encoder_packet(&packet); } } circlebuf_free(&stream->packets); stream->packets = new_buf; stream->min_priority = drop_priority; stream->min_drop_dts_usec = last_drop_dts_usec; stream->dropped_frames += num_frames_dropped; debug("New packet count: %d", (int)num_buffered_packets(stream)); }
static void drop_frames(struct rtmp_stream *stream) { struct circlebuf new_buf = {0}; int drop_priority = 0; uint64_t last_drop_dts_usec = 0; blog(LOG_DEBUG, "Previous packet count: %d", (int)num_buffered_packets(stream)); circlebuf_reserve(&new_buf, sizeof(struct encoder_packet) * 8); while (stream->packets.size) { struct encoder_packet packet; circlebuf_pop_front(&stream->packets, &packet, sizeof(packet)); last_drop_dts_usec = packet.dts_usec; if (packet.type == OBS_ENCODER_AUDIO) { circlebuf_push_back(&new_buf, &packet, sizeof(packet)); } else { if (drop_priority < packet.drop_priority) drop_priority = packet.drop_priority; obs_free_encoder_packet(&packet); } } circlebuf_free(&stream->packets); stream->packets = new_buf; stream->min_priority = drop_priority; stream->min_drop_dts_usec = last_drop_dts_usec; blog(LOG_DEBUG, "New packet count: %d", (int)num_buffered_packets(stream)); }
static inline void free_packets(struct rtmp_stream *stream) { size_t num_packets; pthread_mutex_lock(&stream->packets_mutex); num_packets = num_buffered_packets(stream); if (num_packets) info("Freeing %d remaining packets", (int)num_packets); while (stream->packets.size) { struct encoder_packet packet; circlebuf_pop_front(&stream->packets, &packet, sizeof(packet)); obs_free_encoder_packet(&packet); } pthread_mutex_unlock(&stream->packets_mutex); }
static void check_to_drop_frames(struct rtmp_stream *stream) { struct encoder_packet first; int64_t buffer_duration_usec; if (num_buffered_packets(stream) < 5) return; circlebuf_peek_front(&stream->packets, &first, sizeof(first)); /* do not drop frames if frames were just dropped within this time */ if (first.dts_usec < stream->min_drop_dts_usec) return; /* if the amount of time stored in the buffered packets waiting to be * sent is higher than threshold, drop frames */ buffer_duration_usec = stream->last_dts_usec - first.dts_usec; if (buffer_duration_usec > stream->drop_threshold_usec) { drop_frames(stream); blog(LOG_INFO, "dropping %" PRId64 " worth of frames", buffer_duration_usec); } }