int main(int argc, char **argv) { ssize_t readen; int have_data = 1; int ntimeouts = 0; time_t timeout_start = time(NULL); int rtp_hdr_pos = 0, num_packets = 0; struct rlimit rl; if (getrlimit(RLIMIT_STACK, &rl) == 0) { if (rl.rlim_cur > THREAD_STACK_SIZE) { rl.rlim_cur = THREAD_STACK_SIZE; setrlimit(RLIMIT_STACK, &rl); } } memset(rtp_hdr[0], 0, RTP_HDR_SZ); memset(rtp_hdr[1], 0, RTP_HDR_SZ); data_init(&ts); ts_set_log_func(LOG_func); parse_options(&ts, argc, argv); if (ts.pidfile) daemonize(ts.pidfile); if (ts.syslog_active) { if (ts.syslog_remote) { log_init(ts.ident, 1, 1, ts.syslog_host, ts.syslog_port); remote_syslog = 1; } else { openlog(ts.ident, LOG_NDELAY | LOG_PID, LOG_USER); local_syslog = 1; } } ts.notify = notify_alloc(&ts); ts_LOGf("Start %s\n", program_id); notify(&ts, "START", "Starting %s", program_id); if (ts.input.type == NET_IO && udp_connect_input(&ts.input) < 1) goto EXIT; if (ts.output.type == NET_IO && udp_connect_output(&ts.output) < 1) goto EXIT; signal(SIGCHLD, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGINT , signal_quit); signal(SIGTERM, signal_quit); if (ts.threaded) { pthread_create(&ts.decode_thread, &ts.thread_attr, &decode_thread, &ts); pthread_create(&ts.write_thread , &ts.thread_attr, &write_thread , &ts); } ts.emm_last_report = time(NULL) + FIRST_REPORT_SEC; ts.ecm_last_report = time(NULL) + FIRST_REPORT_SEC; camd_start(&ts); if (packet_from_file) { uint8_t tmp[2048]; ts_hex_dump_buf((char *)tmp, sizeof(tmp), packet_buf, packet_buflen, 16); ts_LOGf("%s | Processing packet with CAID 0x%04x\n", packet_type == ECM_MSG ? "ECM" : "EMM", ts.forced_caid); ts_LOGf("%s | Packet dump:\n%s\n", packet_type == ECM_MSG ? "ECM" : "EMM", tmp); camd_process_packet(&ts, camd_msg_alloc(packet_type, ts.forced_caid, ts.forced_service_id, packet_buf, packet_buflen)); goto EXIT; } do { if (!ts.camd.constant_codeword) do_reports(&ts); if (ts.input.type == NET_IO) { set_log_io_errors(0); if (!ts.rtp_input) { readen = fdread_ex(ts.input.fd, (char *)ts_packet, FRAME_SIZE, 250, 4, 1); } else { readen = fdread_ex(ts.input.fd, (char *)ts_packet, FRAME_SIZE + RTP_HDR_SZ, 250, 4, 1); if (readen > RTP_HDR_SZ) { memcpy(rtp_hdr[rtp_hdr_pos], ts_packet, RTP_HDR_SZ); memmove(ts_packet, ts_packet + RTP_HDR_SZ, FRAME_SIZE); readen -= RTP_HDR_SZ; uint16_t ssrc = (rtp_hdr[rtp_hdr_pos][2] << 8) | rtp_hdr[rtp_hdr_pos][3]; uint16_t pssrc = (rtp_hdr[!rtp_hdr_pos][2] << 8) | rtp_hdr[!rtp_hdr_pos][3]; rtp_hdr_pos = !rtp_hdr_pos; if (pssrc + 1 != ssrc && (ssrc != 0 && pssrc != 0xffff) && num_packets > 2) if (ts.ts_discont) ts_LOGf("--- | RTP discontinuity last_ssrc %5d, curr_ssrc %5d, lost %d packet\n", pssrc, ssrc, ((ssrc - pssrc)-1) & 0xffff); num_packets++; } } set_log_io_errors(1); if (!keep_running) break; if (readen < 0) { ts_LOGf("--- | Input read timeout.\n"); if (!ntimeouts) { timeout_start = time(NULL); notify(&ts, "INPUT_TIMEOUT", "Read timeout on input %s://%s:%s/", ts.rtp_input ? "rtp" : "udp", ts.input.hostname, ts.input.service); } ts.no_input = 1; ntimeouts++; } else { if (ntimeouts && readen > 0) { time_t now = time(NULL); ts_LOGf("+++ | Input OK after %ld sec timeout.\n", (now - timeout_start) + 2); notify(&ts, "INPUT_OK", "Data is available on input %s://%s:%s/ after %ld seconds timeout.", ts.rtp_input ? "rtp" : "udp", ts.input.hostname, ts.input.service, (now - timeout_start) + 2); // Timeout is detected when ~2 seconds there is no incoming data ts.no_input = 0; ntimeouts = 0; } } } else { readen = read(ts.input.fd, ts_packet, FRAME_SIZE); have_data = !(readen <= 0); } if (readen > 0) { if (ts.input_dump_file) fwrite(ts_packet, readen, 1, ts.input_dump_file); process_packets(&ts, ts_packet, readen); } } while (have_data && keep_running); EXIT: camd_stop(&ts); // If pthread_join failes make sure we exit... signal(SIGINT , SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGALRM, signal_alarm); alarm(2); if (ts.threaded) { ts.decode_stop = 1; ts.write_stop = 1; if (ts.decode_thread) pthread_join(ts.decode_thread, NULL); if (ts.write_thread) pthread_join(ts.write_thread, NULL); } show_pid_report(&ts); notify_sync(&ts, "STOP", "Stopping %s", program_id); ts_LOGf("Stop %s\n", program_id); if (ts.syslog_active) { if (ts.syslog_remote) log_close(); else closelog(); } if (ts.input_dump_file) fclose(ts.input_dump_file); if (ts.pidfile) unlink(ts.pidfile); if (log_file) fclose(log_file); notify_free(&ts.notify); data_free(&ts); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { struct videohub_data *data = &maindata; parse_options(data, argc, argv); set_log_io_errors(0); if (!test_data) { data->dev_fd = connect_client(SOCK_STREAM, data->dev_host, data->dev_port); if (data->dev_fd < 0) exit(EXIT_FAILURE); } reset_routed_to(&data->inputs); reset_routed_to(&data->outputs); reset_routed_to(&data->serial); reset_routed_to(&data->proc_units); reset_routed_to(&data->frames); read_device_command_stream(data); if (test_data) parse_text_buffer(data, test_data); if (!strlen(data->device.protocol_ver) || !strlen(data->device.model_name)) die("The device does not respond correctly. Is it Videohub?"); if (strstr(data->device.protocol_ver, "2.") != data->device.protocol_ver) q("WARNING: Device protocol is %s but this program is tested with 2.x only.\n", data->device.protocol_ver); if (!data->device.dev_present) { if (data->device.needs_fw_update) { die("Device reports that it needs firmware update."); } die("Device reports that it is not present."); } check_number_of_ports(&data->inputs); check_number_of_ports(&data->outputs); check_number_of_ports(&data->mon_outputs); check_number_of_ports(&data->serial); check_number_of_ports(&data->proc_units); check_number_of_ports(&data->frames); if (num_parsed_cmds) { unsigned int i; for (i = 0; i < ARRAY_SIZE(parsed_cmds.entry); i++) { struct vcmd_entry *ve = &parsed_cmds.entry[i]; if (!ve->p1.param) continue; prepare_cmd_entry(data, &parsed_cmds.entry[i]); } for (i = 0; i < ARRAY_SIZE(parsed_cmds.entry); i++) { char cmd_buffer[1024]; struct vcmd_entry *ve = &parsed_cmds.entry[i]; if (!ve->p1.param) continue; format_cmd_text(ve, cmd_buffer, sizeof(cmd_buffer)); if (strlen(cmd_buffer)) { show_cmd(data, ve); send_device_command(data, cmd_buffer); read_device_command_stream(data); } } // Show the result after commands if (test_data) print_device_full(data); } else if (show_monitor) { while (1) { int sleeps = 0; printf("\e[2J\e[H"); // Clear screen time_t now = time(NULL); struct tm *tm = localtime(&now); printf("Last update: %s\n", asctime(tm)); print_device_info(data); print_device_video_inputs(data); print_device_video_outputs(data); fflush(stdout); do { usleep(500000); if (++sleeps >= 20) send_device_command(data, "PING:\n\n"); } while (read_device_command_stream(data) == 0); } } else if (show_list) {