in libftl/media.c [645:767]
int media_send_video(ftl_stream_configuration_private_t *ftl, int64_t dts_usec, uint8_t *data, int32_t len, int end_of_frame) {
ftl_media_component_common_t *mc = &ftl->video.media_component;
uint8_t nalu_type = 0;
uint8_t nri;
int bytes_queued = 0;
int pkt_len;
int payload_size;
nack_slot_t *slot;
int remaining = len;
int first_fu = 1;
// Before we send any video we want to make sure the audio stream
// is also ready to run. If the stream isn't ready drop this data.
if (!ftl->audio.is_ready_to_send)
{
if (end_of_frame)
{
mc->stats.dropped_frames++;
}
return bytes_queued;
}
if (os_trylock_mutex(&ftl->video.mutex)) {
if (ftl_get_state(ftl, FTL_MEDIA_READY)) {
nalu_type = data[0] & 0x1F;
nri = (data[0] >> 5) & 0x3;
if (ftl->video.wait_for_idr_frame) {
if (nalu_type == H264_NALU_TYPE_SPS) {
ftl->video.wait_for_idr_frame = FALSE;
if (!ftl->video.has_sent_first_frame) {
FTL_LOG(ftl, FTL_LOG_INFO, "Audio is ready and we have the first iframe, starting stream. (dropped %d frames)\n", mc->stats.dropped_frames);
ftl->video.has_sent_first_frame = TRUE;
}
else {
FTL_LOG(ftl, FTL_LOG_INFO, "Got key frame, continuing (dropped %d frames)\n", mc->stats.dropped_frames);
}
}
else {
if (end_of_frame) {
mc->stats.dropped_frames++;
}
os_unlock_mutex(&ftl->video.mutex);
return bytes_queued;
}
}
_update_timestamp(ftl, mc, dts_usec);
if (nalu_type == H264_NALU_TYPE_IDR) {
mc->tmp_seq_num = mc->seq_num;
}
while (remaining > 0) {
uint16_t sn = mc->seq_num;
uint32_t ssrc = mc->ssrc;
uint8_t *pkt_buf;
if ((slot = _media_get_empty_slot(ftl, ssrc, sn)) == NULL) {
if (nri) {
FTL_LOG(ftl, FTL_LOG_INFO, "Video queue full, dropping packets until next key frame\n");
ftl->video.wait_for_idr_frame = TRUE;
}
os_unlock_mutex(&ftl->video.mutex);
return bytes_queued;
}
os_lock_mutex(&slot->mutex);
pkt_buf = slot->packet;
pkt_len = sizeof(slot->packet);
slot->first = 0;
slot->last = 0;
payload_size = _media_make_video_rtp_packet(ftl, data, remaining, pkt_buf, &pkt_len, first_fu);
first_fu = 0;
remaining -= payload_size;
data += payload_size;
bytes_queued += pkt_len;
mc->stats.payload_bytes_sent += payload_size;
/*if all data has been consumed set marker bit*/
if (remaining <= 0 && end_of_frame) {
_media_set_marker_bit(mc, pkt_buf);
slot->last = 1;
}
slot->len = pkt_len;
slot->sn = sn;
gettimeofday(&slot->insert_time, NULL);
slot->isPartOfIframe = nalu_type == H264_NALU_TYPE_IDR;
os_unlock_mutex(&slot->mutex);
os_semaphore_post(&mc->pkt_ready);
mc->stats.packets_queued++;
mc->stats.bytes_queued += pkt_len;
}
mc->stats.current_frame_size += len;
if (end_of_frame) {
mc->stats.frames_received++;
if (mc->stats.current_frame_size > mc->stats.max_frame_size) {
mc->stats.max_frame_size = mc->stats.current_frame_size;
}
mc->stats.current_frame_size = 0;
}
}
os_unlock_mutex(&ftl->video.mutex);
}
return bytes_queued;
}