void kr_v4l2s_run(kr_v4l2s *v4l2s) { kr_image cam_image; kr_image scaled_image; uint8_t *pixels; kr_convert conv; kr_codeme_t *vcodeme; int32_t ret; kr_image_convert_init(&conv); vcodeme = kr_codeme_kludge_create(); pixels = malloc(v4l2s->params->width * v4l2s->params->height * 2); scaled_image.w = v4l2s->params->width; scaled_image.h = v4l2s->params->height; scaled_image.px = pixels; scaled_image.ppx[0] = pixels; scaled_image.ppx[1] = pixels + (v4l2s->params->width * v4l2s->params->height); scaled_image.ppx[2] = pixels + (v4l2s->params->width * v4l2s->params->height) + ((v4l2s->params->width / 2) * (v4l2s->params->height / 2)); scaled_image.ppx[3] = 0; scaled_image.pps[0] = v4l2s->params->width; scaled_image.pps[1] = v4l2s->params->width / 2; scaled_image.pps[2] = v4l2s->params->width / 2; scaled_image.pps[3] = 0; scaled_image.fmt = PIX_FMT_YUV420P; kr_v4l2_capture(v4l2s->v4l2, 1); v4l2s->timer = kr_timer_create(); krad_vpx_encoder_deadline_set(v4l2s->vpx_enc, 1); kr_timer_start(v4l2s->timer); while (!destruct) { ret = kr_v4l2_poll(v4l2s->v4l2, 15); if (ret < 1) { continue; } scaled_image.tc = kr_timer_current_ms(v4l2s->timer); ret = kr_v4l2_read(v4l2s->v4l2, &cam_image); kr_image_convert(&conv, &scaled_image, &cam_image); kr_image_unref(&cam_image); ret = kr_vpx_encode(v4l2s->vpx_enc, vcodeme, &scaled_image); if (ret == 1) { kr_mkv_add_video_tc(v4l2s->mkv, 1, vcodeme->data, vcodeme->sz, vcodeme->key, vcodeme->tc); } printf("\rKrad V4L2 Stream Frame# %12"PRIu64" ", v4l2s->frames++); fflush(stdout); } kr_codeme_kludge_destroy(&vcodeme); kr_image_convert_clear(&conv); free(pixels); kr_timer_destroy(v4l2s->timer); }
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); }
int krad_transponder_handler ( krad_transponder_t *krad_transponder, krad_ipc_server_t *krad_ipc ) { krad_link_t *krad_link; uint32_t ebml_id; uint32_t command; uint64_t ebml_data_size; kr_address_t address; uint64_t element; uint64_t response; uint64_t payload_loc; char string[256]; uint64_t bigint; //int regint; uint8_t tinyint; int k; int devices; //float floatval; string[0] = '\0'; bigint = 0; k = 0; krad_ipc_server_read_command ( krad_ipc, &command, &ebml_data_size); switch ( command ) { case EBML_ID_KRAD_TRANSPONDER_CMD_LIST_LINKS: //printk ("krad transponder handler! LIST_LINKS"); krad_Xtransponder_list ( krad_transponder->krad_Xtransponder ); krad_ipc_server_response_start ( krad_ipc, EBML_ID_KRAD_TRANSPONDER_MSG, &response); for (k = 0; k < KRAD_TRANSPONDER_MAX_LINKS; k++) { if (krad_transponder->krad_link[k] != NULL) { printk ("Link %d Active: %s", k, krad_transponder->krad_link[k]->mount); krad_transponder_link_to_ebml ( krad_ipc->current_client, krad_transponder->krad_link[k]); } } krad_ipc_server_response_finish ( krad_ipc, response ); break; case EBML_ID_KRAD_TRANSPONDER_CMD_CREATE_LINK: for (k = 0; k < KRAD_TRANSPONDER_MAX_LINKS; k++) { if (krad_transponder->krad_link[k] == NULL) { krad_transponder->krad_link[k] = krad_link_prepare (k); krad_link = krad_transponder->krad_link[k]; krad_link->link_num = k; krad_link->krad_radio = krad_transponder->krad_radio; krad_link->krad_transponder = krad_transponder; krad_transponder_ebml_to_link ( krad_ipc, krad_link ); krad_link_start (krad_link); /* if ((krad_link->operation_mode == TRANSMIT) || (krad_link->operation_mode == RECORD)) { if (krad_link_wait_codec_init (krad_link) == 0) { krad_transponder_broadcast_link_created ( krad_ipc, krad_link ); } } else { krad_transponder_broadcast_link_created ( krad_ipc, krad_link ); } */ break; } } break; case EBML_ID_KRAD_TRANSPONDER_CMD_DESTROY_LINK: tinyint = krad_ipc_server_read_number (krad_ipc, ebml_data_size); k = tinyint; //printk ("krad transponder handler! DESTROY_LINK: %d %u", k, tinyint); if (krad_transponder->krad_link[k] != NULL) { krad_link_destroy (krad_transponder->krad_link[k]); krad_transponder->krad_link[k] = NULL; } /* krad_ipc_server_simple_number_broadcast ( krad_ipc, EBML_ID_KRAD_TRANSPONDER_MSG, EBML_ID_KRAD_TRANSPONDER_LINK_DESTROYED, EBML_ID_KRAD_TRANSPONDER_LINK_NUMBER, k); */ break; case EBML_ID_KRAD_TRANSPONDER_CMD_UPDATE_LINK: //printk ("krad transponder handler! UPDATE_LINK"); krad_ebml_read_element (krad_ipc->current_client->krad_ebml, &ebml_id, &ebml_data_size); if (ebml_id == EBML_ID_KRAD_TRANSPONDER_LINK_NUMBER) { tinyint = krad_ipc_server_read_number (krad_ipc, ebml_data_size); k = tinyint; //printk ("krad transponder handler! UPDATE_LINK: %d %u", k, tinyint); if (krad_transponder->krad_link[k] != NULL) { krad_ebml_read_element (krad_ipc->current_client->krad_ebml, &ebml_id, &ebml_data_size); if (krad_transponder->krad_link[k]->audio_codec == OPUS) { /* if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_APPLICATION) { krad_ebml_read_string (krad_ipc->current_client->krad_ebml, string, ebml_data_size); if (strncmp(string, "OPUS_APPLICATION_VOIP", 21) == 0) { krad_opus_set_application (krad_transponder->krad_link[k]->krad_opus, OPUS_APPLICATION_VOIP); } if (strncmp(string, "OPUS_APPLICATION_AUDIO", 22) == 0) { krad_opus_set_application (krad_transponder->krad_link[k]->krad_opus, OPUS_APPLICATION_AUDIO); } if (strncmp(string, "OPUS_APPLICATION_RESTRICTED_LOWDELAY", 36) == 0) { krad_opus_set_application (krad_transponder->krad_link[k]->krad_opus, OPUS_APPLICATION_RESTRICTED_LOWDELAY); } } */ if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_SIGNAL) { krad_ebml_read_string (krad_ipc->current_client->krad_ebml, string, ebml_data_size); krad_opus_set_signal (krad_transponder->krad_link[k]->krad_opus, krad_opus_string_to_signal(string)); } if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_BANDWIDTH) { krad_ebml_read_string (krad_ipc->current_client->krad_ebml, string, ebml_data_size); krad_opus_set_bandwidth (krad_transponder->krad_link[k]->krad_opus, krad_opus_string_to_bandwidth(string)); } if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_BITRATE) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if ((bigint >= 500) && (bigint <= 512000)) { krad_opus_set_bitrate (krad_transponder->krad_link[k]->krad_opus, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_COMPLEXITY) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if ((bigint >= 0) && (bigint <= 10)) { krad_opus_set_complexity (krad_transponder->krad_link[k]->krad_opus, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_FRAME_SIZE) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if ((bigint == 120) || (bigint == 240) || (bigint == 480) || (bigint == 960) || (bigint == 1920) || (bigint == 2880)) { krad_opus_set_frame_size (krad_transponder->krad_link[k]->krad_opus, bigint); } } //FIXME verify ogg container if (ebml_id == EBML_ID_KRAD_LINK_LINK_OGG_MAX_PACKETS_PER_PAGE) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if ((bigint > 0) && (bigint < 200)) { krad_ogg_set_max_packets_per_page (krad_transponder->krad_link[k]->krad_container->krad_ogg, bigint); } } } if (krad_transponder->krad_link[k]->video_codec == THEORA) { if (ebml_id == EBML_ID_KRAD_LINK_LINK_THEORA_QUALITY) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); krad_theora_encoder_quality_set (krad_transponder->krad_link[k]->krad_theora_encoder, bigint); } } if (krad_transponder->krad_link[k]->video_codec == VP8) { if (ebml_id == EBML_ID_KRAD_LINK_LINK_VP8_BITRATE) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if (bigint > 0) { krad_vpx_encoder_bitrate_set (krad_transponder->krad_link[k]->krad_vpx_encoder, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_VP8_MIN_QUANTIZER) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if (bigint > 0) { krad_vpx_encoder_min_quantizer_set (krad_transponder->krad_link[k]->krad_vpx_encoder, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_VP8_MAX_QUANTIZER) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if (bigint > 0) { krad_vpx_encoder_max_quantizer_set (krad_transponder->krad_link[k]->krad_vpx_encoder, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_VP8_DEADLINE) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if (bigint > 0) { krad_vpx_encoder_deadline_set (krad_transponder->krad_link[k]->krad_vpx_encoder, bigint); } } if (ebml_id == EBML_ID_KRAD_LINK_LINK_VP8_FORCE_KEYFRAME) { bigint = krad_ebml_read_number (krad_ipc->current_client->krad_ebml, ebml_data_size); if (bigint > 0) { krad_vpx_encoder_want_keyframe (krad_transponder->krad_link[k]->krad_vpx_encoder); } } } /* if ((ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_BANDWIDTH) || (ebml_id == EBML_ID_KRAD_LINK_LINK_OPUS_SIGNAL)) { krad_ipc_server_advanced_string_broadcast ( krad_ipc, EBML_ID_KRAD_TRANSPONDER_MSG, EBML_ID_KRAD_TRANSPONDER_LINK_UPDATED, EBML_ID_KRAD_TRANSPONDER_LINK_NUMBER, k, ebml_id, string); } else { krad_ipc_server_advanced_number_broadcast ( krad_ipc, EBML_ID_KRAD_TRANSPONDER_MSG, EBML_ID_KRAD_TRANSPONDER_LINK_UPDATED, EBML_ID_KRAD_TRANSPONDER_LINK_NUMBER, k, ebml_id, bigint); } */ } } break; case EBML_ID_KRAD_TRANSPONDER_CMD_LIST_ADAPTERS: address.path.unit = KR_TRANSPONDER; address.path.subunit.transponder_subunit = KR_ADAPTER; #ifdef KR_LINUX devices = krad_v4l2_detect_devices (); for (k = 0; k < devices; k++) { if (krad_v4l2_get_device_filename (k, string) > 0) { address.id.number = k; krad_ipc_server_response_start_with_address_and_type ( krad_ipc, &address, EBML_ID_KRAD_SUBUNIT_INFO, &response); krad_ipc_server_payload_start ( krad_ipc, &payload_loc); krad_ebml_write_string (krad_ipc->current_client->krad_ebml2, EBML_ID_KRAD_TRANSPONDER_V4L2_DEVICE_FILENAME, string); //krad_ebml_start_element (kr_ipc->current_client->krad_ebml2, EBML_ID_KRAD_RADIO_REMOTE_STATUS, &element); //krad_ipc_server_respond_string ( kr_ipc, EBML_ID_KRAD_RADIO_REMOTE_INTERFACE, kr_ipc->tcp_interface[i]); //krad_ipc_server_respond_number ( kr_ipc, EBML_ID_KRAD_RADIO_REMOTE_PORT, kr_ipc->tcp_port[i]); //krad_ebml_finish_element (kr_ipc->current_client->krad_ebml2, element); krad_ipc_server_payload_finish ( krad_ipc, payload_loc ); krad_ipc_server_response_finish ( krad_ipc, response ); } } #endif devices = krad_decklink_detect_devices(); for (k = 0; k < devices; k++) { krad_decklink_get_device_name (k, string); address.id.number = k; krad_ipc_server_response_start_with_address_and_type ( krad_ipc, &address, EBML_ID_KRAD_SUBUNIT_INFO, &response); krad_ipc_server_payload_start ( krad_ipc, &payload_loc); krad_ebml_write_string (krad_ipc->current_client->krad_ebml2, EBML_ID_KRAD_TRANSPONDER_DECKLINK_DEVICE_NAME, string); //krad_ebml_start_element (kr_ipc->current_client->krad_ebml2, EBML_ID_KRAD_RADIO_REMOTE_STATUS, &element); //krad_ipc_server_respond_string ( kr_ipc, EBML_ID_KRAD_RADIO_REMOTE_INTERFACE, kr_ipc->tcp_interface[i]); //krad_ipc_server_respond_number ( kr_ipc, EBML_ID_KRAD_RADIO_REMOTE_PORT, kr_ipc->tcp_port[i]); //krad_ebml_finish_element (kr_ipc->current_client->krad_ebml2, element); krad_ipc_server_payload_finish ( krad_ipc, payload_loc ); krad_ipc_server_response_finish ( krad_ipc, response ); } return 1; case EBML_ID_KRAD_TRANSPONDER_CMD_LISTEN_ENABLE: krad_ebml_read_element ( krad_ipc->current_client->krad_ebml, &ebml_id, &ebml_data_size); if (ebml_id != EBML_ID_KRAD_RADIO_TCP_PORT) { printke ("hrm wtf6"); } bigint = krad_ebml_read_number ( krad_ipc->current_client->krad_ebml, ebml_data_size); krad_receiver_listen_on (krad_transponder->krad_receiver, bigint); break; case EBML_ID_KRAD_TRANSPONDER_CMD_LISTEN_DISABLE: krad_receiver_stop_listening (krad_transponder->krad_receiver); break; case EBML_ID_KRAD_TRANSPONDER_CMD_TRANSMITTER_ENABLE: krad_ebml_read_element ( krad_ipc->current_client->krad_ebml, &ebml_id, &ebml_data_size); if (ebml_id != EBML_ID_KRAD_RADIO_TCP_PORT) { printke ("hrm wtf6"); } bigint = krad_ebml_read_number ( krad_ipc->current_client->krad_ebml, ebml_data_size); krad_transmitter_listen_on (krad_transponder->krad_transmitter, bigint); break; case EBML_ID_KRAD_TRANSPONDER_CMD_TRANSMITTER_DISABLE: krad_transmitter_stop_listening (krad_transponder->krad_transmitter); break; } return 0; }