in libftl/media.c [95:218]
ftl_status_t media_init(ftl_stream_configuration_private_t *ftl) {
ftl_media_config_t *media = &ftl->media;
ftl_status_t status = FTL_SUCCESS;
int idx;
if (ftl_get_state(ftl, FTL_MEDIA_READY)) {
return FTL_SUCCESS;
}
do {
os_init_mutex(&media->mutex);
os_init_mutex(&ftl->video.mutex);
os_init_mutex(&ftl->audio.mutex);
//use the same socket family as the control connection
media->media_socket = socket(ftl->socket_family, SOCK_DGRAM, IPPROTO_UDP);
if (media->media_socket == -1) {
return FTL_DNS_FAILURE;
}
if ((status = _get_addr_info(ftl->socket_family, ftl->ingest_ip, media->assigned_port, &media->ingest_addr, &media->ingest_addrlen)) != FTL_SUCCESS) {
return status;
}
media->max_mtu = MAX_MTU;
gettimeofday(&media->stats_tv, NULL);
media->sender_report_base_ntp.tv_usec = 0;
media->sender_report_base_ntp.tv_sec = 0;
ftl_media_component_common_t *media_comp[] = { &ftl->video.media_component, &ftl->audio.media_component };
ftl_media_component_common_t *comp;
for (idx = 0; idx < sizeof(media_comp) / sizeof(media_comp[0]); idx++) {
comp = media_comp[idx];
comp->nack_slots_initalized = FALSE;
if ((status = _nack_init(comp)) != FTL_SUCCESS) {
goto cleanup;
}
// According to RTP the time stamps should start at random values,
// but to help sync issues and to make sync easier to calculate we
// start at 0.
comp->timestamp = 0;
comp->producer = 0;
comp->consumer = 0;
comp->base_dts_usec = -1;
_clear_stats(&comp->stats);
}
ftl->video.media_component.timestamp_clock = VIDEO_RTP_TS_CLOCK_HZ;
ftl->audio.media_component.timestamp_clock = AUDIO_SAMPLE_RATE;
ftl->audio.is_ready_to_send = FALSE;
ftl->video.has_sent_first_frame = FALSE;
ftl->video.wait_for_idr_frame = TRUE;
// We need set this flag now so it is ready when the thread starts, but also
// so it is set if we destroy this before the thread starts it will be cleaned up.
ftl_set_state(ftl, FTL_RX_THRD);
if ((os_create_thread(&media->recv_thread, NULL, recv_thread, ftl)) != 0) {
ftl_clear_state(ftl, FTL_RX_THRD);
status = FTL_MALLOC_FAILURE;
break;
}
if (os_semaphore_create(&ftl->video.media_component.pkt_ready, "/VideoPkt", O_CREAT, 0) < 0) {
status = FTL_MALLOC_FAILURE;
break;
}
if (os_semaphore_create(&ftl->audio.media_component.pkt_ready, "/AudioPkt", O_CREAT, 0) < 0) {
status = FTL_MALLOC_FAILURE;
break;
}
// We need set this flag now so it is ready when the thread starts, but also
// so it is set if we destroy this before the thread starts it will be cleaned up.
ftl_set_state(ftl, FTL_TX_THRD);
if ((os_create_thread(&media->video_send_thread, NULL, video_send_thread, ftl)) != 0) {
ftl_clear_state(ftl, FTL_TX_THRD);
status = FTL_MALLOC_FAILURE;
break;
}
// We need set this flag now so it is ready when the thread starts, but also
// so it is set if we destroy this before the thread starts it will be cleaned up.
ftl_set_state(ftl, FTL_TX_THRD);
if ((os_create_thread(&media->audio_send_thread, NULL, audio_send_thread, ftl)) != 0) {
ftl_clear_state(ftl, FTL_TX_THRD);
status = FTL_MALLOC_FAILURE;
break;
}
if (os_semaphore_create(&media->ping_thread_shutdown, "/PingThreadShutdown", O_CREAT, 0) < 0) {
status = FTL_MALLOC_FAILURE;
break;
}
// We need set this flag now so it is ready when the thread starts, but also
// so it is set if we destroy this before the thread starts it will be cleaned up.
ftl_set_state(ftl, FTL_PING_THRD);
if ((os_create_thread(&media->ping_thread, NULL, ping_thread, ftl)) != 0) {
ftl_clear_state(ftl, FTL_PING_THRD);
status = FTL_MALLOC_FAILURE;
break;
}
ftl_clear_state(ftl, FTL_SPEED_TEST);
ftl_set_state(ftl, FTL_MEDIA_READY);
return FTL_SUCCESS;
} while (0);
cleanup:
_internal_media_destroy(ftl);
return status;
}