krad_mixer_t *krad_mixer_create (char *name) { int p; krad_mixer_t *krad_mixer; if ((krad_mixer = calloc (1, sizeof (krad_mixer_t))) == NULL) { failfast ("Krad Mixer memory alloc failure"); } krad_mixer->address.path.unit = KR_MIXER; krad_mixer->address.path.subunit.mixer_subunit = KR_UNIT; krad_mixer->name = strdup (name); krad_mixer->sample_rate = KRAD_MIXER_DEFAULT_SAMPLE_RATE; krad_mixer->rms_window_size = (krad_mixer->sample_rate / 1000) * KRAD_MIXER_RMS_WINDOW_SIZE_MS; krad_mixer->ticker_period = KRAD_MIXER_DEFAULT_TICKER_PERIOD; krad_mixer->frames_per_peak_broadcast = 1536; krad_mixer->crossfade_group = calloc (KRAD_MIXER_MAX_PORTGROUPS / 2, sizeof (krad_mixer_crossfade_group_t)); for (p = 0; p < KRAD_MIXER_MAX_PORTGROUPS; p++) { krad_mixer->portgroup[p] = calloc (1, sizeof (krad_mixer_portgroup_t)); } krad_mixer->krad_audio = krad_audio_create (krad_mixer); krad_mixer->master_mix = krad_mixer_portgroup_create (krad_mixer, "MasterBUS", MIX, NOTOUTPUT, 2, DEFAULT_MASTERBUS_LEVEL, NULL, MIXBUS, NULL, 0); krad_mixer->tone_port = krad_mixer_portgroup_create (krad_mixer, "DTMF", INPUT, NOTOUTPUT, 1, 35.0f, krad_mixer->master_mix, KRAD_TONE, NULL, 0); krad_mixer_portgroup_mixmap_channel (krad_mixer->tone_port, 0, 1); return krad_mixer; }
void *krad_transmitter_listening_thread (void *arg) { krad_transmitter_t *krad_transmitter = (krad_transmitter_t *)arg; krad_system_set_thread_name ("kr_tx_listen"); krad_transmission_receiver_t *krad_transmission_receiver; int e; int ret; int eret; int cret; int addr_size; int client_fd; struct sockaddr_in remote_address; char hbuf[NI_MAXHOST]; char sbuf[NI_MAXSERV]; printk ("Krad Transmitter: Listening thread starting"); addr_size = 0; e = 0; ret = 0; eret = 0; cret = 0; krad_transmission_receiver = NULL; memset (&remote_address, 0, sizeof(remote_address)); addr_size = sizeof (remote_address); while (krad_transmitter->stop_listening == 0) { ret = epoll_wait (krad_transmitter->incoming_connections_efd, krad_transmitter->incoming_connection_events, KRAD_TRANSMITTER_MAXEVENTS, 50); if (ret < 0) { if ((ret < 0) && (errno == EINTR)) { continue; } printke ("Krad Transmitter: Failed on epoll wait %s", strerror(errno)); krad_transmitter->stop_listening = 1; break; } if (ret > 0) { for (e = 0; e < ret; e++) { if ((krad_transmitter->incoming_connection_events[e].events & EPOLLERR) || (krad_transmitter->incoming_connection_events[e].events & EPOLLHUP)) { if (krad_transmitter->incoming_connections_sd == krad_transmitter->incoming_connection_events[e].data.fd) { failfast ("Krad Transmitter: error on listen socket"); } else { if (krad_transmitter->incoming_connection_events[e].events & EPOLLHUP) { printke ("Krad Transmitter: incoming transmitter connection hangup"); } if (krad_transmitter->incoming_connection_events[e].events & EPOLLERR) { printke ("Krad Transmitter: incoming transmitter connection error"); } krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr); continue; } } if (krad_transmitter->incoming_connections_sd == krad_transmitter->incoming_connection_events[e].data.fd) { while (1) { client_fd = accept (krad_transmitter->incoming_connections_sd, (struct sockaddr *)&remote_address, (socklen_t *)&addr_size); if (client_fd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { // We have processed all incoming connections. break; } else { failfast ("Krad Transmitter: error on listen socket accept"); } } if (getnameinfo ((struct sockaddr *)&remote_address, addr_size, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV) == 0) { printk ("Krad Transmitter: Accepted transmitter connection on descriptor %d (host=%s, port=%s)", client_fd, hbuf, sbuf); } else { printke ("Krad Transmitter: Accepted transmitter connection on descriptor %d ... but could not getnameinfo()?", client_fd, hbuf, sbuf); } krad_system_set_socket_nonblocking (client_fd); krad_transmission_receiver = krad_transmitter_receiver_create (krad_transmitter, client_fd); if (krad_transmission_receiver == NULL) { failfast ("Krad Transmitter: ran out of connections!"); } eret = epoll_ctl (krad_transmitter->incoming_connections_efd, EPOLL_CTL_ADD, client_fd, &krad_transmission_receiver->event); if (eret != 0) { failfast ("Krad Transmitter: incoming transmitter connection epoll error eret is %d errno is %i", eret, errno); } } continue; } if (krad_transmitter->incoming_connection_events[e].events & EPOLLIN) { while (1) { krad_transmission_receiver = (krad_transmission_receiver_t *)krad_transmitter->incoming_connection_events[e].data.ptr; cret = read (krad_transmission_receiver->fd, krad_transmission_receiver->buffer + krad_transmission_receiver->position, sizeof (krad_transmission_receiver->buffer) - krad_transmission_receiver->position); if (cret == -1) { if (errno != EAGAIN) { printke ("Krad Transmitter: error reading from a new incoming connection socket"); krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr); } break; } if (cret == 0) { printk ("Krad Transmitter: Client EOF Closed connection"); krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr); break; } if (cret > 0) { krad_transmission_receiver->position += cret; krad_transmitter_handle_incoming_connection (krad_transmitter, krad_transmission_receiver); break; } } } } } if (ret == 0) { //printk ("Krad Transmitter: Listening thread... nothing happened"); } } close (krad_transmitter->incoming_connections_efd); close (krad_transmitter->incoming_connections_sd); free (krad_transmitter->incoming_connection_events); krad_transmitter->port = 0; krad_transmitter->listening = 0; printk ("Krad Transmitter: Listening thread exiting"); return NULL; }
static int krad_transmitter_transmission_transmit (krad_transmission_t *krad_transmission, krad_transmission_receiver_t *krad_transmission_receiver) { int ret; uint64_t buf_avail; uint32_t vec_pos; uint32_t vec_avail; krad_ringbuffer_data_t *vec; vec_avail = 0; vec_pos = 0; ret = 0; buf_avail = 0; if ((krad_transmission == NULL) || (krad_transmission_receiver == NULL)) { failfast ("Krad Transmitter: this should not be"); } while (1) { if ((krad_transmission_receiver->wrote_http_header != 1) || (krad_transmission_receiver->wrote_header != 1)) { ret = krad_transmitter_transmission_transmit_header (krad_transmission, krad_transmission_receiver); if (ret == 1) { continue; } else { return 0; } } if (krad_transmission_receiver->position == krad_transmission->position) { if (krad_transmission_receiver->ready == 0) { krad_transmission_add_ready (krad_transmission, krad_transmission_receiver); } break; } if (krad_transmission_receiver->position < krad_transmission->horizon) { printke ("Krad Transmitter: client fell so far behind oh no"); krad_transmitter_receiver_destroy (krad_transmission_receiver); break; } buf_avail = krad_transmission->position - krad_transmission_receiver->position; if (buf_avail > krad_transmission->tx_vec[1].len) { vec = &krad_transmission->tx_vec[0]; vec_pos = krad_transmission->tx_vec[0].len - (buf_avail - krad_transmission->tx_vec[1].len); vec_avail = vec->len - vec_pos; ret = write (krad_transmission_receiver->fd, vec->buf + vec_pos, vec_avail); } else { vec = &krad_transmission->tx_vec[1]; vec_pos = krad_transmission->tx_vec[1].len - buf_avail; vec_avail = vec->len - vec_pos; ret = write (krad_transmission_receiver->fd, vec->buf + vec_pos, vec_avail); } if (ret == -1) { if (errno != EAGAIN) { printke ("Krad Transmitter: transmission error writing to socket"); krad_transmitter_receiver_destroy (krad_transmission_receiver); break; } if (krad_transmission_receiver->ready == 1) { krad_transmission_remove_ready (krad_transmission, krad_transmission_receiver); } break; } if (ret == 0) { printk ("Krad Transmitter: transmission transmit wrote to client 0 bytes"); krad_transmitter_receiver_destroy (krad_transmission_receiver); break; } if (ret > 0) { krad_transmission_receiver->position += ret; } if (ret < vec_avail) { if (krad_transmission_receiver->ready == 1) { krad_transmission_remove_ready (krad_transmission, krad_transmission_receiver); } break; } } return 0; }
static int krad_app_client_init (krad_app_client_t *client, int timeout_ms) { int rc; char port_string[6]; struct sockaddr_un unix_saddr; struct in6_addr serveraddr; struct addrinfo hints; struct addrinfo *res; res = NULL; //FIXME make connect nonblocking if (client->tcp_port != 0) { //FIXME hrm we don't know the sysname of a remote connect! crazy ? //printf ("Krad APP Client: Connecting to remote %s:%d", client->host, client->tcp_port); memset(&hints, 0x00, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rc = inet_pton (AF_INET, client->host, &serveraddr); if (rc == 1) { hints.ai_family = AF_INET; hints.ai_flags |= AI_NUMERICHOST; } else { rc = inet_pton (AF_INET6, client->host, &serveraddr); if (rc == 1) { hints.ai_family = AF_INET6; hints.ai_flags |= AI_NUMERICHOST; } } snprintf (port_string, 6, "%d", client->tcp_port); rc = getaddrinfo (client->host, port_string, &hints, &res); if (rc != 0) { printf ("Krad APP Client: Host not found --> %s\n", gai_strerror(rc)); return 0; } client->sd = socket (res->ai_family, res->ai_socktype, res->ai_protocol); if (client->sd < 0) { printf ("Krad APP Client: Socket Error"); if (res != NULL) { freeaddrinfo (res); res = NULL; } return 0; } rc = connect (client->sd, res->ai_addr, res->ai_addrlen); if (rc < 0) { printf ("Krad APP Client: Remote Connect Error\n"); if (res != NULL) { freeaddrinfo (res); res = NULL; } return 0; } if (res != NULL) { freeaddrinfo (res); res = NULL; } } else { client->sd = socket (AF_UNIX, SOCK_STREAM, 0); if (client->sd == -1) { failfast ("Krad APP Client: socket fail"); return 0; } memset(&unix_saddr, 0x00, sizeof(unix_saddr)); unix_saddr.sun_family = AF_UNIX; snprintf (unix_saddr.sun_path, sizeof(unix_saddr.sun_path), "%s", client->api_path); if (client->on_linux) { unix_saddr.sun_path[0] = '\0'; } if (connect (client->sd, (struct sockaddr *) &unix_saddr, sizeof (unix_saddr)) == -1) { close (client->sd); client->sd = 0; printke ("Krad APP Client: Can't connect to socket %s", client->api_path); return 0; } } krad_system_set_socket_nonblocking (client->sd); return client->sd; }
krad_vpx_encoder_t *krad_vpx_encoder_create (int width, int height, int fps_numerator, int fps_denominator, int bitrate) { krad_vpx_encoder_t *vpx; vpx = calloc (1, sizeof(krad_vpx_encoder_t)); vpx->width = width; vpx->height = height; vpx->fps_numerator = fps_numerator; vpx->fps_denominator = fps_denominator; vpx->bitrate = bitrate; printk ("Krad Radio using libvpx version: %s", vpx_codec_version_str ()); vpx->res = vpx_codec_enc_config_default (vpx_codec_vp8_cx(), &vpx->cfg, 0); if (vpx->res) { failfast ("Failed to get config: %s\n", vpx_codec_err_to_string(vpx->res)); } // print default config krad_vpx_encoder_print_config (vpx); //TEMP //vpx->cfg.g_lag_in_frames = 1; vpx->cfg.g_w = vpx->width; vpx->cfg.g_h = vpx->height; /* Next two lines are really right */ vpx->cfg.g_timebase.num = vpx->fps_denominator; vpx->cfg.g_timebase.den = vpx->fps_numerator; vpx->cfg.rc_target_bitrate = bitrate; vpx->cfg.g_threads = 4; vpx->cfg.kf_mode = VPX_KF_AUTO; vpx->cfg.rc_end_usage = VPX_VBR; vpx->cfg.kf_max_dist = 120; vpx->deadline = 15 * 1000; vpx->min_quantizer = vpx->cfg.rc_min_quantizer; vpx->max_quantizer = vpx->cfg.rc_max_quantizer; //krad_vpx_encoder_print_config (vpx); if (vpx_codec_enc_init (&vpx->encoder, vpx_codec_vp8_cx(), &vpx->cfg, 0)) { krad_vpx_fail (&vpx->encoder, "Failed to initialize encoder"); } krad_vpx_encoder_print_config (vpx); //vpx_codec_control (&vpx->encoder, VP8E_SET_ENABLEAUTOALTREF, 1); return vpx; }
krad_mixer_portgroup_t *krad_mixer_portgroup_create (krad_mixer_t *krad_mixer, char *sysname, int direction, krad_mixer_output_t output_type, int channels, float volume, krad_mixer_mixbus_t *mixbus, krad_mixer_portgroup_io_t io_type, void *io_ptr, krad_audio_api_t api) { int p; int c; krad_mixer_portgroup_t *portgroup; portgroup = NULL; /* prevent dupe names */ for (p = 0; p < KRAD_MIXER_MAX_PORTGROUPS; p++) { if (krad_mixer->portgroup[p]->active != 0) { if (strncmp(sysname, krad_mixer->portgroup[p]->sysname, strlen(sysname)) == 0) { return NULL; } } } //FIXME race here if portgroup being created via ipc and transponder at same moment for (p = 0; p < KRAD_MIXER_MAX_PORTGROUPS; p++) { if (krad_mixer->portgroup[p]->active == 0) { portgroup = krad_mixer->portgroup[p]; break; } } if (portgroup == NULL) { return NULL; } /* Prevent multiple JACK direct outputs as this is redundant */ if ((api == JACK) && (direction == OUTPUT) && (output_type == DIRECT)) { for (p = 0; p < KRAD_MIXER_MAX_PORTGROUPS; p++) { if ((krad_mixer->portgroup[p]->active == 1) || (krad_mixer->portgroup[p]->active == 2)) { if ((krad_mixer_portgroup_is_jack(krad_mixer->portgroup[p])) && (krad_mixer->portgroup[p]->direction == OUTPUT) && (krad_mixer->portgroup[p]->output_type == DIRECT)) { return NULL; } } } } portgroup->krad_mixer = krad_mixer; strcpy (portgroup->sysname, sysname); portgroup->channels = channels; portgroup->io_type = io_type; portgroup->output_type = output_type; portgroup->mixbus = mixbus; portgroup->direction = direction; portgroup->address.path.unit = KR_MIXER; portgroup->address.path.subunit.mixer_subunit = KR_PORTGROUP; strcpy (portgroup->address.id.name, portgroup->sysname); for (c = 0; c < KRAD_MIXER_MAX_CHANNELS; c++) { if (c < portgroup->channels) { portgroup->mixmap[c] = c; } else { portgroup->mixmap[c] = -1; } portgroup->map[c] = c; portgroup->mapped_samples[c] = &portgroup->samples[c]; if ((portgroup->direction != OUTPUT) || (portgroup->output_type == AUX)) { portgroup->volume[c] = volume; } else { portgroup->volume[c] = 100.0f; } portgroup->volume_actual[c] = (float)(portgroup->volume[c]/100.0f); portgroup->volume_actual[c] *= portgroup->volume_actual[c]; portgroup->new_volume_actual[c] = portgroup->volume_actual[c]; switch ( portgroup->io_type ) { case KRAD_TONE: portgroup->samples[c] = calloc (1, 16384); break; case MIXBUS: portgroup->samples[c] = calloc (1, 16384); break; case KRAD_AUDIO: break; case KRAD_LINK: portgroup->samples[c] = calloc (1, 16384); break; case KLOCALSHM: break; } } switch ( portgroup->io_type ) { case KRAD_TONE: portgroup->io_ptr = krad_tone_create (krad_mixer->sample_rate); case MIXBUS: break; case KRAD_AUDIO: portgroup->io_ptr = krad_audio_portgroup_create (krad_mixer->krad_audio, portgroup->sysname, portgroup->direction, portgroup->channels, api); break; case KRAD_LINK: portgroup->io_ptr = io_ptr; break; case KLOCALSHM: portgroup->io_ptr = io_ptr; break; } if (portgroup->io_type != KRAD_LINK) { portgroup->krad_tags = krad_tags_create (portgroup->sysname); //if ((portgroup->krad_tags != NULL) && (krad_mixer->krad_ipc != NULL)) { // krad_tags_set_set_tag_callback (portgroup->krad_tags, krad_mixer->krad_ipc, // (void (*)(void *, char *, char *, char *, int))krad_ipc_server_broadcast_tag); //} } else { portgroup->krad_tags = krad_link_get_tags (portgroup->io_ptr); } if (portgroup->krad_tags == NULL) { failfast ("Oh I couldn't find me tags"); } portgroup->effects = kr_effects_create (portgroup->channels, portgroup->krad_mixer->sample_rate); if (portgroup->effects == NULL) { failfast ("Oh I couldn't make effects"); } if (portgroup->direction == INPUT) { kr_effects_effect_add2 (portgroup->effects, kr_effects_string_to_effect ("eq"), portgroup->krad_mixer, portgroup->sysname); kr_effects_effect_add2 (portgroup->effects, kr_effects_string_to_effect ("lowpass"), portgroup->krad_mixer, portgroup->sysname); kr_effects_effect_add2 (portgroup->effects, kr_effects_string_to_effect ("highpass"), portgroup->krad_mixer, portgroup->sysname); kr_effects_effect_add2 (portgroup->effects, kr_effects_string_to_effect ("analog"), portgroup->krad_mixer, portgroup->sysname); } if (portgroup->io_type != KLOCALSHM) { portgroup->active = 1; } return portgroup; }
void krad_x11_enable_capture (krad_x11_t *x11, uint32_t window_id) { xcb_get_geometry_reply_t *geo; xcb_query_tree_reply_t *tree; xcb_translate_coordinates_cookie_t translateCookie; xcb_translate_coordinates_reply_t *trans; geo = xcb_get_geometry_reply (x11->connection, xcb_get_geometry (x11->connection, window_id), NULL); if (geo == NULL) { window_id = 0; } else { tree = xcb_query_tree_reply (x11->connection, xcb_query_tree (x11->connection, window_id), NULL); if (tree == NULL) { window_id = 0; free (geo); } else { translateCookie = xcb_translate_coordinates (x11->connection, window_id, x11->screen->root, geo->x, geo->y); trans = xcb_translate_coordinates_reply (x11->connection, translateCookie, NULL); if (trans == NULL) { window_id = 0; free (tree); free (geo); } else { x11->width = geo->width; x11->height = geo->height; x11->x = trans->dst_x - geo->x; x11->y = trans->dst_y - geo->y; free (trans); free (tree); free (geo); } } } if (window_id == 0) { x11->width = x11->screen_width; x11->height = x11->screen_height; x11->window = x11->screen->root; } //printf ("capture width %d height %d x %d y %d\n", // x11->width, x11->height, x11->x, x11->y); x11->img = xcb_image_create_native (x11->connection, x11->width, x11->height, XCB_IMAGE_FORMAT_Z_PIXMAP, x11->screen_bit_depth, 0, ~0, 0); if (!x11->img) { exit (15); } x11->stride = x11->img->stride; x11->shminfo.shmid = shmget (IPC_PRIVATE, x11->img->stride * x11->img->height, (IPC_CREAT | 0666)); if (x11->shminfo.shmid == (uint32_t)-1) { xcb_image_destroy (x11->img); failfast ("shminfo fail"); } x11->shminfo.shmaddr = shmat (x11->shminfo.shmid, 0, 0); x11->img->data = x11->shminfo.shmaddr; if (x11->img->data == (uint8_t *)-1) { xcb_image_destroy (x11->img); failfast ("xcb image fail"); } x11->shminfo.shmseg = xcb_generate_id (x11->connection); xcb_shm_attach (x11->connection, x11->shminfo.shmseg, x11->shminfo.shmid, 0); x11->capture_enabled = 1; }
void krad_slicer_sendto (krad_slicer_t *krad_slicer, unsigned char *data, int size, int track, int keyframe, char *ip, int port) { int ret; int remaining; int payload_size; int packet_size; int sent; int packet; struct sockaddr_in remote_client; ret = 0; sent = 0; payload_size = 0; packet_size = 0; packet = 0; remaining = size; memset((char *) &remote_client, 0, sizeof(remote_client)); remote_client.sin_port = htons(port); remote_client.sin_family = AF_INET; if (inet_pton(remote_client.sin_family, ip, &(remote_client.sin_addr)) != 1) { failfast ("inet_pton() failed"); } while (remaining) { packet++; if (remaining > KRAD_UDP_MAX_PAYOAD_SIZE) { payload_size = KRAD_UDP_MAX_PAYOAD_SIZE; } else { payload_size = remaining; } remaining -= payload_size; packet_size = payload_size + KRAD_UDP_HEADER_SIZE; // header|key|track number|sequence number|start_byte|total_bytes if (keyframe == 1) { krad_slicer->data[2] = 'K'; } else { krad_slicer->data[2] = 'N'; } memcpy (krad_slicer->data + 3, &track, 4); memcpy (krad_slicer->data + 7, &krad_slicer->track_seq[track], 4); memcpy (krad_slicer->data + 11, &sent, 4); memcpy (krad_slicer->data + 15, &size, 4); memcpy (krad_slicer->data + 19, data + sent, payload_size); //printk("track: %d slice: %d size: %d packet: %d range: %d - %d packet size: %d payload size: %d\n", // track, krad_slicer->track_seq[track], size, packet, sent, sent + payload_size - 1, packet_size, payload_size); ret = sendto(krad_slicer->sd, krad_slicer->data, packet_size, 0, (struct sockaddr *) &remote_client, sizeof(remote_client)); if (ret != packet_size) { failfast ("udp sending error"); } sent += payload_size; } krad_slicer->track_seq[track]++; }
void kr_streamer_run (kr_streamer_t *streamer) { krad_frame_t *frame; int32_t frames; kr_medium_t *amedium; kr_codeme_t *acodeme; kr_medium_t *vmedium; kr_codeme_t *vcodeme; struct SwsContext *converter; int sws_algo; int32_t ret; int32_t muxdelay; uint32_t c; muxdelay = 1; signal (SIGINT, signal_recv); signal (SIGTERM, signal_recv); converter = NULL; sws_algo = SWS_BILINEAR; amedium = kr_medium_kludge_create (); acodeme = kr_codeme_kludge_create (); vmedium = kr_medium_kludge_create (); vcodeme = kr_codeme_kludge_create (); streamer->timer = krad_timer_create (); kr_audioport_connect(streamer->audioport); kr_videoport_activate (streamer->videoport); while (!destroy) { while (krad_ringbuffer_read_space (streamer->audio_ring[1]) >= 1024 * 4) { for (c = 0; c < streamer->params->channels; c++) { krad_ringbuffer_read (streamer->audio_ring[c], (char *)amedium->a.samples[c], 1024 * 4); } amedium->a.count = 1024; amedium->a.channels = streamer->params->channels; ret = kr_vorbis_encode (streamer->vorbis_enc, acodeme, amedium); if (ret == 1) { kr_mkv_add_audio (streamer->mkv, 2, acodeme->data, acodeme->sz, acodeme->count); muxdelay = 0; while (1) { ret = kr_vorbis_encode (streamer->vorbis_enc, acodeme, NULL); if (ret == 1) { kr_mkv_add_audio (streamer->mkv, 2, acodeme->data, acodeme->sz, acodeme->count); } else { break; } } } } if (muxdelay > 0) { continue; } frame = NULL; frames = krad_ringbuffer_read_space (streamer->frame_ring) / sizeof(void *); if (frames > 1) { krad_vpx_encoder_deadline_set (streamer->vpx_enc, 1); sws_algo = SWS_POINT; } if (frames == 0) { krad_vpx_encoder_deadline_set (streamer->vpx_enc, 10000); sws_algo = SWS_BILINEAR; usleep (2000); continue; } if (frames > 0) { krad_ringbuffer_read (streamer->frame_ring, (char *)&frame, sizeof(krad_frame_t *)); vmedium->v.tc = krad_timer_current_ms (streamer->timer); if (!krad_timer_started (streamer->timer)) { krad_timer_start (streamer->timer); } frame->yuv_pixels[0] = (uint8_t *)frame->pixels; frame->format = PIX_FMT_RGB32; frame->yuv_pixels[1] = NULL; frame->yuv_pixels[2] = NULL; frame->yuv_strides[0] = streamer->width * 4; frame->yuv_strides[1] = 0; frame->yuv_strides[2] = 0; frame->yuv_strides[3] = 0; converter = sws_getCachedContext ( converter, streamer->width, streamer->height, frame->format, streamer->params->width, streamer->params->height, PIX_FMT_YUV420P, sws_algo, NULL, NULL, NULL); if (converter == NULL) { failfast ("Krad streamer: could not sws_getCachedContext"); } vmedium->v.pps[0] = streamer->params->width; vmedium->v.pps[1] = streamer->params->width/2; vmedium->v.pps[2] = streamer->params->width/2; vmedium->v.ppx[0] = vmedium->data; vmedium->v.ppx[1] = vmedium->data + streamer->params->width * (streamer->params->height); vmedium->v.ppx[2] = vmedium->data + streamer->params->width * (streamer->params->height) + ((streamer->params->width * (streamer->params->height)) /4); sws_scale (converter, (const uint8_t * const*)frame->yuv_pixels, frame->yuv_strides, 0, streamer->height, vmedium->v.ppx, vmedium->v.pps); krad_framepool_unref_frame (frame); ret = kr_vpx_encode (streamer->vpx_enc, vcodeme, vmedium); if (ret == 1) { kr_mkv_add_video_tc (streamer->mkv, 1, vcodeme->data, vcodeme->sz, vcodeme->key, vcodeme->tc); } printf ("\rKrad Streamer Frame# %12"PRIu64"", streamer->eframes++); fflush (stdout); //krad_ticker_wait (streamer->ticker); } } kr_medium_kludge_destroy (&vmedium); kr_codeme_kludge_destroy (&vcodeme); kr_medium_kludge_destroy (&amedium); kr_codeme_kludge_destroy (&acodeme); if (converter != NULL) { sws_freeContext (converter); converter = NULL; } krad_timer_destroy (streamer->timer); }
static krad_stream_t *kr_stream_connect (char *host, int port) { krad_stream_t *stream; int ret; int flags; char port_string[6]; struct in6_addr serveraddr; struct addrinfo hints; struct addrinfo *res; res = NULL; if ((host == NULL) || ((port < 0) || (port > 65535))) { return NULL; } stream = calloc (1, sizeof(krad_stream_t)); memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; ret = inet_pton (AF_INET, host, &serveraddr); if (ret == 1) { hints.ai_family = AF_INET; hints.ai_flags |= AI_NUMERICHOST; } else { ret = inet_pton (AF_INET6, host, &serveraddr); if (ret == 1) { hints.ai_family = AF_INET6; hints.ai_flags |= AI_NUMERICHOST; } } snprintf (port_string, 6, "%d", port); ret = getaddrinfo (host, port_string, &hints, &res); if (ret != 0) { kr_stream_destroy (&stream); return NULL; } stream->sd = socket (res->ai_family, res->ai_socktype, res->ai_protocol); if (stream->sd < 0) { kr_stream_destroy (&stream); } else { flags = fcntl (stream->sd, F_GETFL, 0); if (flags == -1) { failfast ("Krad System: error on syscall fcntl F_GETFL"); } else { flags |= O_NONBLOCK; ret = fcntl (stream->sd, F_SETFL, flags); if (ret == -1) { failfast ("Krad System: error on syscall fcntl F_SETFL"); } else { ret = connect (stream->sd, res->ai_addr, res->ai_addrlen); if ((ret < 0) && (errno != EINPROGRESS)) { kr_stream_destroy (&stream); } } } } if (res != NULL) { freeaddrinfo (res); } return stream; }
krad_opus_t *krad_opus_decoder_create (unsigned char *header_data, int header_length, float output_sample_rate) { int c; krad_opus_t *krad_opus = calloc (1, sizeof(krad_opus_t)); krad_opus->output_sample_rate = output_sample_rate; krad_opus->opus_header = calloc (1, sizeof(OpusHeader)); if (opus_header_parse (header_data, header_length, krad_opus->opus_header) != 1) { failfast ("krad_opus_decoder_create problem reading opus header"); } // oops //krad_opus->input_sample_rate = krad_opus->opus_header->input_sample_rate; krad_opus->channels = krad_opus->opus_header->channels; krad_opus->interleaved_samples = malloc(16 * 8192); for (c = 0; c < krad_opus->channels; c++) { krad_opus->ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->resampled_ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->samples[c] = malloc (16 * 8192); krad_opus->read_samples[c] = malloc (16 * 8192); krad_opus->resampled_samples[c] = malloc (16 * 8192); krad_opus->src_resampler[c] = src_new (KRAD_OPUS_SRC_QUALITY, 1, &krad_opus->src_error[c]); if (krad_opus->src_resampler[c] == NULL) { failfast ("krad_opus_decoder_create src resampler error: %s", src_strerror (krad_opus->src_error[c])); } krad_opus->src_data[c].src_ratio = output_sample_rate / 48000; printk ("krad_opus_decoder_create src resampler ratio is: %f", krad_opus->src_data[c].src_ratio); } krad_opus->streams = krad_opus->opus_header->nb_streams; krad_opus->coupled_streams = krad_opus->opus_header->nb_coupled; memcpy (krad_opus->mapping, krad_opus->opus_header->stream_map, 256); printk ("krad_opus_decoder_create channels %d streams %d coupled %d", krad_opus->channels, krad_opus->streams, krad_opus->coupled_streams ); krad_opus->decoder = opus_multistream_decoder_create (48000, krad_opus->opus_header->channels, krad_opus->streams, krad_opus->coupled_streams, krad_opus->mapping, &krad_opus->opus_decoder_error); if (krad_opus->opus_decoder_error != OPUS_OK) { failfast ("Cannot create decoder: %s", opus_strerror (krad_opus->opus_decoder_error)); } return krad_opus; }
krad_opus_t *krad_opus_encoder_create (int channels, int input_sample_rate, int bitrate, int application) { int c; krad_opus_t *krad_opus = calloc(1, sizeof(krad_opus_t)); krad_opus->opus_header = calloc(1, sizeof(OpusHeader)); krad_opus->input_sample_rate = input_sample_rate; krad_opus->channels = channels; krad_opus->bitrate = bitrate; krad_opus->application = application; krad_opus->complexity = DEFAULT_OPUS_COMPLEXITY; krad_opus->signal = OPUS_AUTO; krad_opus->frame_size = DEFAULT_OPUS_FRAME_SIZE; krad_opus->bandwidth = OPUS_BANDWIDTH_FULLBAND; krad_opus->new_frame_size = krad_opus->frame_size; krad_opus->new_complexity = krad_opus->complexity; krad_opus->new_bitrate = krad_opus->bitrate; krad_opus->new_signal = krad_opus->signal; krad_opus->new_bandwidth = krad_opus->bandwidth; for (c = 0; c < krad_opus->channels; c++) { krad_opus->ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->resampled_ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->samples[c] = malloc(16 * 8192); krad_opus->resampled_samples[c] = malloc(16 * 8192); krad_opus->src_resampler[c] = src_new (KRAD_OPUS_SRC_QUALITY, 1, &krad_opus->src_error[c]); if (krad_opus->src_resampler[c] == NULL) { failfast ("Krad Opus Encoder: src resampler error: %s", src_strerror (krad_opus->src_error[c])); } krad_opus->src_data[c].src_ratio = 48000.0 / krad_opus->input_sample_rate; } if (krad_opus->channels < 3) { krad_opus->streams = 1; if (krad_opus->channels == 2) { krad_opus->coupled_streams = 1; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; } else { krad_opus->coupled_streams = 0; krad_opus->mapping[0] = 0; } krad_opus->opus_header->channel_mapping = 0; } else { krad_opus->opus_header->channel_mapping = 1; switch (krad_opus->channels) { case 3: krad_opus->streams = 2; krad_opus->coupled_streams = 1; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; krad_opus->mapping[2] = 2; case 4: krad_opus->streams = 2; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; krad_opus->mapping[2] = 2; krad_opus->mapping[3] = 3; case 5: krad_opus->streams = 3; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; case 6: krad_opus->streams = 4; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 5; case 7: krad_opus->streams = 5; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 5; krad_opus->mapping[6] = 6; case 8: krad_opus->streams = 5; krad_opus->coupled_streams = 3; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 6; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 4; krad_opus->mapping[6] = 5; krad_opus->mapping[7] = 7; } } krad_opus->opus_header->channels = krad_opus->channels; krad_opus->opus_header->nb_streams = krad_opus->streams; krad_opus->opus_header->nb_coupled = krad_opus->coupled_streams; memcpy (krad_opus->opus_header->stream_map, krad_opus->mapping, 256); krad_opus->encoder = opus_multistream_encoder_create (48000, krad_opus->channels, krad_opus->streams, krad_opus->coupled_streams, krad_opus->mapping, krad_opus->application, &krad_opus->err); if (krad_opus->err != OPUS_OK) { failfast ("Krad Opus Encoder: Cannot create encoder: %s", opus_strerror (krad_opus->err)); } opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_GET_LOOKAHEAD (&krad_opus->lookahead)); krad_opus->opus_header->preskip = krad_opus->lookahead; krad_opus->opus_header->gain = 0; krad_opus->opus_header->input_sample_rate = 48000; if (opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BITRATE (krad_opus->bitrate)) != OPUS_OK) { failfast ("Krad Opus Encoder: bitrate request failed"); } krad_opus->header_data_size = opus_header_to_packet (krad_opus->opus_header, krad_opus->header_data, 100); krad_opus->krad_codec_header.codec = OPUS; krad_opus->krad_codec_header.header[0] = krad_opus->header_data; krad_opus->krad_codec_header.header_size[0] = krad_opus->header_data_size; krad_opus->krad_codec_header.header_combined = krad_opus->header_data; krad_opus->krad_codec_header.header_combined_size = krad_opus->header_data_size; krad_opus->krad_codec_header.header_count = 2; krad_opus->krad_codec_header.header_size[1] = 8 + 4 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER=") + strlen (APPVERSION); krad_opus->opustags_header = calloc (1, krad_opus->krad_codec_header.header_size[1]); memcpy (krad_opus->opustags_header, "OpusTags", 8); krad_opus->opustags_header[8] = strlen (opus_get_version_string ()); memcpy (krad_opus->opustags_header + 12, opus_get_version_string (), strlen (opus_get_version_string ())); krad_opus->opustags_header[12 + strlen (opus_get_version_string ())] = 1; krad_opus->opustags_header[12 + strlen (opus_get_version_string ()) + 4] = strlen ("ENCODER=") + strlen (APPVERSION); memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4, "ENCODER=", strlen ("ENCODER=")); memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER="), APPVERSION, strlen (APPVERSION)); krad_opus->krad_codec_header.header[1] = krad_opus->opustags_header; return krad_opus; }
int krad_opus_encoder_read (krad_opus_t *krad_opus, unsigned char *buffer, int *nframes) { int ready; int bytes; int resp; int s, c; while (krad_ringbuffer_read_space (krad_opus->ringbuf[krad_opus->channels - 1]) >= 512 * 4 ) { for (c = 0; c < krad_opus->channels; c++) { krad_opus->ret = krad_ringbuffer_peek (krad_opus->ringbuf[c], (char *)krad_opus->samples[c], (512 * 4) ); krad_opus->src_data[c].data_in = krad_opus->samples[c]; krad_opus->src_data[c].input_frames = 512; krad_opus->src_data[c].data_out = krad_opus->resampled_samples[c]; krad_opus->src_data[c].output_frames = 2048; krad_opus->src_error[c] = src_process (krad_opus->src_resampler[c], &krad_opus->src_data[c]); if (krad_opus->src_error[c] != 0) { failfast ("Krad Opus Encoder: src resampler error: %s\n", src_strerror(krad_opus->src_error[c])); } krad_ringbuffer_read_advance (krad_opus->ringbuf[c], (krad_opus->src_data[c].input_frames_used * 4) ); krad_opus->ret = krad_ringbuffer_write (krad_opus->resampled_ringbuf[c], (char *)krad_opus->resampled_samples[c], (krad_opus->src_data[c].output_frames_gen * 4) ); } } if (krad_opus->new_bitrate != krad_opus->bitrate) { krad_opus->bitrate = krad_opus->new_bitrate; resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BITRATE(krad_opus->bitrate)); if (resp != OPUS_OK) { failfast ("Krad Opus Encoder: bitrate request failed %s\n", opus_strerror (resp)); } else { printk ("Krad Opus Encoder: set opus bitrate %d\n", krad_opus->bitrate); } } if (krad_opus->new_frame_size != krad_opus->frame_size) { krad_opus->frame_size = krad_opus->new_frame_size; printk ("Krad Opus Encoder: frame size is now %d\n", krad_opus->frame_size); } if (krad_opus->new_complexity != krad_opus->complexity) { krad_opus->complexity = krad_opus->new_complexity; resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_COMPLEXITY(krad_opus->complexity)); if (resp != OPUS_OK) { failfast ("Krad Opus Encoder: complexity request failed %s. \n", opus_strerror(resp)); } else { printk ("Krad Opus Encoder: set opus complexity %d\n", krad_opus->complexity); } } if (krad_opus->new_signal != krad_opus->signal) { krad_opus->signal = krad_opus->new_signal; resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_SIGNAL(krad_opus->signal)); if (resp != OPUS_OK) { failfast ("Krad Opus Encoder: signal request failed %s\n", opus_strerror(resp)); } else { printk ("Krad Opus Encoder: set opus signal mode %d\n", krad_opus->signal); } } if (krad_opus->new_bandwidth != krad_opus->bandwidth) { krad_opus->bandwidth = krad_opus->new_bandwidth; resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BANDWIDTH(krad_opus->bandwidth)); if (resp != OPUS_OK) { failfast ("Krad Opus Encoder: bandwidth request failed %s\n", opus_strerror(resp)); } else { printk ("Krad Opus Encoder: Set Opus bandwidth mode %d\n", krad_opus->bandwidth); } } ready = 1; for (c = 0; c < krad_opus->channels; c++) { if (krad_ringbuffer_read_space (krad_opus->resampled_ringbuf[c]) < krad_opus->frame_size * 4) { ready = 0; } } if (ready == 1) { for (c = 0; c < krad_opus->channels; c++) { krad_opus->ret = krad_ringbuffer_read (krad_opus->resampled_ringbuf[c], (char *)krad_opus->resampled_samples[c], (krad_opus->frame_size * 4) ); } for (s = 0; s < krad_opus->frame_size; s++) { for (c = 0; c < krad_opus->channels; c++) { krad_opus->interleaved_resampled_samples[s * krad_opus->channels + c] = krad_opus->resampled_samples[c][s]; } } bytes = opus_multistream_encode_float (krad_opus->encoder, krad_opus->interleaved_resampled_samples, krad_opus->frame_size, buffer, krad_opus->frame_size * 2); if (bytes < 0) { failfast ("Krad Opus Encoding failed: %s.", opus_strerror (bytes)); } *nframes = krad_opus->frame_size; return bytes; } return 0; }